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(q->thread() == qApp->thread(), "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 if (q->isVisible()) {
1405 // If widget is already shown, set window visible, too
1406 win->setNativeWindowVisibility(true);
1407 }
1408}
1409
1410#ifdef Q_OS_WIN
1411static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1412#endif
1413
1414void QWidgetPrivate::createTLSysExtra()
1415{
1416 Q_Q(QWidget);
1417 if (!extra->topextra->window && (q->testAttribute(attribute: Qt::WA_NativeWindow) || q->isWindow())) {
1418 extra->topextra->window = new QWidgetWindow(q);
1419 if (extra->minw || extra->minh)
1420 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1421 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1422 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1423 if (extra->topextra->opacity != 255 && q->isWindow())
1424 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1425
1426 const bool isTipLabel = q->inherits(classname: "QTipLabel");
1427 const bool isAlphaWidget = !isTipLabel && q->inherits(classname: "QAlphaWidget");
1428#ifdef Q_OS_WIN
1429 // Pass on native parent handle for Widget embedded into Active X.
1430 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1431 if (activeXNativeParentHandle.isValid())
1432 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1433 if (isTipLabel || isAlphaWidget)
1434 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1435#endif
1436 if (isTipLabel || isAlphaWidget || q->inherits(classname: "QRollEffect"))
1437 qt_window_private(window: extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1438
1439 updateIsTranslucent();
1440 }
1441
1442}
1443
1444/*!
1445 Destroys the widget.
1446
1447 All this widget's children are deleted first. The application
1448 exits if this widget is the main widget.
1449*/
1450
1451QWidget::~QWidget()
1452{
1453 Q_D(QWidget);
1454 d->data.in_destructor = true;
1455
1456#if defined (QT_CHECK_STATE)
1457 if (Q_UNLIKELY(paintingActive()))
1458 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1459#endif
1460
1461#ifndef QT_NO_GESTURES
1462 if (QGestureManager *manager = QGestureManager::instance(ic: QGestureManager::DontForceCreation)) {
1463 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1464 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1465 manager->cleanupCachedGestures(target: this, type: *it);
1466 }
1467 d->gestureContext.clear();
1468#endif
1469
1470#ifndef QT_NO_ACTION
1471 // remove all actions from this widget
1472 for (auto action : std::as_const(t&: d->actions)) {
1473 QActionPrivate *apriv = action->d_func();
1474 apriv->associatedObjects.removeAll(t: this);
1475 }
1476 d->actions.clear();
1477#endif
1478
1479#ifndef QT_NO_SHORTCUT
1480 // Remove all shortcuts grabbed by this
1481 // widget, unless application is closing
1482 if (!QApplicationPrivate::is_app_closing && testAttribute(attribute: Qt::WA_GrabbedShortcut))
1483 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id: 0, owner: this, key: QKeySequence());
1484#endif
1485
1486 // delete layout while we still are a valid widget
1487 delete d->layout;
1488 d->layout = nullptr;
1489
1490 // Remove this from focus list
1491 d->removeFromFocusChain(rules: QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1492
1493 QT_TRY {
1494#if QT_CONFIG(graphicsview)
1495 const QWidget* w = this;
1496 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1497 w = w->d_func()->extra->focus_proxy;
1498 QWidget *window = w->window();
1499 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1500 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1501#endif
1502 clearFocus();
1503 } QT_CATCH(...) {
1504 // swallow this problem because we are in a destructor
1505 }
1506
1507 d->setDirtyOpaqueRegion();
1508
1509 if (isWindow() && isVisible() && internalWinId()) {
1510 QT_TRY {
1511 d->close();
1512 } QT_CATCH(...) {
1513 // if we're out of memory, at least hide the window.
1514 QT_TRY {
1515 hide();
1516 } QT_CATCH(...) {
1517 // and if that also doesn't work, then give up
1518 }
1519 }
1520 } else if (isVisible()) {
1521 qApp->d_func()->sendSyntheticEnterLeave(widget: this);
1522 }
1523
1524 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1525 repaintManager->removeDirtyWidget(w: this);
1526 if (testAttribute(attribute: Qt::WA_StaticContents))
1527 repaintManager->removeStaticWidget(widget: this);
1528 }
1529
1530 delete d->needsFlush;
1531 d->needsFlush = nullptr;
1532
1533 // The next 20 lines are duplicated from QObject, but required here
1534 // since QWidget deletes is children itself
1535 bool blocked = d->blockSig;
1536 d->blockSig = 0; // unblock signals so we always emit destroyed()
1537
1538 if (d->isSignalConnected(signalIdx: 0)) {
1539 QT_TRY {
1540 emit destroyed(this);
1541 } QT_CATCH(...) {
1542 // all the signal/slots connections are still in place - if we don't
1543 // quit now, we will crash pretty soon.
1544 qWarning(msg: "Detected an unexpected exception in ~QWidget while emitting destroyed().");
1545 QT_RETHROW;
1546 }
1547 }
1548
1549 if (d->declarativeData) {
1550 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1551 if (QAbstractDeclarativeData::destroyed)
1552 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1553 d->declarativeData = nullptr; // don't activate again in ~QObject
1554 d->wasDeleted = false;
1555 }
1556
1557 d->blockSig = blocked;
1558
1559 if (!d->children.isEmpty())
1560 d->deleteChildren();
1561
1562 QCoreApplication::removePostedEvents(receiver: this);
1563
1564 QT_TRY {
1565 destroy(); // platform-dependent cleanup
1566 } QT_CATCH(...) {
1567 // if this fails we can't do anything about it but at least we are not allowed to throw.
1568 }
1569 --QWidgetPrivate::instanceCounter;
1570
1571 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1572 QWidgetPrivate::allWidgets->remove(value: this);
1573
1574 QT_TRY {
1575 QEvent e(QEvent::Destroy);
1576 QCoreApplication::sendEvent(receiver: this, event: &e);
1577 } QT_CATCH(const std::exception&) {
1578 // if this fails we can't do anything about it but at least we are not allowed to throw.
1579 }
1580
1581#if QT_CONFIG(graphicseffect)
1582 delete d->graphicsEffect;
1583#endif
1584 d->deleteExtra();
1585
1586 d->isWidget = false;
1587}
1588
1589int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1590int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1591
1592void QWidgetPrivate::setWinId(WId id) // set widget identifier
1593{
1594 Q_Q(QWidget);
1595 if (mapper && data.winid) {
1596 mapper->remove(key: data.winid);
1597 }
1598
1599 const WId oldWinId = data.winid;
1600
1601 data.winid = id;
1602 if (mapper && id) {
1603 mapper->insert(key: data.winid, value: q);
1604 }
1605
1606 if (oldWinId != id) {
1607 QEvent e(QEvent::WinIdChange);
1608 QCoreApplication::sendEvent(receiver: q, event: &e);
1609 }
1610}
1611
1612void QWidgetPrivate::createTLExtra()
1613{
1614 if (!extra)
1615 createExtra();
1616 if (!extra->topextra) {
1617 extra->topextra = std::make_unique<QTLWExtra>();
1618 QTLWExtra* x = extra->topextra.get();
1619 x->backingStore = nullptr;
1620 x->sharedPainter = nullptr;
1621 x->incw = x->inch = 0;
1622 x->basew = x->baseh = 0;
1623 x->frameStrut.setCoords(xp1: 0, yp1: 0, xp2: 0, yp2: 0);
1624 x->normalGeometry = QRect(0,0,-1,-1);
1625 x->savedFlags = { };
1626 x->opacity = 255;
1627 x->posIncludesFrame = 0;
1628 x->sizeAdjusted = false;
1629 x->embedded = 0;
1630 x->window = nullptr;
1631 x->initialScreen = nullptr;
1632
1633#ifdef QWIDGET_EXTRA_DEBUG
1634 static int count = 0;
1635 qDebug() << "tlextra" << ++count;
1636#endif
1637 }
1638}
1639
1640/*!
1641 \internal
1642 Creates the widget extra data.
1643*/
1644
1645void QWidgetPrivate::createExtra()
1646{
1647 if (!extra) { // if not exists
1648 extra = std::make_unique<QWExtra>();
1649 extra->glContext = nullptr;
1650#if QT_CONFIG(graphicsview)
1651 extra->proxyWidget = nullptr;
1652#endif
1653 extra->minw = 0;
1654 extra->minh = 0;
1655 extra->maxw = QWIDGETSIZE_MAX;
1656 extra->maxh = QWIDGETSIZE_MAX;
1657 extra->customDpiX = 0;
1658 extra->customDpiY = 0;
1659 extra->explicitMinSize = 0;
1660 extra->explicitMaxSize = 0;
1661 extra->autoFillBackground = 0;
1662 extra->nativeChildrenForced = 0;
1663 extra->inRenderWithPainter = 0;
1664 extra->hasWindowContainer = false;
1665 extra->hasMask = 0;
1666 createSysExtra();
1667#ifdef QWIDGET_EXTRA_DEBUG
1668 static int count = 0;
1669 qDebug() << "extra" << ++count;
1670#endif
1671 }
1672}
1673
1674void QWidgetPrivate::createSysExtra()
1675{
1676}
1677
1678/*!
1679 \internal
1680 Deletes the widget extra data.
1681*/
1682
1683void QWidgetPrivate::deleteExtra()
1684{
1685 if (extra) { // if exists
1686 deleteSysExtra();
1687#ifndef QT_NO_STYLE_STYLESHEET
1688 // dereference the stylesheet style
1689 if (QStyleSheetStyle *proxy = qt_styleSheet(style: extra->style))
1690 proxy->deref();
1691#endif
1692 if (extra->topextra)
1693 deleteTLSysExtra();
1694
1695 // extra->xic destroyed in QWidget::destroy()
1696 extra.reset();
1697 }
1698}
1699
1700void QWidgetPrivate::deleteSysExtra()
1701{
1702}
1703
1704void QWidgetPrivate::deleteTLSysExtra()
1705{
1706 Q_Q(QWidget);
1707 if (extra && extra->topextra) {
1708 if (extra->hasWindowContainer)
1709 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
1710
1711 delete extra->topextra->window;
1712 extra->topextra->window = nullptr;
1713 }
1714}
1715
1716/*
1717 Returns \c region of widgets above this which overlap with
1718 \a rect, which is in parent's coordinate system (same as crect).
1719*/
1720
1721QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1722{
1723 Q_Q(const QWidget);
1724
1725 const QWidget *w = q;
1726 QRect r = rect;
1727 QPoint p;
1728 QRegion region;
1729 while (w) {
1730 if (w->isWindow())
1731 break;
1732 QWidgetPrivate *pd = w->parentWidget()->d_func();
1733 bool above = false;
1734 for (int i = 0; i < pd->children.size(); ++i) {
1735 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
1736 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1737 continue;
1738 if (!above) {
1739 above = (sibling == w);
1740 continue;
1741 }
1742
1743 const QRect siblingRect = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
1744 if (qRectIntersects(r1: siblingRect, r2: r)) {
1745 const auto &siblingExtra = sibling->d_func()->extra;
1746 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1747 && !siblingExtra->mask.translated(p: sibling->data->crect.topLeft()).intersects(r)) {
1748 continue;
1749 }
1750 region += siblingRect.translated(p: -p);
1751 if (breakAfterFirst)
1752 break;
1753 }
1754 }
1755 w = w->parentWidget();
1756 r.translate(p: pd->data.crect.topLeft());
1757 p += pd->data.crect.topLeft();
1758 }
1759 return region;
1760}
1761
1762void QWidgetPrivate::syncBackingStore()
1763{
1764 if (shouldPaintOnScreen()) {
1765 paintOnScreen(rgn: dirty);
1766 dirty = QRegion();
1767 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1768 repaintManager->sync();
1769 }
1770}
1771
1772void QWidgetPrivate::syncBackingStore(const QRegion &region)
1773{
1774 if (shouldPaintOnScreen())
1775 paintOnScreen(rgn: region);
1776 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1777 repaintManager->sync(exposedWidget: q_func(), exposedRegion: region);
1778 }
1779}
1780
1781void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1782{
1783 if (data.in_destructor)
1784 return;
1785
1786 if (shouldDiscardSyncRequest())
1787 return;
1788
1789 Q_Q(QWidget);
1790 if (q->testAttribute(attribute: Qt::WA_StaticContents)) {
1791 if (!extra)
1792 createExtra();
1793 extra->staticContentsSize = data.crect.size();
1794 }
1795
1796 QPaintEngine *engine = q->paintEngine();
1797
1798 // QGLWidget does not support partial updates if:
1799 // 1) The context is double buffered
1800 // 2) The context is single buffered and auto-fill background is enabled.
1801 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1802 || engine->type() == QPaintEngine::OpenGL2))
1803 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1804 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1805
1806 toBePainted &= clipRect();
1807 clipToEffectiveMask(region&: toBePainted);
1808 if (toBePainted.isEmpty())
1809 return; // Nothing to repaint.
1810
1811 drawWidget(pdev: q, rgn: toBePainted, offset: QPoint(), flags: QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, sharedPainter: nullptr);
1812
1813 if (Q_UNLIKELY(q->paintingActive()))
1814 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1815}
1816
1817void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1818{
1819 Q_Q(QWidget);
1820
1821 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1822 return; // nothing we can do
1823
1824 if (enable != q->testAttribute(attribute: Qt::WA_UpdatesDisabled))
1825 return; // nothing to do
1826
1827 q->setAttribute(Qt::WA_UpdatesDisabled, on: !enable);
1828 if (enable)
1829 q->update();
1830
1831 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1832 for (int i = 0; i < children.size(); ++i) {
1833 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
1834 if (w && !w->isWindow() && !w->testAttribute(attribute))
1835 w->d_func()->setUpdatesEnabled_helper(enable);
1836 }
1837}
1838
1839/*!
1840 \internal
1841
1842 Propagate this widget's palette to all children, except style sheet
1843 widgets, and windows that don't enable window propagation (palettes don't
1844 normally propagate to windows).
1845*/
1846void QWidgetPrivate::propagatePaletteChange()
1847{
1848 Q_Q(QWidget);
1849 // Propagate a new inherited mask to all children.
1850#if QT_CONFIG(graphicsview)
1851 if (!q->parentWidget() && extra && extra->proxyWidget) {
1852 QGraphicsProxyWidget *p = extra->proxyWidget;
1853 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1854 } else
1855#endif // QT_CONFIG(graphicsview)
1856 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
1857 inheritedPaletteResolveMask = 0;
1858 }
1859
1860 directPaletteResolveMask = data.pal.resolveMask();
1861 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1862
1863 const bool useStyleSheetPropagationInWidgetStyles =
1864 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1865
1866 QEvent pc(QEvent::PaletteChange);
1867 QCoreApplication::sendEvent(receiver: q, event: &pc);
1868 for (int i = 0; i < children.size(); ++i) {
1869 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
1870 if (w && (!w->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1871 && (!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
1872 QWidgetPrivate *wd = w->d_func();
1873 wd->inheritedPaletteResolveMask = mask;
1874 wd->resolvePalette();
1875 }
1876 }
1877}
1878
1879/*
1880 Returns the widget's clipping rectangle.
1881*/
1882QRect QWidgetPrivate::clipRect() const
1883{
1884 Q_Q(const QWidget);
1885 const QWidget * w = q;
1886 if (!w->isVisible())
1887 return QRect();
1888 QRect r = effectiveRectFor(rect: q->rect());
1889 int ox = 0;
1890 int oy = 0;
1891 while (w
1892 && w->isVisible()
1893 && !w->isWindow()
1894 && w->parentWidget()) {
1895 ox -= w->x();
1896 oy -= w->y();
1897 w = w->parentWidget();
1898 r &= QRect(ox, oy, w->width(), w->height());
1899 }
1900 return r;
1901}
1902
1903/*
1904 Returns the widget's clipping region (without siblings).
1905*/
1906QRegion QWidgetPrivate::clipRegion() const
1907{
1908 Q_Q(const QWidget);
1909 if (!q->isVisible())
1910 return QRegion();
1911 QRegion r(q->rect());
1912 const QWidget * w = q;
1913 const QWidget *ignoreUpTo;
1914 int ox = 0;
1915 int oy = 0;
1916 while (w
1917 && w->isVisible()
1918 && !w->isWindow()
1919 && w->parentWidget()) {
1920 ox -= w->x();
1921 oy -= w->y();
1922 ignoreUpTo = w;
1923 w = w->parentWidget();
1924 r &= QRegion(ox, oy, w->width(), w->height());
1925
1926 int i = 0;
1927 while(w->d_func()->children.at(i: i++) != static_cast<const QObject *>(ignoreUpTo))
1928 ;
1929 for ( ; i < w->d_func()->children.size(); ++i) {
1930 if (QWidget *sibling = qobject_cast<QWidget *>(o: w->d_func()->children.at(i))) {
1931 if (sibling->isVisible() && !sibling->isWindow()) {
1932 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1933 sibling->width(), sibling->height());
1934 if (qRectIntersects(r1: siblingRect, r2: q->rect()))
1935 r -= QRegion(siblingRect);
1936 }
1937 }
1938 }
1939 }
1940 return r;
1941}
1942
1943void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1944{
1945// Transform the system clip region from device-independent pixels to device pixels
1946 QTransform scaleTransform;
1947 scaleTransform.scale(sx: devicePixelRatio, sy: devicePixelRatio);
1948
1949 paintEngine->d_func()->baseSystemClip = region;
1950 paintEngine->d_func()->setSystemTransform(scaleTransform);
1951
1952}
1953
1954#if QT_CONFIG(graphicseffect)
1955void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1956{
1957 Q_Q(QWidget);
1958 QWidget *w = q;
1959 do {
1960 if (w->graphicsEffect()) {
1961 QWidgetEffectSourcePrivate *sourced =
1962 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1963 if (!sourced->updateDueToGraphicsEffect)
1964 w->graphicsEffect()->source()->d_func()->invalidateCache();
1965 }
1966 w = w->parentWidget();
1967 } while (w);
1968}
1969#endif // QT_CONFIG(graphicseffect)
1970
1971void QWidgetPrivate::setDirtyOpaqueRegion()
1972{
1973 Q_Q(QWidget);
1974
1975 dirtyOpaqueChildren = true;
1976
1977#if QT_CONFIG(graphicseffect)
1978 invalidateGraphicsEffectsRecursively();
1979#endif // QT_CONFIG(graphicseffect)
1980
1981 if (q->isWindow())
1982 return;
1983
1984 QWidget *parent = q->parentWidget();
1985 if (!parent)
1986 return;
1987
1988 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1989 QWidgetPrivate *pd = parent->d_func();
1990 if (!pd->dirtyOpaqueChildren)
1991 pd->setDirtyOpaqueRegion();
1992}
1993
1994const QRegion &QWidgetPrivate::getOpaqueChildren() const
1995{
1996 if (!dirtyOpaqueChildren)
1997 return opaqueChildren;
1998
1999 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2000 that->opaqueChildren = QRegion();
2001
2002 for (int i = 0; i < children.size(); ++i) {
2003 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
2004 if (!child || !child->isVisible() || child->isWindow())
2005 continue;
2006
2007 const QPoint offset = child->geometry().topLeft();
2008 QWidgetPrivate *childd = child->d_func();
2009 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2010 if (childd->extra && childd->extra->hasMask)
2011 r &= childd->extra->mask;
2012 if (r.isEmpty())
2013 continue;
2014 r.translate(p: offset);
2015 that->opaqueChildren += r;
2016 }
2017
2018 that->opaqueChildren &= q_func()->rect();
2019 that->dirtyOpaqueChildren = false;
2020
2021 return that->opaqueChildren;
2022}
2023
2024void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2025{
2026 if (children.isEmpty() || clipRect.isEmpty())
2027 return;
2028
2029 const QRegion &r = getOpaqueChildren();
2030 if (!r.isEmpty())
2031 source -= (r & clipRect);
2032}
2033
2034//subtract any relatives that are higher up than me --- this is too expensive !!!
2035void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2036 bool alsoNonOpaque) const
2037{
2038 Q_Q(const QWidget);
2039 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue(varName: "QT_NO_SUBTRACTOPAQUESIBLINGS");
2040 if (disableSubtractOpaqueSiblings || q->isWindow())
2041 return;
2042
2043 QRect clipBoundingRect;
2044 bool dirtyClipBoundingRect = true;
2045
2046 QRegion parentClip;
2047 bool dirtyParentClip = true;
2048
2049 QPoint parentOffset = data.crect.topLeft();
2050
2051 const QWidget *w = q;
2052
2053 while (w) {
2054 if (w->isWindow())
2055 break;
2056 QWidgetPrivate *pd = w->parentWidget()->d_func();
2057 const int myIndex = pd->children.indexOf(t: const_cast<QWidget *>(w));
2058 const QRect widgetGeometry = w->d_func()->effectiveRectFor(rect: w->data->crect);
2059 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2060 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
2061 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2062 continue;
2063
2064 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
2065 if (!qRectIntersects(r1: siblingGeometry, r2: widgetGeometry))
2066 continue;
2067
2068 if (dirtyClipBoundingRect) {
2069 clipBoundingRect = sourceRegion.boundingRect();
2070 dirtyClipBoundingRect = false;
2071 }
2072
2073 if (!qRectIntersects(r1: siblingGeometry, r2: clipBoundingRect.translated(p: parentOffset)))
2074 continue;
2075
2076 if (dirtyParentClip) {
2077 parentClip = sourceRegion.translated(p: parentOffset);
2078 dirtyParentClip = false;
2079 }
2080
2081 const QPoint siblingPos(sibling->data->crect.topLeft());
2082 const QRect siblingClipRect(sibling->d_func()->clipRect());
2083 QRegion siblingDirty(parentClip);
2084 siblingDirty &= (siblingClipRect.translated(p: siblingPos));
2085 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2086 && !sibling->d_func()->graphicsEffect;
2087 if (hasMask)
2088 siblingDirty &= sibling->d_func()->extra->mask.translated(p: siblingPos);
2089 if (siblingDirty.isEmpty())
2090 continue;
2091
2092 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2093 if (hasMask) {
2094 siblingDirty.translate(p: -parentOffset);
2095 sourceRegion -= siblingDirty;
2096 } else {
2097 sourceRegion -= siblingGeometry.translated(p: -parentOffset);
2098 }
2099 } else {
2100 if (hasDirtySiblingsAbove)
2101 *hasDirtySiblingsAbove = true;
2102 if (sibling->d_func()->children.isEmpty())
2103 continue;
2104 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2105 opaqueSiblingChildren.translate(p: -parentOffset + siblingPos);
2106 sourceRegion -= opaqueSiblingChildren;
2107 }
2108 if (sourceRegion.isEmpty())
2109 return;
2110
2111 dirtyClipBoundingRect = true;
2112 dirtyParentClip = true;
2113 }
2114
2115 w = w->parentWidget();
2116 parentOffset += pd->data.crect.topLeft();
2117 dirtyParentClip = true;
2118 }
2119}
2120
2121void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2122{
2123 Q_Q(const QWidget);
2124
2125 const QWidget *w = q;
2126 QPoint offset;
2127
2128#if QT_CONFIG(graphicseffect)
2129 if (graphicsEffect) {
2130 w = q->parentWidget();
2131 offset -= data.crect.topLeft();
2132 }
2133#endif // QT_CONFIG(graphicseffect)
2134
2135 while (w) {
2136 const QWidgetPrivate *wd = w->d_func();
2137 if (wd->extra && wd->extra->hasMask)
2138 region &= (w != q) ? wd->extra->mask.translated(p: offset) : wd->extra->mask;
2139 if (w->isWindow())
2140 return;
2141 offset -= wd->data.crect.topLeft();
2142 w = w->parentWidget();
2143 }
2144}
2145
2146bool QWidgetPrivate::shouldPaintOnScreen() const
2147{
2148#if defined(QT_NO_BACKINGSTORE)
2149 return true;
2150#else
2151 Q_Q(const QWidget);
2152 if (q->testAttribute(attribute: Qt::WA_PaintOnScreen)
2153 || (!q->isWindow() && q->window()->testAttribute(attribute: Qt::WA_PaintOnScreen))) {
2154 return true;
2155 }
2156
2157 return false;
2158#endif
2159}
2160
2161void QWidgetPrivate::updateIsOpaque()
2162{
2163 // hw: todo: only needed if opacity actually changed
2164 setDirtyOpaqueRegion();
2165
2166#if QT_CONFIG(graphicseffect)
2167 if (graphicsEffect) {
2168 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2169 setOpaque(false);
2170 return;
2171 }
2172#endif // QT_CONFIG(graphicseffect)
2173
2174 Q_Q(QWidget);
2175 if (q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) || q->testAttribute(attribute: Qt::WA_PaintOnScreen)) {
2176 setOpaque(true);
2177 return;
2178 }
2179
2180 const QPalette &pal = q->palette();
2181
2182 if (q->autoFillBackground()) {
2183 const QBrush &autoFillBrush = pal.brush(cr: q->backgroundRole());
2184 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2185 setOpaque(true);
2186 return;
2187 }
2188 }
2189
2190 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
2191 const QBrush &windowBrush = q->palette().brush(cr: QPalette::Window);
2192 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2193 setOpaque(true);
2194 return;
2195 }
2196 }
2197 setOpaque(false);
2198}
2199
2200void QWidgetPrivate::setOpaque(bool opaque)
2201{
2202 if (isOpaque != opaque) {
2203 isOpaque = opaque;
2204 updateIsTranslucent();
2205 }
2206}
2207
2208void QWidgetPrivate::updateIsTranslucent()
2209{
2210 Q_Q(QWidget);
2211 if (QWindow *window = q->windowHandle()) {
2212 QSurfaceFormat format = window->format();
2213 const int oldAlpha = format.alphaBufferSize();
2214 const int newAlpha = q->testAttribute(attribute: Qt::WA_TranslucentBackground) ? 8 : -1;
2215 if (oldAlpha != newAlpha) {
2216 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2217 //
2218 // If that is not the case, then the setFormat() is not just futile
2219 // but downright dangerous. Futile because the format matters only
2220 // when creating the native window, no point in changing it
2221 // afterwards. Dangerous because a QOpenGLContext or something else
2222 // may eventually query the QWindow's format(), in order to ensure
2223 // compatibility (in terms of native concepts such as pixel format,
2224 // EGLConfig, etc.), and if we change it here, then the returned
2225 // format does not describe reality anymore. (reality being the
2226 // settings with which the native resource was created).
2227 //
2228 // Whereas if one does a destroy()-create() then this all here
2229 // won't matter because the format is updated in
2230 // QWidgetPrivate::create() again.
2231 //
2232 if (!window->handle()) {
2233 format.setAlphaBufferSize(newAlpha);
2234 window->setFormat(format);
2235 }
2236 }
2237 }
2238}
2239
2240static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2241{
2242 Q_ASSERT(painter);
2243
2244 if (brush.style() == Qt::TexturePattern) {
2245 const QRect rect(rgn.boundingRect());
2246 painter->setClipRegion(rgn);
2247 painter->drawTiledPixmap(rect, pm: brush.texture(), offset: rect.topLeft());
2248 } else if (brush.gradient()
2249 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2250 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2251 painter->save();
2252 painter->setClipRegion(rgn);
2253 painter->fillRect(x: 0, y: 0, w: painter->device()->width(), h: painter->device()->height(), b: brush);
2254 painter->restore();
2255 } else {
2256 for (const QRect &rect : rgn)
2257 painter->fillRect(rect, brush);
2258 }
2259}
2260
2261bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2262{
2263#if QT_CONFIG(scrollarea)
2264 Q_Q(const QWidget);
2265 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2266 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2267 return false;
2268 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(object: parent);
2269 if (scrollArea && scrollArea->viewport() == q) {
2270 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2271 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2272 painter->setBrushOrigin(-priv->contentsOffset());
2273 }
2274#endif // QT_CONFIG(scrollarea)
2275 return true;
2276}
2277
2278void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2279{
2280 Q_Q(const QWidget);
2281
2282 bool brushOriginSet = false;
2283 const QBrush autoFillBrush = q->palette().brush(cr: q->backgroundRole());
2284
2285 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2286 const QBrush bg = q->palette().brush(cr: QPalette::Window);
2287 if (!brushOriginSet)
2288 brushOriginSet = updateBrushOrigin(painter, brush: bg);
2289 if (!(flags & DontSetCompositionMode)) {
2290 //copy alpha straight in
2291 QPainter::CompositionMode oldMode = painter->compositionMode();
2292 painter->setCompositionMode(QPainter::CompositionMode_Source);
2293 fillRegion(painter, rgn, brush: bg);
2294 painter->setCompositionMode(oldMode);
2295 } else {
2296 fillRegion(painter, rgn, brush: bg);
2297 }
2298 }
2299
2300 if (q->autoFillBackground()) {
2301 if (!brushOriginSet)
2302 brushOriginSet = updateBrushOrigin(painter, brush: autoFillBrush);
2303 fillRegion(painter, rgn, brush: autoFillBrush);
2304 }
2305
2306 if (q->testAttribute(attribute: Qt::WA_StyledBackground)) {
2307 painter->setClipRegion(rgn);
2308 QStyleOption opt;
2309 opt.initFrom(w: q);
2310 q->style()->drawPrimitive(pe: QStyle::PE_Widget, opt: &opt, p: painter, w: q);
2311 }
2312}
2313
2314/*
2315 \internal
2316 This function is called when a widget is hidden or destroyed.
2317 It resets some application global pointers that should only refer active,
2318 visible widgets.
2319*/
2320
2321extern QWidget *qt_button_down;
2322
2323void QWidgetPrivate::deactivateWidgetCleanup()
2324{
2325 Q_Q(QWidget);
2326 // If this was the active application window, reset it
2327 if (QApplication::activeWindow() == q)
2328 QApplicationPrivate::setActiveWindow(nullptr);
2329 // If the is the active mouse press widget, reset it
2330 if (q == qt_button_down)
2331 qt_button_down = nullptr;
2332}
2333
2334
2335/*!
2336 Returns a pointer to the widget with window identifier/handle \a
2337 id.
2338
2339 The window identifier type depends on the underlying window
2340 system, see \c qwindowdefs.h for the actual definition. If there
2341 is no widget with this identifier, \nullptr is returned.
2342*/
2343
2344QWidget *QWidget::find(WId id)
2345{
2346 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(key: id, defaultValue: 0) : nullptr;
2347}
2348
2349
2350
2351/*!
2352 \fn WId QWidget::internalWinId() const
2353 \internal
2354 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2355
2356*/
2357
2358/*!
2359 \fn WId QWidget::winId() const
2360
2361 Returns the window system identifier of the widget.
2362
2363 Portable in principle, but if you use it you are probably about to
2364 do something non-portable. Be careful.
2365
2366 If a widget is non-native (alien) and winId() is invoked on it, that widget
2367 will be provided a native handle.
2368
2369 This value may change at run-time. An event with type QEvent::WinIdChange
2370 will be sent to the widget following a change in window system identifier.
2371
2372 \sa find()
2373*/
2374WId QWidget::winId() const
2375{
2376 if (!data->in_destructor
2377 && (!testAttribute(attribute: Qt::WA_WState_Created) || !internalWinId()))
2378 {
2379 QWidget *that = const_cast<QWidget*>(this);
2380 that->setAttribute(Qt::WA_NativeWindow);
2381 that->d_func()->createWinId();
2382 return that->data->winid;
2383 }
2384 return data->winid;
2385}
2386
2387void QWidgetPrivate::createWinId()
2388{
2389 Q_Q(QWidget);
2390
2391 const bool forceNativeWindow = q->testAttribute(attribute: Qt::WA_NativeWindow);
2392 if (!q->testAttribute(attribute: Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2393 if (!q->isWindow()) {
2394 QWidget *parent = q->parentWidget();
2395 QWidgetPrivate *pd = parent->d_func();
2396 if (forceNativeWindow && !q->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors))
2397 parent->setAttribute(Qt::WA_NativeWindow);
2398 if (!parent->internalWinId()) {
2399 pd->createWinId();
2400 }
2401
2402 for (int i = 0; i < pd->children.size(); ++i) {
2403 QWidget *w = qobject_cast<QWidget *>(o: pd->children.at(i));
2404 if (w && !w->isWindow() && (!w->testAttribute(attribute: Qt::WA_WState_Created)
2405 || (!w->internalWinId() && w->testAttribute(attribute: Qt::WA_NativeWindow)))) {
2406 w->create();
2407 }
2408 }
2409 } else {
2410 q->create();
2411 }
2412 }
2413}
2414
2415/*!
2416\internal
2417Ensures that the widget is set on the screen point is on. This is handy getting a correct
2418size hint before a resize in e.g QMenu and QToolTip.
2419Returns if the screen was changed.
2420*/
2421
2422bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2423{
2424 Q_Q(QWidget);
2425 if (!q->isWindow())
2426 return false;
2427 // Find the screen for pos and make the widget understand it is on that screen.
2428 return setScreen(QGuiApplication::screenAt(point: pos));
2429}
2430
2431/*!
2432\internal
2433Ensures that the widget's QWindow is set to be on the given \a screen.
2434Returns true if the screen was changed.
2435*/
2436
2437bool QWidgetPrivate::setScreen(QScreen *screen)
2438{
2439 Q_Q(QWidget);
2440 if (!screen || !q->isWindow())
2441 return false;
2442 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2443 if (currentScreen != screen) {
2444 topData()->initialScreen = screen;
2445 if (windowHandle())
2446 windowHandle()->setScreen(screen);
2447 return true;
2448 }
2449 return false;
2450}
2451
2452/*!
2453\internal
2454Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2455
2456*/
2457
2458void QWidget::createWinId()
2459{
2460 Q_D(QWidget);
2461 d->createWinId();
2462}
2463
2464/*!
2465 \since 4.4
2466
2467 Returns the effective window system identifier of the widget, i.e. the
2468 native parent's window system identifier.
2469
2470 If the widget is native, this function returns the native widget ID.
2471 Otherwise, the window ID of the first native parent widget, i.e., the
2472 top-level widget that contains this widget, is returned.
2473
2474 \note We recommend that you do not store this value as it is likely to
2475 change at run-time.
2476
2477 \sa nativeParentWidget()
2478*/
2479WId QWidget::effectiveWinId() const
2480{
2481 const WId id = internalWinId();
2482 if (id || !testAttribute(attribute: Qt::WA_WState_Created))
2483 return id;
2484 if (const QWidget *realParent = nativeParentWidget())
2485 return realParent->internalWinId();
2486 return 0;
2487}
2488
2489/*!
2490 If this is a native widget, return the associated QWindow.
2491 Otherwise return null.
2492
2493 Native widgets include toplevel widgets, QGLWidget, and child widgets
2494 on which winId() was called.
2495
2496 \since 5.0
2497
2498 \sa winId(), screen()
2499*/
2500QWindow *QWidget::windowHandle() const
2501{
2502 Q_D(const QWidget);
2503 return d->windowHandle();
2504}
2505
2506/*!
2507 Returns the screen the widget is on.
2508
2509 \since 5.14
2510
2511 \sa windowHandle()
2512*/
2513QScreen *QWidget::screen() const
2514{
2515 Q_D(const QWidget);
2516 if (auto associatedScreen = d->associatedScreen())
2517 return associatedScreen;
2518 if (auto topLevel = window()) {
2519 if (auto topData = qt_widget_private(widget: topLevel)->topData()) {
2520 if (topData->initialScreen)
2521 return topData->initialScreen;
2522 }
2523 if (auto screenByPos = QGuiApplication::screenAt(point: topLevel->geometry().center()))
2524 return screenByPos;
2525 }
2526 return QGuiApplication::primaryScreen();
2527}
2528
2529/*!
2530 Sets the screen on which the widget should be shown to \a screen.
2531
2532 Setting the screen only makes sense for windows. If necessary, the widget's
2533 window will get recreated on \a screen.
2534
2535 \note If the screen is part of a virtual desktop of multiple screens,
2536 the window will not move automatically to \a screen. To place the
2537 window relative to the screen, use the screen's topLeft() position.
2538
2539 \sa QWindow::setScreen()
2540*/
2541void QWidget::setScreen(QScreen *screen)
2542{
2543 Q_D(QWidget);
2544 d->setScreen(screen);
2545}
2546
2547#ifndef QT_NO_STYLE_STYLESHEET
2548
2549/*!
2550 \property QWidget::styleSheet
2551 \brief the widget's style sheet
2552 \since 4.2
2553
2554 The style sheet contains a textual description of customizations to the
2555 widget's style, as described in the \l{Qt Style Sheets} document.
2556
2557 Since Qt 4.5, Qt style sheets fully supports \macos.
2558
2559 \warning Qt style sheets are currently not supported for custom QStyle
2560 subclasses. We plan to address this in some future release.
2561
2562 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2563*/
2564QString QWidget::styleSheet() const
2565{
2566 Q_D(const QWidget);
2567 if (!d->extra)
2568 return QString();
2569 return d->extra->styleSheet;
2570}
2571
2572void QWidget::setStyleSheet(const QString& styleSheet)
2573{
2574 Q_D(QWidget);
2575 if (data->in_destructor)
2576 return;
2577 d->createExtra();
2578
2579 QStyleSheetStyle *proxy = qt_styleSheet(style: d->extra->style);
2580 d->extra->styleSheet = styleSheet;
2581 if (styleSheet.isEmpty()) { // stylesheet removed
2582 if (!proxy)
2583 return;
2584
2585 d->inheritStyle();
2586 return;
2587 }
2588
2589 if (proxy) { // style sheet update
2590 bool repolish = d->polished;
2591 if (!repolish) {
2592 const auto childWidgets = findChildren<QWidget*>();
2593 for (auto child : childWidgets) {
2594 repolish = child->d_func()->polished;
2595 if (repolish)
2596 break;
2597 }
2598 }
2599 if (repolish)
2600 proxy->repolish(widget: this);
2601 return;
2602 }
2603
2604 if (testAttribute(attribute: Qt::WA_SetStyle)) {
2605 d->setStyle_helper(newStyle: new QStyleSheetStyle(d->extra->style), propagate: true);
2606 } else {
2607 d->setStyle_helper(newStyle: new QStyleSheetStyle(nullptr), propagate: true);
2608 }
2609}
2610
2611#endif // QT_NO_STYLE_STYLESHEET
2612
2613/*!
2614 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2615*/
2616
2617QStyle *QWidget::style() const
2618{
2619 Q_D(const QWidget);
2620
2621 if (d->extra && d->extra->style)
2622 return d->extra->style;
2623 return QApplication::style();
2624}
2625
2626/*!
2627 Sets the widget's GUI style to \a style. The ownership of the style
2628 object is not transferred.
2629
2630 If no style is set, the widget uses the application's style,
2631 QApplication::style() instead.
2632
2633 Setting a widget's style has no effect on existing or future child
2634 widgets.
2635
2636 \warning This function is particularly useful for demonstration
2637 purposes, where you want to show Qt's styling capabilities. Real
2638 applications should avoid it and use one consistent GUI style
2639 instead.
2640
2641 \warning Qt style sheets are currently not supported for custom QStyle
2642 subclasses. We plan to address this in some future release.
2643
2644 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2645*/
2646
2647void QWidget::setStyle(QStyle *style)
2648{
2649 Q_D(QWidget);
2650 setAttribute(Qt::WA_SetStyle, on: style != nullptr);
2651 d->createExtra();
2652#ifndef QT_NO_STYLE_STYLESHEET
2653 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2654 //if for some reason someone try to set a QStyleSheetStyle, ref it
2655 //(this may happen for example in QButtonDialogBox which propagates its style)
2656 styleSheetStyle->ref();
2657 d->setStyle_helper(newStyle: style, propagate: false);
2658 } else if (qt_styleSheet(style: d->extra->style) || !qApp->styleSheet().isEmpty()) {
2659 // if we have an application stylesheet or have a proxy already, propagate
2660 d->setStyle_helper(newStyle: new QStyleSheetStyle(style), propagate: true);
2661 } else
2662#endif
2663 d->setStyle_helper(newStyle: style, propagate: false);
2664}
2665
2666void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2667{
2668 Q_Q(QWidget);
2669 QStyle *oldStyle = q->style();
2670
2671 createExtra();
2672
2673#ifndef QT_NO_STYLE_STYLESHEET
2674 QPointer<QStyle> origStyle = extra->style;
2675#endif
2676 extra->style = newStyle;
2677
2678 // repolish
2679 if (polished && q->windowType() != Qt::Desktop) {
2680 oldStyle->unpolish(widget: q);
2681 q->style()->polish(widget: q);
2682 }
2683
2684 if (propagate) {
2685 // We copy the list because the order may be modified
2686 const QObjectList childrenList = children;
2687 for (int i = 0; i < childrenList.size(); ++i) {
2688 QWidget *c = qobject_cast<QWidget*>(o: childrenList.at(i));
2689 if (c)
2690 c->d_func()->inheritStyle();
2691 }
2692 }
2693
2694#ifndef QT_NO_STYLE_STYLESHEET
2695 if (!qt_styleSheet(style: newStyle)) {
2696 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(style: origStyle)) {
2697 cssStyle->clearWidgetFont(w: q);
2698 }
2699 }
2700#endif
2701
2702 QEvent e(QEvent::StyleChange);
2703 QCoreApplication::sendEvent(receiver: q, event: &e);
2704
2705#ifndef QT_NO_STYLE_STYLESHEET
2706 // dereference the old stylesheet style
2707 if (QStyleSheetStyle *proxy = qt_styleSheet(style: origStyle))
2708 proxy->deref();
2709#endif
2710}
2711
2712// Inherits style from the current parent and propagates it as necessary
2713void QWidgetPrivate::inheritStyle()
2714{
2715#ifndef QT_NO_STYLE_STYLESHEET
2716 Q_Q(QWidget);
2717
2718 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2719
2720 QStyleSheetStyle *proxy = qt_styleSheet(style: extraStyle);
2721
2722 if (!q->styleSheet().isEmpty()) {
2723 Q_ASSERT(proxy);
2724 proxy->repolish(widget: q);
2725 return;
2726 }
2727
2728 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2729 QWidget *parent = q->parentWidget();
2730 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2731 // If we have stylesheet on app or parent has stylesheet style, we need
2732 // to be running a proxy
2733 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(style: parentStyle)) {
2734 QStyle *newStyle = parentStyle;
2735 if (q->testAttribute(attribute: Qt::WA_SetStyle) && qt_styleSheet(style: origStyle) == nullptr)
2736 newStyle = new QStyleSheetStyle(origStyle);
2737 else if (auto *styleSheetStyle = qt_styleSheet(style: origStyle))
2738 newStyle = styleSheetStyle;
2739 else if (QStyleSheetStyle *newProxy = qt_styleSheet(style: parentStyle))
2740 newProxy->ref();
2741
2742 setStyle_helper(newStyle, propagate: true);
2743 return;
2744 }
2745
2746 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2747 // we just need our original style back
2748 if (origStyle == extraStyle) // is it any different?
2749 return;
2750
2751 // We could have inherited the proxy from our parent (which has a custom style)
2752 // In such a case we need to start following the application style (i.e revert
2753 // the propagation behavior of QStyleSheetStyle)
2754 if (!q->testAttribute(attribute: Qt::WA_SetStyle))
2755 origStyle = nullptr;
2756
2757 setStyle_helper(newStyle: origStyle, propagate: true);
2758#endif // QT_NO_STYLE_STYLESHEET
2759}
2760
2761
2762/*!
2763 \fn bool QWidget::isWindow() const
2764
2765 Returns \c true if the widget is an independent window, otherwise
2766 returns \c false.
2767
2768 A window is a widget that isn't visually the child of any other
2769 widget and that usually has a frame and a
2770 \l{QWidget::setWindowTitle()}{window title}.
2771
2772 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2773 It will then be grouped with its parent and deleted when the
2774 parent is deleted, minimized when the parent is minimized etc. If
2775 supported by the window manager, it will also have a common
2776 taskbar entry with its parent.
2777
2778 QDialog and QMainWindow widgets are by default windows, even if a
2779 parent widget is specified in the constructor. This behavior is
2780 specified by the Qt::Window flag.
2781
2782 \sa window(), isModal(), parentWidget()
2783*/
2784
2785/*!
2786 \property QWidget::modal
2787 \brief whether the widget is a modal widget
2788
2789 This property only makes sense for windows. A modal widget
2790 prevents widgets in all other windows from getting any input.
2791
2792 By default, this property is \c false.
2793
2794 \sa isWindow(), windowModality, QDialog
2795*/
2796
2797/*!
2798 \property QWidget::windowModality
2799 \brief which windows are blocked by the modal widget
2800 \since 4.1
2801
2802 This property only makes sense for windows. A modal widget
2803 prevents widgets in other windows from getting input. The value of
2804 this property controls which windows are blocked when the widget
2805 is visible. Changing this property while the window is visible has
2806 no effect; you must hide() the widget first, then show() it again.
2807
2808 By default, this property is Qt::NonModal.
2809
2810 \sa isWindow(), QWidget::modal, QDialog
2811*/
2812
2813Qt::WindowModality QWidget::windowModality() const
2814{
2815 return static_cast<Qt::WindowModality>(data->window_modality);
2816}
2817
2818void QWidget::setWindowModality(Qt::WindowModality windowModality)
2819{
2820 data->window_modality = windowModality;
2821 // setModal_sys() will be called by setAttribute()
2822 setAttribute(Qt::WA_ShowModal, on: (data->window_modality != Qt::NonModal));
2823 setAttribute(Qt::WA_SetWindowModality, on: true);
2824}
2825
2826void QWidgetPrivate::setModal_sys()
2827{
2828 Q_Q(QWidget);
2829 if (q->windowHandle())
2830 q->windowHandle()->setModality(q->windowModality());
2831}
2832
2833/*!
2834 \fn bool QWidget::underMouse() const
2835
2836 Returns \c true if the widget is under the mouse cursor; otherwise
2837 returns \c false.
2838
2839 This value is not updated properly during drag and drop
2840 operations.
2841
2842 \sa enterEvent(), leaveEvent()
2843*/
2844
2845/*!
2846 \property QWidget::minimized
2847 \brief whether this widget is minimized (iconified)
2848
2849 This property is only relevant for windows.
2850
2851 By default, this property is \c false.
2852
2853 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2854*/
2855bool QWidget::isMinimized() const
2856{ return data->window_state & Qt::WindowMinimized; }
2857
2858/*!
2859 Shows the widget minimized, as an icon.
2860
2861 Calling this function only affects \l{isWindow()}{windows}.
2862
2863 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2864 isMinimized()
2865*/
2866void QWidget::showMinimized()
2867{
2868 bool isMin = isMinimized();
2869 if (isMin && isVisible())
2870 return;
2871
2872 ensurePolished();
2873
2874 if (!isMin)
2875 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2876 setVisible(true);
2877}
2878
2879/*!
2880 \property QWidget::maximized
2881 \brief whether this widget is maximized
2882
2883 This property is only relevant for windows.
2884
2885 \note Due to limitations on some window systems, this does not always
2886 report the expected results (e.g., if the user on X11 maximizes the
2887 window via the window manager, Qt has no way of distinguishing this
2888 from any other resize). This is expected to improve as window manager
2889 protocols evolve.
2890
2891 By default, this property is \c false.
2892
2893 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2894*/
2895bool QWidget::isMaximized() const
2896{ return data->window_state & Qt::WindowMaximized; }
2897
2898
2899
2900/*!
2901 Returns the current window state. The window state is a OR'ed
2902 combination of Qt::WindowState: Qt::WindowMinimized,
2903 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2904
2905 \sa Qt::WindowState, setWindowState()
2906 */
2907Qt::WindowStates QWidget::windowState() const
2908{
2909 return Qt::WindowStates(data->window_state);
2910}
2911
2912/*!\internal
2913
2914 The function sets the window state on child widgets similar to
2915 setWindowState(). The difference is that the window state changed
2916 event has the isOverride() flag set. It exists mainly to keep
2917 QWorkspace working.
2918 */
2919void QWidget::overrideWindowState(Qt::WindowStates newstate)
2920{
2921 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2922 data->window_state = newstate;
2923 QCoreApplication::sendEvent(receiver: this, event: &e);
2924}
2925
2926/*!
2927 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2928
2929 Sets the window state to \a windowState. The window state is a OR'ed
2930 combination of Qt::WindowState: Qt::WindowMinimized,
2931 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2932
2933 If the window is not visible (i.e. isVisible() returns \c false), the
2934 window state will take effect when show() is called. For visible
2935 windows, the change is immediate. For example, to toggle between
2936 full-screen and normal mode, use the following code:
2937
2938 \snippet code/src_gui_kernel_qwidget.cpp 0
2939
2940 To restore and activate a minimized window (while
2941 preserving its maximized and/or full-screen state), use the following:
2942
2943 \snippet code/src_gui_kernel_qwidget.cpp 1
2944
2945 Calling this function will hide the widget. You must call show() to make
2946 the widget visible again.
2947
2948 \note On some window systems Qt::WindowActive is not immediate, and may be
2949 ignored in certain cases.
2950
2951 When the window state changes, the widget receives a changeEvent()
2952 of type QEvent::WindowStateChange.
2953
2954 \sa Qt::WindowState, windowState()
2955*/
2956void QWidget::setWindowState(Qt::WindowStates newstate)
2957{
2958 Q_D(QWidget);
2959 Qt::WindowStates oldstate = windowState();
2960 if (newstate.testFlag(flag: Qt::WindowMinimized)) // QTBUG-46763
2961 newstate.setFlag(flag: Qt::WindowActive, on: false);
2962 if (oldstate == newstate)
2963 return;
2964 if (isWindow() && !testAttribute(attribute: Qt::WA_WState_Created))
2965 create();
2966
2967 data->window_state = newstate;
2968 data->in_set_window_state = 1;
2969 if (isWindow()) {
2970 // Ensure the initial size is valid, since we store it as normalGeometry below.
2971 if (!testAttribute(attribute: Qt::WA_Resized) && !isVisible())
2972 adjustSize();
2973
2974 d->createTLExtra();
2975 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2976 d->topData()->normalGeometry = geometry();
2977
2978 Q_ASSERT(windowHandle());
2979 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2980 }
2981 data->in_set_window_state = 0;
2982
2983 if (newstate & Qt::WindowActive)
2984 activateWindow();
2985
2986 QWindowStateChangeEvent e(oldstate);
2987 QCoreApplication::sendEvent(receiver: this, event: &e);
2988}
2989
2990/*!
2991 \property QWidget::fullScreen
2992 \brief whether the widget is shown in full screen mode
2993
2994 A widget in full screen mode occupies the whole screen area and does not
2995 display window decorations, such as a title bar.
2996
2997 By default, this property is \c false.
2998
2999 \sa windowState(), minimized, maximized
3000*/
3001bool QWidget::isFullScreen() const
3002{ return data->window_state & Qt::WindowFullScreen; }
3003
3004/*!
3005 Shows the widget in full-screen mode.
3006
3007 Calling this function only affects \l{isWindow()}{windows}.
3008
3009 To return from full-screen mode, call showNormal() or close().
3010
3011 \note Full-screen mode works fine under Windows, but has certain
3012 problems under X. These problems are due to limitations of the
3013 ICCCM protocol that specifies the communication between X11
3014 clients and the window manager. ICCCM simply does not understand
3015 the concept of non-decorated full-screen windows. Therefore, the
3016 best you can do is to request a borderless window and place and
3017 resize it to fill the entire screen. Depending on the window
3018 manager, this may or may not work. The borderless window is
3019 requested using MOTIF hints, which are at least partially
3020 supported by virtually all modern window managers.
3021
3022 An alternative would be to bypass the window manager entirely and
3023 create a window with the Qt::X11BypassWindowManagerHint flag. This
3024 has other severe problems though, like broken keyboard focus
3025 and very strange effects on desktop changes or when the user raises
3026 other windows.
3027
3028 X11 window managers that follow modern post-ICCCM specifications
3029 support full-screen mode properly.
3030
3031 On macOS, showing a window full screen puts the entire application in
3032 full-screen mode, providing it with a dedicated desktop. Showing another
3033 window while the application runs in full-screen mode might automatically
3034 make that window full screen as well. To prevent that, exit full-screen
3035 mode by calling showNormal() or by close() on the full screen window
3036 before showing another window.
3037
3038 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3039*/
3040void QWidget::showFullScreen()
3041{
3042 ensurePolished();
3043
3044 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3045 | Qt::WindowFullScreen);
3046 setVisible(true);
3047#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3048 // activating it here before libscreen activates it causes problems
3049 activateWindow();
3050#endif
3051}
3052
3053/*!
3054 Shows the widget maximized.
3055
3056 Calling this function only affects \l{isWindow()}{windows}.
3057
3058 On X11, this function may not work properly with certain window
3059 managers. See the \l{Window Geometry} documentation for an explanation.
3060
3061 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3062*/
3063void QWidget::showMaximized()
3064{
3065 ensurePolished();
3066
3067 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3068 | Qt::WindowMaximized);
3069 setVisible(true);
3070}
3071
3072/*!
3073 Restores the widget after it has been maximized or minimized.
3074
3075 Calling this function only affects \l{isWindow()}{windows}.
3076
3077 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3078*/
3079void QWidget::showNormal()
3080{
3081 ensurePolished();
3082
3083 setWindowState(windowState() & ~(Qt::WindowMinimized
3084 | Qt::WindowMaximized
3085 | Qt::WindowFullScreen));
3086 setVisible(true);
3087}
3088
3089/*!
3090 Returns \c true if this widget would become enabled if \a ancestor is
3091 enabled; otherwise returns \c false.
3092
3093
3094
3095 This is the case if neither the widget itself nor every parent up
3096 to but excluding \a ancestor has been explicitly disabled.
3097
3098 isEnabledTo(0) returns false if this widget or any if its ancestors
3099 was explicitly disabled.
3100
3101 The word ancestor here means a parent widget within the same window.
3102
3103 Therefore isEnabledTo(0) stops at this widget's window, unlike
3104 isEnabled() which also takes parent windows into considerations.
3105
3106 \sa setEnabled(), enabled
3107*/
3108
3109bool QWidget::isEnabledTo(const QWidget *ancestor) const
3110{
3111 const QWidget * w = this;
3112 while (!w->testAttribute(attribute: Qt::WA_ForceDisabled)
3113 && !w->isWindow()
3114 && w->parentWidget()
3115 && w->parentWidget() != ancestor)
3116 w = w->parentWidget();
3117 return !w->testAttribute(attribute: Qt::WA_ForceDisabled);
3118}
3119
3120#ifndef QT_NO_ACTION
3121/*!
3122 Appends the action \a action to this widget's list of actions.
3123
3124 All QWidgets have a list of \l{QAction}s. However, they can be
3125 represented graphically in many different ways. The default use of
3126 the QAction list (as returned by actions()) is to create a context
3127 QMenu.
3128
3129 A QWidget should only have one of each action and adding an action
3130 it already has will not cause the same action to be in the widget twice.
3131
3132 The ownership of \a action is not transferred to this QWidget.
3133
3134 \sa removeAction(), insertAction(), actions(), QMenu
3135*/
3136void QWidget::addAction(QAction *action)
3137{
3138 insertAction(before: nullptr, action);
3139}
3140
3141/*!
3142 Appends the actions \a actions to this widget's list of actions.
3143
3144 \sa removeAction(), QMenu, addAction()
3145*/
3146void QWidget::addActions(const QList<QAction *> &actions)
3147{
3148 for(int i = 0; i < actions.size(); i++)
3149 insertAction(before: nullptr, action: actions.at(i));
3150}
3151
3152/*!
3153 Inserts the action \a action to this widget's list of actions,
3154 before the action \a before. It appends the action if \a before is \nullptr or
3155 \a before is not a valid action for this widget.
3156
3157 A QWidget should only have one of each action.
3158
3159 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3160*/
3161void QWidget::insertAction(QAction *before, QAction *action)
3162{
3163 if (Q_UNLIKELY(!action)) {
3164 qWarning(msg: "QWidget::insertAction: Attempt to insert null action");
3165 return;
3166 }
3167
3168 Q_D(QWidget);
3169 if (d->actions.contains(t: action))
3170 removeAction(action);
3171
3172 int pos = d->actions.indexOf(t: before);
3173 if (pos < 0) {
3174 before = nullptr;
3175 pos = d->actions.size();
3176 }
3177 d->actions.insert(i: pos, t: action);
3178
3179 QActionPrivate *apriv = action->d_func();
3180 apriv->associatedObjects.append(t: this);
3181
3182 QActionEvent e(QEvent::ActionAdded, action, before);
3183 QCoreApplication::sendEvent(receiver: this, event: &e);
3184}
3185
3186/*!
3187 Inserts the actions \a actions to this widget's list of actions,
3188 before the action \a before. It appends the action if \a before is \nullptr or
3189 \a before is not a valid action for this widget.
3190
3191 A QWidget can have at most one of each action.
3192
3193 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3194*/
3195void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3196{
3197 for(int i = 0; i < actions.size(); ++i)
3198 insertAction(before, action: actions.at(i));
3199}
3200
3201/*!
3202 Removes the action \a action from this widget's list of actions.
3203 \sa insertAction(), actions(), insertAction()
3204*/
3205void QWidget::removeAction(QAction *action)
3206{
3207 if (!action)
3208 return;
3209
3210 Q_D(QWidget);
3211
3212 QActionPrivate *apriv = action->d_func();
3213 apriv->associatedObjects.removeAll(t: this);
3214
3215 if (d->actions.removeAll(t: action)) {
3216 QActionEvent e(QEvent::ActionRemoved, action);
3217 QCoreApplication::sendEvent(receiver: this, event: &e);
3218 }
3219}
3220
3221/*!
3222 Returns the (possibly empty) list of this widget's actions.
3223
3224 \sa contextMenuPolicy, insertAction(), removeAction()
3225*/
3226QList<QAction*> QWidget::actions() const
3227{
3228 Q_D(const QWidget);
3229 return d->actions;
3230}
3231
3232/*!
3233 \fn QAction *QWidget::addAction(const QString &text);
3234 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3235 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3236 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3237
3238 \since 6.3
3239
3240 These convenience functions create a new action with text \a text,
3241 icon \a icon and shortcut \a shortcut, if any.
3242
3243 The functions add the newly created action to the widget's
3244 list of actions, and return it.
3245
3246 QWidget takes ownership of the returned QAction.
3247*/
3248QAction *QWidget::addAction(const QString &text)
3249{
3250 QAction *ret = new QAction(text, this);
3251 addAction(action: ret);
3252 return ret;
3253}
3254
3255QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3256{
3257 QAction *ret = new QAction(icon, text, this);
3258 addAction(action: ret);
3259 return ret;
3260}
3261
3262#if QT_CONFIG(shortcut)
3263QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3264{
3265 QAction *ret = addAction(text);
3266 ret->setShortcut(shortcut);
3267 return ret;
3268}
3269
3270QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3271{
3272 QAction *ret = addAction(icon, text);
3273 ret->setShortcut(shortcut);
3274 return ret;
3275}
3276#endif
3277
3278/*!
3279 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3280 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3281 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3282 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3283
3284 \overload
3285 \since 6.3
3286
3287 This convenience function creates a new action with the text \a
3288 text, icon \a icon, and shortcut \a shortcut, if any.
3289
3290 The action's \l{QAction::triggered()}{triggered()} signal is connected
3291 to the \a receiver's \a member slot. The function adds the newly created
3292 action to the widget's list of actions and returns it.
3293
3294 QWidget takes ownership of the returned QAction.
3295*/
3296QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3297 Qt::ConnectionType type)
3298{
3299 QAction *action = addAction(text);
3300 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3301 return action;
3302}
3303
3304QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3305 const QObject *receiver, const char* member,
3306 Qt::ConnectionType type)
3307{
3308 QAction *action = addAction(icon, text);
3309 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3310 return action;
3311}
3312
3313#if QT_CONFIG(shortcut)
3314QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3315 const QObject *receiver, const char* member,
3316 Qt::ConnectionType type)
3317{
3318 QAction *action = addAction(text, receiver, member, type);
3319 action->setShortcut(shortcut);
3320 return action;
3321}
3322
3323QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3324 const QObject *receiver, const char* member,
3325 Qt::ConnectionType type)
3326{
3327 QAction *action = addAction(icon, text, receiver, member, type);
3328 action->setShortcut(shortcut);
3329 return action;
3330}
3331#endif // QT_CONFIG(shortcut)
3332
3333/*!
3334 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3335 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3336 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3337 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3338
3339 \since 6.3
3340 \overload
3341
3342 These convenience functions create a new action with the text \a text,
3343 icon \a icon, and shortcut \a shortcut, if any.
3344
3345 The action's \l{QAction::triggered()}{triggered()} signal is connected
3346 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3347 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3348
3349 The function adds the newly created action to the widget's list of
3350 actions and returns it.
3351
3352 QWidget takes ownership of the returned QAction.
3353*/
3354#endif // QT_NO_ACTION
3355
3356/*!
3357 \property QWidget::enabled
3358 \brief whether the widget is enabled
3359
3360 In general an enabled widget handles keyboard and mouse events; a disabled
3361 widget does not. An exception is made with \l{QAbstractButton}.
3362
3363 Some widgets display themselves differently when they are
3364 disabled. For example a button might draw its label grayed out. If
3365 your widget needs to know when it becomes enabled or disabled, you
3366 can use the changeEvent() with type QEvent::EnabledChange.
3367
3368 Disabling a widget implicitly disables all its children. Enabling
3369 respectively enables all child widgets unless they have been
3370 explicitly disabled. It it not possible to explicitly enable a child
3371 widget which is not a window while its parent widget remains disabled.
3372
3373 By default, this property is \c true.
3374
3375 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3376*/
3377void QWidget::setEnabled(bool enable)
3378{
3379 Q_D(QWidget);
3380 setAttribute(Qt::WA_ForceDisabled, on: !enable);
3381 d->setEnabled_helper(enable);
3382}
3383
3384void QWidgetPrivate::setEnabled_helper(bool enable)
3385{
3386 Q_Q(QWidget);
3387
3388 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3389 return; // nothing we can do
3390
3391 if (enable != q->testAttribute(attribute: Qt::WA_Disabled))
3392 return; // nothing to do
3393
3394 q->setAttribute(Qt::WA_Disabled, on: !enable);
3395 updateSystemBackground();
3396
3397 if (!enable && q->window()->focusWidget() == q) {
3398 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3399 if (!parentIsEnabled || !q->focusNextChild())
3400 q->clearFocus();
3401 }
3402
3403 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3404 for (int i = 0; i < children.size(); ++i) {
3405 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
3406 if (w && !w->testAttribute(attribute))
3407 w->d_func()->setEnabled_helper(enable);
3408 }
3409#ifndef QT_NO_CURSOR
3410 if (q->testAttribute(attribute: Qt::WA_SetCursor) || q->isWindow()) {
3411 // enforce the windows behavior of clearing the cursor on
3412 // disabled widgets
3413 qt_qpa_set_cursor(w: q, force: false);
3414 }
3415#endif
3416#ifndef QT_NO_IM
3417 if (q->testAttribute(attribute: Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3418 QWidget *focusWidget = effectiveFocusWidget();
3419
3420 if (enable) {
3421 if (focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled))
3422 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3423 } else {
3424 QGuiApplication::inputMethod()->commit();
3425 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3426 }
3427 }
3428#endif //QT_NO_IM
3429 QEvent e(QEvent::EnabledChange);
3430 QCoreApplication::sendEvent(receiver: q, event: &e);
3431}
3432
3433/*!
3434 \property QWidget::acceptDrops
3435 \brief whether drop events are enabled for this widget
3436
3437 Setting this property to true announces to the system that this
3438 widget \e may be able to accept drop events.
3439
3440 If the widget is the desktop (windowType() == Qt::Desktop), this may
3441 fail if another application is using the desktop; you can call
3442 acceptDrops() to test if this occurs.
3443
3444 \warning Do not modify this property in a drag and drop event handler.
3445
3446 By default, this property is \c false.
3447
3448 \sa {Drag and Drop in Qt}{Drag and Drop}
3449*/
3450bool QWidget::acceptDrops() const
3451{
3452 return testAttribute(attribute: Qt::WA_AcceptDrops);
3453}
3454
3455void QWidget::setAcceptDrops(bool on)
3456{
3457 setAttribute(Qt::WA_AcceptDrops, on);
3458
3459}
3460
3461/*!
3462 Disables widget input events if \a disable is true; otherwise
3463 enables input events.
3464
3465 See the \l enabled documentation for more information.
3466
3467 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3468*/
3469void QWidget::setDisabled(bool disable)
3470{
3471 setEnabled(!disable);
3472}
3473
3474/*!
3475 \property QWidget::frameGeometry
3476 \brief geometry of the widget relative to its parent including any
3477 window frame
3478
3479 See the \l{Window Geometry} documentation for an overview of geometry
3480 issues with windows.
3481
3482 By default, this property contains a value that depends on the user's
3483 platform and screen geometry.
3484
3485 \sa geometry(), x(), y(), pos()
3486*/
3487QRect QWidget::frameGeometry() const
3488{
3489 Q_D(const QWidget);
3490 if (isWindow() && ! (windowType() == Qt::Popup)) {
3491 QRect fs = d->frameStrut();
3492 return QRect(data->crect.x() - fs.left(),
3493 data->crect.y() - fs.top(),
3494 data->crect.width() + fs.left() + fs.right(),
3495 data->crect.height() + fs.top() + fs.bottom());
3496 }
3497 return data->crect;
3498}
3499
3500/*!
3501 \property QWidget::x
3502
3503 \brief the x coordinate of the widget relative to its parent including
3504 any window frame
3505
3506 See the \l{Window Geometry} documentation for an overview of geometry
3507 issues with windows.
3508
3509 By default, this property has a value of 0.
3510
3511 \sa frameGeometry, y, pos
3512*/
3513int QWidget::x() const
3514{
3515 Q_D(const QWidget);
3516 if (isWindow() && ! (windowType() == Qt::Popup))
3517 return data->crect.x() - d->frameStrut().left();
3518 return data->crect.x();
3519}
3520
3521/*!
3522 \property QWidget::y
3523 \brief the y coordinate of the widget relative to its parent and
3524 including any window frame
3525
3526 See the \l{Window Geometry} documentation for an overview of geometry
3527 issues with windows.
3528
3529 By default, this property has a value of 0.
3530
3531 \sa frameGeometry, x, pos
3532*/
3533int QWidget::y() const
3534{
3535 Q_D(const QWidget);
3536 if (isWindow() && ! (windowType() == Qt::Popup))
3537 return data->crect.y() - d->frameStrut().top();
3538 return data->crect.y();
3539}
3540
3541/*!
3542 \property QWidget::pos
3543 \brief the position of the widget within its parent widget
3544
3545 If the widget is a window, the position is that of the widget on
3546 the desktop, including its frame.
3547
3548 When changing the position, the widget, if visible, receives a
3549 move event (moveEvent()) immediately. If the widget is not
3550 currently visible, it is guaranteed to receive an event before it
3551 is shown.
3552
3553 By default, this property contains a position that refers to the
3554 origin.
3555
3556 \warning Calling move() or setGeometry() inside moveEvent() can
3557 lead to infinite recursion.
3558
3559 See the \l{Window Geometry} documentation for an overview of geometry
3560 issues with windows.
3561
3562 \note Not all windowing systems support setting or querying top level window positions.
3563 On such a system, programmatically moving windows may not have any effect, and artificial
3564 values may be returned for the current positions, such as \c QPoint(0, 0).
3565
3566 \sa frameGeometry, size, x(), y()
3567*/
3568QPoint QWidget::pos() const
3569{
3570 Q_D(const QWidget);
3571 QPoint result = data->crect.topLeft();
3572 if (isWindow() && ! (windowType() == Qt::Popup))
3573 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3574 result -= d->frameStrut().topLeft();
3575 return result;
3576}
3577
3578/*!
3579 \property QWidget::geometry
3580 \brief the geometry of the widget relative to its parent and
3581 excluding the window frame
3582
3583 When changing the geometry, the widget, if visible, receives a
3584 move event (moveEvent()) and/or a resize event (resizeEvent())
3585 immediately. If the widget is not currently visible, it is
3586 guaranteed to receive appropriate events before it is shown.
3587
3588 The size component is adjusted if it lies outside the range
3589 defined by minimumSize() and maximumSize().
3590
3591 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3592 can lead to infinite recursion.
3593
3594 See the \l{Window Geometry} documentation for an overview of geometry
3595 issues with windows.
3596
3597 By default, this property contains a value that depends on the user's
3598 platform and screen geometry.
3599
3600 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3601 resizeEvent(), minimumSize(), maximumSize()
3602*/
3603
3604/*!
3605 \property QWidget::size
3606 \brief the size of the widget excluding any window frame
3607
3608 If the widget is visible when it is being resized, it receives a resize event
3609 (resizeEvent()) immediately. If the widget is not currently
3610 visible, it is guaranteed to receive an event before it is shown.
3611
3612 The size is adjusted if it lies outside the range defined by
3613 minimumSize() and maximumSize().
3614
3615 By default, this property contains a value that depends on the user's
3616 platform and screen geometry.
3617
3618 \warning Calling resize() or setGeometry() inside resizeEvent() can
3619 lead to infinite recursion.
3620
3621 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3622 appear on screen. This also applies to windows.
3623
3624 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3625*/
3626
3627/*!
3628 \property QWidget::width
3629 \brief the width of the widget excluding any window frame
3630
3631 See the \l{Window Geometry} documentation for an overview of geometry
3632 issues with windows.
3633
3634 \note Do not use this function to find the width of a screen on
3635 a multi-screen desktop. See QScreen for details.
3636
3637 By default, this property contains a value that depends on the user's
3638 platform and screen geometry.
3639
3640 \sa geometry, height, size
3641*/
3642
3643/*!
3644 \property QWidget::height
3645 \brief the height of the widget excluding any window frame
3646
3647 See the \l{Window Geometry} documentation for an overview of geometry
3648 issues with windows.
3649
3650 By default, this property contains a value that depends on the user's
3651 platform and \l{QScreen::geometry}{screen geometry}.
3652
3653 \sa geometry, width, size
3654*/
3655
3656/*!
3657 \property QWidget::rect
3658 \brief the internal geometry of the widget excluding any window
3659 frame
3660
3661 The rect property equals QRect(0, 0, width(), height()).
3662
3663 See the \l{Window Geometry} documentation for an overview of geometry
3664 issues with windows.
3665
3666 By default, this property contains a value that depends on the user's
3667 platform and screen geometry.
3668
3669 \sa size
3670*/
3671
3672/*!
3673 \property QWidget::normalGeometry
3674
3675 \brief the geometry of the widget as it will appear when shown as
3676 a normal (not maximized or full screen) top-level widget
3677
3678 If the widget is already in this state the normal geometry will
3679 reflect the widget's current geometry().
3680
3681 For child widgets this property always holds an empty rectangle.
3682
3683 By default, this property contains an empty rectangle.
3684
3685 \sa QWidget::windowState(), QWidget::geometry
3686*/
3687QRect QWidget::normalGeometry() const
3688{
3689 Q_D(const QWidget);
3690 if (!isWindow())
3691 return QRect();
3692
3693 if (!isMaximized() && !isFullScreen())
3694 return geometry();
3695
3696 return d->topData()->normalGeometry;
3697}
3698
3699
3700/*!
3701 \property QWidget::childrenRect
3702 \brief the bounding rectangle of the widget's children
3703
3704 Hidden children are excluded.
3705
3706 By default, for a widget with no children, this property contains a
3707 rectangle with zero width and height located at the origin.
3708
3709 \sa childrenRegion(), geometry()
3710*/
3711
3712QRect QWidget::childrenRect() const
3713{
3714 Q_D(const QWidget);
3715 QRect r(0, 0, 0, 0);
3716 for (int i = 0; i < d->children.size(); ++i) {
3717 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3718 if (w && !w->isWindow() && !w->isHidden())
3719 r |= w->geometry();
3720 }
3721 return r;
3722}
3723
3724/*!
3725 \property QWidget::childrenRegion
3726 \brief the combined region occupied by the widget's children
3727
3728 Hidden children are excluded.
3729
3730 By default, for a widget with no children, this property contains an
3731 empty region.
3732
3733 \sa childrenRect(), geometry(), mask()
3734*/
3735
3736QRegion QWidget::childrenRegion() const
3737{
3738 Q_D(const QWidget);
3739 QRegion r;
3740 for (int i = 0; i < d->children.size(); ++i) {
3741 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3742 if (w && !w->isWindow() && !w->isHidden()) {
3743 QRegion mask = w->mask();
3744 if (mask.isEmpty())
3745 r |= w->geometry();
3746 else
3747 r |= mask.translated(p: w->pos());
3748 }
3749 }
3750 return r;
3751}
3752
3753
3754/*!
3755 \property QWidget::minimumSize
3756 \brief the widget's minimum size
3757
3758 The widget cannot be resized to a smaller size than the minimum
3759 widget size. The widget's size is forced to the minimum size if
3760 the current size is smaller.
3761
3762 The minimum size set by this function will override the minimum size
3763 defined by QLayout. To unset the minimum size, use a
3764 value of \c{QSize(0, 0)}.
3765
3766 By default, this property contains a size with zero width and height.
3767
3768 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3769*/
3770
3771QSize QWidget::minimumSize() const
3772{
3773 Q_D(const QWidget);
3774 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3775}
3776
3777/*!
3778 \property QWidget::maximumSize
3779 \brief the widget's maximum size in pixels
3780
3781 The widget cannot be resized to a larger size than the maximum
3782 widget size.
3783
3784 By default, this property contains a size in which both width and height
3785 have values of 16777215.
3786
3787 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3788 of widgets.
3789
3790 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3791*/
3792
3793QSize QWidget::maximumSize() const
3794{
3795 Q_D(const QWidget);
3796 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3797 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3798}
3799
3800
3801/*!
3802 \property QWidget::minimumWidth
3803 \brief the widget's minimum width in pixels
3804
3805 This property corresponds to the width held by the \l minimumSize property.
3806
3807 By default, this property has a value of 0.
3808
3809 \sa minimumSize, minimumHeight
3810*/
3811
3812/*!
3813 \property QWidget::minimumHeight
3814 \brief the widget's minimum height in pixels
3815
3816 This property corresponds to the height held by the \l minimumSize property.
3817
3818 By default, this property has a value of 0.
3819
3820 \sa minimumSize, minimumWidth
3821*/
3822
3823/*!
3824 \property QWidget::maximumWidth
3825 \brief the widget's maximum width in pixels
3826
3827 This property corresponds to the width held by the \l maximumSize property.
3828
3829 By default, this property contains a value of 16777215.
3830
3831 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3832 of widgets.
3833
3834 \sa maximumSize, maximumHeight
3835*/
3836
3837/*!
3838 \property QWidget::maximumHeight
3839 \brief the widget's maximum height in pixels
3840
3841 This property corresponds to the height held by the \l maximumSize property.
3842
3843 By default, this property contains a value of 16777215.
3844
3845 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3846 of widgets.
3847
3848 \sa maximumSize, maximumWidth
3849*/
3850
3851/*!
3852 \property QWidget::sizeIncrement
3853 \brief the size increment of the widget
3854
3855 When the user resizes the window, the size will move in steps of
3856 sizeIncrement().width() pixels horizontally and
3857 sizeIncrement.height() pixels vertically, with baseSize() as the
3858 basis. Preferred widget sizes are for non-negative integers \e i
3859 and \e j:
3860 \snippet code/src_gui_kernel_qwidget.cpp 2
3861
3862 Note that while you can set the size increment for all widgets, it
3863 only affects windows.
3864
3865 By default, this property contains a size with zero width and height.
3866
3867 \warning The size increment has no effect under Windows, and may
3868 be disregarded by the window manager on X11.
3869
3870 \sa size, minimumSize, maximumSize
3871*/
3872QSize QWidget::sizeIncrement() const
3873{
3874 Q_D(const QWidget);
3875 return (d->extra && d->extra->topextra)
3876 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3877 : QSize(0, 0);
3878}
3879
3880/*!
3881 \property QWidget::baseSize
3882 \brief the base size of the widget
3883
3884 The base size is used to calculate a proper widget size if the
3885 widget defines sizeIncrement().
3886
3887 By default, for a newly-created widget, this property contains a size with
3888 zero width and height.
3889
3890 \sa setSizeIncrement()
3891*/
3892
3893QSize QWidget::baseSize() const
3894{
3895 Q_D(const QWidget);
3896 return (d->extra && d->extra->topextra)
3897 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3898 : QSize(0, 0);
3899}
3900
3901bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3902{
3903 Q_Q(QWidget);
3904
3905 int mw = minw, mh = minh;
3906 if (mw == QWIDGETSIZE_MAX)
3907 mw = 0;
3908 if (mh == QWIDGETSIZE_MAX)
3909 mh = 0;
3910 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3911 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) "
3912 "The largest allowed size is (%d,%d)",
3913 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3914 QWIDGETSIZE_MAX);
3915 minw = mw = qMin<int>(a: minw, QWIDGETSIZE_MAX);
3916 minh = mh = qMin<int>(a: minh, QWIDGETSIZE_MAX);
3917 }
3918 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3919 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3920 "are not possible",
3921 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3922 minw = mw = qMax(a: minw, b: 0);
3923 minh = mh = qMax(a: minh, b: 0);
3924 }
3925 createExtra();
3926 if (extra->minw == mw && extra->minh == mh)
3927 return false;
3928 extra->minw = mw;
3929 extra->minh = mh;
3930 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3931 return true;
3932}
3933
3934void QWidgetPrivate::setConstraints_sys()
3935{
3936 Q_Q(QWidget);
3937 if (extra && q->windowHandle()) {
3938 QWindow *win = q->windowHandle();
3939 QWindowPrivate *winp = qt_window_private(window: win);
3940
3941 winp->minimumSize = QSize(extra->minw, extra->minh);
3942 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3943
3944 if (extra->topextra) {
3945 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3946 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3947 }
3948
3949 if (winp->platformWindow) {
3950 fixPosIncludesFrame();
3951 winp->platformWindow->propagateSizeHints();
3952 }
3953 }
3954}
3955
3956/*!
3957 \overload
3958
3959 This function corresponds to setMinimumSize(QSize(minw, minh)).
3960 Sets the minimum width to \a minw and the minimum height to \a
3961 minh.
3962*/
3963
3964void QWidget::setMinimumSize(int minw, int minh)
3965{
3966 Q_D(QWidget);
3967 if (!d->setMinimumSize_helper(minw, minh))
3968 return;
3969
3970 if (isWindow())
3971 d->setConstraints_sys();
3972 if (minw > width() || minh > height()) {
3973 bool resized = testAttribute(attribute: Qt::WA_Resized);
3974 bool maximized = isMaximized();
3975 resize(w: qMax(a: minw,b: width()), h: qMax(a: minh,b: height()));
3976 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
3977 if (maximized)
3978 data->window_state = data->window_state | Qt::WindowMaximized;
3979 }
3980#if QT_CONFIG(graphicsview)
3981 if (d->extra) {
3982 if (d->extra->proxyWidget)
3983 d->extra->proxyWidget->setMinimumSize(aw: minw, ah: minh);
3984 }
3985#endif
3986 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3987}
3988
3989bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3990{
3991 Q_Q(QWidget);
3992 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3993 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) "
3994 "The largest allowed size is (%d,%d)",
3995 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3996 QWIDGETSIZE_MAX);
3997 maxw = qMin<int>(a: maxw, QWIDGETSIZE_MAX);
3998 maxh = qMin<int>(a: maxh, QWIDGETSIZE_MAX);
3999 }
4000 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4001 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4002 "are not possible",
4003 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4004 maxw = qMax(a: maxw, b: 0);
4005 maxh = qMax(a: maxh, b: 0);
4006 }
4007 createExtra();
4008 if (extra->maxw == maxw && extra->maxh == maxh)
4009 return false;
4010 extra->maxw = maxw;
4011 extra->maxh = maxh;
4012 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4013 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4014 return true;
4015}
4016
4017/*!
4018 \overload
4019
4020 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4021 maxh)). Sets the maximum width to \a maxw and the maximum height
4022 to \a maxh.
4023*/
4024void QWidget::setMaximumSize(int maxw, int maxh)
4025{
4026 Q_D(QWidget);
4027 if (!d->setMaximumSize_helper(maxw, maxh))
4028 return;
4029
4030 if (isWindow())
4031 d->setConstraints_sys();
4032 if (maxw < width() || maxh < height()) {
4033 bool resized = testAttribute(attribute: Qt::WA_Resized);
4034 resize(w: qMin(a: maxw,b: width()), h: qMin(a: maxh,b: height()));
4035 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
4036 }
4037
4038#if QT_CONFIG(graphicsview)
4039 if (d->extra) {
4040 if (d->extra->proxyWidget)
4041 d->extra->proxyWidget->setMaximumSize(aw: maxw, ah: maxh);
4042 }
4043#endif
4044
4045 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4046}
4047
4048/*!
4049 \overload
4050
4051 Sets the x (width) size increment to \a w and the y (height) size
4052 increment to \a h.
4053*/
4054void QWidget::setSizeIncrement(int w, int h)
4055{
4056 Q_D(QWidget);
4057 d->createTLExtra();
4058 QTLWExtra* x = d->topData();
4059 if (x->incw == w && x->inch == h)
4060 return;
4061 x->incw = w;
4062 x->inch = h;
4063 if (isWindow())
4064 d->setConstraints_sys();
4065}
4066
4067/*!
4068 \overload
4069
4070 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4071 the widgets base size to width \a basew and height \a baseh.
4072*/
4073void QWidget::setBaseSize(int basew, int baseh)
4074{
4075 Q_D(QWidget);
4076 d->createTLExtra();
4077 QTLWExtra* x = d->topData();
4078 if (x->basew == basew && x->baseh == baseh)
4079 return;
4080 x->basew = basew;
4081 x->baseh = baseh;
4082 if (isWindow())
4083 d->setConstraints_sys();
4084}
4085
4086/*!
4087 Sets both the minimum and maximum sizes of the widget to \a s,
4088 thereby preventing it from ever growing or shrinking.
4089
4090 This will override the default size constraints set by QLayout.
4091
4092 To remove constraints, set the size to QWIDGETSIZE_MAX.
4093
4094 Alternatively, if you want the widget to have a
4095 fixed size based on its contents, you can call
4096 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4097
4098 \sa maximumSize, minimumSize
4099*/
4100
4101void QWidget::setFixedSize(const QSize & s)
4102{
4103 setFixedSize(w: s.width(), h: s.height());
4104}
4105
4106
4107/*!
4108 \fn void QWidget::setFixedSize(int w, int h)
4109 \overload
4110
4111 Sets the width of the widget to \a w and the height to \a h.
4112*/
4113
4114void QWidget::setFixedSize(int w, int h)
4115{
4116 Q_D(QWidget);
4117 bool minSizeSet = d->setMinimumSize_helper(minw&: w, minh&: h);
4118 bool maxSizeSet = d->setMaximumSize_helper(maxw&: w, maxh&: h);
4119 if (!minSizeSet && !maxSizeSet)
4120 return;
4121
4122 if (isWindow())
4123 d->setConstraints_sys();
4124 else
4125 d->updateGeometry_helper(forceUpdate: true);
4126
4127 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4128 resize(w, h);
4129}
4130
4131void QWidget::setMinimumWidth(int w)
4132{
4133 Q_D(QWidget);
4134 d->createExtra();
4135 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4136 setMinimumSize(minw: w, minh: minimumSize().height());
4137 d->extra->explicitMinSize = expl;
4138}
4139
4140void QWidget::setMinimumHeight(int h)
4141{
4142 Q_D(QWidget);
4143 d->createExtra();
4144 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4145 setMinimumSize(minw: minimumSize().width(), minh: h);
4146 d->extra->explicitMinSize = expl;
4147}
4148
4149void QWidget::setMaximumWidth(int w)
4150{
4151 Q_D(QWidget);
4152 d->createExtra();
4153 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4154 setMaximumSize(maxw: w, maxh: maximumSize().height());
4155 d->extra->explicitMaxSize = expl;
4156}
4157
4158void QWidget::setMaximumHeight(int h)
4159{
4160 Q_D(QWidget);
4161 d->createExtra();
4162 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4163 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4164 d->extra->explicitMaxSize = expl;
4165}
4166
4167/*!
4168 Sets both the minimum and maximum width of the widget to \a w
4169 without changing the heights. Provided for convenience.
4170
4171 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4172*/
4173
4174void QWidget::setFixedWidth(int w)
4175{
4176 Q_D(QWidget);
4177 d->createExtra();
4178 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4179 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4180 setMinimumSize(minw: w, minh: minimumSize().height());
4181 setMaximumSize(maxw: w, maxh: maximumSize().height());
4182 d->extra->explicitMinSize = explMin;
4183 d->extra->explicitMaxSize = explMax;
4184}
4185
4186
4187/*!
4188 Sets both the minimum and maximum heights of the widget to \a h
4189 without changing the widths. Provided for convenience.
4190
4191 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4192*/
4193
4194void QWidget::setFixedHeight(int h)
4195{
4196 Q_D(QWidget);
4197 d->createExtra();
4198 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4199 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4200 setMinimumSize(minw: minimumSize().width(), minh: h);
4201 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4202 d->extra->explicitMinSize = explMin;
4203 d->extra->explicitMaxSize = explMax;
4204}
4205
4206
4207/*!
4208 Translates the widget coordinate \a pos to the coordinate system
4209 of \a parent. The \a parent must not be \nullptr and must be a parent
4210 of the calling widget.
4211
4212 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4213 \since 6.0
4214*/
4215
4216QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4217{
4218 QPointF p = pos;
4219 if (parent) {
4220 const QWidget * w = this;
4221 while (w != parent) {
4222 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPointF &pos)",
4223 "parent must be in parent hierarchy");
4224 p = w->mapToParent(p);
4225 w = w->parentWidget();
4226 }
4227 }
4228 return p;
4229}
4230
4231/*!
4232 \overload
4233*/
4234QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4235{
4236 return mapTo(parent, pos: QPointF(pos)).toPoint();
4237}
4238
4239/*!
4240 Translates the widget coordinate \a pos from the coordinate system
4241 of \a parent to this widget's coordinate system. The \a parent
4242 must not be \nullptr and must be a parent of the calling widget.
4243
4244 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4245 \since 6.0
4246*/
4247
4248QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4249{
4250 QPointF p(pos);
4251 if (parent) {
4252 const QWidget * w = this;
4253 while (w != parent) {
4254 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4255 "parent must be in parent hierarchy");
4256
4257 p = w->mapFromParent(p);
4258 w = w->parentWidget();
4259 }
4260 }
4261 return p;
4262}
4263
4264/*!
4265 \overload
4266*/
4267QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4268{
4269 return mapFrom(parent, pos: QPointF(pos)).toPoint();
4270}
4271
4272/*!
4273 Translates the widget coordinate \a pos to a coordinate in the
4274 parent widget.
4275
4276 Same as mapToGlobal() if the widget has no parent.
4277
4278 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4279 \since 6.0
4280*/
4281
4282QPointF QWidget::mapToParent(const QPointF &pos) const
4283{
4284 return pos + QPointF(data->crect.topLeft());
4285}
4286
4287/*!
4288 \overload
4289*/
4290QPoint QWidget::mapToParent(const QPoint &pos) const
4291{
4292 return pos + data->crect.topLeft();
4293}
4294
4295/*!
4296 Translates the parent widget coordinate \a pos to widget
4297 coordinates.
4298
4299 Same as mapFromGlobal() if the widget has no parent.
4300
4301 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4302 \since 6.0
4303*/
4304
4305QPointF QWidget::mapFromParent(const QPointF &pos) const
4306{
4307 return pos - QPointF(data->crect.topLeft());
4308}
4309
4310/*!
4311 \overload
4312*/
4313QPoint QWidget::mapFromParent(const QPoint &pos) const
4314{
4315 return pos - data->crect.topLeft();
4316}
4317
4318
4319/*!
4320 Returns the window for this widget, i.e. the next ancestor widget
4321 that has (or could have) a window-system frame.
4322
4323 If the widget is a window, the widget itself is returned.
4324
4325 Typical usage is changing the window title:
4326
4327 \snippet code/src_gui_kernel_qwidget.cpp 3
4328
4329 \sa isWindow()
4330*/
4331
4332QWidget *QWidget::window() const
4333{
4334 QWidget *w = const_cast<QWidget *>(this);
4335 QWidget *p = w->parentWidget();
4336 while (!w->isWindow() && p) {
4337 w = p;
4338 p = p->parentWidget();
4339 }
4340 return w;
4341}
4342
4343/*!
4344 \since 4.4
4345
4346 Returns the native parent for this widget, i.e. the next ancestor widget
4347 that has a system identifier, or \nullptr if it does not have any native
4348 parent.
4349
4350 \sa effectiveWinId()
4351*/
4352QWidget *QWidget::nativeParentWidget() const
4353{
4354 QWidget *parent = parentWidget();
4355 while (parent && !parent->internalWinId())
4356 parent = parent->parentWidget();
4357 return parent;
4358}
4359
4360/*! \fn QWidget *QWidget::topLevelWidget() const
4361 \deprecated
4362
4363 Use window() instead.
4364*/
4365
4366
4367
4368/*!
4369 Returns the background role of the widget.
4370
4371 The background role defines the brush from the widget's \l palette that
4372 is used to render the background.
4373
4374 If no explicit background role is set, the widget inherits its parent
4375 widget's background role.
4376
4377 \sa setBackgroundRole(), foregroundRole()
4378 */
4379QPalette::ColorRole QWidget::backgroundRole() const
4380{
4381
4382 const QWidget *w = this;
4383 do {
4384 QPalette::ColorRole role = w->d_func()->bg_role;
4385 if (role != QPalette::NoRole)
4386 return role;
4387 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4388 break;
4389 w = w->parentWidget();
4390 } while (w);
4391 return QPalette::Window;
4392}
4393
4394/*!
4395 Sets the background role of the widget to \a role.
4396
4397 The background role defines the brush from the widget's \l palette that
4398 is used to render the background.
4399
4400 If \a role is QPalette::NoRole, then the widget inherits its
4401 parent's background role.
4402
4403 Note that styles are free to choose any color from the palette.
4404 You can modify the palette or set a style sheet if you don't
4405 achieve the result you want with setBackgroundRole().
4406
4407 \sa backgroundRole(), foregroundRole()
4408 */
4409
4410void QWidget::setBackgroundRole(QPalette::ColorRole role)
4411{
4412 Q_D(QWidget);
4413 d->bg_role = role;
4414 d->updateSystemBackground();
4415 d->propagatePaletteChange();
4416 d->updateIsOpaque();
4417}
4418
4419/*!
4420 Returns the foreground role.
4421
4422 The foreground role defines the color from the widget's \l palette that
4423 is used to draw the foreground.
4424
4425 If no explicit foreground role is set, the function returns a role
4426 that contrasts with the background role.
4427
4428 \sa setForegroundRole(), backgroundRole()
4429 */
4430QPalette::ColorRole QWidget::foregroundRole() const
4431{
4432 Q_D(const QWidget);
4433 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4434 if (rl != QPalette::NoRole)
4435 return rl;
4436 QPalette::ColorRole role = QPalette::WindowText;
4437 switch (backgroundRole()) {
4438 case QPalette::Button:
4439 role = QPalette::ButtonText;
4440 break;
4441 case QPalette::Base:
4442 role = QPalette::Text;
4443 break;
4444 case QPalette::Dark:
4445 case QPalette::Shadow:
4446 role = QPalette::Light;
4447 break;
4448 case QPalette::Highlight:
4449 role = QPalette::HighlightedText;
4450 break;
4451 case QPalette::ToolTipBase:
4452 role = QPalette::ToolTipText;
4453 break;
4454 default:
4455 ;
4456 }
4457 return role;
4458}
4459
4460/*!
4461 Sets the foreground role of the widget to \a role.
4462
4463 The foreground role defines the color from the widget's \l palette that
4464 is used to draw the foreground.
4465
4466 If \a role is QPalette::NoRole, the widget uses a foreground role
4467 that contrasts with the background role.
4468
4469 Note that styles are free to choose any color from the palette.
4470 You can modify the palette or set a style sheet if you don't
4471 achieve the result you want with setForegroundRole().
4472
4473 \sa foregroundRole(), backgroundRole()
4474 */
4475void QWidget::setForegroundRole(QPalette::ColorRole role)
4476{
4477 Q_D(QWidget);
4478 d->fg_role = role;
4479 d->updateSystemBackground();
4480 d->propagatePaletteChange();
4481}
4482
4483/*!
4484 \property QWidget::palette
4485 \brief the widget's palette
4486
4487 This property describes the widget's palette. The palette is used by the
4488 widget's style when rendering standard components, and is available as a
4489 means to ensure that custom widgets can maintain consistency with the
4490 native platform's look and feel. It's common that different platforms, or
4491 different styles, have different palettes.
4492
4493 When you assign a new palette to a widget, the color roles from this
4494 palette are combined with the widget's default palette to form the
4495 widget's final palette. The palette entry for the widget's background role
4496 is used to fill the widget's background (see QWidget::autoFillBackground),
4497 and the foreground role initializes QPainter's pen.
4498
4499 The default depends on the system environment. QApplication maintains a
4500 system/theme palette which serves as a default for all widgets. There may
4501 also be special palette defaults for certain types of widgets (e.g., on
4502 Windows Vista, all classes that derive from QMenuBar have a special
4503 default palette). You can also define default palettes for widgets
4504 yourself by passing a custom palette and the name of a widget to
4505 QApplication::setPalette(). Finally, the style always has the option of
4506 polishing the palette as it's assigned (see QStyle::polish()).
4507
4508 QWidget propagates explicit palette roles from parent to child. If you
4509 assign a brush or color to a specific role on a palette and assign that
4510 palette to a widget, that role will propagate to all the widget's
4511 children, overriding any system defaults for that role. Note that palettes
4512 by default don't propagate to windows (see isWindow()) unless the
4513 Qt::WA_WindowPropagation attribute is enabled.
4514
4515 QWidget's palette propagation is similar to its font propagation.
4516
4517 The current style, which is used to render the content of all standard Qt
4518 widgets, is free to choose colors and brushes from the widget palette, or,
4519 in some cases, to ignore the palette (partially, or completely). In
4520 particular, certain styles like GTK style, Mac style, and Windows Vista
4521 style, depend on third party APIs to render the content of widgets,
4522 and these styles typically do not follow the palette. Because of this,
4523 assigning roles to a widget's palette is not guaranteed to change the
4524 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4525
4526 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4527 When using style sheets, the palette of a widget can be customized using
4528 the "color", "background-color", "selection-color",
4529 "selection-background-color" and "alternate-background-color".
4530
4531 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4532*/
4533const QPalette &QWidget::palette() const
4534{
4535 if (!isEnabled()) {
4536 data->pal.setCurrentColorGroup(QPalette::Disabled);
4537 } else if ((!isVisible() || isActiveWindow())
4538#if defined(Q_OS_WIN)
4539 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4540#endif
4541 ) {
4542 data->pal.setCurrentColorGroup(QPalette::Active);
4543 } else {
4544 data->pal.setCurrentColorGroup(QPalette::Inactive);
4545 }
4546 return data->pal;
4547}
4548
4549void QWidget::setPalette(const QPalette &palette)
4550{
4551 Q_D(QWidget);
4552 setAttribute(Qt::WA_SetPalette, on: palette.resolveMask() != 0);
4553
4554 // Determine which palette is inherited from this widget's ancestors and
4555 // QApplication::palette, resolve this against \a palette (attributes from
4556 // the inherited palette are copied over this widget's palette). Then
4557 // propagate this palette to this widget's children.
4558 QPalette naturalPalette = d->naturalWidgetPalette(inheritedMask: d->inheritedPaletteResolveMask);
4559 QPalette resolvedPalette = palette.resolve(other: naturalPalette);
4560 d->setPalette_helper(resolvedPalette);
4561}
4562
4563/*!
4564 \internal
4565
4566 Returns the palette that the widget \a w inherits from its ancestors and
4567 QApplication::palette. \a inheritedMask is the combination of the widget's
4568 ancestors palette request masks (i.e., which attributes from the parent
4569 widget's palette are implicitly imposed on this widget by the user). Note
4570 that this font does not take into account the palette set on \a w itself.
4571*/
4572QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4573{
4574 Q_Q(const QWidget);
4575
4576 const bool useStyleSheetPropagationInWidgetStyles =
4577 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4578
4579 QPalette naturalPalette = QApplication::palette(q);
4580 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4581 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4582#if QT_CONFIG(graphicsview)
4583 || (extra && extra->proxyWidget)
4584#endif // QT_CONFIG(graphicsview)
4585 )) {
4586 if (QWidget *p = q->parentWidget()) {
4587 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4588 if (!naturalPalette.isCopyOf(p: QGuiApplication::palette())) {
4589 QPalette inheritedPalette = p->palette();
4590 inheritedPalette.setResolveMask(inheritedMask);
4591 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4592 } else {
4593 naturalPalette = p->palette();
4594 }
4595 }
4596 }
4597#if QT_CONFIG(graphicsview)
4598 else if (extra && extra->proxyWidget) {
4599 QPalette inheritedPalette = extra->proxyWidget->palette();
4600 inheritedPalette.setResolveMask(inheritedMask);
4601 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4602 }
4603#endif // QT_CONFIG(graphicsview)
4604 }
4605 naturalPalette.setResolveMask(0);
4606 return naturalPalette;
4607}
4608/*!
4609 \internal
4610
4611 Determine which palette is inherited from this widget's ancestors and
4612 QApplication::palette, resolve this against this widget's palette
4613 (attributes from the inherited palette are copied over this widget's
4614 palette). Then propagate this palette to this widget's children.
4615*/
4616void QWidgetPrivate::resolvePalette()
4617{
4618 QPalette naturalPalette = naturalWidgetPalette(inheritedMask: inheritedPaletteResolveMask);
4619 QPalette resolvedPalette = data.pal.resolve(other: naturalPalette);
4620 setPalette_helper(resolvedPalette);
4621}
4622
4623void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4624{
4625 Q_Q(QWidget);
4626 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4627 return;
4628 data.pal = palette;
4629 updateSystemBackground();
4630 propagatePaletteChange();
4631 updateIsOpaque();
4632 q->update();
4633 updateIsOpaque();
4634}
4635
4636void QWidgetPrivate::updateSystemBackground()
4637{
4638}
4639
4640/*!
4641 \property QWidget::font
4642 \brief the font currently set for the widget
4643
4644 This property describes the widget's requested font. The font is used by
4645 the widget's style when rendering standard components, and is available as
4646 a means to ensure that custom widgets can maintain consistency with the
4647 native platform's look and feel. It's common that different platforms, or
4648 different styles, define different fonts for an application.
4649
4650 When you assign a new font to a widget, the properties from this font are
4651 combined with the widget's default font to form the widget's final
4652 font. You can call fontInfo() to get a copy of the widget's final
4653 font. The final font is also used to initialize QPainter's font.
4654
4655 The default depends on the system environment. QApplication maintains a
4656 system/theme font which serves as a default for all widgets. There may
4657 also be special font defaults for certain types of widgets. You can also
4658 define default fonts for widgets yourself by passing a custom font and the
4659 name of a widget to QApplication::setFont(). Finally, the font is matched
4660 against Qt's font database to find the best match.
4661
4662 QWidget propagates explicit font properties from parent to child. If you
4663 change a specific property on a font and assign that font to a widget,
4664 that property will propagate to all the widget's children, overriding any
4665 system defaults for that property. Note that fonts by default don't
4666 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4667 attribute is enabled.
4668
4669 QWidget's font propagation is similar to its palette propagation.
4670
4671 The current style, which is used to render the content of all standard Qt
4672 widgets, is free to choose to use the widget font, or in some cases, to
4673 ignore it (partially, or completely). In particular, certain styles like
4674 GTK style, Mac style, and Windows Vista style, apply special
4675 modifications to the widget font to match the platform's native look and
4676 feel. Because of this, assigning properties to a widget's font is not
4677 guaranteed to change the appearance of the widget. Instead, you may choose
4678 to apply a \l styleSheet.
4679
4680 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4681 style sheets will take precedence if the settings conflict.
4682
4683 \sa fontInfo(), fontMetrics()
4684*/
4685
4686void QWidget::setFont(const QFont &font)
4687{
4688 Q_D(QWidget);
4689
4690#ifndef QT_NO_STYLE_STYLESHEET
4691 const QStyleSheetStyle* style;
4692 if (d->extra && (style = qt_styleSheet(style: d->extra->style)))
4693 style->saveWidgetFont(w: this, font);
4694#endif
4695
4696 setAttribute(Qt::WA_SetFont, on: font.resolveMask() != 0);
4697
4698 // Determine which font is inherited from this widget's ancestors and
4699 // QApplication::font, resolve this against \a font (attributes from the
4700 // inherited font are copied over). Then propagate this font to this
4701 // widget's children.
4702 QFont naturalFont = d->naturalWidgetFont(inheritedMask: d->inheritedFontResolveMask);
4703 QFont resolvedFont = font.resolve(naturalFont);
4704 d->setFont_helper(resolvedFont);
4705}
4706
4707/*
4708 \internal
4709
4710 Returns the font that the widget \a w inherits from its ancestors and
4711 QApplication::font. \a inheritedMask is the combination of the widget's
4712 ancestors font request masks (i.e., which attributes from the parent
4713 widget's font are implicitly imposed on this widget by the user). Note
4714 that this font does not take into account the font set on \a w itself.
4715
4716 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4717 is applied, fonts are not propagated anymore
4718*/
4719QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4720{
4721 Q_Q(const QWidget);
4722
4723 const bool useStyleSheetPropagationInWidgetStyles =
4724 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4725
4726 QFont naturalFont = QApplication::font(q);
4727 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4728 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4729#if QT_CONFIG(graphicsview)
4730 || (extra && extra->proxyWidget)
4731#endif // QT_CONFIG(graphicsview)
4732 )) {
4733 if (QWidget *p = q->parentWidget()) {
4734 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4735 if (!naturalFont.isCopyOf(QApplication::font())) {
4736 if (inheritedMask != 0) {
4737 QFont inheritedFont = p->font();
4738 inheritedFont.setResolveMask(inheritedMask);
4739 naturalFont = inheritedFont.resolve(naturalFont);
4740 } // else nothing to do (naturalFont = naturalFont)
4741 } else {
4742 naturalFont = p->font();
4743 }
4744 }
4745 }
4746#if QT_CONFIG(graphicsview)
4747 else if (extra && extra->proxyWidget) {
4748 if (inheritedMask != 0) {
4749 QFont inheritedFont = extra->proxyWidget->font();
4750 inheritedFont.setResolveMask(inheritedMask);
4751 naturalFont = inheritedFont.resolve(naturalFont);
4752 } // else nothing to do (naturalFont = naturalFont)
4753 }
4754#endif // QT_CONFIG(graphicsview)
4755 }
4756 naturalFont.setResolveMask(0);
4757 return naturalFont;
4758}
4759
4760/*!
4761 \internal
4762
4763 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4764*/
4765QFont QWidgetPrivate::localFont() const
4766{
4767 QFont localfont = data.fnt;
4768 localfont.setResolveMask(directFontResolveMask);
4769 return localfont;
4770}
4771
4772/*!
4773 \internal
4774
4775 Determine which font is implicitly imposed on this widget by its ancestors
4776 and QApplication::font, resolve this against its own font (attributes from
4777 the implicit font are copied over). Then propagate this font to this
4778 widget's children.
4779*/
4780void QWidgetPrivate::resolveFont()
4781{
4782 QFont naturalFont = naturalWidgetFont(inheritedMask: inheritedFontResolveMask);
4783 QFont resolvedFont = localFont().resolve(naturalFont);
4784 setFont_helper(resolvedFont);
4785}
4786
4787/*!
4788 \internal
4789
4790 Assign \a font to this widget, and propagate it to all children, except
4791 style sheet widgets (handled differently) and windows that don't enable
4792 window propagation. \a implicitMask is the union of all ancestor widgets'
4793 font request masks, and determines which attributes from this widget's
4794 font should propagate.
4795*/
4796void QWidgetPrivate::updateFont(const QFont &font)
4797{
4798 Q_Q(QWidget);
4799#ifndef QT_NO_STYLE_STYLESHEET
4800 const QStyleSheetStyle* cssStyle;
4801 cssStyle = extra ? qt_styleSheet(style: extra->style) : nullptr;
4802 const bool useStyleSheetPropagationInWidgetStyles =
4803 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4804#endif
4805
4806 data.fnt = QFont(font, q);
4807
4808 // Combine new mask with natural mask and propagate to children.
4809#if QT_CONFIG(graphicsview)
4810 if (!q->parentWidget() && extra && extra->proxyWidget) {
4811 QGraphicsProxyWidget *p = extra->proxyWidget;
4812 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4813 } else
4814#endif // QT_CONFIG(graphicsview)
4815 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
4816 inheritedFontResolveMask = 0;
4817 }
4818 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4819 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4820 // isn't all weak information, but save the original mask to be able to let new changes on the
4821 // parent widget font propagate correctly.
4822 directFontResolveMask = data.fnt.resolveMask();
4823 data.fnt.setResolveMask(newMask);
4824
4825 for (int i = 0; i < children.size(); ++i) {
4826 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4827 if (w) {
4828 if (0) {
4829#ifndef QT_NO_STYLE_STYLESHEET
4830 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(attribute: Qt::WA_StyleSheet)) {
4831 // Style sheets follow a different font propagation scheme.
4832 if (cssStyle)
4833 cssStyle->updateStyleSheetFont(w);
4834#endif
4835 } else if ((!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
4836 // Propagate font changes.
4837 QWidgetPrivate *wd = w->d_func();
4838 wd->inheritedFontResolveMask = newMask;
4839 wd->resolveFont();
4840 }
4841 }
4842 }
4843
4844#ifndef QT_NO_STYLE_STYLESHEET
4845 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4846 cssStyle->updateStyleSheetFont(w: q);
4847 }
4848#endif
4849
4850 QEvent e(QEvent::FontChange);
4851 QCoreApplication::sendEvent(receiver: q, event: &e);
4852}
4853
4854void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4855{
4856 Q_Q(QWidget);
4857
4858 if ( (direction == Qt::RightToLeft) == q->testAttribute(attribute: Qt::WA_RightToLeft))
4859 return;
4860 q->setAttribute(Qt::WA_RightToLeft, on: (direction == Qt::RightToLeft));
4861 if (!children.isEmpty()) {
4862 for (int i = 0; i < children.size(); ++i) {
4863 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4864 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4865 w->d_func()->setLayoutDirection_helper(direction);
4866 }
4867 }
4868 QEvent e(QEvent::LayoutDirectionChange);
4869 QCoreApplication::sendEvent(receiver: q, event: &e);
4870}
4871
4872void QWidgetPrivate::resolveLayoutDirection()
4873{
4874 Q_Q(const QWidget);
4875 if (!q->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4876 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4877}
4878
4879/*!
4880 \property QWidget::layoutDirection
4881
4882 \brief the layout direction for this widget.
4883
4884 \note This method no longer affects text layout direction since Qt 4.7.
4885
4886 By default, this property is set to Qt::LeftToRight.
4887
4888 When the layout direction is set on a widget, it will propagate to
4889 the widget's children, but not to a child that is a window and not
4890 to a child for which setLayoutDirection() has been explicitly
4891 called. Also, child widgets added \e after setLayoutDirection()
4892 has been called for the parent do not inherit the parent's layout
4893 direction.
4894
4895
4896 \sa QApplication::layoutDirection
4897*/
4898void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4899{
4900 Q_D(QWidget);
4901
4902 if (direction == Qt::LayoutDirectionAuto) {
4903 unsetLayoutDirection();
4904 return;
4905 }
4906
4907 setAttribute(Qt::WA_SetLayoutDirection);
4908 d->setLayoutDirection_helper(direction);
4909}
4910
4911Qt::LayoutDirection QWidget::layoutDirection() const
4912{
4913 return testAttribute(attribute: Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4914}
4915
4916void QWidget::unsetLayoutDirection()
4917{
4918 Q_D(QWidget);
4919 setAttribute(Qt::WA_SetLayoutDirection, on: false);
4920 d->resolveLayoutDirection();
4921}
4922
4923/*!
4924 \fn QFontMetrics QWidget::fontMetrics() const
4925
4926 Returns the font metrics for the widget's current font.
4927 Equivalent to \c QFontMetrics(widget->font()).
4928
4929 \sa font(), fontInfo(), setFont()
4930*/
4931
4932/*!
4933 \fn QFontInfo QWidget::fontInfo() const
4934
4935 Returns the font info for the widget's current font.
4936 Equivalent to \c QFontInfo(widget->font()).
4937
4938 \sa font(), fontMetrics(), setFont()
4939*/
4940
4941
4942/*!
4943 \property QWidget::cursor
4944 \brief the cursor shape for this widget
4945
4946 The mouse cursor will assume this shape when it's over this
4947 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4948
4949 An editor widget might use an I-beam cursor:
4950 \snippet code/src_gui_kernel_qwidget.cpp 6
4951
4952 If no cursor has been set, or after a call to unsetCursor(), the
4953 parent's cursor is used.
4954
4955 By default, this property contains a cursor with the Qt::ArrowCursor
4956 shape.
4957
4958 Some underlying window implementations will reset the cursor if it
4959 leaves a widget even if the mouse is grabbed. If you want to have
4960 a cursor set for all widgets, even when outside the window, consider
4961 QGuiApplication::setOverrideCursor().
4962
4963 \sa QGuiApplication::setOverrideCursor()
4964*/
4965
4966#ifndef QT_NO_CURSOR
4967QCursor QWidget::cursor() const
4968{
4969 Q_D(const QWidget);
4970 if (testAttribute(attribute: Qt::WA_SetCursor))
4971 return (d->extra && d->extra->curs)
4972 ? *d->extra->curs
4973 : QCursor(Qt::ArrowCursor);
4974 if (isWindow() || !parentWidget())
4975 return QCursor(Qt::ArrowCursor);
4976 return parentWidget()->cursor();
4977}
4978
4979void QWidget::setCursor(const QCursor &cursor)
4980{
4981 Q_D(QWidget);
4982 if (cursor.shape() != Qt::ArrowCursor
4983 || (d->extra && d->extra->curs))
4984 {
4985 d->createExtra();
4986 d->extra->curs = std::make_unique<QCursor>(args: cursor);
4987 }
4988 setAttribute(Qt::WA_SetCursor);
4989 d->setCursor_sys(cursor);
4990
4991 QEvent event(QEvent::CursorChange);
4992 QCoreApplication::sendEvent(receiver: this, event: &event);
4993}
4994
4995void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4996{
4997 Q_UNUSED(cursor);
4998 Q_Q(QWidget);
4999 qt_qpa_set_cursor(w: q, force: false);
5000}
5001
5002void QWidget::unsetCursor()
5003{
5004 Q_D(QWidget);
5005 if (d->extra)
5006 d->extra->curs.reset();
5007 if (!isWindow())
5008 setAttribute(Qt::WA_SetCursor, on: false);
5009 d->unsetCursor_sys();
5010
5011 QEvent event(QEvent::CursorChange);
5012 QCoreApplication::sendEvent(receiver: this, event: &event);
5013}
5014
5015void QWidgetPrivate::unsetCursor_sys()
5016{
5017 Q_Q(QWidget);
5018 qt_qpa_set_cursor(w: q, force: false);
5019}
5020
5021static inline void applyCursor(QWidget *w, const QCursor &c)
5022{
5023 if (QWindow *window = w->windowHandle())
5024 window->setCursor(c);
5025}
5026
5027static inline void unsetCursor(QWidget *w)
5028{
5029 if (QWindow *window = w->windowHandle())
5030 window->unsetCursor();
5031}
5032
5033void qt_qpa_set_cursor(QWidget *w, bool force)
5034{
5035 if (!w->testAttribute(attribute: Qt::WA_WState_Created))
5036 return;
5037
5038 static QPointer<QWidget> lastUnderMouse = nullptr;
5039 if (force) {
5040 lastUnderMouse = w;
5041 } else if (lastUnderMouse) {
5042 const WId lastWinId = lastUnderMouse->effectiveWinId();
5043 const WId winId = w->effectiveWinId();
5044 if (lastWinId && lastWinId == winId)
5045 w = lastUnderMouse;
5046 } else if (!w->internalWinId()) {
5047 return; // The mouse is not under this widget, and it's not native, so don't change it.
5048 }
5049
5050 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5051 && !w->testAttribute(attribute: Qt::WA_SetCursor))
5052 w = w->parentWidget();
5053
5054 QWidget *nativeParent = w;
5055 if (!w->internalWinId())
5056 nativeParent = w->nativeParentWidget();
5057 if (!nativeParent || !nativeParent->internalWinId())
5058 return;
5059
5060 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_SetCursor)) {
5061 if (w->isEnabled())
5062 applyCursor(w: nativeParent, c: w->cursor());
5063 else
5064 // Enforce the windows behavior of clearing the cursor on
5065 // disabled widgets.
5066 unsetCursor(w: nativeParent);
5067 } else {
5068 unsetCursor(w: nativeParent);
5069 }
5070}
5071#endif
5072
5073/*!
5074 \enum QWidget::RenderFlag
5075
5076 This enum describes how to render the widget when calling QWidget::render().
5077
5078 \value DrawWindowBackground If you enable this option, the widget's background
5079 is rendered into the target even if autoFillBackground is not set. By default,
5080 this option is enabled.
5081
5082 \value DrawChildren If you enable this option, the widget's children
5083 are rendered recursively into the target. By default, this option is enabled.
5084
5085 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5086 is ignored when rendering into the target. By default, this option is disabled.
5087
5088 \since 4.3
5089*/
5090
5091/*!
5092 \since 4.3
5093
5094 Renders the \a sourceRegion of this widget into the \a target
5095 using \a renderFlags to determine how to render. Rendering
5096 starts at \a targetOffset in the \a target. For example:
5097
5098 \snippet code/src_gui_kernel_qwidget.cpp 7
5099
5100 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5101 the region, i.e. the entire widget.
5102
5103 Ensure that you call QPainter::end() for the \a target device's
5104 active painter (if any) before rendering. For example:
5105
5106 \snippet code/src_gui_kernel_qwidget.cpp 8
5107
5108 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5109 instead.
5110*/
5111void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5112 const QRegion &sourceRegion, RenderFlags renderFlags)
5113{
5114 QPainter p(target);
5115 render(painter: &p, targetOffset, sourceRegion, renderFlags);
5116}
5117
5118/*!
5119 \overload
5120
5121 Renders the widget into the \a painter's QPainter::device().
5122
5123 Transformations and settings applied to the \a painter will be used
5124 when rendering.
5125
5126 \note The \a painter must be active. On \macos the widget will be
5127 rendered into a QPixmap and then drawn by the \a painter.
5128
5129 \sa QPainter::device()
5130*/
5131void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5132 const QRegion &sourceRegion, RenderFlags renderFlags)
5133{
5134 if (Q_UNLIKELY(!painter)) {
5135 qWarning(msg: "QWidget::render: Null pointer to painter");
5136 return;
5137 }
5138
5139 if (Q_UNLIKELY(!painter->isActive())) {
5140 qWarning(msg: "QWidget::render: Cannot render with an inactive painter");
5141 return;
5142 }
5143
5144 const qreal opacity = painter->opacity();
5145 if (qFuzzyIsNull(d: opacity))
5146 return; // Fully transparent.
5147
5148 Q_D(QWidget);
5149 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5150 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(region: sourceRegion, renderFlags)
5151 : sourceRegion;
5152 if (toBePainted.isEmpty())
5153 return;
5154
5155 if (!d->extra)
5156 d->createExtra();
5157 d->extra->inRenderWithPainter = true;
5158
5159 QPaintEngine *engine = painter->paintEngine();
5160 Q_ASSERT(engine);
5161 QPaintEnginePrivate *enginePriv = engine->d_func();
5162 Q_ASSERT(enginePriv);
5163 QPaintDevice *target = engine->paintDevice();
5164 Q_ASSERT(target);
5165
5166 // Render via a pixmap when dealing with non-opaque painters or printers.
5167 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5168 d->render_helper(painter, targetOffset, sourceRegion: toBePainted, renderFlags);
5169 d->extra->inRenderWithPainter = inRenderWithPainter;
5170 return;
5171 }
5172
5173 // Set new shared painter.
5174 QPainter *oldPainter = d->sharedPainter();
5175 d->setSharedPainter(painter);
5176
5177 // Save current system clip, viewport and transform,
5178 const QTransform oldTransform = enginePriv->systemTransform;
5179 const QRegion oldSystemClip = enginePriv->systemClip;
5180 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5181 const QRegion oldSystemViewport = enginePriv->systemViewport;
5182 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5183
5184 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5185 if (painter->hasClipping()) {
5186 const QRegion painterClip = painter->deviceTransform().map(r: painter->clipRegion());
5187 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5188 } else {
5189 enginePriv->setSystemViewport(oldSystemClip);
5190 }
5191 painter->setLayoutDirection(layoutDirection());
5192
5193 d->render(target, targetOffset, sourceRegion: toBePainted, renderFlags);
5194
5195 // Restore system clip, viewport and transform.
5196 enginePriv->baseSystemClip = oldBaseClip;
5197 enginePriv->setSystemTransformAndViewport(xform: oldTransform, region: oldSystemViewport);
5198 enginePriv->systemStateChanged();
5199 painter->setLayoutDirection(oldLayoutDirection);
5200
5201 // Restore shared painter.
5202 d->setSharedPainter(oldPainter);
5203
5204 d->extra->inRenderWithPainter = inRenderWithPainter;
5205}
5206
5207static void sendResizeEvents(QWidget *target)
5208{
5209 QResizeEvent e(target->size(), QSize());
5210 QCoreApplication::sendEvent(receiver: target, event: &e);
5211
5212 const QObjectList children = target->children();
5213 for (int i = 0; i < children.size(); ++i) {
5214 if (!children.at(i)->isWidgetType())
5215 continue;
5216 QWidget *child = static_cast<QWidget*>(children.at(i));
5217 if (!child->isWindow() && child->testAttribute(attribute: Qt::WA_PendingResizeEvent))
5218 sendResizeEvents(target: child);
5219 }
5220}
5221
5222/*!
5223 \since 5.0
5224
5225 Renders the widget into a pixmap restricted by the
5226 given \a rectangle. If the widget has any children, then
5227 they are also painted in the appropriate positions.
5228
5229 If a rectangle with an invalid size is specified (the default),
5230 the entire widget is painted.
5231
5232 \sa render(), QPixmap
5233*/
5234QPixmap QWidget::grab(const QRect &rectangle)
5235{
5236 Q_D(QWidget);
5237 if (testAttribute(attribute: Qt::WA_PendingResizeEvent) || !testAttribute(attribute: Qt::WA_WState_Created))
5238 sendResizeEvents(target: this);
5239
5240 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5241
5242 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5243 QRect r(rectangle);
5244 if (r.width() < 0 || r.height() < 0) {
5245 // For grabbing widgets that haven't been shown yet,
5246 // we trigger the layouting mechanism to determine the widget's size.
5247 r = d->prepareToRender(region: QRegion(), renderFlags).boundingRect();
5248 r.setTopLeft(rectangle.topLeft());
5249 }
5250
5251 if (!r.intersects(r: rect()))
5252 return QPixmap();
5253
5254 const qreal dpr = devicePixelRatio();
5255 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5256 res.setDevicePixelRatio(dpr);
5257 if (!d->isOpaque)
5258 res.fill(fillColor: Qt::transparent);
5259 d->render(target: &res, targetOffset: QPoint(), sourceRegion: QRegion(r), renderFlags);
5260
5261 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5262 return res;
5263}
5264
5265/*!
5266 \brief The graphicsEffect function returns a pointer to the
5267 widget's graphics effect.
5268
5269 If the widget has no graphics effect, \nullptr is returned.
5270
5271 \since 4.6
5272
5273 \sa setGraphicsEffect()
5274*/
5275#if QT_CONFIG(graphicseffect)
5276QGraphicsEffect *QWidget::graphicsEffect() const
5277{
5278 Q_D(const QWidget);
5279 return d->graphicsEffect;
5280}
5281#endif // QT_CONFIG(graphicseffect)
5282
5283/*!
5284
5285 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5286
5287 Sets \a effect as the widget's effect. If there already is an effect installed
5288 on this widget, QWidget will delete the existing effect before installing
5289 the new \a effect.
5290
5291 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5292 the effect from the widget and install it on this widget.
5293
5294 QWidget takes ownership of \a effect.
5295
5296 \note This function will apply the effect on itself and all its children.
5297
5298 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5299 QOpenGLWidget and QQuickWidget.
5300
5301 \since 4.6
5302
5303 \sa graphicsEffect()
5304*/
5305#if QT_CONFIG(graphicseffect)
5306void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5307{
5308 Q_D(QWidget);
5309 if (d->graphicsEffect == effect)
5310 return;
5311
5312 if (d->graphicsEffect) {
5313 d->invalidateBackingStore(rect());
5314 delete d->graphicsEffect;
5315 d->graphicsEffect = nullptr;
5316 }
5317
5318 if (effect) {
5319 // Set new effect.
5320 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5321 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5322 d->graphicsEffect = effect;
5323 effect->d_func()->setGraphicsEffectSource(source);
5324 update();
5325 }
5326
5327 d->updateIsOpaque();
5328}
5329#endif // QT_CONFIG(graphicseffect)
5330
5331bool QWidgetPrivate::isAboutToShow() const
5332{
5333 if (data.in_show)
5334 return true;
5335
5336 Q_Q(const QWidget);
5337 if (q->isHidden())
5338 return false;
5339
5340 // The widget will be shown if any of its ancestors are about to show.
5341 QWidget *parent = q->parentWidget();
5342 return parent ? parent->d_func()->isAboutToShow() : false;
5343}
5344
5345QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5346{
5347 Q_Q(QWidget);
5348 const bool isVisible = q->isVisible();
5349
5350 // Make sure the widget is laid out correctly.
5351 if (!isVisible && !isAboutToShow()) {
5352 QWidget *topLevel = q->window();
5353 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5354 topLevel->ensurePolished();
5355
5356 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5357 // they're not explicitly hidden.
5358 QWidget *widget = q;
5359 QWidgetList hiddenWidgets;
5360 while (widget) {
5361 if (widget->isHidden()) {
5362 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
5363 hiddenWidgets.append(t: widget);
5364 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5365 widget->d_func()->updateGeometry_helper(forceUpdate: true);
5366 }
5367 widget = widget->parentWidget();
5368 }
5369
5370 // Activate top-level layout.
5371 if (topLevel->d_func()->layout)
5372 topLevel->d_func()->layout->activate();
5373
5374 // Adjust size if necessary.
5375 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5376 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5377 && !topLevel->testAttribute(attribute: Qt::WA_Resized)) {
5378 topLevel->adjustSize();
5379 topLevel->setAttribute(Qt::WA_Resized, on: false);
5380 }
5381
5382 // Activate child layouts.
5383 topLevel->d_func()->activateChildLayoutsRecursively();
5384
5385 // We're not cheating with WA_WState_Hidden anymore.
5386 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5387 QWidget *widget = hiddenWidgets.at(i);
5388 widget->setAttribute(Qt::WA_WState_Hidden);
5389 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5390 widget->parentWidget()->d_func()->layout->invalidate();
5391 }
5392 } else if (isVisible) {
5393 q->window()->d_func()->sendPendingMoveAndResizeEvents(recursive: true, disableUpdates: true);
5394 }
5395
5396 // Calculate the region to be painted.
5397 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5398 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5399 toBePainted &= extra->mask;
5400 return toBePainted;
5401}
5402
5403void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5404 QWidget::RenderFlags renderFlags)
5405{
5406 Q_ASSERT(painter);
5407 Q_ASSERT(!toBePainted.isEmpty());
5408
5409 Q_Q(QWidget);
5410 const QTransform originalTransform = painter->worldTransform();
5411 const bool useDeviceCoordinates = originalTransform.isScaling();
5412 if (!useDeviceCoordinates) {
5413 // Render via a pixmap.
5414 const QRect rect = toBePainted.boundingRect();
5415 const QSize size = rect.size();
5416 if (size.isNull())
5417 return;
5418
5419 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5420 QPixmap pixmap(size * pixmapDevicePixelRatio);
5421 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5422
5423 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5424 pixmap.fill(fillColor: Qt::transparent);
5425 q->render(target: &pixmap, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5426
5427 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5428 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: true);
5429
5430 painter->drawPixmap(p: targetOffset, pm: pixmap);
5431
5432 if (restore)
5433 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: false);
5434
5435 } else {
5436 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5437 QTransform transform = originalTransform;
5438 transform.translate(dx: targetOffset.x(), dy: targetOffset.y());
5439
5440 QPaintDevice *device = painter->device();
5441 Q_ASSERT(device);
5442
5443 // Calculate device rect.
5444 const QRectF rect(toBePainted.boundingRect());
5445 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5446 deviceRect &= QRect(0, 0, device->width(), device->height());
5447
5448 QPixmap pixmap(deviceRect.size());
5449 pixmap.fill(fillColor: Qt::transparent);
5450
5451 // Create a pixmap device coordinate painter.
5452 QPainter pixmapPainter(&pixmap);
5453 pixmapPainter.setRenderHints(hints: painter->renderHints());
5454 transform *= QTransform::fromTranslate(dx: -deviceRect.x(), dy: -deviceRect.y());
5455 pixmapPainter.setTransform(transform);
5456
5457 q->render(painter: &pixmapPainter, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5458 pixmapPainter.end();
5459
5460 // And then draw the pixmap.
5461 painter->setTransform(transform: QTransform());
5462 painter->drawPixmap(p: deviceRect.topLeft(), pm: pixmap);
5463 painter->setTransform(transform: originalTransform);
5464 }
5465}
5466
5467void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5468 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5469{
5470 if (rgn.isEmpty())
5471 return;
5472
5473 Q_Q(QWidget);
5474
5475 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5476 << "into paint device" << pdev << "with" << flags;
5477
5478 const bool asRoot = flags & DrawAsRoot;
5479 bool onScreen = shouldPaintOnScreen();
5480
5481#if QT_CONFIG(graphicseffect)
5482 if (graphicsEffect && graphicsEffect->isEnabled()) {
5483 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5484 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5485 (source->d_func());
5486 if (!sourced->context) {
5487 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5488 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5489 sourced->context = &context;
5490 if (!sharedPainter) {
5491 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: effectRgn.translated(p: offset));
5492 QPainter p(pdev);
5493 p.translate(offset);
5494 context.painter = &p;
5495 graphicsEffect->draw(painter: &p);
5496 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5497 } else {
5498 context.painter = sharedPainter;
5499 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5500 sourced->invalidateCache();
5501 sourced->lastEffectTransform = sharedPainter->worldTransform();
5502 }
5503 sharedPainter->save();
5504 sharedPainter->translate(offset);
5505 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: sharedPainter->device()->devicePixelRatio(), region: effectRgn.translated(p: offset));
5506 graphicsEffect->draw(painter: sharedPainter);
5507 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: 1, region: QRegion());
5508 sharedPainter->restore();
5509 }
5510 sourced->context = nullptr;
5511
5512 if (repaintManager)
5513 repaintManager->markNeedsFlush(widget: q, region: effectRgn, topLevelOffset: offset);
5514
5515 return;
5516 }
5517 }
5518#endif // QT_CONFIG(graphicseffect)
5519 flags = flags & ~UseEffectRegionBounds;
5520
5521 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5522 const bool recursive = flags & DrawRecursive;
5523 const bool alsoInvisible = flags & DrawInvisible;
5524
5525 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5526
5527 QRegion toBePainted(rgn);
5528 if (asRoot && !alsoInvisible)
5529 toBePainted &= clipRect(); //(rgn & visibleRegion());
5530 if (!(flags & DontSubtractOpaqueChildren))
5531 subtractOpaqueChildren(source&: toBePainted, clipRect: q->rect());
5532
5533 if (!toBePainted.isEmpty()) {
5534 if (!onScreen || alsoOnScreen) {
5535 //update the "in paint event" flag
5536 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5537 qWarning(msg: "QWidget::repaint: Recursive repaint detected");
5538 q->setAttribute(Qt::WA_WState_InPaintEvent);
5539
5540 //clip away the new area
5541 QPaintEngine *paintEngine = pdev->paintEngine();
5542 if (paintEngine) {
5543 setRedirected(replacement: pdev, offset: -offset);
5544
5545 if (sharedPainter)
5546 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted);
5547 else
5548 paintEngine->d_func()->systemRect = q->data->crect;
5549
5550 //paint the background
5551 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(attribute: Qt::WA_StyledBackground))
5552 && !q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
5553 beginBackingStorePainting();
5554 QPainter p(q);
5555 p.setRenderHint(hint: QPainter::SmoothPixmapTransform);
5556 paintBackground(painter: &p, rgn: toBePainted, flags: (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5557 endBackingStorePainting();
5558 }
5559
5560 if (!sharedPainter)
5561 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted.translated(p: offset));
5562
5563 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(attribute: Qt::WA_TintedBackground)) {
5564 beginBackingStorePainting();
5565 QPainter p(q);
5566 QColor tint = q->palette().window().color();
5567 tint.setAlphaF(.6f);
5568 p.fillRect(toBePainted.boundingRect(), color: tint);
5569 endBackingStorePainting();
5570 }
5571 }
5572
5573#if 0
5574 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5575 qDebug() << "clipping to" << toBePainted << "location == " << offset
5576 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5577#endif
5578
5579 bool skipPaintEvent = false;
5580 if (renderToTexture) {
5581 // This widget renders into a texture which is composed later. We just need to
5582 // punch a hole in the backingstore, so the texture will be visible.
5583 beginBackingStorePainting();
5584 if (!q->testAttribute(attribute: Qt::WA_AlwaysStackOnTop) && repaintManager) {
5585 QPainter p(q);
5586 p.setCompositionMode(QPainter::CompositionMode_Source);
5587 p.fillRect(r: q->rect(), c: Qt::transparent);
5588 } else if (!repaintManager) {
5589 // We are not drawing to a backingstore: fall back to QImage
5590 QImage img = grabFramebuffer();
5591 // grabFramebuffer() always sets the format to RGB32
5592 // regardless of whether it is transparent or not.
5593 if (img.format() == QImage::Format_RGB32)
5594 img.reinterpretAsFormat(f: QImage::Format_ARGB32_Premultiplied);
5595 QPainter p(q);
5596 p.drawImage(r: q->rect(), image: img);
5597 skipPaintEvent = true;
5598 }
5599 endBackingStorePainting();
5600 if (renderToTextureReallyDirty)
5601 renderToTextureReallyDirty = 0;
5602 else
5603 skipPaintEvent = true;
5604 }
5605
5606 if (!skipPaintEvent) {
5607 //actually send the paint event
5608 sendPaintEvent(toBePainted);
5609 }
5610
5611 if (repaintManager)
5612 repaintManager->markNeedsFlush(widget: q, region: toBePainted, topLevelOffset: offset);
5613
5614 //restore
5615 if (paintEngine) {
5616 restoreRedirected();
5617 if (!sharedPainter)
5618 paintEngine->d_func()->systemRect = QRect();
5619 else
5620 paintEngine->d_func()->currentClipDevice = nullptr;
5621
5622 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5623 }
5624 q->setAttribute(Qt::WA_WState_InPaintEvent, on: false);
5625 if (Q_UNLIKELY(q->paintingActive()))
5626 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5627
5628 if (paintEngine && paintEngine->autoDestruct()) {
5629 delete paintEngine;
5630 }
5631 } else if (q->isWindow()) {
5632 QPaintEngine *engine = pdev->paintEngine();
5633 if (engine) {
5634 QPainter p(pdev);
5635 p.setClipRegion(toBePainted);
5636 const QBrush bg = q->palette().brush(cr: QPalette::Window);
5637 if (bg.style() == Qt::TexturePattern)
5638 p.drawTiledPixmap(rect: q->rect(), pm: bg.texture());
5639 else
5640 p.fillRect(q->rect(), bg);
5641
5642 if (engine->autoDestruct())
5643 delete engine;
5644 }
5645 }
5646 }
5647
5648 if (recursive && !children.isEmpty()) {
5649 paintSiblingsRecursive(pdev, children, index: children.size() - 1, rgn, offset, flags: flags & ~DrawAsRoot,
5650 sharedPainter, repaintManager);
5651 }
5652}
5653
5654void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5655{
5656 Q_Q(QWidget);
5657 QPaintEvent e(toBePainted);
5658 QCoreApplication::sendSpontaneousEvent(receiver: q, event: &e);
5659
5660 if (renderToTexture)
5661 resolveSamples();
5662}
5663
5664void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5665 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5666{
5667 if (Q_UNLIKELY(!target)) {
5668 qWarning(msg: "QWidget::render: null pointer to paint device");
5669 return;
5670 }
5671
5672 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5673 QRegion paintRegion = !inRenderWithPainter
5674 ? prepareToRender(region: sourceRegion, renderFlags)
5675 : sourceRegion;
5676 if (paintRegion.isEmpty())
5677 return;
5678
5679 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5680
5681 // Use the target's shared painter if set (typically set when doing
5682 // "other->render(widget);" in the widget's paintEvent.
5683 if (target->devType() == QInternal::Widget) {
5684 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5685 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5686 QPainter *targetPainter = targetPrivate->sharedPainter();
5687 if (targetPainter && targetPainter->isActive())
5688 setSharedPainter(targetPainter);
5689 }
5690 }
5691
5692 // Use the target's redirected device if set and adjust offset and paint
5693 // region accordingly. This is typically the case when people call render
5694 // from the paintEvent.
5695 QPoint offset = targetOffset;
5696 offset -= paintRegion.boundingRect().topLeft();
5697 QPoint redirectionOffset;
5698 QPaintDevice *redirected = nullptr;
5699
5700 if (target->devType() == QInternal::Widget)
5701 redirected = static_cast<QWidget *>(target)->d_func()->redirected(offset: &redirectionOffset);
5702
5703 if (redirected) {
5704 target = redirected;
5705 offset -= redirectionOffset;
5706 }
5707
5708 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5709 if (QPaintEngine *targetEngine = target->paintEngine()) {
5710 const QRegion targetSystemClip = targetEngine->systemClip();
5711 if (!targetSystemClip.isEmpty())
5712 paintRegion &= targetSystemClip.translated(p: -offset);
5713 }
5714 }
5715
5716 // Set backingstore flags.
5717 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5718 if (renderFlags & QWidget::DrawWindowBackground)
5719 flags |= DrawAsRoot;
5720
5721 if (renderFlags & QWidget::DrawChildren)
5722 flags |= DrawRecursive;
5723 else
5724 flags |= DontSubtractOpaqueChildren;
5725
5726 flags |= DontSetCompositionMode;
5727
5728 // Render via backingstore.
5729 drawWidget(pdev: target, rgn: paintRegion, offset, flags, sharedPainter: sharedPainter());
5730
5731 // Restore shared painter.
5732 if (oldSharedPainter)
5733 setSharedPainter(oldSharedPainter);
5734}
5735
5736void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5737 const QPoint &offset, DrawWidgetFlags flags
5738 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5739{
5740 QWidget *w = nullptr;
5741 QRect boundingRect;
5742 bool dirtyBoundingRect = true;
5743 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5744 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5745
5746 do {
5747 QWidget *x = qobject_cast<QWidget*>(o: siblings.at(i: index));
5748 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5749 && !(excludeNativeChildren && x->internalWinId())) {
5750 if (dirtyBoundingRect) {
5751 boundingRect = rgn.boundingRect();
5752 dirtyBoundingRect = false;
5753 }
5754
5755 if (qRectIntersects(r1: boundingRect, r2: x->d_func()->effectiveRectFor(rect: x->data->crect))) {
5756 w = x;
5757 break;
5758 }
5759 }
5760 --index;
5761 } while (index >= 0);
5762
5763 if (!w)
5764 return;
5765
5766 QWidgetPrivate *wd = w->d_func();
5767 const QPoint widgetPos(w->data->crect.topLeft());
5768 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5769 if (index > 0) {
5770 QRegion wr(rgn);
5771 if (wd->isOpaque)
5772 wr -= hasMask ? wd->extra->mask.translated(p: widgetPos) : w->data->crect;
5773 paintSiblingsRecursive(pdev, siblings, index: --index, rgn: wr, offset, flags,
5774 sharedPainter, repaintManager);
5775 }
5776
5777 if (w->updatesEnabled()
5778#if QT_CONFIG(graphicsview)
5779 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5780#endif // QT_CONFIG(graphicsview)
5781 ) {
5782 QRegion wRegion(rgn);
5783 wRegion &= wd->effectiveRectFor(rect: w->data->crect);
5784 wRegion.translate(p: -widgetPos);
5785 if (hasMask)
5786 wRegion &= wd->extra->mask;
5787 wd->drawWidget(pdev, rgn: wRegion, offset: offset + widgetPos, flags, sharedPainter, repaintManager);
5788 }
5789}
5790
5791#if QT_CONFIG(graphicseffect)
5792QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5793{
5794 if (system != Qt::DeviceCoordinates)
5795 return m_widget->rect();
5796
5797 if (Q_UNLIKELY(!context)) {
5798 // Device coordinates without context not yet supported.
5799 qWarning(msg: "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5800 return QRectF();
5801 }
5802
5803 return context->painter->worldTransform().mapRect(m_widget->rect());
5804}
5805
5806void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5807{
5808 if (!context || context->painter != painter) {
5809 m_widget->render(painter);
5810 return;
5811 }
5812
5813 // The region saved in the context is neither clipped to the rect
5814 // nor the mask, so we have to clip it here before calling drawWidget.
5815 QRegion toBePainted = context->rgn;
5816 toBePainted &= m_widget->rect();
5817 QWidgetPrivate *wd = qt_widget_private(widget: m_widget);
5818 if (wd->extra && wd->extra->hasMask)
5819 toBePainted &= wd->extra->mask;
5820
5821 wd->drawWidget(pdev: context->pdev, rgn: toBePainted, offset: context->offset, flags: context->flags,
5822 sharedPainter: context->sharedPainter, repaintManager: context->repaintManager);
5823}
5824
5825QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5826 QGraphicsEffect::PixmapPadMode mode) const
5827{
5828 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5829 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5830 // Device coordinates without context not yet supported.
5831 qWarning(msg: "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5832 return QPixmap();
5833 }
5834
5835 QPoint pixmapOffset;
5836 QRectF sourceRect = m_widget->rect();
5837
5838 if (deviceCoordinates) {
5839 const QTransform &painterTransform = context->painter->worldTransform();
5840 sourceRect = painterTransform.mapRect(sourceRect);
5841 pixmapOffset = painterTransform.map(p: pixmapOffset);
5842 }
5843
5844 QRect effectRect;
5845
5846 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5847 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5848 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5849 effectRect = sourceRect.adjusted(xp1: -1, yp1: -1, xp2: 1, yp2: 1).toAlignedRect();
5850 else
5851 effectRect = sourceRect.toAlignedRect();
5852
5853 if (offset)
5854 *offset = effectRect.topLeft();
5855
5856 pixmapOffset -= effectRect.topLeft();
5857
5858 qreal dpr(1.0);
5859 if (const auto *paintDevice = context->painter->device())
5860 dpr = paintDevice->devicePixelRatio();
5861 else
5862 qWarning(msg: "QWidgetEffectSourcePrivate::pixmap: Painter not active");
5863 QPixmap pixmap(effectRect.size() * dpr);
5864 pixmap.setDevicePixelRatio(dpr);
5865
5866 pixmap.fill(fillColor: Qt::transparent);
5867 m_widget->render(target: &pixmap, targetOffset: pixmapOffset, sourceRegion: QRegion(), renderFlags: QWidget::DrawChildren);
5868 return pixmap;
5869}
5870#endif // QT_CONFIG(graphicseffect)
5871
5872#if QT_CONFIG(graphicsview)
5873/*!
5874 \internal
5875
5876 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5877 widget and its ancestors. The search starts at \a origin (inclusive).
5878 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5879 embedded widget was found.
5880*/
5881QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5882{
5883 if (origin) {
5884 const auto &extra = origin->d_func()->extra;
5885 if (extra && extra->proxyWidget)
5886 return extra->proxyWidget;
5887 return nearestGraphicsProxyWidget(origin: origin->parentWidget());
5888 }
5889 return nullptr;
5890}
5891#endif
5892
5893/*!
5894 \property QWidget::locale
5895 \brief the widget's locale
5896 \since 4.3
5897
5898 As long as no special locale has been set, this is either
5899 the parent's locale or (if this widget is a top level widget),
5900 the default locale.
5901
5902 If the widget displays dates or numbers, these should be formatted
5903 using the widget's locale.
5904
5905 \sa QLocale, QLocale::setDefault()
5906*/
5907
5908void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5909{
5910 Q_Q(QWidget);
5911 if (locale == loc && !forceUpdate)
5912 return;
5913
5914 locale = loc;
5915
5916 if (!children.isEmpty()) {
5917 for (int i = 0; i < children.size(); ++i) {
5918 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
5919 if (!w)
5920 continue;
5921 if (w->testAttribute(attribute: Qt::WA_SetLocale))
5922 continue;
5923 if (w->isWindow() && !w->testAttribute(attribute: Qt::WA_WindowPropagation))
5924 continue;
5925 w->d_func()->setLocale_helper(loc, forceUpdate);
5926 }
5927 }
5928 QEvent e(QEvent::LocaleChange);
5929 QCoreApplication::sendEvent(receiver: q, event: &e);
5930}
5931
5932void QWidget::setLocale(const QLocale &locale)
5933{
5934 Q_D(QWidget);
5935
5936 setAttribute(Qt::WA_SetLocale);
5937 d->setLocale_helper(loc: locale);
5938}
5939
5940QLocale QWidget::locale() const
5941{
5942 Q_D(const QWidget);
5943
5944 return d->locale;
5945}
5946
5947void QWidgetPrivate::resolveLocale()
5948{
5949 Q_Q(const QWidget);
5950
5951 if (!q->testAttribute(attribute: Qt::WA_SetLocale)) {
5952 QWidget *parent = q->parentWidget();
5953 setLocale_helper(loc: !parent || (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation))
5954 ? QLocale() : parent->locale());
5955 }
5956}
5957
5958void QWidget::unsetLocale()
5959{
5960 Q_D(QWidget);
5961 setAttribute(Qt::WA_SetLocale, on: false);
5962 d->resolveLocale();
5963}
5964
5965/*!
5966 \property QWidget::windowTitle
5967 \brief the window title (caption)
5968
5969 This property only makes sense for top-level widgets, such as
5970 windows and dialogs. If no caption has been set, the title is based of the
5971 \l windowFilePath. If neither of these is set, then the title is
5972 an empty string.
5973
5974 If you use the \l windowModified mechanism, the window title must
5975 contain a "[*]" placeholder, which indicates where the '*' should
5976 appear. Normally, it should appear right after the file name
5977 (e.g., "document1.txt[*] - Text Editor"). If the \l
5978 windowModified property is \c false (the default), the placeholder
5979 is simply removed.
5980
5981 On some desktop platforms (including Windows and Unix), the application name
5982 (from QGuiApplication::applicationDisplayName) is added at the end of the
5983 window title, if set. This is done by the QPA plugin, so it is shown to the
5984 user, but isn't part of the windowTitle string.
5985
5986 \sa windowIcon, windowModified, windowFilePath
5987*/
5988QString QWidget::windowTitle() const
5989{
5990 Q_D(const QWidget);
5991 if (d->extra && d->extra->topextra) {
5992 if (!d->extra->topextra->caption.isEmpty())
5993 return d->extra->topextra->caption;
5994 if (!d->extra->topextra->filePath.isEmpty())
5995 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
5996 }
5997 return QString();
5998}
5999
6000/*!
6001 Returns a modified window title with the [*] place holder
6002 replaced according to the rules described in QWidget::setWindowTitle
6003
6004 This function assumes that "[*]" can be quoted by another
6005 "[*]", so it will replace two place holders by one and
6006 a single last one by either "*" or nothing depending on
6007 the modified flag.
6008
6009 \internal
6010*/
6011QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6012{
6013 Q_ASSERT(widget);
6014
6015 QString cap = title;
6016 if (cap.isEmpty())
6017 return cap;
6018
6019 const auto placeHolder = "[*]"_L1;
6020 int index = cap.indexOf(s: placeHolder);
6021
6022 // here the magic begins
6023 while (index != -1) {
6024 index += placeHolder.size();
6025 int count = 1;
6026 while (cap.indexOf(s: placeHolder, from: index) == index) {
6027 ++count;
6028 index += placeHolder.size();
6029 }
6030
6031 if (count%2) { // odd number of [*] -> replace last one
6032 int lastIndex = cap.lastIndexOf(s: placeHolder, from: index - 1);
6033 if (widget->isWindowModified()
6034 && widget->style()->styleHint(stylehint: QStyle::SH_TitleBar_ModifyNotification, opt: nullptr, widget))
6035 cap.replace(i: lastIndex, len: 3, after: QWidget::tr(s: "*"));
6036 else
6037 cap.remove(i: lastIndex, len: 3);
6038 }
6039
6040 index = cap.indexOf(s: placeHolder, from: index);
6041 }
6042
6043 cap.replace(before: "[*][*]"_L1, after: placeHolder);
6044
6045 return cap;
6046}
6047
6048void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6049{
6050 Q_Q(QWidget);
6051 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6052 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6053}
6054
6055void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6056{
6057 Q_Q(QWidget);
6058 if (!q->isWindow())
6059 return;
6060
6061 if (QWindow *window = q->windowHandle())
6062 window->setTitle(caption);
6063
6064}
6065
6066void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6067{
6068 Q_Q(QWidget);
6069 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6070 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6071}
6072
6073void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6074{
6075#if QT_CONFIG(xcb)
6076 Q_Q(QWidget);
6077 // ### The QWidget property is deprecated, but the XCB window function is not.
6078 // It should remain available for the rare application that needs it.
6079 if (QWindow *window = q->windowHandle()) {
6080 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6081 xcbWindow->setWindowIconText(iconText);
6082 }
6083#else
6084 Q_UNUSED(iconText);
6085#endif
6086}
6087
6088/*!
6089 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6090
6091 This signal is emitted when the window's icon text has changed, with the
6092 new \a iconText as an argument.
6093
6094 \since 5.2
6095 \deprecated
6096
6097 This signal is deprecated.
6098*/
6099
6100void QWidget::setWindowIconText(const QString &iconText)
6101{
6102 if (QWidget::windowIconText() == iconText)
6103 return;
6104
6105 Q_D(QWidget);
6106 d->topData()->iconText = iconText;
6107 d->setWindowIconText_helper(iconText);
6108
6109 QEvent e(QEvent::IconTextChange);
6110 QCoreApplication::sendEvent(receiver: this, event: &e);
6111
6112 emit windowIconTextChanged(iconText);
6113}
6114
6115/*!
6116 \fn void QWidget::windowTitleChanged(const QString &title)
6117
6118 This signal is emitted when the window's title has changed, with the
6119 new \a title as an argument.
6120
6121 \since 5.2
6122*/
6123
6124void QWidget::setWindowTitle(const QString &title)
6125{
6126 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6127 return;
6128
6129#if QT_CONFIG(accessibility)
6130 QString oldAccessibleName;
6131 const QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(this);
6132 if (accessible)
6133 oldAccessibleName = accessible->text(t: QAccessible::Name);
6134#endif
6135
6136 Q_D(QWidget);
6137 d->topData()->caption = title;
6138 d->setWindowTitle_helper(title);
6139
6140 QEvent e(QEvent::WindowTitleChange);
6141 QCoreApplication::sendEvent(receiver: this, event: &e);
6142
6143 emit windowTitleChanged(title);
6144
6145#if QT_CONFIG(accessibility)
6146 if (accessible && accessible->text(t: QAccessible::Name) != oldAccessibleName) {
6147 QAccessibleEvent event(this, QAccessible::NameChanged);
6148 QAccessible::updateAccessibility(event: &event);
6149 }
6150#endif
6151}
6152
6153
6154/*!
6155 \property QWidget::windowIcon
6156 \brief the widget's icon
6157
6158 This property only makes sense for windows. If no icon
6159 has been set, windowIcon() returns the application icon
6160 (QApplication::windowIcon()).
6161
6162 \note On \macos, window icons represent the active document,
6163 and will not be displayed unless a file path has also been
6164 set using setWindowFilePath.
6165
6166 \sa windowTitle, setWindowFilePath
6167*/
6168QIcon QWidget::windowIcon() const
6169{
6170 const QWidget *w = this;
6171 while (w) {
6172 const QWidgetPrivate *d = w->d_func();
6173 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6174 return *d->extra->topextra->icon;
6175 w = w->parentWidget();
6176 }
6177 return QApplication::windowIcon();
6178}
6179
6180void QWidgetPrivate::setWindowIcon_helper()
6181{
6182 Q_Q(QWidget);
6183 QEvent e(QEvent::WindowIconChange);
6184
6185 // Do not send the event if the widget is a top level.
6186 // In that case, setWindowIcon_sys does it, and event propagation from
6187 // QWidgetWindow to the top level QWidget ensures that the event reaches
6188 // the top level anyhow
6189 if (!q->windowHandle())
6190 QCoreApplication::sendEvent(receiver: q, event: &e);
6191 for (int i = 0; i < children.size(); ++i) {
6192 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
6193 if (w && !w->isWindow())
6194 QCoreApplication::sendEvent(receiver: w, event: &e);
6195 }
6196}
6197
6198/*!
6199 \fn void QWidget::windowIconChanged(const QIcon &icon)
6200
6201 This signal is emitted when the window's icon has changed, with the
6202 new \a icon as an argument.
6203
6204 \since 5.2
6205*/
6206
6207void QWidget::setWindowIcon(const QIcon &icon)
6208{
6209 Q_D(QWidget);
6210
6211 setAttribute(Qt::WA_SetWindowIcon, on: !icon.isNull());
6212 d->createTLExtra();
6213
6214 if (!d->extra->topextra->icon)
6215 d->extra->topextra->icon = std::make_unique<QIcon>(args: icon);
6216 else
6217 *d->extra->topextra->icon = icon;
6218
6219 d->setWindowIcon_sys();
6220 d->setWindowIcon_helper();
6221
6222 emit windowIconChanged(icon);
6223}
6224
6225void QWidgetPrivate::setWindowIcon_sys()
6226{
6227 Q_Q(QWidget);
6228 if (QWindow *window = q->windowHandle())
6229 window->setIcon(q->windowIcon());
6230}
6231
6232/*!
6233 \property QWidget::windowIconText
6234 \brief the text to be displayed on the icon of a minimized window
6235
6236 This property only makes sense for windows. If no icon
6237 text has been set, this accessor returns an empty string.
6238 It is only implemented on the X11 platform, and only certain
6239 window managers use this window property.
6240
6241 \deprecated
6242 This property is deprecated.
6243
6244 \sa windowIcon, windowTitle
6245*/
6246
6247QString QWidget::windowIconText() const
6248{
6249 Q_D(const QWidget);
6250 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6251}
6252
6253/*!
6254 \property QWidget::windowFilePath
6255 \since 4.4
6256 \brief the file path associated with a widget
6257
6258 This property only makes sense for windows. It associates a file path with
6259 a window. If you set the file path, but have not set the window title, Qt
6260 sets the window title to the file name of the specified path, obtained using
6261 QFileInfo::fileName().
6262
6263 If the window title is set at any point, then the window title takes precedence and
6264 will be shown instead of the file path string.
6265
6266 Additionally, on \macos, this has an added benefit that it sets the
6267 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6268 for the window, assuming that the file path exists.
6269
6270 If no file path is set, this property contains an empty string.
6271
6272 By default, this property contains an empty string.
6273
6274 \sa windowTitle, windowIcon
6275*/
6276
6277QString QWidget::windowFilePath() const
6278{
6279 Q_D(const QWidget);
6280 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6281}
6282
6283void QWidget::setWindowFilePath(const QString &filePath)
6284{
6285 if (filePath == windowFilePath())
6286 return;
6287
6288 Q_D(QWidget);
6289
6290 d->createTLExtra();
6291 d->extra->topextra->filePath = filePath;
6292 d->setWindowFilePath_helper(filePath);
6293}
6294
6295void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6296{
6297 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6298#ifdef Q_OS_MAC
6299 setWindowTitle_helper(QFileInfo(filePath).fileName());
6300#else
6301 Q_Q(QWidget);
6302 Q_UNUSED(filePath);
6303 setWindowTitle_helper(q->windowTitle());
6304#endif
6305 }
6306#ifdef Q_OS_MAC
6307 setWindowFilePath_sys(filePath);
6308#endif
6309}
6310
6311void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6312{
6313 Q_Q(QWidget);
6314 if (!q->isWindow())
6315 return;
6316
6317 if (QWindow *window = q->windowHandle())
6318 window->setFilePath(filePath);
6319}
6320
6321/*!
6322 Returns the window's role, or an empty string.
6323
6324 \sa windowIcon, windowTitle
6325*/
6326
6327QString QWidget::windowRole() const
6328{
6329 Q_D(const QWidget);
6330 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6331}
6332
6333/*!
6334 Sets the window's role to \a role. This only makes sense for
6335 windows on X11.
6336*/
6337void QWidget::setWindowRole(const QString &role)
6338{
6339#if QT_CONFIG(xcb)
6340 Q_D(QWidget);
6341 d->createTLExtra();
6342 d->topData()->role = role;
6343 if (windowHandle()) {
6344 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6345 xcbWindow->setWindowRole(role);
6346 }
6347#else
6348 Q_UNUSED(role);
6349#endif
6350}
6351
6352/*!
6353 \property QWidget::mouseTracking
6354 \brief whether mouse tracking is enabled for the widget
6355
6356 If mouse tracking is disabled (the default), the widget only
6357 receives mouse move events when at least one mouse button is
6358 pressed while the mouse is being moved.
6359
6360 If mouse tracking is enabled, the widget receives mouse move
6361 events even if no buttons are pressed.
6362
6363 \sa mouseMoveEvent()
6364*/
6365
6366/*!
6367 \property QWidget::tabletTracking
6368 \brief whether tablet tracking is enabled for the widget
6369 \since 5.9
6370
6371 If tablet tracking is disabled (the default), the widget only
6372 receives tablet move events when the stylus is in contact with
6373 the tablet, or at least one stylus button is pressed,
6374 while the stylus is being moved.
6375
6376 If tablet tracking is enabled, the widget receives tablet move
6377 events even while hovering in proximity. This is useful for
6378 monitoring position as well as the auxiliary properties such
6379 as rotation and tilt, and providing feedback in the UI.
6380
6381 \sa tabletEvent()
6382*/
6383
6384
6385/*!
6386 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6387 function resets this widget to have no focus proxy.
6388
6389 Some widgets can "have focus", but create a child widget, such as
6390 QLineEdit, to actually handle the focus. In this case, the widget
6391 can set the line edit to be its focus proxy.
6392
6393 setFocusProxy() sets the widget which will actually get focus when
6394 "this widget" gets it. If there is a focus proxy, setFocus() and
6395 hasFocus() operate on the focus proxy. If "this widget" is the focus
6396 widget, then setFocusProxy() moves focus to the new focus proxy.
6397
6398 \sa focusProxy()
6399*/
6400
6401void QWidget::setFocusProxy(QWidget * w)
6402{
6403 Q_D(QWidget);
6404 if (!w && !d->extra)
6405 return;
6406
6407 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6408 if (Q_UNLIKELY(fp == this)) {
6409 qWarning(msg: "QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6410 return;
6411 }
6412 }
6413
6414 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6415
6416 d->createExtra();
6417 d->extra->focus_proxy = w;
6418
6419 if (w && isAncestorOf(child: w)) {
6420 // If the focus proxy is a child of this (so this is a compound widget), then
6421 // we need to make sure that this widget is immediately in front of its own children
6422 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6423 // widgets that are positioned between this compound widget, and its proxy in
6424 // the focus chain.
6425 const QWidget *parentOfW = w->parentWidget();
6426 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6427 QWidget *firstChild = nullptr;
6428 const auto childList = children();
6429 for (QObject *child : childList) {
6430 if ((firstChild = qobject_cast<QWidget *>(o: child)))
6431 break;
6432 }
6433 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6434 d->insertIntoFocusChainBefore(position: firstChild);
6435 } else if (w && w->isAncestorOf(child: this)) {
6436 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6437 // remove it from the chain and insert this into the focus chain after its parent
6438
6439 // is this the case already?
6440 QWidget *parentsNext = w->nextInFocusChain();
6441 if (parentsNext == this) {
6442 // nothing to do.
6443 Q_ASSERT(previousInFocusChain() == w);
6444 } else {
6445 d->QWidgetPrivate::insertIntoFocusChainAfter(position: w);
6446 }
6447 }
6448
6449 if (moveFocusToProxy)
6450 setFocus(Qt::OtherFocusReason);
6451}
6452
6453
6454/*!
6455 Returns the focus proxy, or \nullptr if there is no focus proxy.
6456
6457 \sa setFocusProxy()
6458*/
6459
6460QWidget *QWidget::focusProxy() const
6461{
6462 Q_D(const QWidget);
6463 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6464}
6465
6466
6467/*!
6468 \property QWidget::focus
6469 \brief whether this widget (or its focus proxy) has the keyboard
6470 input focus
6471
6472 By default, this property is \c false.
6473
6474 \note Obtaining the value of this property for a widget is effectively equivalent
6475 to checking whether QApplication::focusWidget() refers to the widget.
6476
6477 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6478*/
6479bool QWidget::hasFocus() const
6480{
6481 const QWidget* w = this;
6482 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6483 w = w->d_func()->extra->focus_proxy;
6484#if QT_CONFIG(graphicsview)
6485 if (QWidget *window = w->window()) {
6486 const auto &e = window->d_func()->extra;
6487 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6488 return true;
6489 }
6490#endif // QT_CONFIG(graphicsview)
6491 return (QApplication::focusWidget() == w);
6492}
6493
6494/*!
6495 Gives the keyboard input focus to this widget (or its focus
6496 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6497 be passed into any focus event sent from this function, it is used
6498 to give an explanation of what caused the widget to get focus.
6499 If the window is not active, the widget will be given the focus when
6500 the window becomes active.
6501
6502 First, a focus about to change event is sent to the focus widget (if any) to
6503 tell it that it is about to lose the focus. Then focus is changed, a
6504 focus out event is sent to the previous focus item and a focus in event is sent
6505 to the new item to tell it that it just received the focus.
6506 (Nothing happens if the focus in and focus out widgets are the
6507 same.)
6508
6509 \note On embedded platforms, setFocus() will not cause an input panel
6510 to be opened by the input method. If you want this to happen, you
6511 have to send a QEvent::RequestSoftwareInputPanel event to the
6512 widget yourself.
6513
6514 setFocus() gives focus to a widget regardless of its focus policy,
6515 but does not clear any keyboard grab (see grabKeyboard()).
6516
6517 Be aware that if the widget is hidden, it will not accept focus
6518 until it is shown.
6519
6520 \warning If you call setFocus() in a function which may itself be
6521 called from focusOutEvent() or focusInEvent(), you may get an
6522 infinite recursion.
6523
6524 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6525 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6526 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6527*/
6528
6529void QWidget::setFocus(Qt::FocusReason reason)
6530{
6531 if (!isEnabled())
6532 return;
6533
6534 QWidget *f = d_func()->deepestFocusProxy();
6535 if (!f)
6536 f = this;
6537
6538 if (QApplication::focusWidget() == f)
6539 return;
6540
6541#if QT_CONFIG(graphicsview)
6542 QWidget *previousProxyFocus = nullptr;
6543 if (const auto &topData = window()->d_func()->extra) {
6544 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6545 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6546 if (previousProxyFocus && previousProxyFocus->focusProxy())
6547 previousProxyFocus = previousProxyFocus->focusProxy();
6548 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6549 return;
6550 }
6551 }
6552#endif
6553
6554#if QT_CONFIG(graphicsview)
6555 // Update proxy state
6556 if (const auto &topData = window()->d_func()->extra) {
6557 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6558 f->d_func()->updateFocusChild();
6559 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6560 topData->proxyWidget->setFocus(reason);
6561 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6562 }
6563 }
6564#endif
6565
6566 if (f->isActiveWindow()) {
6567 QWidget *prev = QApplicationPrivate::focus_widget;
6568 if (prev) {
6569 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6570 && prev->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
6571 QGuiApplication::inputMethod()->commit();
6572 }
6573
6574 if (reason != Qt::NoFocusReason) {
6575 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6576 QCoreApplication::sendEvent(receiver: prev, event: &focusAboutToChange);
6577 }
6578 }
6579
6580 f->d_func()->updateFocusChild();
6581
6582 QApplicationPrivate::setFocusWidget(focus: f, reason);
6583#if QT_CONFIG(accessibility)
6584 // menus update the focus manually and this would create bogus events
6585 if (!(f->inherits(classname: "QMenuBar") || f->inherits(classname: "QMenu") || f->inherits(classname: "QMenuItem")))
6586 {
6587 QAccessibleEvent event(f, QAccessible::Focus);
6588 QAccessible::updateAccessibility(event: &event);
6589 }
6590#endif
6591#if QT_CONFIG(graphicsview)
6592 if (const auto &topData = window()->d_func()->extra) {
6593 if (topData->proxyWidget) {
6594 if (previousProxyFocus && previousProxyFocus != f) {
6595 // Send event to self
6596 QFocusEvent event(QEvent::FocusOut, reason);
6597 QPointer<QWidget> that = previousProxyFocus;
6598 QCoreApplication::sendEvent(receiver: previousProxyFocus, event: &event);
6599 if (that)
6600 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6601 }
6602 if (!isHidden()) {
6603#if QT_CONFIG(graphicsview)
6604 // Update proxy state
6605 if (const auto &topData = window()->d_func()->extra)
6606 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6607 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6608#endif
6609 // Send event to self
6610 QFocusEvent event(QEvent::FocusIn, reason);
6611 QPointer<QWidget> that = f;
6612 QCoreApplication::sendEvent(receiver: f, event: &event);
6613 if (that)
6614 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6615 }
6616 }
6617 }
6618#endif
6619 } else {
6620 f->d_func()->updateFocusChild();
6621 }
6622}
6623
6624
6625/*!\internal
6626 * A focus proxy can have its own focus proxy, which can have its own
6627 * proxy, and so on. This helper function returns the widget that sits
6628 * at the bottom of the proxy chain, and therefore the one that should
6629 * normally get focus if this widget receives a focus request.
6630 */
6631QWidget *QWidgetPrivate::deepestFocusProxy() const
6632{
6633 Q_Q(const QWidget);
6634
6635 QWidget *focusProxy = q->focusProxy();
6636 if (!focusProxy)
6637 return nullptr;
6638
6639 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6640 focusProxy = nextFocusProxy;
6641
6642 return focusProxy;
6643}
6644
6645static inline bool isEmbedded(const QWindow *w)
6646{
6647 const auto platformWindow = w->handle();
6648 return platformWindow && platformWindow->isEmbedded();
6649}
6650
6651void QWidgetPrivate::setFocus_sys()
6652{
6653 Q_Q(QWidget);
6654 // Embedded native widget may have taken the focus; get it back to toplevel
6655 // if that is the case (QTBUG-25852), unless widget is a window container.
6656 if (extra && extra->hasWindowContainer)
6657 return;
6658 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6659 // unless the application is embedded (QTBUG-71991).
6660 if (QWindow *nativeWindow = q->testAttribute(attribute: Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6661 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6662 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6663 || QCoreApplication::testAttribute(attribute: Qt::AA_PluginApplication)
6664 || isEmbedded(w: nativeWindow))) {
6665 nativeWindow->requestActivate();
6666 }
6667 }
6668}
6669
6670// updates focus_child on parent widgets to point into this widget
6671void QWidgetPrivate::updateFocusChild()
6672{
6673 Q_Q(QWidget);
6674
6675 QWidget *w = q;
6676 if (q->isHidden()) {
6677 while (w && w->isHidden()) {
6678 w->d_func()->focus_child = q;
6679 w = w->isWindow() ? nullptr : w->parentWidget();
6680 }
6681 } else {
6682 while (w) {
6683 w->d_func()->focus_child = q;
6684 w = w->isWindow() ? nullptr : w->parentWidget();
6685 }
6686 }
6687
6688 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6689 if (extra->window)
6690 emit extra->window->focusObjectChanged(object: q);
6691 }
6692}
6693
6694/*!
6695 \fn void QWidget::setFocus()
6696 \overload
6697
6698 Gives the keyboard input focus to this widget (or its focus
6699 proxy) if this widget or one of its parents is the
6700 \l{isActiveWindow()}{active window}.
6701*/
6702
6703/*!
6704 Takes keyboard input focus from the widget.
6705
6706 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6707 lost the focus.
6708
6709 This widget must enable focus setting to get the keyboard
6710 input focus; that is, it must call setFocusPolicy().
6711
6712 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6713 setFocusPolicy(), QApplication::focusWidget()
6714*/
6715
6716void QWidget::clearFocus()
6717{
6718 if (hasFocus()) {
6719 if (testAttribute(attribute: Qt::WA_InputMethodEnabled))
6720 QGuiApplication::inputMethod()->commit();
6721
6722 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6723 QCoreApplication::sendEvent(receiver: this, event: &focusAboutToChange);
6724 }
6725
6726 QTLWExtra *extra = window()->d_func()->maybeTopData();
6727 QObject *originalFocusObject = nullptr;
6728 if (extra && extra->window) {
6729 originalFocusObject = extra->window->focusObject();
6730 // the window's focus object might already be nullptr if we are in the destructor, but we still
6731 // need to update QGuiApplication and input context if we have a focus widget.
6732 if (!originalFocusObject)
6733 originalFocusObject = focusWidget();
6734 }
6735
6736 QWidget *w = this;
6737 while (w) {
6738 // Just like setFocus(), we update (clear) the focus_child of our parents
6739 if (w->d_func()->focus_child == this)
6740 w->d_func()->focus_child = nullptr;
6741 w = w->parentWidget();
6742 }
6743
6744 // We've potentially cleared the focus_child of our parents, so we need
6745 // to report this to the rest of Qt. Note that the focus_child is not the same
6746 // thing as the application's focusWidget, which is why this piece of code is
6747 // not inside a hasFocus() block.
6748 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6749 emit extra->window->focusObjectChanged(object: extra->window->focusObject());
6750
6751#if QT_CONFIG(graphicsview)
6752 const auto &topData = d_func()->extra;
6753 if (topData && topData->proxyWidget)
6754 topData->proxyWidget->clearFocus();
6755#endif
6756
6757 if (hasFocus()) {
6758 // Update proxy state
6759 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::OtherFocusReason);
6760#if QT_CONFIG(accessibility)
6761 QAccessibleEvent event(this, QAccessible::Focus);
6762 QAccessible::updateAccessibility(event: &event);
6763#endif
6764 }
6765}
6766
6767
6768/*!
6769 \fn bool QWidget::focusNextChild()
6770
6771 Finds a new widget to give the keyboard focus to, as appropriate
6772 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6773 false if it can't.
6774
6775 \sa focusPreviousChild()
6776*/
6777
6778/*!
6779 \fn bool QWidget::focusPreviousChild()
6780
6781 Finds a new widget to give the keyboard focus to, as appropriate
6782 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6783 or false if it can't.
6784
6785 \sa focusNextChild()
6786*/
6787
6788/*!
6789 Finds a new widget to give the keyboard focus to, as appropriate
6790 for Tab and Shift+Tab, and returns \c true if it can find a new
6791 widget, or false if it can't.
6792
6793 If \a next is true, this function searches forward, if \a next
6794 is false, it searches backward.
6795
6796 Sometimes, you will want to reimplement this function. For
6797 example, a web browser might reimplement it to move its "current
6798 active link" forward or backward, and call
6799 focusNextPrevChild() only when it reaches the last or
6800 first link on the "page".
6801
6802 Child widgets call focusNextPrevChild() on their parent widgets,
6803 but only the window that contains the child widgets decides where
6804 to redirect focus. By reimplementing this function for an object,
6805 you thus gain control of focus traversal for all child widgets.
6806
6807 \sa focusNextChild(), focusPreviousChild()
6808*/
6809
6810bool QWidget::focusNextPrevChild(bool next)
6811{
6812 QWidget* p = parentWidget();
6813 bool isSubWindow = (windowType() == Qt::SubWindow);
6814 if (!isWindow() && !isSubWindow && p)
6815 return p->focusNextPrevChild(next);
6816#if QT_CONFIG(graphicsview)
6817 Q_D(QWidget);
6818 if (d->extra && d->extra->proxyWidget)
6819 return d->extra->proxyWidget->focusNextPrevChild(next);
6820#endif
6821
6822 bool wrappingOccurred = false;
6823 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(toplevel: this, next,
6824 wrappingOccurred: &wrappingOccurred);
6825 if (!w) return false;
6826
6827 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6828
6829 /* If we are about to wrap the focus chain, give the platform
6830 * implementation a chance to alter the wrapping behavior. This is
6831 * especially needed when the window is embedded in a window created by
6832 * another process.
6833 */
6834 if (wrappingOccurred) {
6835 QWindow *window = windowHandle();
6836 if (window != nullptr) {
6837 QWindowPrivate *winp = qt_window_private(window);
6838
6839 if (winp->platformWindow != nullptr) {
6840 QFocusEvent event(QEvent::FocusIn, reason);
6841 event.ignore();
6842 winp->platformWindow->windowEvent(event: &event);
6843 if (event.isAccepted()) return true;
6844 }
6845 }
6846 }
6847
6848 w->setFocus(reason);
6849 return true;
6850}
6851
6852/*!
6853 Returns the last child of this widget that setFocus had been
6854 called on. For top level widgets this is the widget that will get
6855 focus in case this window gets activated
6856
6857 This is not the same as QApplication::focusWidget(), which returns
6858 the focus widget in the currently active window.
6859*/
6860
6861QWidget *QWidget::focusWidget() const
6862{
6863 return const_cast<QWidget *>(d_func()->focus_child);
6864}
6865
6866QObject *QWidgetPrivate::focusObject()
6867{
6868 Q_Q(QWidget);
6869 QWidget *proxy = deepestFocusProxy();
6870 return proxy ? proxy : q;
6871}
6872
6873/*!
6874 Returns the next widget in this widget's focus chain.
6875
6876 \sa previousInFocusChain()
6877*/
6878QWidget *QWidget::nextInFocusChain() const
6879{
6880 Q_D(const QWidget);
6881 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Next);
6882}
6883
6884/*!
6885 \brief The previousInFocusChain function returns the previous
6886 widget in this widget's focus chain.
6887
6888 \sa nextInFocusChain()
6889
6890 \since 4.6
6891*/
6892QWidget *QWidget::previousInFocusChain() const
6893{
6894 Q_D(const QWidget);
6895 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Previous);
6896}
6897
6898/*!
6899 \property QWidget::isActiveWindow
6900 \brief whether this widget's window is the active window
6901
6902 The active window is the window that contains the widget that has
6903 keyboard focus (The window may still have focus if it has no
6904 widgets or none of its widgets accepts keyboard focus).
6905
6906 When popup windows are visible, this property is \c true for both the
6907 active window \e and for the popup.
6908
6909 By default, this property is \c false.
6910
6911 \sa activateWindow(), QApplication::activeWindow()
6912*/
6913bool QWidget::isActiveWindow() const
6914{
6915 QWidget *tlw = window();
6916 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6917 return true;
6918
6919#if QT_CONFIG(graphicsview)
6920 if (const auto &tlwExtra = tlw->d_func()->extra) {
6921 if (isVisible() && tlwExtra->proxyWidget)
6922 return tlwExtra->proxyWidget->isActiveWindow();
6923 }
6924#endif
6925
6926 if (style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: this)) {
6927 if (tlw->windowType() == Qt::Tool &&
6928 !tlw->isModal() &&
6929 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6930 return true;
6931 QWidget *w = QApplication::activeWindow();
6932 while(w && tlw->windowType() == Qt::Tool &&
6933 !w->isModal() && w->parentWidget()) {
6934 w = w->parentWidget()->window();
6935 if (w == tlw)
6936 return true;
6937 }
6938 }
6939
6940 // Check for an active window container
6941 if (QWindow *ww = QGuiApplication::focusWindow()) {
6942 while (ww) {
6943 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(object: ww);
6944 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(object: qww->widget()) : 0;
6945 if (qwc && qwc->topLevelWidget() == tlw)
6946 return true;
6947 ww = ww->parent();
6948 }
6949 }
6950
6951 // Check if platform adaptation thinks the window is active. This is necessary for
6952 // example in case of ActiveQt servers that are embedded into another application.
6953 // Those are separate processes that are not part of the parent application Qt window/widget
6954 // hierarchy, so they need to rely on native methods to determine if they are part of the
6955 // active window.
6956 if (const QWindow *w = tlw->windowHandle()) {
6957 if (w->handle())
6958 return w->handle()->isActive();
6959 }
6960
6961 return false;
6962}
6963
6964/*!
6965 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6966 \overload
6967 \since 6.6
6968
6969 Sets the tab order for the widgets in the \a widgets list by calling
6970 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6971 pair of widgets.
6972
6973 Instead of setting up each pair manually like this:
6974
6975 \snippet code/src_gui_kernel_qwidget.cpp 9
6976
6977 you can call:
6978
6979 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6980
6981 The call does not create a closed tab focus loop. If there are more widgets
6982 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
6983 of those widgets, not back to \c{a}.
6984
6985 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6986*/
6987
6988/*!
6989 Puts the \a second widget after the \a first widget in the focus order.
6990
6991 It effectively removes the \a second widget from its focus chain and
6992 inserts it after the \a first widget.
6993
6994 Note that since the tab order of the \a second widget is changed, you
6995 should order a chain like this:
6996
6997 \snippet code/src_gui_kernel_qwidget.cpp 9
6998
6999 \e not like this:
7000
7001 \snippet code/src_gui_kernel_qwidget.cpp 10
7002
7003 If \a first or \a second has a focus proxy, setTabOrder()
7004 correctly substitutes the proxy.
7005
7006 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7007 a compound widget. When setting a tab order between one or two compound widgets, the
7008 local tab order inside each will be preserved. This means that if both widgets are
7009 compound widgets, the resulting tab order will be from the last child inside
7010 \a first, to the first child inside \a second.
7011
7012 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7013*/
7014void QWidget::setTabOrder(QWidget* first, QWidget *second)
7015{
7016 if (!first || !second || first == second
7017 || first->focusPolicy() == Qt::NoFocus
7018 || second->focusPolicy() == Qt::NoFocus)
7019 return;
7020
7021 if (Q_UNLIKELY(first->window() != second->window())) {
7022 qWarning(msg: "QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7023 return;
7024 }
7025
7026 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7027 {
7028 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7029 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7030 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7031 // 'lastFocusChild' will be set to the target itself.
7032 QWidget *lastFocusChild = target;
7033
7034 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7035 if (!focusProxy) {
7036 // QTBUG-81097: Another case is possible here. We can have a child
7037 // widget, that sets its focusProxy() to the parent (target).
7038 // An example of such widget is a QLineEdit, nested into
7039 // a QAbstractSpinBox. In this case such widget should be considered
7040 // the last focus child.
7041 for (auto *object : target->children()) {
7042 QWidget *w = qobject_cast<QWidget*>(o: object);
7043 if (w && w->focusProxy() == target) {
7044 lastFocusChild = w;
7045 break;
7046 }
7047 }
7048 } else if (target->isAncestorOf(child: focusProxy)) {
7049 lastFocusChild = focusProxy;
7050 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7051 focusNext != focusProxy && target->isAncestorOf(child: focusNext) && focusNext->window() == focusProxy->window();
7052 focusNext = focusNext->nextInFocusChain()) {
7053 if (focusNext == noFurtherThan)
7054 break;
7055 if (focusNext->focusPolicy() != Qt::NoFocus)
7056 lastFocusChild = focusNext;
7057 }
7058 }
7059 return lastFocusChild;
7060 };
7061 // detect inflection in case we have compound widgets
7062 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7063 if (lastFocusChildOfFirst == second)
7064 lastFocusChildOfFirst = first;
7065 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7066 if (lastFocusChildOfSecond == first)
7067 lastFocusChildOfSecond = second;
7068
7069 // Return if only NoFocus widgets are between first and second
7070 QWidget *oldPrev = second->previousInFocusChain();
7071 QWidget *prevWithFocus = oldPrev;
7072 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7073 prevWithFocus = prevWithFocus->previousInFocusChain();
7074 if (prevWithFocus == first)
7075 return;
7076 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(from: second, to: lastFocusChildOfSecond);
7077 QWidgetPrivate::insertIntoFocusChain(toBeInserted: chain, direction: QWidgetPrivate::FocusDirection::Next, position: lastFocusChildOfFirst);
7078}
7079
7080void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7081{
7082 QWidget *prev = nullptr;
7083 for (const auto &widget : widgets) {
7084 if (!prev) {
7085 prev = widget;
7086 } else {
7087 QWidget::setTabOrder(first: prev, second: widget);
7088 prev = widget;
7089 }
7090 }
7091}
7092
7093
7094/*!\internal
7095
7096 Moves the relevant subwidgets of this widget from the \a oldtlw's
7097 tab chain to that of the new parent, if there's anything to move and
7098 we're really moving
7099
7100 This function is called from QWidget::reparent() *after* the widget
7101 has been reparented.
7102
7103 \sa reparent()
7104*/
7105
7106void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7107{
7108 Q_Q(QWidget);
7109 if (oldtlw == q->window())
7110 return; // nothing to do
7111
7112 if (focus_child)
7113 focus_child->clearFocus();
7114
7115 reparentFocusChildren(direction: QWidgetPrivate::FocusDirection::Next);
7116}
7117
7118/*!
7119 \property QWidget::frameSize
7120 \brief the size of the widget including any window frame
7121
7122 By default, this property contains a value that depends on the user's
7123 platform and screen geometry.
7124*/
7125QSize QWidget::frameSize() const
7126{
7127 Q_D(const QWidget);
7128 if (isWindow() && !(windowType() == Qt::Popup)) {
7129 QRect fs = d->frameStrut();
7130 return QSize(data->crect.width() + fs.left() + fs.right(),
7131 data->crect.height() + fs.top() + fs.bottom());
7132 }
7133 return data->crect.size();
7134}
7135
7136/*! \fn void QWidget::move(int x, int y)
7137
7138 \overload
7139
7140 This corresponds to move(QPoint(\a x, \a y)).
7141*/
7142
7143void QWidget::move(const QPoint &p)
7144{
7145 Q_D(QWidget);
7146 setAttribute(Qt::WA_Moved);
7147 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7148 if (isWindow())
7149 d->topData()->posIncludesFrame = false;
7150 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7151 p.y() + geometry().y() - QWidget::y(),
7152 width(), height(), true);
7153 d->setDirtyOpaqueRegion();
7154 } else {
7155 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7156 if (isWindow())
7157 d->topData()->posIncludesFrame = true;
7158 data->crect.moveTopLeft(p); // no frame yet
7159 setAttribute(Qt::WA_PendingMoveEvent);
7160 }
7161
7162 if (d->extra && d->extra->hasWindowContainer)
7163 QWindowContainer::parentWasMoved(parent: this);
7164}
7165
7166// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7167// unknown), that is, crect has a position including the frame.
7168// If we can determine the frame strut, fix that and clear the flag.
7169// FIXME: This does not play well with window states other than
7170// Qt::WindowNoState, as we depend on calling setGeometry() on the
7171// platform window after fixing up the position so that the new
7172// geometry is reflected in the platform window, but when the frame
7173// comes in after the window has been shown (e.g. maximized), we're
7174// not in a position to do that kind of fixup.
7175void QWidgetPrivate::fixPosIncludesFrame()
7176{
7177 Q_Q(QWidget);
7178 if (QTLWExtra *te = maybeTopData()) {
7179 if (te->posIncludesFrame) {
7180 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7181 // example, in QGraphicsProxyWidget).
7182 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
7183 te->posIncludesFrame = 0;
7184 } else {
7185 if (q->windowHandle() && q->windowHandle()->handle()) {
7186 updateFrameStrut();
7187 if (!q->data->fstrut_dirty) {
7188 data.crect.translate(dx: te->frameStrut.x(), dy: te->frameStrut.y());
7189 te->posIncludesFrame = 0;
7190 }
7191 } // windowHandle()
7192 } // !WA_DontShowOnScreen
7193 } // posIncludesFrame
7194 } // QTLWExtra
7195}
7196
7197/*! \fn void QWidget::resize(int w, int h)
7198 \overload
7199
7200 This corresponds to resize(QSize(\a w, \a h)).
7201*/
7202
7203void QWidget::resize(const QSize &s)
7204{
7205 Q_D(QWidget);
7206 setAttribute(Qt::WA_Resized);
7207 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7208 d->fixPosIncludesFrame();
7209 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7210 d->setDirtyOpaqueRegion();
7211 } else {
7212 const auto oldRect = data->crect;
7213 data->crect.setSize(s.boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7214 if (oldRect != data->crect)
7215 setAttribute(Qt::WA_PendingResizeEvent);
7216 }
7217}
7218
7219void QWidget::setGeometry(const QRect &r)
7220{
7221 Q_D(QWidget);
7222 setAttribute(Qt::WA_Resized);
7223 setAttribute(Qt::WA_Moved);
7224 if (isWindow())
7225 d->topData()->posIncludesFrame = 0;
7226 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7227 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7228 d->setDirtyOpaqueRegion();
7229 } else {
7230 const auto oldRect = data->crect;
7231 data->crect.setTopLeft(r.topLeft());
7232 data->crect.setSize(r.size().boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7233 if (oldRect != data->crect) {
7234 setAttribute(Qt::WA_PendingMoveEvent);
7235 setAttribute(Qt::WA_PendingResizeEvent);
7236 }
7237 }
7238
7239 if (d->extra && d->extra->hasWindowContainer)
7240 QWindowContainer::parentWasMoved(parent: this);
7241}
7242
7243void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7244{
7245 Q_Q(QWidget);
7246 if (extra) { // any size restrictions?
7247 w = qMin(a: w,b: extra->maxw);
7248 h = qMin(a: h,b: extra->maxh);
7249 w = qMax(a: w,b: extra->minw);
7250 h = qMax(a: h,b: extra->minh);
7251 }
7252
7253 if (q->isWindow() && q->windowHandle()) {
7254 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7255 if (!integration->hasCapability(cap: QPlatformIntegration::NonFullScreenWindows)) {
7256 x = 0;
7257 y = 0;
7258 w = q->windowHandle()->width();
7259 h = q->windowHandle()->height();
7260 }
7261 }
7262
7263 QPoint oldp = q->geometry().topLeft();
7264 QSize olds = q->size();
7265 QRect r(x, y, w, h);
7266
7267 bool isResize = olds != r.size();
7268 if (!isMove)
7269 isMove = oldp != r.topLeft();
7270
7271
7272 // We only care about stuff that changes the geometry, or may
7273 // cause the window manager to change its state
7274 if (r.size() == olds && oldp == r.topLeft())
7275 return;
7276
7277 if (!data.in_set_window_state) {
7278 q->data->window_state &= ~Qt::WindowMaximized;
7279 q->data->window_state &= ~Qt::WindowFullScreen;
7280 if (q->isWindow())
7281 topData()->normalGeometry = QRect(0, 0, -1, -1);
7282 }
7283
7284 QPoint oldPos = q->pos();
7285 data.crect = r;
7286
7287 bool needsShow = false;
7288
7289 if (q->isWindow() || q->windowHandle()) {
7290 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7291 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
7292 if (q->isVisible())
7293 hide_sys();
7294 data.crect = QRect(x, y, w, h);
7295 } else if (q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7296 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
7297 needsShow = true;
7298 }
7299 }
7300
7301 if (q->isVisible()) {
7302 if (!q->testAttribute(attribute: Qt::WA_DontShowOnScreen) && !q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7303 if (QWindow *win = q->windowHandle()) {
7304 if (q->isWindow()) {
7305 if (isResize && !isMove)
7306 win->resize(w, h);
7307 else if (isMove && !isResize)
7308 win->setPosition(posx: x, posy: y);
7309 else
7310 win->setGeometry(q->geometry());
7311 } else {
7312 QPoint posInNativeParent = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
7313 win->setGeometry(QRect(posInNativeParent,r.size()));
7314 }
7315
7316 if (needsShow)
7317 show_sys();
7318 }
7319
7320 if (!q->isWindow()) {
7321 if (renderToTexture) {
7322 QRegion updateRegion(q->geometry());
7323 updateRegion += QRect(oldPos, olds);
7324 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7325 } else if (isMove && !isResize) {
7326 moveRect(QRect(oldPos, olds), dx: x - oldPos.x(), dy: y - oldPos.y());
7327 } else {
7328 invalidateBackingStore_resizeHelper(oldPos, oldSize: olds);
7329 }
7330 }
7331 }
7332
7333 if (isMove) {
7334 QMoveEvent e(q->pos(), oldPos);
7335 QCoreApplication::sendEvent(receiver: q, event: &e);
7336 }
7337 if (isResize) {
7338 QResizeEvent e(r.size(), olds);
7339 QCoreApplication::sendEvent(receiver: q, event: &e);
7340 if (q->windowHandle())
7341 q->update();
7342 }
7343 } else { // not visible
7344 if (isMove && q->pos() != oldPos)
7345 q->setAttribute(Qt::WA_PendingMoveEvent, on: true);
7346 if (isResize)
7347 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7348 }
7349
7350}
7351
7352/*!
7353 \since 4.2
7354 Saves the current geometry and state for top-level widgets.
7355
7356 To save the geometry when the window closes, you can
7357 implement a close event like this:
7358
7359 \snippet code/src_gui_kernel_qwidget.cpp 11
7360
7361 See the \l{Window Geometry} documentation for an overview of geometry
7362 issues with windows.
7363
7364 Use QMainWindow::saveState() to save the geometry and the state of
7365 toolbars and dock widgets.
7366
7367 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7368*/
7369QByteArray QWidget::saveGeometry() const
7370{
7371 QByteArray array;
7372 QDataStream stream(&array, QIODevice::WriteOnly);
7373 stream.setVersion(QDataStream::Qt_4_0);
7374 const quint32 magicNumber = 0x1D9D0CB;
7375 // Version history:
7376 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7377 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7378 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7379 quint16 majorVersion = 3;
7380 quint16 minorVersion = 0;
7381 const int screenNumber = QGuiApplication::screens().indexOf(t: screen());
7382 stream << magicNumber
7383 << majorVersion
7384 << minorVersion
7385 << frameGeometry()
7386 << normalGeometry()
7387 << qint32(screenNumber)
7388 << quint8(windowState() & Qt::WindowMaximized)
7389 << quint8(windowState() & Qt::WindowFullScreen)
7390 << qint32(screen()->geometry().width()) // added in 2.0
7391 << geometry(); // added in 3.0
7392 return array;
7393}
7394
7395/*!
7396 \internal
7397
7398 Check a if \a restoredGeometry fits into \a availableGeometry
7399 This method is used to verify that a widget is restored to a geometry, which
7400 fits into the target screen.
7401
7402 \param frameHeight represents the height of the widget's title bar, which is expected
7403 to be on its top.
7404
7405 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7406 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7407 be full screen.
7408
7409 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7410 \a restoredGeometry will be moved
7411 \list
7412 \li down if its top is off screen
7413 \li up if its bottom is off screen
7414 \li right if its left edge is off screen
7415 \li left if its right edge is off screen
7416 \endlist
7417 */
7418void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7419 int frameHeight)
7420{
7421 // compare with restored geometry's height increased by frameHeight
7422 const int height = restoredGeometry->height() + frameHeight;
7423
7424 // Step 1: Resize if necessary:
7425 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7426 if (availableGeometry.height() <= height)
7427 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7428 if (availableGeometry.width() <= restoredGeometry->width())
7429 restoredGeometry->setWidth(availableGeometry.width() - 2);
7430
7431 // Step 2: Move if necessary:
7432 // Construct a rectangle from restored Geometry adjusted by frameHeight
7433 const QRect restored = restoredGeometry->adjusted(xp1: 0, yp1: -frameHeight, xp2: 0, yp2: 0);
7434
7435 // Return if restoredGeometry (including frame) fits into screen
7436 if (availableGeometry.contains(r: restored))
7437 return;
7438
7439 // (size is correct, but at least one edge is off screen)
7440
7441 // Top out of bounds => move down
7442 if (restored.top() <= availableGeometry.top()) {
7443 restoredGeometry->moveTop(pos: availableGeometry.top() + 1 + frameHeight);
7444 } else if (restored.bottom() >= availableGeometry.bottom()) {
7445 // Bottom out of bounds => move up
7446 restoredGeometry->moveBottom(pos: availableGeometry.bottom() - 1);
7447 }
7448
7449 // Left edge out of bounds => move right
7450 if (restored.left() <= availableGeometry.left()) {
7451 restoredGeometry->moveLeft(pos: availableGeometry.left() + 1);
7452 } else if (restored.right() >= availableGeometry.right()) {
7453 // Right edge out of bounds => move left
7454 restoredGeometry->moveRight(pos: availableGeometry.right() - 1);
7455 }
7456}
7457
7458/*!
7459 \since 4.2
7460
7461 Restores the geometry and state of top-level widgets stored in the
7462 byte array \a geometry. Returns \c true on success; otherwise
7463 returns \c false.
7464
7465 If the restored geometry is off-screen, it will be modified to be
7466 inside the available screen geometry.
7467
7468 To restore geometry saved using QSettings, you can use code like
7469 this:
7470
7471 \snippet code/src_gui_kernel_qwidget.cpp 12
7472
7473 See the \l{Window Geometry} documentation for an overview of geometry
7474 issues with windows.
7475
7476 Use QMainWindow::restoreState() to restore the geometry and the
7477 state of toolbars and dock widgets.
7478
7479 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7480*/
7481bool QWidget::restoreGeometry(const QByteArray &geometry)
7482{
7483 if (geometry.size() < 4)
7484 return false;
7485 QDataStream stream(geometry);
7486 stream.setVersion(QDataStream::Qt_4_0);
7487
7488 const quint32 magicNumber = 0x1D9D0CB;
7489 quint32 storedMagicNumber;
7490 stream >> storedMagicNumber;
7491 if (storedMagicNumber != magicNumber)
7492 return false;
7493
7494 const quint16 currentMajorVersion = 3;
7495 quint16 majorVersion = 0;
7496 quint16 minorVersion = 0;
7497
7498 stream >> majorVersion >> minorVersion;
7499
7500 if (majorVersion > currentMajorVersion)
7501 return false;
7502 // (Allow all minor versions.)
7503
7504 QRect restoredFrameGeometry;
7505 QRect restoredGeometry;
7506 QRect restoredNormalGeometry;
7507 qint32 restoredScreenNumber;
7508 quint8 maximized;
7509 quint8 fullScreen;
7510 qint32 restoredScreenWidth = 0;
7511
7512 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7513 >> restoredNormalGeometry
7514 >> restoredScreenNumber
7515 >> maximized
7516 >> fullScreen;
7517
7518 if (majorVersion > 1)
7519 stream >> restoredScreenWidth;
7520 if (majorVersion > 2)
7521 stream >> restoredGeometry;
7522
7523 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7524
7525 if (restoredScreenNumber >= qMax(a: QGuiApplication::screens().size(), b: 1))
7526 restoredScreenNumber = 0;
7527 const QScreen *restoredScreen = QGuiApplication::screens().value(i: restoredScreenNumber, defaultValue: nullptr);
7528 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7529 // Sanity check bailing out when large variations of screen sizes occur due to
7530 // high DPI scaling or different levels of DPI awareness.
7531 if (restoredScreenWidth) {
7532 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7533 if (factor < 0.8 || factor > 1.25)
7534 return false;
7535 } else {
7536 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7537 // unless the size will be adapted by maximized or fullscreen.
7538 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7539 return false;
7540 }
7541
7542 const int frameHeight = QApplication::style()
7543 ? QApplication::style()->pixelMetric(metric: QStyle::PM_TitleBarHeight, option: nullptr, widget: this)
7544 : 20;
7545
7546 if (!restoredNormalGeometry.isValid())
7547 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7548 if (!restoredNormalGeometry.isValid()) {
7549 // use the widget's adjustedSize if the sizeHint() doesn't help
7550 restoredNormalGeometry.setSize(restoredNormalGeometry
7551 .size()
7552 .expandedTo(otherSize: d_func()->adjustedSize()));
7553 }
7554
7555 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7556 : QRect();
7557
7558 // Modify the restored geometry if we are about to restore to coordinates
7559 // that would make the window "lost". This happens if:
7560 // - The restored geometry is completely or partly oustside the available geometry
7561 // - The title bar is outside the available geometry.
7562
7563 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredGeometry, frameHeight);
7564 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredNormalGeometry, frameHeight);
7565
7566 if (maximized || fullScreen) {
7567 // set geometry before setting the window state to make
7568 // sure the window is maximized to the right screen.
7569 Qt::WindowStates ws = windowState();
7570#ifndef Q_OS_WIN
7571 setGeometry(restoredNormalGeometry);
7572#else
7573 if (ws & Qt::WindowFullScreen) {
7574 // Full screen is not a real window state on Windows.
7575 move(availableGeometry.topLeft());
7576 } else if (ws & Qt::WindowMaximized) {
7577 // Setting a geometry on an already maximized window causes this to be
7578 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7579 // Move the window in normal state if needed.
7580 if (restoredScreen != screen()) {
7581 setWindowState(Qt::WindowNoState);
7582 setGeometry(restoredNormalGeometry);
7583 }
7584 } else {
7585 setGeometry(restoredNormalGeometry);
7586 }
7587#endif // Q_OS_WIN
7588 if (maximized)
7589 ws |= Qt::WindowMaximized;
7590 if (fullScreen)
7591 ws |= Qt::WindowFullScreen;
7592 setWindowState(ws);
7593 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7594 } else {
7595 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7596
7597 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7598 if (majorVersion > 2)
7599 setGeometry(restoredGeometry);
7600 else
7601 setGeometry(restoredNormalGeometry);
7602 }
7603 return true;
7604}
7605
7606/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7607 \overload
7608
7609 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7610*/
7611
7612/*!
7613 Sets the margins around the contents of the widget to have the sizes
7614 \a left, \a top, \a right, and \a bottom. The margins are used by
7615 the layout system, and may be used by subclasses to specify the area
7616 to draw in (e.g. excluding the frame).
7617
7618 Changing the margins will trigger a resizeEvent().
7619
7620 \sa contentsRect(), contentsMargins()
7621*/
7622void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7623{
7624 Q_D(QWidget);
7625 if (left == d->leftmargin && top == d->topmargin
7626 && right == d->rightmargin && bottom == d->bottommargin)
7627 return;
7628 d->leftmargin = left;
7629 d->topmargin = top;
7630 d->rightmargin = right;
7631 d->bottommargin = bottom;
7632
7633 d->updateContentsRect();
7634}
7635
7636/*!
7637 \overload
7638 \since 4.6
7639
7640 \brief The setContentsMargins function sets the margins around the
7641 widget's contents.
7642
7643 Sets the margins around the contents of the widget to have the
7644 sizes determined by \a margins. The margins are
7645 used by the layout system, and may be used by subclasses to
7646 specify the area to draw in (e.g. excluding the frame).
7647
7648 Changing the margins will trigger a resizeEvent().
7649
7650 \sa contentsRect(), contentsMargins()
7651*/
7652void QWidget::setContentsMargins(const QMargins &margins)
7653{
7654 setContentsMargins(left: margins.left(), top: margins.top(),
7655 right: margins.right(), bottom: margins.bottom());
7656}
7657
7658void QWidgetPrivate::updateContentsRect()
7659{
7660 Q_Q(QWidget);
7661
7662 if (layout)
7663 layout->update(); //force activate; will do updateGeometry
7664 else
7665 q->updateGeometry();
7666
7667 if (q->isVisible()) {
7668 q->update();
7669 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7670 QCoreApplication::sendEvent(receiver: q, event: &e);
7671 } else {
7672 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7673 }
7674
7675 QEvent e(QEvent::ContentsRectChange);
7676 QCoreApplication::sendEvent(receiver: q, event: &e);
7677}
7678
7679/*!
7680 \since 4.6
7681
7682 \brief The contentsMargins function returns the widget's contents margins.
7683
7684 \sa setContentsMargins(), contentsRect()
7685 */
7686QMargins QWidget::contentsMargins() const
7687{
7688 Q_D(const QWidget);
7689 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7690 return testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea) ?
7691 userMargins | d->safeAreaMargins() : userMargins;
7692}
7693
7694/*!
7695 Returns the area inside the widget's margins.
7696
7697 \sa setContentsMargins(), contentsMargins()
7698*/
7699QRect QWidget::contentsRect() const
7700{
7701 return rect() - contentsMargins();
7702}
7703
7704QMargins QWidgetPrivate::safeAreaMargins() const
7705{
7706 Q_Q(const QWidget);
7707 QWidget *nativeWidget = q->window();
7708 if (!nativeWidget->windowHandle())
7709 return QMargins();
7710
7711 QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7712 if (!platformWindow)
7713 return QMargins();
7714
7715 QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7716
7717 if (!q->isWindow()) {
7718 // In theory the native parent widget already has a contents rect reflecting
7719 // the safe area of that widget, but we can't be sure that the widget or child
7720 // widgets of that widget have respected the contents rect when setting their
7721 // geometry, so we need to manually compute the safe area.
7722
7723 // Unless the native widget doesn't have any margins, in which case there's
7724 // nothing for us to compute.
7725 if (safeAreaMargins.isNull())
7726 return QMargins();
7727
7728 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7729 // set, and the widget respects the safe area, then we know that the layout has already
7730 // taken care of placing us inside the safe area, by taking the contents rect of its
7731 // parent widget into account.
7732 const QWidget *assumedSafeWidget = nullptr;
7733 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7734 QWidget *parentWidget = w->parentWidget();
7735 if (!parentWidget->testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea))
7736 continue; // Layout can't help us
7737
7738 if (parentWidget->testAttribute(attribute: Qt::WA_LayoutOnEntireRect))
7739 continue; // Layout not going to help us
7740
7741 QLayout *layout = parentWidget->layout();
7742 if (!layout)
7743 continue;
7744
7745 if (layout->geometry().isNull())
7746 continue; // Layout hasn't been activated yet
7747
7748 if (layout->indexOf(w) < 0)
7749 continue; // Widget is not in layout
7750
7751 assumedSafeWidget = w;
7752 break;
7753 }
7754
7755#if !defined(QT_DEBUG)
7756 if (assumedSafeWidget) {
7757 // We found a layout that we assume will take care of keeping us within the safe area
7758 // For debug builds we still map the safe area using the fallback logic, so that we
7759 // can detect any misbehaving layouts.
7760 return QMargins();
7761 }
7762#endif
7763
7764 // In all other cases we need to map the safe area of the native parent to the widget.
7765 // This depends on the widget being positioned and sized already, which means the initial
7766 // layout will be wrong, but the layout will then adjust itself.
7767 QPoint topLeftMargins = q->mapFrom(parent: nativeWidget, pos: QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7768 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7769 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(parent: nativeWidget,
7770 pos: nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7771
7772 // Margins should never be negative
7773 safeAreaMargins = QMargins(qMax(a: 0, b: topLeftMargins.x()), qMax(a: 0, b: topLeftMargins.y()),
7774 qMax(a: 0, b: bottomRightMargins.x()), qMax(a: 0, b: bottomRightMargins.y()));
7775
7776 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7777 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7778 qWarning() << layout << "is laying out" << assumedSafeWidget
7779 << "outside of the contents rect of" << layout->parentWidget();
7780 return QMargins(); // Return empty margin to visually highlight the error
7781 }
7782 }
7783
7784 return safeAreaMargins;
7785}
7786
7787/*!
7788 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7789
7790 This signal is emitted when the widget's \l contextMenuPolicy is
7791 Qt::CustomContextMenu, and the user has requested a context menu on
7792 the widget. The position \a pos is the position of the context menu
7793 event that the widget receives. Normally this is in widget
7794 coordinates. The exception to this rule is QAbstractScrollArea and
7795 its subclasses that map the context menu event to coordinates of the
7796 \l{QAbstractScrollArea::viewport()}{viewport()}.
7797
7798
7799 \sa mapToGlobal(), QMenu, contextMenuPolicy
7800*/
7801
7802
7803/*!
7804 \property QWidget::contextMenuPolicy
7805 \brief how the widget shows a context menu
7806
7807 The default value of this property is Qt::DefaultContextMenu,
7808 which means the contextMenuEvent() handler is called. Other values
7809 are Qt::NoContextMenu, Qt::PreventContextMenu,
7810 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7811 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7812 emitted.
7813
7814 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7815*/
7816
7817Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7818{
7819 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7820}
7821
7822void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7823{
7824 data->context_menu_policy = (uint) policy;
7825}
7826
7827/*!
7828 \property QWidget::focusPolicy
7829 \brief the way the widget accepts keyboard focus
7830
7831 The policy is Qt::TabFocus if the widget accepts keyboard
7832 focus by tabbing, Qt::ClickFocus if the widget accepts
7833 focus by clicking, Qt::StrongFocus if it accepts both, and
7834 Qt::NoFocus (the default) if it does not accept focus at
7835 all.
7836
7837 You must enable keyboard focus for a widget if it processes
7838 keyboard events. This is normally done from the widget's
7839 constructor. For instance, the QLineEdit constructor calls
7840 setFocusPolicy(Qt::StrongFocus).
7841
7842 If the widget has a focus proxy, then the focus policy will
7843 be propagated to it.
7844
7845 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7846*/
7847
7848
7849Qt::FocusPolicy QWidget::focusPolicy() const
7850{
7851 return (Qt::FocusPolicy)data->focus_policy;
7852}
7853
7854void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7855{
7856 data->focus_policy = (uint) policy;
7857 Q_D(QWidget);
7858 if (d->extra && d->extra->focus_proxy)
7859 d->extra->focus_proxy->setFocusPolicy(policy);
7860}
7861
7862/*!
7863 \property QWidget::updatesEnabled
7864 \brief whether updates are enabled
7865
7866 An updates enabled widget receives paint events and has a system
7867 background; a disabled widget does not. This also implies that
7868 calling update() and repaint() has no effect if updates are
7869 disabled.
7870
7871 By default, this property is \c true.
7872
7873 setUpdatesEnabled() is normally used to disable updates for a
7874 short period of time, for instance to avoid screen flicker during
7875 large changes. In Qt, widgets normally do not generate screen
7876 flicker, but on X11 the server might erase regions on the screen
7877 when widgets get hidden before they can be replaced by other
7878 widgets. Disabling updates solves this.
7879
7880 Example:
7881 \snippet code/src_gui_kernel_qwidget.cpp 13
7882
7883 Disabling a widget implicitly disables all its children. Enabling a widget
7884 enables all child widgets \e except top-level widgets or those that
7885 have been explicitly disabled. Re-enabling updates implicitly calls
7886 update() on the widget.
7887
7888 \sa paintEvent()
7889*/
7890void QWidget::setUpdatesEnabled(bool enable)
7891{
7892 Q_D(QWidget);
7893 setAttribute(Qt::WA_ForceUpdatesDisabled, on: !enable);
7894 d->setUpdatesEnabled_helper(enable);
7895}
7896
7897/*!
7898 Shows the widget and its child widgets.
7899
7900 For child windows, this is equivalent to calling setVisible(true).
7901 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7902 or setVisible(true), depending on the platform's default behavior for the window flags.
7903
7904 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7905 showNormal(), isVisible(), windowFlags()
7906*/
7907void QWidget::show()
7908{
7909 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7910
7911 if (!isWindow()) {
7912 setVisible(true);
7913 } else {
7914 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7915 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7916 if (defaultState == Qt::WindowFullScreen)
7917 showFullScreen();
7918 else if (defaultState == Qt::WindowMaximized)
7919 showMaximized();
7920 else
7921 setVisible(true);
7922 }
7923}
7924
7925/*! \internal
7926
7927 Makes the widget visible in the isVisible() meaning of the word.
7928 It is only called for toplevels or widgets with visible parents.
7929 */
7930void QWidgetPrivate::show_recursive()
7931{
7932 Q_Q(QWidget);
7933 // polish if necessary
7934
7935 if (!q->testAttribute(attribute: Qt::WA_WState_Created))
7936 createRecursively();
7937 q->ensurePolished();
7938
7939 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7940 q->parentWidget()->d_func()->layout->activate();
7941 // activate our layout before we and our children become visible
7942 if (layout)
7943 layout->activate();
7944
7945 show_helper();
7946}
7947
7948void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7949{
7950 Q_Q(QWidget);
7951
7952 disableUpdates = disableUpdates && q->updatesEnabled();
7953 if (disableUpdates)
7954 q->setAttribute(Qt::WA_UpdatesDisabled);
7955
7956 if (q->testAttribute(attribute: Qt::WA_PendingMoveEvent)) {
7957 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7958 QCoreApplication::sendEvent(receiver: q, event: &e);
7959 q->setAttribute(Qt::WA_PendingMoveEvent, on: false);
7960 }
7961
7962 if (q->testAttribute(attribute: Qt::WA_PendingResizeEvent)) {
7963 QResizeEvent e(data.crect.size(), QSize());
7964 QCoreApplication::sendEvent(receiver: q, event: &e);
7965 q->setAttribute(Qt::WA_PendingResizeEvent, on: false);
7966 }
7967
7968 if (disableUpdates)
7969 q->setAttribute(Qt::WA_UpdatesDisabled, on: false);
7970
7971 if (!recursive)
7972 return;
7973
7974 for (int i = 0; i < children.size(); ++i) {
7975 if (QWidget *child = qobject_cast<QWidget *>(o: children.at(i)))
7976 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7977 }
7978}
7979
7980void QWidgetPrivate::activateChildLayoutsRecursively()
7981{
7982 sendPendingMoveAndResizeEvents(recursive: false, disableUpdates: true);
7983
7984 for (int i = 0; i < children.size(); ++i) {
7985 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
7986 if (!child || child->isHidden() || child->isWindow())
7987 continue;
7988
7989 child->ensurePolished();
7990
7991 // Activate child's layout
7992 QWidgetPrivate *childPrivate = child->d_func();
7993 if (childPrivate->layout)
7994 childPrivate->layout->activate();
7995
7996 // Pretend we're visible.
7997 const bool wasVisible = child->isVisible();
7998 if (!wasVisible)
7999 child->setAttribute(Qt::WA_WState_Visible);
8000
8001 // Do the same for all my children.
8002 childPrivate->activateChildLayoutsRecursively();
8003
8004 // We're not cheating anymore.
8005 if (!wasVisible)
8006 child->setAttribute(Qt::WA_WState_Visible, on: false);
8007 }
8008}
8009
8010void QWidgetPrivate::show_helper()
8011{
8012 Q_Q(QWidget);
8013 data.in_show = true; // qws optimization
8014 // make sure we receive pending move and resize events
8015 sendPendingMoveAndResizeEvents();
8016
8017 // become visible before showing all children
8018 q->setAttribute(Qt::WA_WState_Visible);
8019
8020 // finally show all children recursively
8021 showChildren(spontaneous: false);
8022
8023
8024
8025 const bool isWindow = q->isWindow();
8026#if QT_CONFIG(graphicsview)
8027 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8028#else
8029 bool isEmbedded = false;
8030#endif
8031
8032 // popup handling: new popups and tools need to be raised, and
8033 // existing popups must be closed. Also propagate the current
8034 // windows's KeyboardFocusChange status.
8035 if (isWindow && !isEmbedded) {
8036 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8037 q->raise();
8038 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(attribute: Qt::WA_KeyboardFocusChange))
8039 q->setAttribute(Qt::WA_KeyboardFocusChange);
8040 } else {
8041 while (QApplication::activePopupWidget()) {
8042 if (!QApplication::activePopupWidget()->close())
8043 break;
8044 }
8045 }
8046 }
8047
8048 // Automatic embedding of child windows of widgets already embedded into
8049 // QGraphicsProxyWidget when they are shown the first time.
8050#if QT_CONFIG(graphicsview)
8051 if (isWindow) {
8052 if (!isEmbedded && !bypassGraphicsProxyWidget(p: q)) {
8053 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(origin: q->parentWidget());
8054 if (ancestorProxy) {
8055 isEmbedded = true;
8056 ancestorProxy->d_func()->embedSubWindow(q);
8057 }
8058 }
8059 }
8060#else
8061 Q_UNUSED(isEmbedded);
8062#endif
8063
8064 // send the show event before showing the window
8065 QShowEvent showEvent;
8066 QCoreApplication::sendEvent(receiver: q, event: &showEvent);
8067
8068 show_sys();
8069
8070 if (!isEmbedded && q->windowType() == Qt::Popup)
8071 qApp->d_func()->openPopup(popup: q);
8072
8073#if QT_CONFIG(accessibility)
8074 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8075 QAccessibleEvent event(q, QAccessible::ObjectShow);
8076 QAccessible::updateAccessibility(event: &event);
8077 }
8078#endif
8079
8080 if (QApplicationPrivate::hidden_focus_widget == q) {
8081 QApplicationPrivate::hidden_focus_widget = nullptr;
8082 q->setFocus(Qt::OtherFocusReason);
8083 }
8084
8085 // Process events when showing a Qt::SplashScreen widget before the event loop
8086 // is spinnning; otherwise it might not show up on particular platforms.
8087 // This makes QSplashScreen behave the same on all platforms.
8088 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8089 QCoreApplication::processEvents();
8090
8091 data.in_show = false; // reset qws optimization
8092}
8093
8094void QWidgetPrivate::show_sys()
8095{
8096 Q_Q(QWidget);
8097
8098 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8099
8100 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8101 invalidateBackingStore(q->rect());
8102 q->setAttribute(Qt::WA_Mapped);
8103 // add our window the modal window list (native dialogs)
8104 if (window && q->isWindow()
8105#if QT_CONFIG(graphicsview)
8106 && (!extra || !extra->proxyWidget)
8107#endif
8108 && q->windowModality() != Qt::NonModal) {
8109 QGuiApplicationPrivate::showModalWindow(window);
8110 }
8111 return;
8112 }
8113
8114 if (renderToTexture && !q->isWindow())
8115 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QUpdateLaterEvent(q->geometry()));
8116 else
8117 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(q->rect()));
8118
8119 if ((!q->isWindow() && !q->testAttribute(attribute: Qt::WA_NativeWindow))
8120 || q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
8121 return;
8122 }
8123
8124 if (window) {
8125 if (q->isWindow())
8126 fixPosIncludesFrame();
8127 QRect geomRect = q->geometry();
8128 if (!q->isWindow()) {
8129 QPoint topLeftOfWindow = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
8130 geomRect.moveTopLeft(p: topLeftOfWindow);
8131 }
8132 const QRect windowRect = window->geometry();
8133 if (windowRect != geomRect) {
8134 if (q->testAttribute(attribute: Qt::WA_Moved)
8135 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
8136 window->setGeometry(geomRect);
8137 else
8138 window->resize(newSize: geomRect.size());
8139 }
8140
8141#ifndef QT_NO_CURSOR
8142 qt_qpa_set_cursor(w: q, force: false); // Needed in case cursor was set before show
8143#endif
8144 invalidateBackingStore(q->rect());
8145 window->setNativeWindowVisibility(true);
8146 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8147 if (window->isTopLevel()) {
8148 const QPoint crectTopLeft = q->data->crect.topLeft();
8149 const QPoint windowTopLeft = window->geometry().topLeft();
8150 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8151 q->data->crect.moveTopLeft(p: windowTopLeft);
8152 }
8153 }
8154}
8155
8156/*!
8157 Hides the widget. This function is equivalent to
8158 setVisible(false).
8159
8160
8161 \note If you are working with QDialog or its subclasses and you invoke
8162 the show() function after this function, the dialog will be displayed in
8163 its original position.
8164
8165 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8166*/
8167void QWidget::hide()
8168{
8169 setVisible(false);
8170}
8171
8172/*!\internal
8173 */
8174void QWidgetPrivate::hide_helper()
8175{
8176 Q_Q(QWidget);
8177
8178 bool isEmbedded = false;
8179#if QT_CONFIG(graphicsview)
8180 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(p: q) && nearestGraphicsProxyWidget(origin: q->parentWidget()) != nullptr;
8181#else
8182 Q_UNUSED(isEmbedded);
8183#endif
8184
8185 if (!isEmbedded && (q->windowType() == Qt::Popup))
8186 qApp->d_func()->closePopup(popup: q);
8187
8188 q->setAttribute(Qt::WA_Mapped, on: false);
8189 hide_sys();
8190
8191 bool wasVisible = q->testAttribute(attribute: Qt::WA_WState_Visible);
8192
8193 if (wasVisible) {
8194 q->setAttribute(Qt::WA_WState_Visible, on: false);
8195
8196 }
8197
8198 QHideEvent hideEvent;
8199 QCoreApplication::sendEvent(receiver: q, event: &hideEvent);
8200 hideChildren(spontaneous: false);
8201
8202 // next bit tries to move the focus if the focus widget is now
8203 // hidden.
8204 if (wasVisible) {
8205 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8206 QWidget *fw = QApplication::focusWidget();
8207 while (fw && !fw->isWindow()) {
8208 if (fw == q) {
8209 q->focusNextPrevChild(next: true);
8210 break;
8211 }
8212 fw = fw->parentWidget();
8213 }
8214 }
8215
8216 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8217 repaintManager->removeDirtyWidget(w: q);
8218
8219#if QT_CONFIG(accessibility)
8220 if (wasVisible) {
8221 QAccessibleEvent event(q, QAccessible::ObjectHide);
8222 QAccessible::updateAccessibility(event: &event);
8223 }
8224#endif
8225}
8226
8227void QWidgetPrivate::hide_sys()
8228{
8229 Q_Q(QWidget);
8230
8231 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8232
8233 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8234 q->setAttribute(Qt::WA_Mapped, on: false);
8235 // remove our window from the modal window list (native dialogs)
8236 if (window && q->isWindow()
8237#if QT_CONFIG(graphicsview)
8238 && (!extra || !extra->proxyWidget)
8239#endif
8240 && q->windowModality() != Qt::NonModal) {
8241 QGuiApplicationPrivate::hideModalWindow(window);
8242 }
8243 // do not return here, if window non-zero, we must hide it
8244 }
8245
8246 deactivateWidgetCleanup();
8247
8248 if (!q->isWindow()) {
8249 QWidget *p = q->parentWidget();
8250 if (p &&p->isVisible()) {
8251 if (renderToTexture)
8252 p->d_func()->invalidateBackingStore(q->geometry());
8253 else
8254 invalidateBackingStore(q->rect());
8255 }
8256 } else {
8257 invalidateBackingStore(q->rect());
8258 }
8259
8260 if (window)
8261 window->setNativeWindowVisibility(false);
8262}
8263
8264/*!
8265 \fn bool QWidget::isHidden() const
8266
8267 Returns \c true if the widget is hidden, otherwise returns \c false.
8268
8269 A hidden widget will only become visible when show() is called on
8270 it. It will not be automatically shown when the parent is shown.
8271
8272 To check visibility, use !isVisible() instead (notice the exclamation mark).
8273
8274 isHidden() implies !isVisible(), but a widget can be not visible
8275 and not hidden at the same time. This is the case for widgets that are children of
8276 widgets that are not visible.
8277
8278
8279 Widgets are hidden if:
8280 \list
8281 \li they were created as independent windows,
8282 \li they were created as children of visible widgets,
8283 \li hide() or setVisible(false) was called.
8284 \endlist
8285*/
8286
8287void QWidget::setVisible(bool visible)
8288{
8289 Q_D(QWidget);
8290 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8291 << "with attributes" << WidgetAttributes{.widget: this}
8292 << "to" << visible << "via QWidget";
8293
8294 if (testAttribute(attribute: Qt::WA_WState_ExplicitShowHide) && testAttribute(attribute: Qt::WA_WState_Hidden) == !visible)
8295 return;
8296
8297 if (d->dontSetExplicitShowHide) {
8298 d->dontSetExplicitShowHide = false;
8299 } else {
8300 // Remember that setVisible was called explicitly
8301 setAttribute(Qt::WA_WState_ExplicitShowHide);
8302 }
8303
8304 d->setVisible(visible);
8305}
8306
8307// This method is called from QWidgetWindow in response to QWindow::setVisible,
8308// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8309// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8310void QWidgetPrivate::setVisible(bool visible)
8311{
8312 Q_Q(QWidget);
8313 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8314 << "with attributes" << WidgetAttributes{.widget: q}
8315 << "to" << visible << "via QWidgetPrivate";
8316
8317 if (visible) { // show
8318 // Designer uses a trick to make grabWidget work without showing
8319 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8320 && !q->parentWidget()->testAttribute(attribute: Qt::WA_WState_Created))
8321 q->parentWidget()->window()->d_func()->createRecursively();
8322
8323 //create toplevels but not children of non-visible parents
8324 QWidget *pw = q->parentWidget();
8325 if (!q->testAttribute(attribute: Qt::WA_WState_Created)
8326 && (q->isWindow() || pw->testAttribute(attribute: Qt::WA_WState_Created))) {
8327 q->create();
8328 }
8329
8330 bool wasResized = q->testAttribute(attribute: Qt::WA_Resized);
8331 Qt::WindowStates initialWindowState = q->windowState();
8332
8333 // polish if necessary
8334 q->ensurePolished();
8335
8336 // whether we need to inform the parent widget immediately
8337 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(attribute: Qt::WA_WState_Hidden);
8338 // we are no longer hidden
8339 q->setAttribute(Qt::WA_WState_Hidden, on: false);
8340
8341 if (needUpdateGeometry)
8342 updateGeometry_helper(forceUpdate: true);
8343
8344 // activate our layout before we and our children become visible
8345 if (layout)
8346 layout->activate();
8347
8348 if (!q->isWindow()) {
8349 QWidget *parent = q->parentWidget();
8350 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8351 parent->d_func()->layout->activate();
8352 if (parent->isWindow())
8353 break;
8354 parent = parent->parentWidget();
8355 }
8356 if (parent)
8357 parent->d_func()->setDirtyOpaqueRegion();
8358 }
8359
8360 // adjust size if necessary
8361 if (!wasResized
8362 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8363 if (q->isWindow()) {
8364 q->adjustSize();
8365 if (q->windowState() != initialWindowState)
8366 q->setWindowState(initialWindowState);
8367 } else {
8368 q->adjustSize();
8369 }
8370 q->setAttribute(Qt::WA_Resized, on: false);
8371 }
8372
8373 q->setAttribute(Qt::WA_KeyboardFocusChange, on: false);
8374
8375 if (q->isWindow() || q->parentWidget()->isVisible()) {
8376 show_helper();
8377
8378 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8379 }
8380
8381 QEvent showToParentEvent(QEvent::ShowToParent);
8382 QCoreApplication::sendEvent(receiver: q, event: &showToParentEvent);
8383 } else { // hide
8384 if (QApplicationPrivate::hidden_focus_widget == q)
8385 QApplicationPrivate::hidden_focus_widget = nullptr;
8386
8387 // hw: The test on getOpaqueRegion() needs to be more intelligent
8388 // currently it doesn't work if the widget is hidden (the region will
8389 // be clipped). The real check should be testing the cached region
8390 // (and dirty flag) directly.
8391 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8392 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8393
8394 if (!q->testAttribute(attribute: Qt::WA_WState_Hidden)) {
8395 q->setAttribute(Qt::WA_WState_Hidden);
8396 hide_helper();
8397 }
8398
8399 // invalidate layout similar to updateGeometry()
8400 if (!q->isWindow() && q->parentWidget()) {
8401 if (q->parentWidget()->d_func()->layout)
8402 q->parentWidget()->d_func()->layout->invalidate();
8403 else if (q->parentWidget()->isVisible())
8404 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QEvent(QEvent::LayoutRequest));
8405 }
8406
8407 QEvent hideToParentEvent(QEvent::HideToParent);
8408 QCoreApplication::sendEvent(receiver: q, event: &hideToParentEvent);
8409 }
8410}
8411
8412/*!
8413 Convenience function, equivalent to setVisible(!\a hidden).
8414*/
8415void QWidget::setHidden(bool hidden)
8416{
8417 setVisible(!hidden);
8418}
8419
8420bool QWidgetPrivate::isExplicitlyHidden() const
8421{
8422 Q_Q(const QWidget);
8423 return q->isHidden() && q->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide);
8424}
8425
8426void QWidgetPrivate::_q_showIfNotHidden()
8427{
8428 Q_Q(QWidget);
8429 if (!isExplicitlyHidden())
8430 q->setVisible(true);
8431}
8432
8433void QWidgetPrivate::showChildren(bool spontaneous)
8434{
8435 Q_Q(QWidget);
8436 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8437 << "spontaneously" << spontaneous;
8438
8439 QList<QObject*> childList = children;
8440 for (int i = 0; i < childList.size(); ++i) {
8441 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8442 if (!widget)
8443 continue;
8444 qCDebug(lcWidgetShowHide) << "Considering" << widget
8445 << "with attributes" << WidgetAttributes{.widget: widget};
8446 if (widget->windowHandle() && !widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
8447 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
8448 if (widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8449 continue;
8450 if (spontaneous) {
8451 widget->setAttribute(Qt::WA_Mapped);
8452 widget->d_func()->showChildren(spontaneous: true);
8453 QShowEvent e;
8454 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8455 } else {
8456 if (widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide)) {
8457 widget->d_func()->show_recursive();
8458 } else {
8459 // Call QWidget::setVisible() here, so that subclasses
8460 // that (wrongly) override setVisible to do initialization
8461 // will still be notified that they are made visible, but
8462 // do so without triggering ExplicitShowHide.
8463 widget->d_func()->dontSetExplicitShowHide = true;
8464 widget->setVisible(true);
8465 widget->d_func()->dontSetExplicitShowHide = false;
8466 }
8467 }
8468 }
8469}
8470
8471void QWidgetPrivate::hideChildren(bool spontaneous)
8472{
8473 Q_Q(QWidget);
8474 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8475 << "spontaneously" << spontaneous;
8476
8477 QList<QObject*> childList = children;
8478 for (int i = 0; i < childList.size(); ++i) {
8479 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8480 if (!widget)
8481 continue;
8482 qCDebug(lcWidgetShowHide) << "Considering" << widget
8483 << "with attributes" << WidgetAttributes{.widget: widget};
8484 if (widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8485 continue;
8486
8487 if (spontaneous)
8488 widget->setAttribute(Qt::WA_Mapped, on: false);
8489 else
8490 widget->setAttribute(Qt::WA_WState_Visible, on: false);
8491 widget->d_func()->hideChildren(spontaneous);
8492 QHideEvent e;
8493 if (spontaneous) {
8494 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8495 } else {
8496 QCoreApplication::sendEvent(receiver: widget, event: &e);
8497 if (widget->internalWinId()
8498 && widget->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
8499 // hide_sys() on an ancestor won't have any affect on this
8500 // widget, so it needs an explicit hide_sys() of its own
8501 widget->d_func()->hide_sys();
8502 }
8503 }
8504 qApp->d_func()->sendSyntheticEnterLeave(widget);
8505#if QT_CONFIG(accessibility)
8506 if (!spontaneous) {
8507 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8508 QAccessible::updateAccessibility(event: &event);
8509 }
8510#endif
8511 }
8512
8513 // If the window of this widget is not closed, then the leave event
8514 // will eventually handle the widget under mouse use case.
8515 // Otherwise, we need to explicitly handle it here.
8516 if (QWidget* widgetWindow = q->window();
8517 widgetWindow && widgetWindow->data->is_closing) {
8518 q->setAttribute(Qt::WA_UnderMouse, on: false);
8519 }
8520}
8521
8522/*!
8523 \internal
8524
8525 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8526 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8527 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8528 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8529 system (i.e. the user clicked the close button in the title bar).
8530
8531 QDialog calls this method directly in its hide() implementation, which might be
8532 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8533 to prevent recursion.
8534
8535 For non-windows, this is called directly by QWidget::close, and \a mode will be
8536 CloseWithEvent.
8537
8538 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8539*/
8540bool QWidgetPrivate::handleClose(CloseMode mode)
8541{
8542 Q_Q(QWidget);
8543 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8544
8545 if (data.is_closing)
8546 return true;
8547
8548 // We might not have initiated the close, so update the state now that we know
8549 data.is_closing = true;
8550
8551 QPointer<QWidget> that = q;
8552
8553 if (data.in_destructor)
8554 mode = CloseNoEvent;
8555
8556 if (mode != CloseNoEvent) {
8557 QCloseEvent e;
8558 if (mode == CloseWithSpontaneousEvent)
8559 QApplication::sendSpontaneousEvent(receiver: q, event: &e);
8560 else
8561 QCoreApplication::sendEvent(receiver: q, event: &e);
8562 if (!that.isNull() && !e.isAccepted()) {
8563 data.is_closing = false;
8564 return false;
8565 }
8566 }
8567
8568 // even for windows, make sure we deliver a hide event and that all children get hidden
8569 if (!that.isNull() && !q->isHidden())
8570 q->hide();
8571
8572 if (!that.isNull()) {
8573 data.is_closing = false;
8574 if (q->testAttribute(attribute: Qt::WA_DeleteOnClose)) {
8575 q->setAttribute(Qt::WA_DeleteOnClose, on: false);
8576 q->deleteLater();
8577 }
8578 }
8579 return true;
8580}
8581
8582
8583/*!
8584 Closes this widget. Returns \c true if the widget was closed;
8585 otherwise returns \c false.
8586
8587 First it sends the widget a QCloseEvent. The widget is
8588 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8589 the close event. If it \l{QEvent::ignore()}{ignores}
8590 the event, nothing happens. The default
8591 implementation of QWidget::closeEvent() accepts the close event.
8592
8593 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8594 is also deleted. A close events is delivered to the widget no
8595 matter if the widget is visible or not.
8596
8597 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8598 last visible primary window (i.e. window with no parent) with the
8599 Qt::WA_QuitOnClose attribute set is closed. By default this
8600 attribute is set for all widgets except transient windows such as
8601 splash screens, tool windows, and popup menus.
8602
8603*/
8604
8605bool QWidget::close()
8606{
8607 return d_func()->close();
8608}
8609
8610bool QWidgetPrivate::close()
8611{
8612 // FIXME: We're not setting is_closing here, even though that would
8613 // make sense, as the code below will not end up in handleClose to
8614 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8615 // and we can't assume close is synchronous so we can't reset it here.
8616
8617 // Close native widgets via QWindow::close() in order to run QWindow
8618 // close code. The QWidget-specific close code in handleClose() will
8619 // in this case be called from the Close event handler in QWidgetWindow.
8620 if (QWindow *widgetWindow = windowHandle()) {
8621 if (widgetWindow->isTopLevel())
8622 return widgetWindow->close();
8623 }
8624
8625 return handleClose(mode: QWidgetPrivate::CloseWithEvent);
8626}
8627
8628/*!
8629 \property QWidget::visible
8630 \brief whether the widget is visible
8631
8632 Calling setVisible(true) or show() sets the widget to visible
8633 status if all its parent widgets up to the window are visible. If
8634 an ancestor is not visible, the widget won't become visible until
8635 all its ancestors are shown. If its size or position has changed,
8636 Qt guarantees that a widget gets move and resize events just
8637 before it is shown. If the widget has not been resized yet, Qt
8638 will adjust the widget's size to a useful default using
8639 adjustSize().
8640
8641 Calling setVisible(false) or hide() hides a widget explicitly. An
8642 explicitly hidden widget will never become visible, even if all
8643 its ancestors become visible, unless you show it.
8644
8645 A widget receives show and hide events when its visibility status
8646 changes. Between a hide and a show event, there is no need to
8647 waste CPU cycles preparing or displaying information to the user.
8648 A video application, for example, might simply stop generating new
8649 frames.
8650
8651 A widget that happens to be obscured by other windows on the
8652 screen is considered to be visible. The same applies to iconified
8653 windows and windows that exist on another virtual
8654 desktop (on platforms that support this concept). A widget
8655 receives spontaneous show and hide events when its mapping status
8656 is changed by the window system, e.g. a spontaneous hide event
8657 when the user minimizes the window, and a spontaneous show event
8658 when the window is restored again.
8659
8660 You seldom have to reimplement the setVisible() function. If
8661 you need to change some settings before a widget is shown, use
8662 showEvent() instead. If you need to do some delayed initialization
8663 use the Polish event delivered to the event() function.
8664
8665 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8666 showEvent(), hideEvent()
8667*/
8668
8669
8670/*!
8671 Returns \c true if this widget would become visible if \a ancestor is
8672 shown; otherwise returns \c false.
8673
8674 The true case occurs if neither the widget itself nor any parent
8675 up to but excluding \a ancestor has been explicitly hidden.
8676
8677 This function will still return true if the widget is obscured by
8678 other windows on the screen, but could be physically visible if it
8679 or they were to be moved.
8680
8681 isVisibleTo(0) is identical to isVisible().
8682
8683 \sa show(), hide(), isVisible()
8684*/
8685
8686bool QWidget::isVisibleTo(const QWidget *ancestor) const
8687{
8688 if (!ancestor)
8689 return isVisible();
8690 const QWidget * w = this;
8691 while (!w->isHidden()
8692 && !w->isWindow()
8693 && w->parentWidget()
8694 && w->parentWidget() != ancestor)
8695 w = w->parentWidget();
8696 return !w->isHidden();
8697}
8698
8699
8700/*!
8701 Returns the unobscured region where paint events can occur.
8702
8703 For visible widgets, this is an approximation of the area not
8704 covered by other widgets; otherwise, this is an empty region.
8705
8706 The repaint() function calls this function if necessary, so in
8707 general you do not need to call it.
8708
8709*/
8710QRegion QWidget::visibleRegion() const
8711{
8712 Q_D(const QWidget);
8713
8714 QRect clipRect = d->clipRect();
8715 if (clipRect.isEmpty())
8716 return QRegion();
8717 QRegion r(clipRect);
8718 d->subtractOpaqueChildren(source&: r, clipRect);
8719 d->subtractOpaqueSiblings(sourceRegion&: r);
8720 return r;
8721}
8722
8723
8724QSize QWidgetPrivate::adjustedSize() const
8725{
8726 Q_Q(const QWidget);
8727
8728 QSize s = q->sizeHint();
8729
8730 if (q->isWindow()) {
8731 Qt::Orientations exp;
8732 if (layout) {
8733 if (layout->hasHeightForWidth())
8734 s.setHeight(layout->totalHeightForWidth(w: s.width()));
8735 exp = layout->expandingDirections();
8736 } else
8737 {
8738 if (q->sizePolicy().hasHeightForWidth())
8739 s.setHeight(q->heightForWidth(s.width()));
8740 exp = q->sizePolicy().expandingDirections();
8741 }
8742 if (exp & Qt::Horizontal)
8743 s.setWidth(qMax(a: s.width(), b: 200));
8744 if (exp & Qt::Vertical)
8745 s.setHeight(qMax(a: s.height(), b: 100));
8746
8747 QRect screen;
8748 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(point: q->pos()))
8749 screen = screenAtPoint->geometry();
8750 else
8751 screen = QGuiApplication::primaryScreen()->geometry();
8752
8753 s.setWidth(qMin(a: s.width(), b: screen.width()*2/3));
8754 s.setHeight(qMin(a: s.height(), b: screen.height()*2/3));
8755
8756 if (QTLWExtra *extra = maybeTopData())
8757 extra->sizeAdjusted = true;
8758 }
8759
8760 if (!s.isValid()) {
8761 QRect r = q->childrenRect(); // get children rectangle
8762 if (r.isNull())
8763 return s;
8764 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8765 }
8766
8767 return s;
8768}
8769
8770/*!
8771 Adjusts the size of the widget to fit its contents.
8772
8773 This function uses sizeHint() if it is valid, i.e., the size hint's width
8774 and height are \>= 0. Otherwise, it sets the size to the children
8775 rectangle that covers all child widgets (the union of all child widget
8776 rectangles).
8777
8778 For windows, the screen size is also taken into account. If the sizeHint()
8779 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8780 {expanding}, the window will be at least (200, 100). The maximum size of
8781 a window is 2/3 of the screen's width and height.
8782
8783 \sa sizeHint(), childrenRect()
8784*/
8785
8786void QWidget::adjustSize()
8787{
8788 Q_D(QWidget);
8789 ensurePolished();
8790 QSize s = d->adjustedSize();
8791
8792 if (d->layout)
8793 d->layout->activate();
8794
8795 if (s.isValid())
8796 resize(s);
8797}
8798
8799
8800/*!
8801 \property QWidget::sizeHint
8802 \brief the recommended size for the widget
8803
8804 If the value of this property is an invalid size, no size is
8805 recommended.
8806
8807 The default implementation of sizeHint() returns an invalid size
8808 if there is no layout for this widget, and returns the layout's
8809 preferred size otherwise.
8810
8811 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8812 setMinimumSize(), updateGeometry()
8813*/
8814
8815QSize QWidget::sizeHint() const
8816{
8817 Q_D(const QWidget);
8818 if (d->layout)
8819 return d->layout->totalSizeHint();
8820 return QSize(-1, -1);
8821}
8822
8823/*!
8824 \property QWidget::minimumSizeHint
8825 \brief the recommended minimum size for the widget
8826
8827 If the value of this property is an invalid size, no minimum size
8828 is recommended.
8829
8830 The default implementation of minimumSizeHint() returns an invalid
8831 size if there is no layout for this widget, and returns the
8832 layout's minimum size otherwise. Most built-in widgets reimplement
8833 minimumSizeHint().
8834
8835 \l QLayout will never resize a widget to a size smaller than the
8836 minimum size hint unless minimumSize() is set or the size policy is
8837 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8838 size hint will be ignored.
8839
8840 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8841*/
8842QSize QWidget::minimumSizeHint() const
8843{
8844 Q_D(const QWidget);
8845 if (d->layout)
8846 return d->layout->totalMinimumSize();
8847 return QSize(-1, -1);
8848}
8849
8850
8851/*!
8852 \fn QWidget *QWidget::parentWidget() const
8853
8854 Returns the parent of this widget, or \nullptr if it does not have any
8855 parent widget.
8856*/
8857
8858
8859/*!
8860 Returns \c true if this widget is a parent, (or grandparent and so on
8861 to any level), of the given \a child, and both widgets are within
8862 the same window; otherwise returns \c false.
8863*/
8864
8865bool QWidget::isAncestorOf(const QWidget *child) const
8866{
8867 while (child) {
8868 if (child == this)
8869 return true;
8870 if (child->isWindow())
8871 return false;
8872 child = child->parentWidget();
8873 }
8874 return false;
8875}
8876
8877/*****************************************************************************
8878 QWidget event handling
8879 *****************************************************************************/
8880
8881/*!
8882 This is the main event handler; it handles event \a event. You can
8883 reimplement this function in a subclass, but we recommend using
8884 one of the specialized event handlers instead.
8885
8886 Key press and release events are treated differently from other
8887 events. event() checks for Tab and Shift+Tab and tries to move the
8888 focus appropriately. If there is no widget to move the focus to
8889 (or the key press is not Tab or Shift+Tab), event() calls
8890 keyPressEvent().
8891
8892 Mouse and tablet event handling is also slightly special: only
8893 when the widget is \l enabled, event() will call the specialized
8894 handlers such as mousePressEvent(); otherwise it will discard the
8895 event.
8896
8897 This function returns \c true if the event was recognized, otherwise
8898 it returns \c false. If the recognized event was accepted (see \l
8899 QEvent::accepted), any further processing such as event
8900 propagation to the parent widget stops.
8901
8902 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8903 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8904 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8905 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8906 QObject::event(), QObject::timerEvent()
8907*/
8908
8909bool QWidget::event(QEvent *event)
8910{
8911 Q_D(QWidget);
8912
8913 // ignore mouse and key events when disabled
8914 if (!isEnabled()) {
8915 switch(event->type()) {
8916 case QEvent::TabletPress:
8917 case QEvent::TabletRelease:
8918 case QEvent::TabletMove:
8919 case QEvent::MouseButtonPress:
8920 case QEvent::MouseButtonRelease:
8921 case QEvent::MouseButtonDblClick:
8922 case QEvent::MouseMove:
8923 case QEvent::TouchBegin:
8924 case QEvent::TouchUpdate:
8925 case QEvent::TouchEnd:
8926 case QEvent::TouchCancel:
8927 case QEvent::ContextMenu:
8928 case QEvent::KeyPress:
8929 case QEvent::KeyRelease:
8930#if QT_CONFIG(wheelevent)
8931 case QEvent::Wheel:
8932#endif
8933 return false;
8934 default:
8935 break;
8936 }
8937 }
8938 switch (event->type()) {
8939 case QEvent::PlatformSurface: {
8940 // Sync up QWidget's view of whether or not the widget has been created
8941 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8942 case QPlatformSurfaceEvent::SurfaceCreated:
8943 if (!testAttribute(attribute: Qt::WA_WState_Created))
8944 create();
8945 break;
8946 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8947 if (testAttribute(attribute: Qt::WA_WState_Created)) {
8948 // Child windows have already been destroyed by QWindow,
8949 // so we skip them here.
8950 destroy(destroyWindow: false, destroySubWindows: false);
8951 }
8952 break;
8953 }
8954 break;
8955 }
8956 case QEvent::MouseMove:
8957 mouseMoveEvent(event: (QMouseEvent*)event);
8958 break;
8959
8960 case QEvent::MouseButtonPress:
8961 mousePressEvent(event: (QMouseEvent*)event);
8962 break;
8963
8964 case QEvent::MouseButtonRelease:
8965 mouseReleaseEvent(event: (QMouseEvent*)event);
8966 break;
8967
8968 case QEvent::MouseButtonDblClick:
8969 mouseDoubleClickEvent(event: (QMouseEvent*)event);
8970 break;
8971#if QT_CONFIG(wheelevent)
8972 case QEvent::Wheel:
8973 wheelEvent(event: (QWheelEvent*)event);
8974 break;
8975#endif
8976#if QT_CONFIG(tabletevent)
8977 case QEvent::TabletMove:
8978 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(attribute: Qt::WA_TabletTracking))
8979 break;
8980 Q_FALLTHROUGH();
8981 case QEvent::TabletPress:
8982 case QEvent::TabletRelease:
8983 tabletEvent(event: (QTabletEvent*)event);
8984 break;
8985#endif
8986 case QEvent::KeyPress: {
8987 QKeyEvent *k = static_cast<QKeyEvent *>(event);
8988 bool res = false;
8989 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
8990 if (k->key() == Qt::Key_Backtab
8991 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
8992 res = focusNextPrevChild(next: false);
8993 else if (k->key() == Qt::Key_Tab)
8994 res = focusNextPrevChild(next: true);
8995 if (res)
8996 break;
8997 }
8998 keyPressEvent(event: k);
8999#ifdef QT_KEYPAD_NAVIGATION
9000 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9001 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9002 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9003 if (k->key() == Qt::Key_Up)
9004 res = focusNextPrevChild(false);
9005 else if (k->key() == Qt::Key_Down)
9006 res = focusNextPrevChild(true);
9007 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9008 if (k->key() == Qt::Key_Up)
9009 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9010 else if (k->key() == Qt::Key_Right)
9011 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9012 else if (k->key() == Qt::Key_Down)
9013 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9014 else if (k->key() == Qt::Key_Left)
9015 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9016 }
9017 if (res) {
9018 k->accept();
9019 break;
9020 }
9021 }
9022#endif
9023#if QT_CONFIG(whatsthis)
9024 if (!k->isAccepted()
9025 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9026 && d->whatsThis.size()) {
9027 QWhatsThis::showText(pos: mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), text: d->whatsThis, w: this);
9028 k->accept();
9029 }
9030#endif
9031 }
9032 break;
9033
9034 case QEvent::KeyRelease:
9035 keyReleaseEvent(event: (QKeyEvent*)event);
9036 Q_FALLTHROUGH();
9037 case QEvent::ShortcutOverride:
9038 break;
9039
9040 case QEvent::InputMethod:
9041 inputMethodEvent((QInputMethodEvent *) event);
9042 break;
9043
9044 case QEvent::InputMethodQuery: {
9045 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9046 Qt::InputMethodQueries queries = query->queries();
9047 for (uint i = 0; i < 32; ++i) {
9048 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9049 if (q) {
9050 QVariant v = inputMethodQuery(q);
9051 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9052 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9053 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9054 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9055 // will only be set if the widget supports IM _and_ is not read-only. So for
9056 // read-only widgets, not all IM features will be supported when ImEnabled is
9057 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9058 v = QVariant(testAttribute(attribute: Qt::WA_InputMethodEnabled));
9059 }
9060 query->setValue(query: q, value: v);
9061 }
9062 }
9063 query->accept();
9064 }
9065 break;
9066
9067 case QEvent::PolishRequest:
9068 ensurePolished();
9069 break;
9070
9071 case QEvent::Polish: {
9072 style()->polish(widget: this);
9073 setAttribute(Qt::WA_WState_Polished);
9074 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9075 d->resolveFont();
9076 if (!QApplication::palette(this).isCopyOf(p: QGuiApplication::palette()))
9077 d->resolvePalette();
9078 }
9079 break;
9080
9081 case QEvent::ApplicationWindowIconChange:
9082 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon)) {
9083 d->setWindowIcon_sys();
9084 d->setWindowIcon_helper();
9085 }
9086 break;
9087 case QEvent::FocusIn:
9088 focusInEvent(event: (QFocusEvent*)event);
9089 d->updateWidgetTransform(event);
9090 break;
9091
9092 case QEvent::FocusOut:
9093 focusOutEvent(event: (QFocusEvent*)event);
9094 break;
9095
9096 case QEvent::Enter:
9097#if QT_CONFIG(statustip)
9098 if (d->statusTip.size()) {
9099 QStatusTipEvent tip(d->statusTip);
9100 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9101 }
9102#endif
9103 enterEvent(event: static_cast<QEnterEvent*>(event));
9104 break;
9105
9106 case QEvent::Leave:
9107#if QT_CONFIG(statustip)
9108 if (d->statusTip.size()) {
9109 QString empty;
9110 QStatusTipEvent tip(empty);
9111 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9112 }
9113#endif
9114 leaveEvent(event);
9115 break;
9116
9117 case QEvent::HoverEnter:
9118 case QEvent::HoverLeave:
9119 update();
9120 break;
9121
9122 case QEvent::Paint:
9123 // At this point the event has to be delivered, regardless
9124 // whether the widget isVisible() or not because it
9125 // already went through the filters
9126 paintEvent(event: (QPaintEvent*)event);
9127 break;
9128
9129 case QEvent::Move:
9130 moveEvent(event: (QMoveEvent*)event);
9131 d->updateWidgetTransform(event);
9132 break;
9133
9134 case QEvent::Resize:
9135 resizeEvent(event: (QResizeEvent*)event);
9136 d->updateWidgetTransform(event);
9137 break;
9138
9139 case QEvent::Close:
9140 closeEvent(event: (QCloseEvent *)event);
9141 break;
9142
9143#ifndef QT_NO_CONTEXTMENU
9144 case QEvent::ContextMenu:
9145 switch (data->context_menu_policy) {
9146 case Qt::PreventContextMenu:
9147 break;
9148 case Qt::DefaultContextMenu:
9149 contextMenuEvent(event: static_cast<QContextMenuEvent *>(event));
9150 break;
9151 case Qt::CustomContextMenu:
9152 emit customContextMenuRequested(pos: static_cast<QContextMenuEvent *>(event)->pos());
9153 break;
9154#if QT_CONFIG(menu)
9155 case Qt::ActionsContextMenu:
9156 if (d->actions.size()) {
9157 QMenu::exec(actions: d->actions, pos: static_cast<QContextMenuEvent *>(event)->globalPos(),
9158 at: nullptr, parent: this);
9159 break;
9160 }
9161 Q_FALLTHROUGH();
9162#endif
9163 default:
9164 event->ignore();
9165 break;
9166 }
9167 break;
9168#endif // QT_NO_CONTEXTMENU
9169
9170#if QT_CONFIG(draganddrop)
9171 case QEvent::Drop:
9172 dropEvent(event: (QDropEvent*) event);
9173 break;
9174
9175 case QEvent::DragEnter:
9176 dragEnterEvent(event: (QDragEnterEvent*) event);
9177 break;
9178
9179 case QEvent::DragMove:
9180 dragMoveEvent(event: (QDragMoveEvent*) event);
9181 break;
9182
9183 case QEvent::DragLeave:
9184 dragLeaveEvent(event: (QDragLeaveEvent*) event);
9185 break;
9186#endif
9187
9188 case QEvent::Show:
9189 showEvent(event: (QShowEvent*) event);
9190 break;
9191
9192 case QEvent::Hide:
9193 hideEvent(event: (QHideEvent*) event);
9194 break;
9195
9196 case QEvent::ShowWindowRequest:
9197 if (!isHidden())
9198 d->show_sys();
9199 break;
9200
9201 case QEvent::ApplicationFontChange:
9202 d->resolveFont();
9203 break;
9204 case QEvent::ApplicationPaletteChange:
9205 if (!(windowType() == Qt::Desktop))
9206 d->resolvePalette();
9207 break;
9208
9209 case QEvent::ToolBarChange:
9210 case QEvent::ActivationChange:
9211 case QEvent::EnabledChange:
9212 case QEvent::FontChange:
9213 case QEvent::StyleChange:
9214 case QEvent::PaletteChange:
9215 case QEvent::WindowTitleChange:
9216 case QEvent::IconTextChange:
9217 case QEvent::ModifiedChange:
9218 case QEvent::MouseTrackingChange:
9219 case QEvent::TabletTrackingChange:
9220 case QEvent::ParentChange:
9221 case QEvent::LocaleChange:
9222 case QEvent::MacSizeChange:
9223 case QEvent::ContentsRectChange:
9224 case QEvent::ThemeChange:
9225 case QEvent::ReadOnlyChange:
9226 changeEvent(event);
9227 break;
9228
9229 case QEvent::WindowStateChange: {
9230 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9231 if (wasMinimized != isMinimized()) {
9232 QWidget *widget = const_cast<QWidget *>(this);
9233 if (wasMinimized) {
9234 // Always send the spontaneous events here, otherwise it can break the application!
9235 if (!d->childrenShownByExpose) {
9236 // Show widgets only when they are not yet shown by the expose event
9237 d->showChildren(spontaneous: true);
9238 QShowEvent showEvent;
9239 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &showEvent);
9240 }
9241 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9242 } else {
9243 QHideEvent hideEvent;
9244 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &hideEvent);
9245 d->hideChildren(spontaneous: true);
9246 d->childrenHiddenByWState = true;
9247 }
9248 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9249 }
9250 changeEvent(event);
9251 }
9252 break;
9253
9254 case QEvent::WindowActivate:
9255 case QEvent::WindowDeactivate: {
9256 if (isVisible() && !palette().isEqual(cr1: QPalette::Active, cr2: QPalette::Inactive))
9257 update();
9258 QList<QObject*> childList = d->children;
9259 for (int i = 0; i < childList.size(); ++i) {
9260 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9261 if (w && w->isVisible() && !w->isWindow())
9262 QCoreApplication::sendEvent(receiver: w, event);
9263 }
9264 break; }
9265
9266 case QEvent::LanguageChange:
9267 changeEvent(event);
9268 {
9269 QList<QObject*> childList = d->children;
9270 for (int i = 0; i < childList.size(); ++i) {
9271 QObject *o = childList.at(i);
9272 if (o)
9273 QCoreApplication::sendEvent(receiver: o, event);
9274 }
9275 }
9276 update();
9277 break;
9278
9279 case QEvent::ApplicationLayoutDirectionChange:
9280 d->resolveLayoutDirection();
9281 break;
9282
9283 case QEvent::LayoutDirectionChange:
9284 if (d->layout)
9285 d->layout->invalidate();
9286 update();
9287 changeEvent(event);
9288 break;
9289 case QEvent::UpdateRequest:
9290 d->syncBackingStore();
9291 break;
9292 case QEvent::UpdateLater:
9293 update(static_cast<QUpdateLaterEvent*>(event)->region());
9294 break;
9295 case QEvent::StyleAnimationUpdate:
9296 if (isVisible() && !window()->isMinimized()) {
9297 event->accept();
9298 update();
9299 }
9300 break;
9301
9302 case QEvent::WindowBlocked:
9303 case QEvent::WindowUnblocked:
9304 if (!d->children.isEmpty()) {
9305 QWidget *modalWidget = QApplication::activeModalWidget();
9306 for (int i = 0; i < d->children.size(); ++i) {
9307 QObject *o = d->children.at(i);
9308 if (o && o != modalWidget && o->isWidgetType()) {
9309 QWidget *w = static_cast<QWidget *>(o);
9310 // do not forward the event to child windows; QApplication does this for us
9311 if (!w->isWindow())
9312 QCoreApplication::sendEvent(receiver: w, event);
9313 }
9314 }
9315 }
9316 break;
9317#if QT_CONFIG(tooltip)
9318 case QEvent::ToolTip:
9319 if (!d->toolTip.isEmpty())
9320 QToolTip::showText(pos: static_cast<QHelpEvent*>(event)->globalPos(), text: d->toolTip, w: this, rect: QRect(), msecShowTime: d->toolTipDuration);
9321 else
9322 event->ignore();
9323 break;
9324#endif
9325#if QT_CONFIG(whatsthis)
9326 case QEvent::WhatsThis:
9327 if (d->whatsThis.size())
9328 QWhatsThis::showText(pos: static_cast<QHelpEvent *>(event)->globalPos(), text: d->whatsThis, w: this);
9329 else
9330 event->ignore();
9331 break;
9332 case QEvent::QueryWhatsThis:
9333 if (d->whatsThis.isEmpty())
9334 event->ignore();
9335 break;
9336#endif
9337 case QEvent::EmbeddingControl:
9338 d->topData()->frameStrut.setCoords(xp1: 0 ,yp1: 0, xp2: 0, yp2: 0);
9339 data->fstrut_dirty = false;
9340 break;
9341#ifndef QT_NO_ACTION
9342 case QEvent::ActionAdded:
9343 case QEvent::ActionRemoved:
9344 case QEvent::ActionChanged:
9345 actionEvent(event: (QActionEvent*)event);
9346 break;
9347#endif
9348
9349 case QEvent::KeyboardLayoutChange:
9350 {
9351 changeEvent(event);
9352
9353 // inform children of the change
9354 QList<QObject*> childList = d->children;
9355 for (int i = 0; i < childList.size(); ++i) {
9356 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9357 if (w && w->isVisible() && !w->isWindow())
9358 QCoreApplication::sendEvent(receiver: w, event);
9359 }
9360 break;
9361 }
9362 case QEvent::TouchBegin:
9363 case QEvent::TouchUpdate:
9364 case QEvent::TouchEnd:
9365 case QEvent::TouchCancel:
9366 {
9367 event->ignore();
9368 break;
9369 }
9370#ifndef QT_NO_GESTURES
9371 case QEvent::Gesture:
9372 event->ignore();
9373 break;
9374#endif
9375 case QEvent::ScreenChangeInternal:
9376 if (const QTLWExtra *te = d->maybeTopData()) {
9377 const QWindow *win = te->window;
9378 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9379 }
9380 break;
9381 case QEvent::DevicePixelRatioChange:
9382 if (d->data.fnt.d->dpi != logicalDpiY())
9383 d->updateFont(font: d->data.fnt);
9384 d->renderToTextureReallyDirty = 1;
9385 break;
9386 case QEvent::DynamicPropertyChange: {
9387 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9388 if (propName.size() == 13 && !qstrncmp(str1: propName, str2: "_q_customDpi", len: 12)) {
9389 uint value = property(name: propName.constData()).toUInt();
9390 if (!d->extra)
9391 d->createExtra();
9392 const char axis = propName.at(i: 12);
9393 if (axis == 'X')
9394 d->extra->customDpiX = value;
9395 else if (axis == 'Y')
9396 d->extra->customDpiY = value;
9397 d->updateFont(font: d->data.fnt);
9398 }
9399 if (windowHandle() && !qstrncmp(str1: propName, str2: "_q_platform_", len: 12))
9400 windowHandle()->setProperty(name: propName, value: property(name: propName));
9401 Q_FALLTHROUGH();
9402 }
9403 default:
9404 return QObject::event(event);
9405 }
9406 return true;
9407}
9408
9409/*!
9410 This event handler can be reimplemented to handle state changes.
9411
9412 The state being changed in this event can be retrieved through the \a event
9413 supplied.
9414
9415 Change events include: QEvent::ToolBarChange,
9416 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9417 QEvent::StyleChange, QEvent::PaletteChange,
9418 QEvent::WindowTitleChange, QEvent::IconTextChange,
9419 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9420 QEvent::ParentChange, QEvent::WindowStateChange,
9421 QEvent::LanguageChange, QEvent::LocaleChange,
9422 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9423
9424*/
9425void QWidget::changeEvent(QEvent * event)
9426{
9427 switch(event->type()) {
9428 case QEvent::EnabledChange: {
9429 update();
9430#if QT_CONFIG(accessibility)
9431 QAccessible::State s;
9432 s.disabled = true;
9433 QAccessibleStateChangeEvent event(this, s);
9434 QAccessible::updateAccessibility(event: &event);
9435#endif
9436 break;
9437 }
9438
9439 case QEvent::FontChange:
9440 case QEvent::StyleChange: {
9441 Q_D(QWidget);
9442 update();
9443 updateGeometry();
9444 if (d->layout)
9445 d->layout->invalidate();
9446 break;
9447 }
9448
9449 case QEvent::PaletteChange:
9450 update();
9451 break;
9452
9453 case QEvent::ThemeChange:
9454 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9455 && qApp && !QCoreApplication::closingDown()) {
9456 if (testAttribute(attribute: Qt::WA_WState_Polished))
9457 QApplication::style()->unpolish(widget: this);
9458 if (testAttribute(attribute: Qt::WA_WState_Polished))
9459 QApplication::style()->polish(widget: this);
9460 QEvent styleChangedEvent(QEvent::StyleChange);
9461 QCoreApplication::sendEvent(receiver: this, event: &styleChangedEvent);
9462 if (isVisible())
9463 update();
9464 }
9465 break;
9466
9467#ifdef Q_OS_MAC
9468 case QEvent::MacSizeChange:
9469 updateGeometry();
9470 break;
9471#endif
9472
9473 default:
9474 break;
9475 }
9476}
9477
9478/*!
9479 This event handler, for event \a event, can be reimplemented in a
9480 subclass to receive mouse move events for the widget.
9481
9482 If mouse tracking is switched off, mouse move events only occur if
9483 a mouse button is pressed while the mouse is being moved. If mouse
9484 tracking is switched on, mouse move events occur even if no mouse
9485 button is pressed.
9486
9487 QMouseEvent::pos() reports the position of the mouse cursor,
9488 relative to this widget. For press and release events, the
9489 position is usually the same as the position of the last mouse
9490 move event, but it might be different if the user's hand shakes.
9491 This is a feature of the underlying window system, not Qt.
9492
9493 If you want to show a tooltip immediately, while the mouse is
9494 moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9495 and show them as a tooltip), you must first enable mouse tracking
9496 as described above. Then, to ensure that the tooltip is updated
9497 immediately, you must call QToolTip::showText() instead of
9498 setToolTip() in your implementation of mouseMoveEvent().
9499
9500 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9501 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9502*/
9503
9504void QWidget::mouseMoveEvent(QMouseEvent *event)
9505{
9506 event->ignore();
9507}
9508
9509/*!
9510 This event handler, for event \a event, can be reimplemented in a
9511 subclass to receive mouse press events for the widget.
9512
9513 If you create new widgets in the mousePressEvent() the
9514 mouseReleaseEvent() may not end up where you expect, depending on
9515 the underlying window system (or X11 window manager), the widgets'
9516 location and maybe more.
9517
9518 The default implementation implements the closing of popup widgets
9519 when you click outside the window. For other widget types it does
9520 nothing.
9521
9522 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9523 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9524*/
9525
9526void QWidget::mousePressEvent(QMouseEvent *event)
9527{
9528 event->ignore();
9529 if ((windowType() == Qt::Popup)) {
9530 event->accept();
9531 QWidget* w;
9532 while ((w = QApplication::activePopupWidget()) && w != this){
9533 w->close();
9534 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9535 w->hide(); // hide at least
9536 }
9537 if (!rect().contains(p: event->position().toPoint())){
9538 close();
9539 }
9540 }
9541}
9542
9543/*!
9544 This event handler, for event \a event, can be reimplemented in a
9545 subclass to receive mouse release events for the widget.
9546
9547 \sa mousePressEvent(), mouseDoubleClickEvent(),
9548 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9549*/
9550
9551void QWidget::mouseReleaseEvent(QMouseEvent *event)
9552{
9553 event->ignore();
9554}
9555
9556/*!
9557 This event handler, for event \a event, can be reimplemented in a
9558 subclass to receive mouse double click events for the widget.
9559
9560 The default implementation calls mousePressEvent().
9561
9562 \note The widget will also receive mouse press and mouse release
9563 events in addition to the double click event. And if another widget
9564 that overlaps this widget disappears in response to press or
9565 release events, then this widget will only receive the double click
9566 event. It is up to the developer to ensure that the application
9567 interprets these events correctly.
9568
9569 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9570 event(), QMouseEvent
9571*/
9572
9573void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9574{
9575 mousePressEvent(event);
9576}
9577
9578#if QT_CONFIG(wheelevent)
9579/*!
9580 This event handler, for event \a event, can be reimplemented in a
9581 subclass to receive wheel events for the widget.
9582
9583 If you reimplement this handler, it is very important that you
9584 \l{QEvent}{ignore()} the event if you do not handle
9585 it, so that the widget's parent can interpret it.
9586
9587 The default implementation ignores the event.
9588
9589 \sa QEvent::ignore(), QEvent::accept(), event(),
9590 QWheelEvent
9591*/
9592
9593void QWidget::wheelEvent(QWheelEvent *event)
9594{
9595 event->ignore();
9596}
9597#endif // QT_CONFIG(wheelevent)
9598
9599#if QT_CONFIG(tabletevent)
9600/*!
9601 This event handler, for event \a event, can be reimplemented in a
9602 subclass to receive tablet events for the widget.
9603
9604 If you reimplement this handler, it is very important that you
9605 \l{QEvent}{ignore()} the event if you do not handle
9606 it, so that the widget's parent can interpret it.
9607
9608 The default implementation ignores the event.
9609
9610 If tablet tracking is switched off, tablet move events only occur if the
9611 stylus is in contact with the tablet, or at least one stylus button is
9612 pressed, while the stylus is being moved. If tablet tracking is switched on,
9613 tablet move events occur even while the stylus is hovering in proximity of
9614 the tablet, with no buttons pressed.
9615
9616 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9617 QTabletEvent
9618*/
9619
9620void QWidget::tabletEvent(QTabletEvent *event)
9621{
9622 event->ignore();
9623}
9624#endif // QT_CONFIG(tabletevent)
9625
9626/*!
9627 This event handler, for event \a event, can be reimplemented in a
9628 subclass to receive key press events for the widget.
9629
9630 A widget must call setFocusPolicy() to accept focus initially and
9631 have focus in order to receive a key press event.
9632
9633 If you reimplement this handler, it is very important that you
9634 call the base class implementation if you do not act upon the key.
9635
9636 The default implementation closes popup widgets if the user
9637 presses the key sequence for QKeySequence::Cancel (typically the
9638 Escape key). Otherwise the event is ignored, so that the widget's
9639 parent can interpret it.
9640
9641 Note that QKeyEvent starts with isAccepted() == true, so you do not
9642 need to call QKeyEvent::accept() - just do not call the base class
9643 implementation if you act upon the key.
9644
9645 \sa keyReleaseEvent(), setFocusPolicy(),
9646 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9647*/
9648
9649void QWidget::keyPressEvent(QKeyEvent *event)
9650{
9651#ifndef QT_NO_SHORTCUT
9652 if ((windowType() == Qt::Popup) && event->matches(key: QKeySequence::Cancel)) {
9653 event->accept();
9654 close();
9655 } else
9656#endif
9657 {
9658 event->ignore();
9659 }
9660}
9661
9662/*!
9663 This event handler, for event \a event, can be reimplemented in a
9664 subclass to receive key release events for the widget.
9665
9666 A widget must \l{setFocusPolicy()}{accept focus}
9667 initially and \l{hasFocus()}{have focus} in order to
9668 receive a key release event.
9669
9670 If you reimplement this handler, it is very important that you
9671 call the base class implementation if you do not act upon the key.
9672
9673 The default implementation ignores the event, so that the widget's
9674 parent can interpret it.
9675
9676 Note that QKeyEvent starts with isAccepted() == true, so you do not
9677 need to call QKeyEvent::accept() - just do not call the base class
9678 implementation if you act upon the key.
9679
9680 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9681 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9682*/
9683
9684void QWidget::keyReleaseEvent(QKeyEvent *event)
9685{
9686 event->ignore();
9687}
9688
9689/*!
9690 \fn void QWidget::focusInEvent(QFocusEvent *event)
9691
9692 This event handler can be reimplemented in a subclass to receive
9693 keyboard focus events (focus received) for the widget. The event
9694 is passed in the \a event parameter
9695
9696 A widget normally must setFocusPolicy() to something other than
9697 Qt::NoFocus to receive focus events. (Note that the
9698 application programmer can call setFocus() on any widget, even
9699 those that do not normally accept focus.)
9700
9701 The default implementation updates the widget (except for windows
9702 that do not specify a focusPolicy()).
9703
9704 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9705 keyReleaseEvent(), event(), QFocusEvent
9706*/
9707
9708void QWidget::focusInEvent(QFocusEvent *)
9709{
9710 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9711 update();
9712 }
9713}
9714
9715/*!
9716 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9717
9718 This event handler can be reimplemented in a subclass to receive
9719 keyboard focus events (focus lost) for the widget. The events is
9720 passed in the \a event parameter.
9721
9722 A widget normally must setFocusPolicy() to something other than
9723 Qt::NoFocus to receive focus events. (Note that the
9724 application programmer can call setFocus() on any widget, even
9725 those that do not normally accept focus.)
9726
9727 The default implementation updates the widget (except for windows
9728 that do not specify a focusPolicy()).
9729
9730 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9731 keyReleaseEvent(), event(), QFocusEvent
9732*/
9733
9734void QWidget::focusOutEvent(QFocusEvent *)
9735{
9736 if (focusPolicy() != Qt::NoFocus || !isWindow())
9737 update();
9738
9739#if !defined(QT_PLATFORM_UIKIT)
9740 // FIXME: revisit autoSIP logic, QTBUG-42906
9741 if (qApp->autoSipEnabled() && testAttribute(attribute: Qt::WA_InputMethodEnabled))
9742 QGuiApplication::inputMethod()->hide();
9743#endif
9744}
9745
9746/*!
9747 \fn void QWidget::enterEvent(QEnterEvent *event)
9748
9749 This event handler can be reimplemented in a subclass to receive
9750 widget enter events which are passed in the \a event parameter.
9751
9752 An event is sent to the widget when the mouse cursor enters the
9753 widget.
9754
9755 \sa leaveEvent(), mouseMoveEvent(), event()
9756*/
9757
9758void QWidget::enterEvent(QEnterEvent *)
9759{
9760}
9761
9762/*!
9763 \fn void QWidget::leaveEvent(QEvent *event)
9764
9765 This event handler can be reimplemented in a subclass to receive
9766 widget leave events which are passed in the \a event parameter.
9767
9768 A leave event is sent to the widget when the mouse cursor leaves
9769 the widget.
9770
9771 \sa enterEvent(), mouseMoveEvent(), event()
9772*/
9773
9774void QWidget::leaveEvent(QEvent *)
9775{
9776}
9777
9778/*!
9779 \fn void QWidget::paintEvent(QPaintEvent *event)
9780
9781 This event handler can be reimplemented in a subclass to receive paint
9782 events passed in \a event.
9783
9784 A paint event is a request to repaint all or part of a widget. It can
9785 happen for one of the following reasons:
9786
9787 \list
9788 \li repaint() or update() was invoked,
9789 \li the widget was obscured and has now been uncovered, or
9790 \li many other reasons.
9791 \endlist
9792
9793 Many widgets can simply repaint their entire surface when asked to, but
9794 some slow widgets need to optimize by painting only the requested region:
9795 QPaintEvent::region(). This speed optimization does not change the result,
9796 as painting is clipped to that region during event processing. QListView
9797 and QTableView do this, for example.
9798
9799 Qt also tries to speed up painting by merging multiple paint events into
9800 one. When update() is called several times or the window system sends
9801 several paint events, Qt merges these events into one event with a larger
9802 region (see QRegion::united()). The repaint() function does not permit this
9803 optimization, so we suggest using update() whenever possible.
9804
9805 When the paint event occurs, the update region has normally been erased, so
9806 you are painting on the widget's background.
9807
9808 The background can be set using setBackgroundRole() and setPalette().
9809
9810 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9811 is no need to write double-buffering code in paintEvent() to avoid flicker.
9812
9813 \note Generally, you should refrain from calling update() or repaint()
9814 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9815 children inside a paintEvent() results in undefined behavior; the child may
9816 or may not get a paint event.
9817
9818 \warning If you are using a custom paint engine without Qt's backingstore,
9819 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9820 never be called; the backingstore will be used instead.
9821
9822 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9823 {Analog Clock}
9824*/
9825
9826void QWidget::paintEvent(QPaintEvent *)
9827{
9828}
9829
9830
9831/*!
9832 \fn void QWidget::moveEvent(QMoveEvent *event)
9833
9834 This event handler can be reimplemented in a subclass to receive
9835 widget move events which are passed in the \a event parameter.
9836 When the widget receives this event, it is already at the new
9837 position.
9838
9839 The old position is accessible through QMoveEvent::oldPos().
9840
9841 \sa resizeEvent(), event(), move(), QMoveEvent
9842*/
9843
9844void QWidget::moveEvent(QMoveEvent *)
9845{
9846}
9847
9848
9849/*!
9850 This event handler can be reimplemented in a subclass to receive
9851 widget resize events which are passed in the \a event parameter.
9852 When resizeEvent() is called, the widget already has its new
9853 geometry. The old size is accessible through
9854 QResizeEvent::oldSize().
9855
9856 The widget will be erased and receive a paint event immediately
9857 after processing the resize event. No drawing need be (or should
9858 be) done inside this handler.
9859
9860
9861 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9862 {Scribble Example}
9863*/
9864
9865void QWidget::resizeEvent(QResizeEvent * /* event */)
9866{
9867}
9868
9869#ifndef QT_NO_ACTION
9870/*!
9871 \fn void QWidget::actionEvent(QActionEvent *event)
9872
9873 This event handler is called with the given \a event whenever the
9874 widget's actions are changed.
9875
9876 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9877*/
9878void QWidget::actionEvent(QActionEvent *)
9879{
9880
9881}
9882#endif
9883
9884/*!
9885 This event handler is called with the given \a event when Qt receives a window
9886 close request for a top-level widget from the window system.
9887
9888 By default, the event is accepted and the widget is closed. You can reimplement
9889 this function to change the way the widget responds to window close requests.
9890 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9891 on all events.
9892
9893 Main window applications typically use reimplementations of this function to check
9894 whether the user's work has been saved and ask for permission before closing.
9895
9896 \sa event(), hide(), close(), QCloseEvent
9897*/
9898
9899void QWidget::closeEvent(QCloseEvent *event)
9900{
9901 event->accept();
9902}
9903
9904#ifndef QT_NO_CONTEXTMENU
9905/*!
9906 This event handler, for event \a event, can be reimplemented in a
9907 subclass to receive widget context menu events.
9908
9909 The handler is called when the widget's \l contextMenuPolicy is
9910 Qt::DefaultContextMenu.
9911
9912 The default implementation ignores the context event.
9913 See the \l QContextMenuEvent documentation for more details.
9914
9915 \sa event(), QContextMenuEvent, customContextMenuRequested()
9916*/
9917
9918void QWidget::contextMenuEvent(QContextMenuEvent *event)
9919{
9920 event->ignore();
9921}
9922#endif // QT_NO_CONTEXTMENU
9923
9924
9925/*!
9926 This event handler, for event \a event, can be reimplemented in a
9927 subclass to receive Input Method composition events. This handler
9928 is called when the state of the input method changes.
9929
9930 Note that when creating custom text editing widgets, the
9931 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9932 (using the setAttribute() function) in order to receive input
9933 method events.
9934
9935 The default implementation calls event->ignore(), which rejects the
9936 Input Method event. See the \l QInputMethodEvent documentation for more
9937 details.
9938
9939 \sa event(), QInputMethodEvent
9940*/
9941void QWidget::inputMethodEvent(QInputMethodEvent *event)
9942{
9943 event->ignore();
9944}
9945
9946/*!
9947 This method is only relevant for input widgets. It is used by the
9948 input method to query a set of properties of the widget to be
9949 able to support complex input method operations as support for
9950 surrounding text and reconversions.
9951
9952 \a query specifies which property is queried.
9953
9954 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9955*/
9956QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9957{
9958 switch(query) {
9959 case Qt::ImCursorRectangle:
9960 return QRect(width()/2, 0, 1, height());
9961 case Qt::ImFont:
9962 return font();
9963 case Qt::ImAnchorPosition:
9964 // Fallback.
9965 return inputMethodQuery(query: Qt::ImCursorPosition);
9966 case Qt::ImHints:
9967 return (int)inputMethodHints();
9968 case Qt::ImInputItemClipRectangle:
9969 return d_func()->clipRect();
9970 default:
9971 return QVariant();
9972 }
9973}
9974
9975/*!
9976 \property QWidget::inputMethodHints
9977 \brief What input method specific hints the widget has.
9978
9979 This is only relevant for input widgets. It is used by
9980 the input method to retrieve hints as to how the input method
9981 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9982 is set, the input method may change its visual components to reflect
9983 that only numbers can be entered.
9984
9985 \warning Some widgets require certain flags to work as
9986 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9987 instead of \c{w->setInputMethodHints(f)}.
9988
9989 \note The flags are only hints, so the particular input method
9990 implementation is free to ignore them. If you want to be
9991 sure that a certain type of characters are entered,
9992 you should also set a QValidator on the widget.
9993
9994 The default value is Qt::ImhNone.
9995
9996 \since 4.6
9997
9998 \sa inputMethodQuery()
9999*/
10000Qt::InputMethodHints QWidget::inputMethodHints() const
10001{
10002#if QT_CONFIG(im)
10003 const QWidgetPrivate *priv = d_func();
10004 while (priv->inheritsInputMethodHints) {
10005 priv = priv->q_func()->parentWidget()->d_func();
10006 Q_ASSERT(priv);
10007 }
10008 return priv->imHints;
10009#else
10010 return Qt::ImhNone;
10011#endif
10012}
10013
10014void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10015{
10016#ifndef QT_NO_IM
10017 Q_D(QWidget);
10018 if (d->imHints == hints)
10019 return;
10020 d->imHints = hints;
10021 if (this == QGuiApplication::focusObject())
10022 QGuiApplication::inputMethod()->update(queries: Qt::ImHints);
10023#else
10024 Q_UNUSED(hints);
10025#endif //QT_NO_IM
10026}
10027
10028
10029#if QT_CONFIG(draganddrop)
10030
10031/*!
10032 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10033
10034 This event handler is called when a drag is in progress and the
10035 mouse enters this widget. The event is passed in the \a event parameter.
10036
10037 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10038 move events}.
10039
10040 See the \l{dnd.html}{Drag-and-drop documentation} for an
10041 overview of how to provide drag-and-drop in your application.
10042
10043 \sa QDrag, QDragEnterEvent
10044*/
10045void QWidget::dragEnterEvent(QDragEnterEvent *)
10046{
10047}
10048
10049/*!
10050 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10051
10052 This event handler is called if a drag is in progress, and when
10053 any of the following conditions occur: the cursor enters this widget,
10054 the cursor moves within this widget, or a modifier key is pressed on
10055 the keyboard while this widget has the focus. The event is passed
10056 in the \a event parameter.
10057
10058 See the \l{dnd.html}{Drag-and-drop documentation} for an
10059 overview of how to provide drag-and-drop in your application.
10060
10061 \sa QDrag, QDragMoveEvent
10062*/
10063void QWidget::dragMoveEvent(QDragMoveEvent *)
10064{
10065}
10066
10067/*!
10068 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10069
10070 This event handler is called when a drag is in progress and the
10071 mouse leaves this widget. The event is passed in the \a event
10072 parameter.
10073
10074 See the \l{dnd.html}{Drag-and-drop documentation} for an
10075 overview of how to provide drag-and-drop in your application.
10076
10077 \sa QDrag, QDragLeaveEvent
10078*/
10079void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10080{
10081}
10082
10083/*!
10084 \fn void QWidget::dropEvent(QDropEvent *event)
10085
10086 This event handler is called when the drag is dropped on this
10087 widget. The event is passed in the \a event parameter.
10088
10089 See the \l{dnd.html}{Drag-and-drop documentation} for an
10090 overview of how to provide drag-and-drop in your application.
10091
10092 \sa QDrag, QDropEvent
10093*/
10094void QWidget::dropEvent(QDropEvent *)
10095{
10096}
10097
10098#endif // QT_CONFIG(draganddrop)
10099
10100/*!
10101 \fn void QWidget::showEvent(QShowEvent *event)
10102
10103 This event handler can be reimplemented in a subclass to receive
10104 widget show events which are passed in the \a event parameter.
10105
10106 Non-spontaneous show events are sent to widgets immediately
10107 before they are shown. The spontaneous show events of windows are
10108 delivered afterwards.
10109
10110 Note: A widget receives spontaneous show and hide events when its
10111 mapping status is changed by the window system, e.g. a spontaneous
10112 hide event when the user minimizes the window, and a spontaneous
10113 show event when the window is restored again. After receiving a
10114 spontaneous hide event, a widget is still considered visible in
10115 the sense of isVisible().
10116
10117 \sa visible, event(), QShowEvent
10118*/
10119void QWidget::showEvent(QShowEvent *)
10120{
10121}
10122
10123/*!
10124 \fn void QWidget::hideEvent(QHideEvent *event)
10125
10126 This event handler can be reimplemented in a subclass to receive
10127 widget hide events. The event is passed in the \a event parameter.
10128
10129 Hide events are sent to widgets immediately after they have been
10130 hidden.
10131
10132 Note: A widget receives spontaneous show and hide events when its
10133 mapping status is changed by the window system, e.g. a spontaneous
10134 hide event when the user minimizes the window, and a spontaneous
10135 show event when the window is restored again. After receiving a
10136 spontaneous hide event, a widget is still considered visible in
10137 the sense of isVisible().
10138
10139 \sa visible, event(), QHideEvent
10140*/
10141void QWidget::hideEvent(QHideEvent *)
10142{
10143}
10144
10145/*!
10146 This special event handler can be reimplemented in a subclass to
10147 receive native platform events identified by \a eventType
10148 which are passed in the \a message parameter.
10149
10150 In your reimplementation of this function, if you want to stop the
10151 event being handled by Qt, return true and set \a result. The \a result
10152 parameter has meaning only on Windows. If you return false, this native
10153 event is passed back to Qt, which translates the event into a Qt event
10154 and sends it to the widget.
10155
10156 \note Events are only delivered to this event handler if the widget
10157 has a native window handle.
10158
10159 \note This function superseedes the event filter functions
10160 x11Event(), winEvent() and macEvent() of Qt 4.
10161
10162 \sa QAbstractNativeEventFilter
10163
10164 \table
10165 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10166 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10167 \row \li macOS \li "NSEvent" \li NSEvent * \li
10168 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10169 \endtable
10170*/
10171
10172bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10173{
10174 Q_UNUSED(eventType);
10175 Q_UNUSED(message);
10176 Q_UNUSED(result);
10177 return false;
10178}
10179
10180/*!
10181 Ensures that the widget and its children have been polished by
10182 QStyle (i.e., have a proper font and palette).
10183
10184 QWidget calls this function after it has been fully constructed
10185 but before it is shown the very first time. You can call this
10186 function if you want to ensure that the widget is polished before
10187 doing an operation, e.g., the correct font size might be needed in
10188 the widget's sizeHint() reimplementation. Note that this function
10189 \e is called from the default implementation of sizeHint().
10190
10191 Polishing is useful for final initialization that must happen after
10192 all constructors (from base classes as well as from subclasses)
10193 have been called.
10194
10195 If you need to change some settings when a widget is polished,
10196 reimplement event() and handle the QEvent::Polish event type.
10197
10198 \b{Note:} The function is declared const so that it can be called from
10199 other const functions (e.g., sizeHint()).
10200
10201 \sa event()
10202*/
10203void QWidget::ensurePolished() const
10204{
10205 Q_D(const QWidget);
10206
10207 const QMetaObject *m = metaObject();
10208 if (m == d->polished)
10209 return;
10210 d->polished = m;
10211
10212 QEvent e(QEvent::Polish);
10213 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &e);
10214
10215 // polish children after 'this'
10216 QList<QObject*> children = d->children;
10217 for (int i = 0; i < children.size(); ++i) {
10218 QObject *o = children.at(i);
10219 if (!o->isWidgetType())
10220 continue;
10221 if (QWidget *w = qobject_cast<QWidget *>(o))
10222 w->ensurePolished();
10223 }
10224
10225 if (d->parent && d->sendChildEvents) {
10226 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10227 QCoreApplication::sendEvent(receiver: d->parent, event: &e);
10228 }
10229}
10230
10231/*!
10232 Returns the mask currently set on a widget. If no mask is set the
10233 return value will be an empty region.
10234
10235 \sa setMask(), clearMask(), QRegion::isEmpty()
10236*/
10237QRegion QWidget::mask() const
10238{
10239 Q_D(const QWidget);
10240 return d->extra ? d->extra->mask : QRegion();
10241}
10242
10243/*!
10244 Returns the layout manager that is installed on this widget, or \nullptr
10245 if no layout manager is installed.
10246
10247 The layout manager sets the geometry of the widget's children
10248 that have been added to the layout.
10249
10250 \sa setLayout(), sizePolicy(), {Layout Management}
10251*/
10252QLayout *QWidget::layout() const
10253{
10254 return d_func()->layout;
10255}
10256
10257
10258/*!
10259 \fn void QWidget::setLayout(QLayout *layout)
10260
10261 Sets the layout manager for this widget to \a layout.
10262
10263 If there already is a layout manager installed on this widget,
10264 QWidget won't let you install another. You must first delete the
10265 existing layout manager (returned by layout()) before you can
10266 call setLayout() with the new layout.
10267
10268 If \a layout is the layout manager on a different widget, setLayout()
10269 will reparent the layout and make it the layout manager for this widget.
10270
10271 Example:
10272
10273 \snippet layouts/layouts.cpp 24
10274
10275 An alternative to calling this function is to pass this widget to
10276 the layout's constructor.
10277
10278 The QWidget will take ownership of \a layout.
10279
10280 \sa layout(), {Layout Management}
10281*/
10282
10283void QWidget::setLayout(QLayout *l)
10284{
10285 if (Q_UNLIKELY(!l)) {
10286 qWarning(msg: "QWidget::setLayout: Cannot set layout to 0");
10287 return;
10288 }
10289 if (layout()) {
10290 if (Q_UNLIKELY(layout() != l))
10291 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10292 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10293 objectName().toLocal8Bit().data());
10294 return;
10295 }
10296
10297 QObject *oldParent = l->parent();
10298 if (oldParent && oldParent != this) {
10299 if (oldParent->isWidgetType()) {
10300 // Steal the layout off a widget parent. Takes effect when
10301 // morphing laid-out container widgets in Designer.
10302 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10303 oldParentWidget->takeLayout();
10304 } else {
10305 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10306 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10307 objectName().toLocal8Bit().data());
10308 return;
10309 }
10310 }
10311
10312 Q_D(QWidget);
10313 l->d_func()->topLevel = true;
10314 d->layout = l;
10315 if (oldParent != this) {
10316 l->setParent(this);
10317 l->d_func()->reparentChildWidgets(mw: this);
10318 l->invalidate();
10319 }
10320
10321 if (isWindow() && d->maybeTopData())
10322 d->topData()->sizeAdjusted = false;
10323}
10324
10325/*!
10326 \fn QLayout *QWidget::takeLayout()
10327
10328 Remove the layout from the widget.
10329 \since 4.5
10330*/
10331
10332QLayout *QWidget::takeLayout()
10333{
10334 Q_D(QWidget);
10335 QLayout *l = layout();
10336 if (!l)
10337 return nullptr;
10338 d->layout = nullptr;
10339 l->setParent(nullptr);
10340 return l;
10341}
10342
10343/*!
10344 \property QWidget::sizePolicy
10345 \brief the default layout behavior of the widget
10346
10347 If there is a QLayout that manages this widget's children, the
10348 size policy specified by that layout is used. If there is no such
10349 QLayout, the result of this function is used.
10350
10351 The default policy is Preferred/Preferred, which means that the
10352 widget can be freely resized, but prefers to be the size
10353 sizeHint() returns. Button-like widgets set the size policy to
10354 specify that they may stretch horizontally, but are fixed
10355 vertically. The same applies to lineedit controls (such as
10356 QLineEdit, QSpinBox or an editable QComboBox) and other
10357 horizontally orientated widgets (such as QProgressBar).
10358 QToolButton's are normally square, so they allow growth in both
10359 directions. Widgets that support different directions (such as
10360 QSlider, QScrollBar or QHeader) specify stretching in the
10361 respective direction only. Widgets that can provide scroll bars
10362 (usually subclasses of QScrollArea) tend to specify that they can
10363 use additional space, and that they can make do with less than
10364 sizeHint().
10365
10366 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10367*/
10368QSizePolicy QWidget::sizePolicy() const
10369{
10370 Q_D(const QWidget);
10371 return d->size_policy;
10372}
10373
10374void QWidget::setSizePolicy(QSizePolicy policy)
10375{
10376 Q_D(QWidget);
10377 setAttribute(Qt::WA_WState_OwnSizePolicy);
10378 if (policy == d->size_policy)
10379 return;
10380
10381 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10382 d->retainSizeWhenHiddenChanged = 1;
10383
10384 d->size_policy = policy;
10385
10386#if QT_CONFIG(graphicsview)
10387 if (const auto &extra = d->extra) {
10388 if (extra->proxyWidget)
10389 extra->proxyWidget->setSizePolicy(policy);
10390 }
10391#endif
10392
10393 updateGeometry();
10394 d->retainSizeWhenHiddenChanged = 0;
10395
10396 if (isWindow() && d->maybeTopData())
10397 d->topData()->sizeAdjusted = false;
10398}
10399
10400/*!
10401 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10402 \overload
10403
10404 Sets the size policy of the widget to \a horizontal and \a
10405 vertical, with standard stretch and no height-for-width.
10406
10407 \sa QSizePolicy::QSizePolicy()
10408*/
10409
10410/*!
10411 Returns the preferred height for this widget, given the width \a w.
10412
10413 If this widget has a layout, the default implementation returns
10414 the layout's preferred height. if there is no layout, the default
10415 implementation returns -1 indicating that the preferred height
10416 does not depend on the width.
10417*/
10418
10419int QWidget::heightForWidth(int w) const
10420{
10421 if (layout() && layout()->hasHeightForWidth())
10422 return layout()->totalHeightForWidth(w);
10423 return -1;
10424}
10425
10426
10427/*!
10428 \since 5.0
10429
10430 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10431*/
10432bool QWidget::hasHeightForWidth() const
10433{
10434 Q_D(const QWidget);
10435 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10436}
10437
10438/*!
10439 \fn QWidget *QWidget::childAt(int x, int y) const
10440
10441 Returns the visible child widget at the position (\a{x}, \a{y})
10442 in the widget's coordinate system. If there is no visible child
10443 widget at the specified position, the function returns \nullptr.
10444*/
10445
10446/*!
10447 \overload
10448
10449 Returns the visible child widget at point \a p in the widget's own
10450 coordinate system.
10451*/
10452
10453QWidget *QWidget::childAt(const QPoint &p) const
10454{
10455 return d_func()->childAt_helper(QPointF(p), false);
10456}
10457
10458/*!
10459 \overload
10460 \since 6.8
10461
10462 Returns the visible child widget at point \a p in the widget's own
10463 coordinate system.
10464*/
10465
10466QWidget *QWidget::childAt(const QPointF &p) const
10467{
10468 return d_func()->childAt_helper(p, false);
10469}
10470
10471QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10472{
10473 if (children.isEmpty())
10474 return nullptr;
10475
10476 if (!pointInsideRectAndMask(p))
10477 return nullptr;
10478 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10479}
10480
10481QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10482{
10483 for (int i = children.size() - 1; i >= 0; --i) {
10484 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
10485 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(attribute: Qt::WA_TransparentForMouseEvents)
10486 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10487 continue;
10488 }
10489
10490 // Map the point 'p' from parent coordinates to child coordinates.
10491 QPointF childPoint = p;
10492 childPoint -= child->data->crect.topLeft();
10493
10494 // Check if the point hits the child.
10495 if (!child->d_func()->pointInsideRectAndMask(p: childPoint))
10496 continue;
10497
10498 // Do the same for the child's descendants.
10499 if (QWidget *w = child->d_func()->childAtRecursiveHelper(p: childPoint, ignoreChildrenInDestructor))
10500 return w;
10501
10502 // We have found our target; namely the child at position 'p'.
10503 return child;
10504 }
10505 return nullptr;
10506}
10507
10508void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10509{
10510 Q_Q(QWidget);
10511 if (widgetItem)
10512 widgetItem->invalidateSizeCache();
10513 QWidget *parent;
10514 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10515 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10516
10517 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10518 if (parent->d_func()->layout)
10519 parent->d_func()->layout->invalidate();
10520 else if (parent->isVisible())
10521 QCoreApplication::postEvent(receiver: parent, event: new QEvent(QEvent::LayoutRequest));
10522 }
10523 }
10524}
10525
10526/*!
10527 Notifies the layout system that this widget has changed and may
10528 need to change geometry.
10529
10530 Call this function if the sizeHint() or sizePolicy() have changed.
10531
10532 For explicitly hidden widgets, updateGeometry() is a no-op. The
10533 layout system will be notified as soon as the widget is shown.
10534*/
10535
10536void QWidget::updateGeometry()
10537{
10538 Q_D(QWidget);
10539 d->updateGeometry_helper(forceUpdate: false);
10540}
10541
10542/*! \property QWidget::windowFlags
10543
10544 Window flags are a combination of a type (e.g. Qt::Dialog) and
10545 zero or more hints to the window system (e.g.
10546 Qt::FramelessWindowHint).
10547
10548 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10549 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10550 0) on the desktop. If the widget is a window and becomes a
10551 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10552 relative to its parent widget.
10553
10554 \note This function calls setParent() when changing the flags for
10555 a window, causing the widget to be hidden. You must call show() to make
10556 the widget visible again..
10557
10558 \sa windowType(), setWindowFlag(), {Window Flags Example}
10559*/
10560void QWidget::setWindowFlags(Qt::WindowFlags flags)
10561{
10562 Q_D(QWidget);
10563 d->setWindowFlags(flags);
10564}
10565
10566/*!
10567 \since 5.9
10568
10569 Sets the window flag \a flag on this widget if \a on is true;
10570 otherwise clears the flag.
10571
10572 \sa setWindowFlags(), windowFlags(), windowType()
10573*/
10574void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10575{
10576 Q_D(QWidget);
10577 if (on)
10578 d->setWindowFlags(data->window_flags | flag);
10579 else
10580 d->setWindowFlags(data->window_flags & ~flag);
10581}
10582
10583/*! \internal
10584
10585 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10586*/
10587void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10588{
10589 Q_Q(QWidget);
10590 if (q->data->window_flags == flags)
10591 return;
10592
10593 if ((q->data->window_flags | flags) & Qt::Window) {
10594 // the old type was a window and/or the new type is a window
10595 QPoint oldPos = q->pos();
10596 bool visible = q->isVisible();
10597 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10598 q->setParent(parent: q->parentWidget(), f: flags);
10599
10600 // if both types are windows or neither of them are, we restore
10601 // the old position
10602 if (!windowFlagChanged && (visible || q->testAttribute(attribute: Qt::WA_Moved)))
10603 q->move(p: oldPos);
10604 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10605 adjustQuitOnCloseAttribute();
10606 } else {
10607 q->data->window_flags = flags;
10608 }
10609}
10610
10611/*!
10612 Sets the window flags for the widget to \a flags,
10613 \e without telling the window system.
10614
10615 \warning Do not call this function unless you really know what
10616 you're doing.
10617
10618 \sa setWindowFlags()
10619*/
10620void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10621{
10622 data->window_flags = flags;
10623}
10624
10625/*!
10626 \fn Qt::WindowType QWidget::windowType() const
10627
10628 Returns the window type of this widget. This is identical to
10629 windowFlags() & Qt::WindowType_Mask.
10630
10631 \sa windowFlags
10632*/
10633
10634/*!
10635 Sets the parent of the widget to \a parent, and resets the window
10636 flags. The widget is moved to position (0, 0) in its new parent.
10637
10638 If the new parent widget is in a different window, the
10639 reparented widget and its children are appended to the end of the
10640 \l{setFocusPolicy()}{tab chain} of the new parent
10641 widget, in the same internal order as before. If one of the moved
10642 widgets had keyboard focus, setParent() calls clearFocus() for that
10643 widget.
10644
10645 If the new parent widget is in the same window as the
10646 old parent, setting the parent doesn't change the tab order or
10647 keyboard focus.
10648
10649 If the "new" parent widget is the old parent widget, this function
10650 does nothing.
10651
10652 \note The widget becomes invisible as part of changing its parent,
10653 even if it was previously visible. You must call show() to make the
10654 widget visible again.
10655
10656 \warning It is very unlikely that you will ever need this
10657 function. If you have a widget that changes its content
10658 dynamically, it is far easier to use \l QStackedWidget.
10659
10660 \sa setWindowFlags()
10661*/
10662void QWidget::setParent(QWidget *parent)
10663{
10664 if (parent == parentWidget())
10665 return;
10666 setParent(parent: (QWidget*)parent, f: windowFlags() & ~Qt::WindowType_Mask);
10667}
10668
10669void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10670{
10671 QWidgetPrivate *d = QWidgetPrivate::get(w: widget);
10672 if (d->renderToTexture) {
10673 QEvent e(eventType);
10674 QCoreApplication::sendEvent(receiver: widget, event: &e);
10675 }
10676
10677 for (int i = 0; i < d->children.size(); ++i) {
10678 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
10679 if (w && !w->isWindow())
10680 qSendWindowChangeToTextureChildrenRecursively(widget: w, eventType);
10681 }
10682
10683 // Notify QWidgetWindow after we've notified all child QWidgets
10684 if (auto *window = d->windowHandle(mode: QWidgetPrivate::WindowHandleMode::Direct)) {
10685 QEvent e(eventType);
10686 QCoreApplication::sendEvent(receiver: window, event: &e);
10687 }
10688}
10689
10690/*!
10691 \overload
10692
10693 This function also takes widget flags, \a f as an argument.
10694*/
10695
10696void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10697{
10698 Q_D(QWidget);
10699 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10700#ifdef QT_DEBUG
10701 const auto checkForParentChildLoops = qScopeGuard(f: [&](){
10702 int depth = 0;
10703 auto p = parentWidget();
10704 while (p) {
10705 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10706 qWarning(msg: "QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10707 "this is undefined behavior",
10708 this, metaObject()->className(), qPrintable(objectName()));
10709 }
10710 p = p->parentWidget();
10711 }
10712 });
10713#endif
10714
10715 const bool resized = testAttribute(attribute: Qt::WA_Resized);
10716 const bool wasCreated = testAttribute(attribute: Qt::WA_WState_Created);
10717 QWidget *oldtlw = window();
10718 Q_ASSERT(oldtlw);
10719 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10720
10721 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10722 d->data.fstrut_dirty = true;
10723
10724 QWidget *desktopWidget = nullptr;
10725 if (parent && parent->windowType() == Qt::Desktop)
10726 desktopWidget = parent;
10727 bool newParent = (parent != parentWidget()) || desktopWidget;
10728
10729 if (newParent && parent && !desktopWidget) {
10730 if (testAttribute(attribute: Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings))
10731 parent->d_func()->enforceNativeChildren();
10732 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(attribute: Qt::WA_PaintOnScreen))
10733 setAttribute(Qt::WA_NativeWindow);
10734 }
10735
10736 if (wasCreated) {
10737 if (!testAttribute(attribute: Qt::WA_WState_Hidden)) {
10738 // Hiding the widget will set WA_WState_Hidden as well, which would
10739 // normally require the widget to be explicitly shown again to become
10740 // visible, even as a child widget. But we refine this value later in
10741 // setParent_sys(), applying WA_WState_Hidden based on whether the
10742 // widget is a top level or not.
10743 hide();
10744
10745 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10746 // when we only had QWidget::setVisible(), which is treated as an
10747 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10748 // that allows us to hide a widget without affecting ExplicitShowHide.
10749 // Though it can be argued that ExplicitShowHide should reflect the
10750 // last update of the widget's state, so if we hide the widget as a
10751 // side effect of changing parent, perhaps we _should_ reset it?
10752 setAttribute(Qt::WA_WState_ExplicitShowHide, on: false);
10753 }
10754 if (newParent) {
10755 QEvent e(QEvent::ParentAboutToChange);
10756 QCoreApplication::sendEvent(receiver: this, event: &e);
10757 }
10758 }
10759
10760 // texture-based widgets need a pre-notification when their associated top-level window changes
10761 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10762 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10763 : oldtlw->d_func()->usesRhiFlush;
10764 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10765 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowAboutToChangeInternal);
10766
10767 // If we get parented into another window, children will be folded
10768 // into the new parent's focus chain, so clear focus now.
10769 if (newParent && isAncestorOf(child: focusWidget()) && !(f & Qt::Window))
10770 focusWidget()->clearFocus();
10771
10772 d->setParent_sys(parent, f);
10773
10774 if (desktopWidget)
10775 parent = nullptr;
10776
10777 if (d->textureChildSeen && parent) {
10778 // set the textureChildSeen flag up the whole parent chain
10779 QWidgetPrivate::get(w: parent)->setTextureChildSeen();
10780 }
10781
10782 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10783 if (newParent)
10784 oldPaintManager->removeDirtyWidget(w: this);
10785 // Move the widget and all its static children from
10786 // the old backing store to the new one.
10787 oldPaintManager->moveStaticWidgets(reparented: this);
10788 }
10789
10790 d->reparentFocusWidgets(oldtlw);
10791 setAttribute(Qt::WA_Resized, on: resized);
10792
10793 const bool useStyleSheetPropagationInWidgetStyles =
10794 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10795
10796 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(attribute: Qt::WA_StyleSheet)
10797 && (!parent || !parent->testAttribute(attribute: Qt::WA_StyleSheet))) {
10798 // if the parent has a font set or inherited, then propagate the mask to the new child
10799 if (parent) {
10800 const auto pd = parent->d_func();
10801 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10802 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10803 }
10804 d->resolveFont();
10805 d->resolvePalette();
10806 }
10807 d->resolveLayoutDirection();
10808 d->resolveLocale();
10809
10810 // Note: GL widgets under WGL or EGL will always need a ParentChange
10811 // event to handle recreation/rebinding of the GL context, hence the
10812 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10813 // platforms).
10814 if (newParent || !wasCreated
10815#if QT_CONFIG(opengles2)
10816 || (f & Qt::MSWindowsOwnDC)
10817#endif
10818 ) {
10819 // propagate enabled updates enabled state to non-windows
10820 if (!isWindow()) {
10821 if (!testAttribute(attribute: Qt::WA_ForceDisabled))
10822 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10823 if (!testAttribute(attribute: Qt::WA_ForceUpdatesDisabled))
10824 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10825 }
10826 d->inheritStyle();
10827
10828 // send and post remaining QObject events
10829 if (parent && d->sendChildEvents) {
10830 QChildEvent e(QEvent::ChildAdded, this);
10831 QCoreApplication::sendEvent(receiver: parent, event: &e);
10832 }
10833
10834 if (parent && d->sendChildEvents && d->polished) {
10835 QChildEvent e(QEvent::ChildPolished, this);
10836 QCoreApplication::sendEvent(receiver: parent, event: &e);
10837 }
10838
10839 QEvent e(QEvent::ParentChange);
10840 QCoreApplication::sendEvent(receiver: this, event: &e);
10841 }
10842
10843 // texture-based widgets need another event when their top-level window
10844 // changes (more precisely, has already changed at this point)
10845 if (oldWidgetUsesRhiFlush && oldtlw != window())
10846 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowChangeInternal);
10847
10848 if (!wasCreated) {
10849 if (isWindow() || parentWidget()->isVisible())
10850 setAttribute(Qt::WA_WState_Hidden, on: true);
10851 else if (!testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
10852 setAttribute(Qt::WA_WState_Hidden, on: false);
10853 }
10854
10855 d->updateIsOpaque();
10856
10857#if QT_CONFIG(graphicsview)
10858 // Embed the widget into a proxy if the parent is embedded.
10859 // ### Doesn't handle reparenting out of an embedded widget.
10860 if (oldtlw->graphicsProxyWidget()) {
10861 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: oldtlw))
10862 ancestorProxy->d_func()->unembedSubWindow(this);
10863 }
10864 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(p: this)) {
10865 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: parent))
10866 ancestorProxy->d_func()->embedSubWindow(this);
10867 }
10868#endif
10869
10870 if (d->extra && d->extra->hasWindowContainer)
10871 QWindowContainer::parentWasChanged(parent: this);
10872
10873 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10874 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10875 // Check if the native parent now needs to switch to RHI
10876 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10877 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10878
10879 QPlatformBackingStoreRhiConfig rhiConfig;
10880 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10881
10882 // First evaluate whether the reparented widget uses RHI.
10883 // We do this as a separate step because the performance
10884 // implications of always checking the native parent are
10885 // problematic when it comes to large widget trees.
10886 if (q_evaluateRhiConfig(w: this, outConfig: &rhiConfig, outType: &surfaceType)) {
10887 // Then check whether the native parent requires RHI
10888 // as a result. It may not, if this widget is a native
10889 // window, and can handle its own RHI flushing.
10890 if (q_evaluateRhiConfig(w: newParentWithWindow, outConfig: nullptr, outType: nullptr)) {
10891 // Finally, check whether we need to recreate the
10892 // native parent to enable RHI flushing.
10893 auto *existingWindow = newParentWithWindow->windowHandle();
10894 auto existingSurfaceType = existingWindow->surfaceType();
10895 if (existingSurfaceType != surfaceType) {
10896 qCDebug(lcWidgetPainting)
10897 << "Recreating" << existingWindow
10898 << "with current type" << existingSurfaceType
10899 << "to support" << surfaceType;
10900 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10901 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10902 newParentWithWindow->destroy();
10903 newParentWithWindow->create();
10904 Q_ASSERT(newParentWithWindow->windowHandle());
10905 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10906 QWidgetPrivate::get(w: newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10907 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10908 // If we don't recreate we still need to make sure the native parent
10909 // widget has a RHI config that the reparented widget can use.
10910 backingStore->handle()->createRhi(window: existingWindow, config: rhiConfig);
10911 // And that it knows it's now flushing with RHI
10912 QWidgetPrivate::get(w: newParentWithWindow)->usesRhiFlush = true;
10913 }
10914 }
10915 }
10916 }
10917}
10918
10919void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10920{
10921 Q_Q(QWidget);
10922
10923 Qt::WindowFlags oldFlags = data.window_flags;
10924 bool wasCreated = q->testAttribute(attribute: Qt::WA_WState_Created);
10925
10926 QScreen *targetScreen = nullptr;
10927 // Handle a request to move the widget to a particular screen
10928 if (newparent && newparent->windowType() == Qt::Desktop) {
10929 // make sure the widget is created on the same screen as the
10930 // programmer specified desktop widget
10931 targetScreen = newparent->screen();
10932 newparent = nullptr;
10933 }
10934
10935 setWinId(0);
10936
10937 if (!newparent) {
10938 f |= Qt::Window;
10939 if (parent)
10940 targetScreen = q->parentWidget()->window()->screen();
10941 }
10942
10943 const bool destroyWindow = (
10944 // Reparenting top level to child
10945 (oldFlags & Qt::Window) && !(f & Qt::Window)
10946 // And we can dispose of the window
10947 && wasCreated && !q->testAttribute(attribute: Qt::WA_NativeWindow)
10948 );
10949
10950 if (parent != newparent) {
10951 // Update object parent now, so we can resolve new parent window below
10952 QObjectPrivate::setParent_helper(newparent);
10953
10954 if (q->windowHandle())
10955 q->windowHandle()->setFlags(f);
10956
10957 // If the widget itself or any of its children have been created,
10958 // we need to reparent their QWindows as well.
10959 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10960 // But if the widget is about to be destroyed we must skip the
10961 // widget itself, and only reparent children.
10962 if (destroyWindow) {
10963 reparentWidgetWindowChildren(parentWithWindow);
10964 } else {
10965 // During reparentWidgetWindows() we need to know whether the reparented
10966 // QWindow should be a top level (with a transient parent) or not. This
10967 // widget has not updated its window flags yet, so we can't ask the widget
10968 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10969 // the QWindow flags always reflect Qt::Window, even for child windows. And
10970 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10971 // which we are in the process of updating. So we propagate the
10972 // new flags of the reparented window here.
10973 reparentWidgetWindows(parentWithWindow, windowFlags: f);
10974 }
10975 }
10976
10977 bool explicitlyHidden = isExplicitlyHidden();
10978
10979 if (destroyWindow) {
10980 if (extra && extra->hasWindowContainer)
10981 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
10982
10983 // There shouldn't be any QWindow children left, but if there
10984 // are, re-parent them now, before we destroy.
10985 if (!q->windowHandle()->children().isEmpty()) {
10986 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10987 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
10988 for (QObject *child : q->windowHandle()->children()) {
10989 if (QWindow *childWindow = qobject_cast<QWindow *>(o: child)) {
10990 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
10991 << "before destroying" << this;
10992 childWindow->setParent(newParentWindow);
10993 }
10994 }
10995 }
10996
10997 // We have reparented any child windows of the widget we are
10998 // about to destroy to the new parent window handle, so we can
10999 // safely destroy this widget without destroying sub windows.
11000 q->destroy(destroyWindow: true, destroySubWindows: false);
11001 }
11002
11003 adjustFlags(flags&: f, w: q);
11004 data.window_flags = f;
11005 q->setAttribute(Qt::WA_WState_Created, on: false);
11006 q->setAttribute(Qt::WA_WState_Visible, on: false);
11007 q->setAttribute(Qt::WA_WState_Hidden, on: false);
11008
11009 if (newparent && wasCreated && (q->testAttribute(attribute: Qt::WA_NativeWindow) || (f & Qt::Window)))
11010 q->createWinId();
11011
11012 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11013 q->setAttribute(Qt::WA_WState_Hidden);
11014 q->setAttribute(Qt::WA_WState_ExplicitShowHide, on: explicitlyHidden);
11015
11016 // move the window to the selected screen
11017 if (!newparent && targetScreen) {
11018 // only if it is already created
11019 if (q->testAttribute(attribute: Qt::WA_WState_Created))
11020 q->windowHandle()->setScreen(targetScreen);
11021 else
11022 topData()->initialScreen = targetScreen;
11023 }
11024}
11025
11026void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11027{
11028 if (QWindow *window = windowHandle()) {
11029 // Reparent this QWindow, and all QWindow children will follow
11030 if (parentWithWindow) {
11031 if (windowFlags & Qt::Window) {
11032 // Top level windows can only have transient parents,
11033 // and the transient parent must be another top level.
11034 QWidget *topLevel = parentWithWindow->window();
11035 auto *transientParent = topLevel->windowHandle();
11036 Q_ASSERT(transientParent);
11037 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11038 window->setTransientParent(transientParent);
11039 window->setParent(nullptr);
11040 } else {
11041 auto *parentWindow = parentWithWindow->windowHandle();
11042 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11043 window->setTransientParent(nullptr);
11044 window->setParent(parentWindow);
11045 }
11046 } else {
11047 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11048 window->setTransientParent(nullptr);
11049 window->setParent(nullptr);
11050 }
11051 } else {
11052 reparentWidgetWindowChildren(parentWithWindow);
11053 }
11054}
11055
11056void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11057{
11058 for (auto *child : std::as_const(t&: children)) {
11059 if (auto *childWidget = qobject_cast<QWidget*>(o: child)) {
11060 auto *childPrivate = QWidgetPrivate::get(w: childWidget);
11061 // Child widgets with QWindows should always continue to be child
11062 // windows, so we pass on the child's current window flags here.
11063 childPrivate->reparentWidgetWindows(parentWithWindow, windowFlags: childWidget->windowFlags());
11064 }
11065 }
11066}
11067
11068/*!
11069 Scrolls the widget including its children \a dx pixels to the
11070 right and \a dy downward. Both \a dx and \a dy may be negative.
11071
11072 After scrolling, the widgets will receive paint events for
11073 the areas that need to be repainted. For widgets that Qt knows to
11074 be opaque, this is only the newly exposed parts.
11075 For example, if an opaque widget is scrolled 8 pixels to the left,
11076 only an 8-pixel wide stripe at the right edge needs updating.
11077
11078 Since widgets propagate the contents of their parents by default,
11079 you need to set the \l autoFillBackground property, or use
11080 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11081 a widget opaque.
11082
11083 For widgets that use contents propagation, a scroll will cause an
11084 update of the entire scroll area.
11085
11086 \sa {Transparency and Double Buffering}
11087*/
11088
11089void QWidget::scroll(int dx, int dy)
11090{
11091 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11092 return;
11093 if (dx == 0 && dy == 0)
11094 return;
11095 Q_D(QWidget);
11096#if QT_CONFIG(graphicsview)
11097 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11098 // Graphics View maintains its own dirty region as a list of rects;
11099 // until we can connect item updates directly to the view, we must
11100 // separately add a translated dirty region.
11101 for (const QRect &rect : d->dirty)
11102 proxy->update(rect: rect.translated(dx, dy));
11103 proxy->scroll(dx, dy, rect: proxy->subWidgetRect(widget: this));
11104 return;
11105 }
11106#endif
11107 d->setDirtyOpaqueRegion();
11108 d->scroll_sys(dx, dy);
11109}
11110
11111void QWidgetPrivate::scroll_sys(int dx, int dy)
11112{
11113 Q_Q(QWidget);
11114 scrollChildren(dx, dy);
11115 scrollRect(q->rect(), dx, dy);
11116}
11117
11118/*!
11119 \overload
11120
11121 This version only scrolls \a r and does not move the children of
11122 the widget.
11123
11124 If \a r is empty or invalid, the result is undefined.
11125
11126 \sa QScrollArea
11127*/
11128void QWidget::scroll(int dx, int dy, const QRect &r)
11129{
11130
11131 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11132 return;
11133 if (dx == 0 && dy == 0)
11134 return;
11135 Q_D(QWidget);
11136#if QT_CONFIG(graphicsview)
11137 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11138 // Graphics View maintains its own dirty region as a list of rects;
11139 // until we can connect item updates directly to the view, we must
11140 // separately add a translated dirty region.
11141 if (!d->dirty.isEmpty()) {
11142 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11143 proxy->update(rect);
11144 }
11145 proxy->scroll(dx, dy, rect: r.translated(p: proxy->subWidgetRect(widget: this).topLeft().toPoint()));
11146 return;
11147 }
11148#endif
11149 d->scroll_sys(dx, dy, r);
11150}
11151
11152void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11153{
11154 scrollRect(r, dx, dy);
11155}
11156
11157/*!
11158 Repaints the widget directly by calling paintEvent() immediately,
11159 unless updates are disabled or the widget is hidden.
11160
11161 We suggest only using repaint() if you need an immediate repaint,
11162 for example during animation. In most circumstances update()
11163 is better, as it permits Qt to optimize for speed and minimize
11164 flicker.
11165
11166 \warning If you call repaint() in a function which may itself be
11167 called from paintEvent(), you may get infinite recursion. The
11168 update() function never causes recursion.
11169
11170 \sa update(), paintEvent(), setUpdatesEnabled()
11171*/
11172
11173void QWidget::repaint()
11174{
11175 repaint(rect());
11176}
11177
11178/*! \overload
11179
11180 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11181 the widget.
11182
11183 If \a w is negative, it is replaced with \c{width() - x}, and if
11184 \a h is negative, it is replaced width \c{height() - y}.
11185*/
11186void QWidget::repaint(int x, int y, int w, int h)
11187{
11188 if (x > data->crect.width() || y > data->crect.height())
11189 return;
11190
11191 if (w < 0)
11192 w = data->crect.width() - x;
11193 if (h < 0)
11194 h = data->crect.height() - y;
11195
11196 repaint(QRect(x, y, w, h));
11197}
11198
11199/*! \overload
11200
11201 This version repaints a rectangle \a rect inside the widget.
11202*/
11203void QWidget::repaint(const QRect &rect)
11204{
11205 Q_D(QWidget);
11206 d->repaint(r: rect);
11207}
11208
11209/*!
11210 \overload
11211
11212 This version repaints a region \a rgn inside the widget.
11213*/
11214void QWidget::repaint(const QRegion &rgn)
11215{
11216 Q_D(QWidget);
11217 d->repaint(r: rgn);
11218}
11219
11220template <typename T>
11221void QWidgetPrivate::repaint(T r)
11222{
11223 Q_Q(QWidget);
11224
11225 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11226 return;
11227
11228 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11229 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11230 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11231}
11232
11233/*!
11234 Updates the widget unless updates are disabled or the widget is
11235 hidden.
11236
11237 This function does not cause an immediate repaint; instead it
11238 schedules a paint event for processing when Qt returns to the main
11239 event loop. This permits Qt to optimize for more speed and less
11240 flicker than a call to repaint() does.
11241
11242 Calling update() several times normally results in just one
11243 paintEvent() call.
11244
11245 Qt normally erases the widget's area before the paintEvent() call.
11246 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11247 responsible for painting all its pixels with an opaque color.
11248
11249 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11250*/
11251void QWidget::update()
11252{
11253 update(rect());
11254}
11255
11256/*! \fn void QWidget::update(int x, int y, int w, int h)
11257 \overload
11258
11259 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11260 the widget.
11261*/
11262
11263/*!
11264 \overload
11265
11266 This version updates a rectangle \a rect inside the widget.
11267*/
11268void QWidget::update(const QRect &rect)
11269{
11270 Q_D(QWidget);
11271 d->update(r: rect);
11272}
11273
11274/*!
11275 \overload
11276
11277 This version repaints a region \a rgn inside the widget.
11278*/
11279void QWidget::update(const QRegion &rgn)
11280{
11281 Q_D(QWidget);
11282 d->update(r: rgn);
11283}
11284
11285template <typename T>
11286void QWidgetPrivate::update(T r)
11287{
11288 Q_Q(QWidget);
11289
11290 if (renderToTexture && !q->isVisible()) {
11291 renderToTextureReallyDirty = 1;
11292 return;
11293 }
11294
11295 if (!q->isVisible() || !q->updatesEnabled())
11296 return;
11297
11298 T clipped = r & q->rect();
11299
11300 if (clipped.isEmpty())
11301 return;
11302
11303 if (q->testAttribute(attribute: Qt::WA_WState_InPaintEvent)) {
11304 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(clipped));
11305 return;
11306 }
11307
11308 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11309 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11310 tlwExtra->repaintManager->markDirty(clipped, q);
11311}
11312
11313 /*!
11314 \internal
11315
11316 This just sets the corresponding attribute bit to 1 or 0
11317 */
11318static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11319 QWidgetPrivate *d)
11320{
11321 if (attribute < int(8*sizeof(uint))) {
11322 if (on)
11323 data->widget_attributes |= (1<<attribute);
11324 else
11325 data->widget_attributes &= ~(1<<attribute);
11326 } else {
11327 const int x = attribute - 8*sizeof(uint);
11328 const int int_off = x / (8*sizeof(uint));
11329 if (on)
11330 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11331 else
11332 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11333 }
11334}
11335
11336#ifdef Q_OS_MAC
11337void QWidgetPrivate::macUpdateSizeAttribute()
11338{
11339 Q_Q(QWidget);
11340 QEvent event(QEvent::MacSizeChange);
11341 QCoreApplication::sendEvent(q, &event);
11342 for (int i = 0; i < children.size(); ++i) {
11343 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11344 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11345 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11346 && !w->testAttribute(Qt::WA_MacSmallSize)
11347 && !w->testAttribute(Qt::WA_MacNormalSize))
11348 w->d_func()->macUpdateSizeAttribute();
11349 }
11350 resolveFont();
11351}
11352#endif
11353
11354/*!
11355 Sets the attribute \a attribute on this widget if \a on is true;
11356 otherwise clears the attribute.
11357
11358 \sa testAttribute()
11359*/
11360void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11361{
11362 if (testAttribute(attribute) == on)
11363 return;
11364
11365 Q_D(QWidget);
11366 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11367 "QWidget::setAttribute(WidgetAttribute, bool): "
11368 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11369#ifdef Q_OS_WIN
11370 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11371 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
11372 // see ::paintEngine for details
11373 paintEngine();
11374 if (d->noPaintOnScreen)
11375 return;
11376 }
11377#endif
11378
11379 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11380 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11381 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11382 if (!platformIntegration->hasCapability(cap: QPlatformIntegration::NativeWidgets))
11383 return;
11384 }
11385
11386 setAttribute_internal(attribute, on, data, d);
11387
11388 switch (attribute) {
11389
11390#if QT_CONFIG(draganddrop)
11391 case Qt::WA_AcceptDrops: {
11392 if (on && !testAttribute(attribute: Qt::WA_DropSiteRegistered))
11393 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: true);
11394 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered)))
11395 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: false);
11396 QEvent e(QEvent::AcceptDropsChange);
11397 QCoreApplication::sendEvent(receiver: this, event: &e);
11398 break;
11399 }
11400 case Qt::WA_DropSiteRegistered: {
11401 for (int i = 0; i < d->children.size(); ++i) {
11402 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
11403 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_AcceptDrops) && w->testAttribute(attribute: Qt::WA_DropSiteRegistered) != on)
11404 w->setAttribute(attribute: Qt::WA_DropSiteRegistered, on);
11405 }
11406 break;
11407 }
11408#endif
11409
11410 case Qt::WA_NoChildEventsForParent:
11411 d->sendChildEvents = !on;
11412 break;
11413 case Qt::WA_NoChildEventsFromChildren:
11414 d->receiveChildEvents = !on;
11415 break;
11416 case Qt::WA_MacNormalSize:
11417 case Qt::WA_MacSmallSize:
11418 case Qt::WA_MacMiniSize:
11419#ifdef Q_OS_MAC
11420 {
11421 // We can only have one of these set at a time
11422 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11423 Qt::WA_MacMiniSize };
11424 for (int i = 0; i < 3; ++i) {
11425 if (MacSizes[i] != attribute)
11426 setAttribute_internal(MacSizes[i], false, data, d);
11427 }
11428 d->macUpdateSizeAttribute();
11429 }
11430#endif
11431 break;
11432 case Qt::WA_ShowModal:
11433 if (!on) {
11434 // reset modality type to NonModal when clearing WA_ShowModal
11435 data->window_modality = Qt::NonModal;
11436 } else if (data->window_modality == Qt::NonModal) {
11437 // If modality hasn't been set prior to setting WA_ShowModal, use
11438 // ApplicationModal.
11439 data->window_modality = Qt::ApplicationModal;
11440 // Some window managers do not allow us to enter modality after the
11441 // window is visible.The window must be hidden before changing the
11442 // windowModality property and then reshown.
11443 }
11444 if (testAttribute(attribute: Qt::WA_WState_Created)) {
11445 // don't call setModal_sys() before create()
11446 d->setModal_sys();
11447 }
11448 break;
11449 case Qt::WA_MouseTracking: {
11450 QEvent e(QEvent::MouseTrackingChange);
11451 QCoreApplication::sendEvent(receiver: this, event: &e);
11452 break; }
11453 case Qt::WA_TabletTracking: {
11454 QEvent e(QEvent::TabletTrackingChange);
11455 QCoreApplication::sendEvent(receiver: this, event: &e);
11456 break; }
11457 case Qt::WA_NativeWindow: {
11458 d->createTLExtra();
11459 if (on)
11460 d->createTLSysExtra();
11461#ifndef QT_NO_IM
11462 QWidget *focusWidget = d->effectiveFocusWidget();
11463 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11464 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11465 QGuiApplication::inputMethod()->commit();
11466 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11467 }
11468 if (!QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11469 parentWidget()->d_func()->enforceNativeChildren();
11470 if (on && !internalWinId() && testAttribute(attribute: Qt::WA_WState_Created))
11471 d->createWinId();
11472 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11473 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11474 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11475 }
11476#endif //QT_NO_IM
11477 break;
11478 }
11479 case Qt::WA_PaintOnScreen:
11480 d->updateIsOpaque();
11481 Q_FALLTHROUGH();
11482 case Qt::WA_OpaquePaintEvent:
11483 d->updateIsOpaque();
11484 break;
11485 case Qt::WA_NoSystemBackground:
11486 d->updateIsOpaque();
11487 Q_FALLTHROUGH();
11488 case Qt::WA_UpdatesDisabled:
11489 d->updateSystemBackground();
11490 break;
11491 case Qt::WA_TransparentForMouseEvents:
11492 break;
11493 case Qt::WA_InputMethodEnabled: {
11494#ifndef QT_NO_IM
11495 if (QGuiApplication::focusObject() == this) {
11496 if (!on)
11497 QGuiApplication::inputMethod()->commit();
11498 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11499 }
11500#endif //QT_NO_IM
11501 break;
11502 }
11503 case Qt::WA_WindowPropagation:
11504 d->resolvePalette();
11505 d->resolveFont();
11506 d->resolveLocale();
11507 break;
11508 case Qt::WA_DontShowOnScreen: {
11509 if (on && isVisible()) {
11510 // Make sure we keep the current state and only hide the widget
11511 // from the desktop. show_sys will only update platform specific
11512 // attributes at this point.
11513 d->hide_sys();
11514 d->show_sys();
11515 }
11516 break;
11517 }
11518
11519 case Qt::WA_X11NetWmWindowTypeDesktop:
11520 case Qt::WA_X11NetWmWindowTypeDock:
11521 case Qt::WA_X11NetWmWindowTypeToolBar:
11522 case Qt::WA_X11NetWmWindowTypeMenu:
11523 case Qt::WA_X11NetWmWindowTypeUtility:
11524 case Qt::WA_X11NetWmWindowTypeSplash:
11525 case Qt::WA_X11NetWmWindowTypeDialog:
11526 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11527 case Qt::WA_X11NetWmWindowTypePopupMenu:
11528 case Qt::WA_X11NetWmWindowTypeToolTip:
11529 case Qt::WA_X11NetWmWindowTypeNotification:
11530 case Qt::WA_X11NetWmWindowTypeCombo:
11531 case Qt::WA_X11NetWmWindowTypeDND:
11532 d->setNetWmWindowTypes();
11533 break;
11534
11535 case Qt::WA_StaticContents:
11536 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11537 if (on)
11538 repaintManager->addStaticWidget(widget: this);
11539 else
11540 repaintManager->removeStaticWidget(widget: this);
11541 }
11542 break;
11543 case Qt::WA_TranslucentBackground:
11544 if (on)
11545 setAttribute(attribute: Qt::WA_NoSystemBackground);
11546 d->updateIsTranslucent();
11547
11548 break;
11549 case Qt::WA_AcceptTouchEvents:
11550 break;
11551 default:
11552 break;
11553 }
11554}
11555
11556/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11557
11558 Returns \c true if attribute \a attribute is set on this widget;
11559 otherwise returns \c false.
11560
11561 \sa setAttribute()
11562 */
11563bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11564{
11565 Q_D(const QWidget);
11566 const int x = attribute - 8*sizeof(uint);
11567 const int int_off = x / (8*sizeof(uint));
11568 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11569}
11570
11571/*!
11572 \property QWidget::windowOpacity
11573
11574 \brief The level of opacity for the window.
11575
11576 The valid range of opacity is from 1.0 (completely opaque) to
11577 0.0 (completely transparent).
11578
11579 By default the value of this property is 1.0.
11580
11581 This feature is available on Embedded Linux, \macos, Windows,
11582 and X11 platforms that support the Composite extension.
11583
11584 \note On X11 you need to have a composite manager running,
11585 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11586 supported by the window manager you are using.
11587
11588 \warning Changing this property from opaque to transparent might issue a
11589 paint event that needs to be processed before the window is displayed
11590 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11591 that semi-transparent windows update and resize significantly slower than
11592 opaque windows.
11593
11594 \sa setMask()
11595*/
11596qreal QWidget::windowOpacity() const
11597{
11598 Q_D(const QWidget);
11599 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11600}
11601
11602void QWidget::setWindowOpacity(qreal opacity)
11603{
11604 Q_D(QWidget);
11605 if (!isWindow())
11606 return;
11607
11608 opacity = qBound(min: qreal(0.0), val: opacity, max: qreal(1.0));
11609 QTLWExtra *extra = d->topData();
11610 extra->opacity = uint(opacity * 255);
11611 setAttribute(attribute: Qt::WA_WState_WindowOpacitySet);
11612 d->setWindowOpacity_sys(opacity);
11613
11614 if (!testAttribute(attribute: Qt::WA_WState_Created))
11615 return;
11616
11617#if QT_CONFIG(graphicsview)
11618 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11619 // Avoid invalidating the cache if set.
11620 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11621 proxy->update();
11622 else if (QGraphicsScene *scene = proxy->scene())
11623 scene->update(rect: proxy->sceneBoundingRect());
11624 return;
11625 }
11626#endif
11627}
11628
11629void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11630{
11631 Q_Q(QWidget);
11632 if (q->windowHandle())
11633 q->windowHandle()->setOpacity(level);
11634}
11635
11636/*!
11637 \property QWidget::windowModified
11638 \brief whether the document shown in the window has unsaved changes
11639
11640 A modified window is a window whose content has changed but has
11641 not been saved to disk. This flag will have different effects
11642 varied by the platform. On \macos the close button will have a
11643 modified look; on other platforms, the window title will have an
11644 '*' (asterisk).
11645
11646 The window title must contain a "[*]" placeholder, which
11647 indicates where the '*' should appear. Normally, it should appear
11648 right after the file name (e.g., "document1.txt[*] - Text
11649 Editor"). If the window isn't modified, the placeholder is simply
11650 removed.
11651
11652 Note that if a widget is set as modified, all its ancestors will
11653 also be set as modified. However, if you call \c
11654 {setWindowModified(false)} on a widget, this will not propagate to
11655 its parent because other children of the parent might have been
11656 modified.
11657
11658 \sa windowTitle
11659*/
11660bool QWidget::isWindowModified() const
11661{
11662 return testAttribute(attribute: Qt::WA_WindowModified);
11663}
11664
11665void QWidget::setWindowModified(bool mod)
11666{
11667 Q_D(QWidget);
11668 setAttribute(attribute: Qt::WA_WindowModified, on: mod);
11669
11670 d->setWindowModified_helper();
11671
11672 QEvent e(QEvent::ModifiedChange);
11673 QCoreApplication::sendEvent(receiver: this, event: &e);
11674}
11675
11676void QWidgetPrivate::setWindowModified_helper()
11677{
11678 Q_Q(QWidget);
11679 QWindow *window = q->windowHandle();
11680 if (!window)
11681 return;
11682 QPlatformWindow *platformWindow = window->handle();
11683 if (!platformWindow)
11684 return;
11685 bool on = q->testAttribute(attribute: Qt::WA_WindowModified);
11686 if (!platformWindow->setWindowModified(on)) {
11687 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11688 qWarning(msg: "QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11689 setWindowTitle_helper(q->windowTitle());
11690 setWindowIconText_helper(q->windowIconText());
11691 }
11692}
11693
11694#if QT_CONFIG(tooltip)
11695/*!
11696 \property QWidget::toolTip
11697
11698 \brief the widget's tooltip
11699
11700 Note that by default tooltips are only shown for widgets that are
11701 children of the active window. You can change this behavior by
11702 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11703 not on the widget with the tooltip.
11704
11705 If you want to control a tooltip's behavior, you can intercept the
11706 event() function and catch the QEvent::ToolTip event (e.g., if you
11707 want to customize the area for which the tooltip should be shown).
11708
11709 By default, this property contains an empty string.
11710
11711 \sa QToolTip, statusTip, whatsThis
11712*/
11713void QWidget::setToolTip(const QString &s)
11714{
11715 Q_D(QWidget);
11716 d->toolTip = s;
11717
11718 QEvent event(QEvent::ToolTipChange);
11719 QCoreApplication::sendEvent(receiver: this, event: &event);
11720}
11721
11722QString QWidget::toolTip() const
11723{
11724 Q_D(const QWidget);
11725 return d->toolTip;
11726}
11727
11728/*!
11729 \property QWidget::toolTipDuration
11730 \brief the widget's tooltip duration
11731 \since 5.2
11732
11733 Specifies how long time the tooltip will be displayed, in milliseconds.
11734 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11735
11736 \sa toolTip
11737*/
11738
11739void QWidget::setToolTipDuration(int msec)
11740{
11741 Q_D(QWidget);
11742 d->toolTipDuration = msec;
11743}
11744
11745int QWidget::toolTipDuration() const
11746{
11747 Q_D(const QWidget);
11748 return d->toolTipDuration;
11749}
11750
11751#endif // QT_CONFIG(tooltip)
11752
11753
11754#if QT_CONFIG(statustip)
11755/*!
11756 \property QWidget::statusTip
11757 \brief the widget's status tip
11758
11759 By default, this property contains an empty string.
11760
11761 \sa toolTip, whatsThis
11762*/
11763void QWidget::setStatusTip(const QString &s)
11764{
11765 Q_D(QWidget);
11766 d->statusTip = s;
11767}
11768
11769QString QWidget::statusTip() const
11770{
11771 Q_D(const QWidget);
11772 return d->statusTip;
11773}
11774#endif // QT_CONFIG(statustip)
11775
11776#if QT_CONFIG(whatsthis)
11777/*!
11778 \property QWidget::whatsThis
11779
11780 \brief the widget's What's This help text.
11781
11782 By default, this property contains an empty string.
11783
11784 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11785*/
11786void QWidget::setWhatsThis(const QString &s)
11787{
11788 Q_D(QWidget);
11789 d->whatsThis = s;
11790}
11791
11792QString QWidget::whatsThis() const
11793{
11794 Q_D(const QWidget);
11795 return d->whatsThis;
11796}
11797#endif // QT_CONFIG(whatsthis)
11798
11799#if QT_CONFIG(accessibility)
11800/*!
11801 \property QWidget::accessibleName
11802
11803 \brief the widget's name as seen by assistive technologies
11804
11805 This is the primary name by which assistive technology such as screen readers
11806 announce this widget. For most widgets setting this property is not required.
11807 For example for QPushButton the button's text will be used.
11808
11809 It is important to set this property when the widget does not provide any
11810 text. For example a button that only contains an icon needs to set this
11811 property to work with screen readers.
11812 The name should be short and equivalent to the visual information conveyed
11813 by the widget.
11814
11815 This property has to be \l{Internationalization with Qt}{localized}.
11816
11817 By default, this property contains an empty string.
11818
11819 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11820*/
11821void QWidget::setAccessibleName(const QString &name)
11822{
11823 Q_D(QWidget);
11824 d->accessibleName = name;
11825 QAccessibleEvent event(this, QAccessible::NameChanged);
11826 QAccessible::updateAccessibility(event: &event);
11827}
11828
11829QString QWidget::accessibleName() const
11830{
11831 Q_D(const QWidget);
11832 return d->accessibleName;
11833}
11834
11835/*!
11836 \property QWidget::accessibleDescription
11837
11838 \brief the widget's description as seen by assistive technologies
11839
11840 The accessible description of a widget should convey what a widget does.
11841 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11842 the description should give more context, such as \gui{Saves the current document}.
11843
11844 This property has to be \l{Internationalization with Qt}{localized}.
11845
11846 By default, this property contains an empty string and Qt falls back
11847 to using the tool tip to provide this information.
11848
11849 \sa QWidget::accessibleName, QAccessibleInterface::text()
11850*/
11851void QWidget::setAccessibleDescription(const QString &description)
11852{
11853 Q_D(QWidget);
11854 d->accessibleDescription = description;
11855 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11856 QAccessible::updateAccessibility(event: &event);
11857}
11858
11859QString QWidget::accessibleDescription() const
11860{
11861 Q_D(const QWidget);
11862 return d->accessibleDescription;
11863}
11864#endif // QT_CONFIG(accessibility)
11865
11866#ifndef QT_NO_SHORTCUT
11867/*!
11868 Adds a shortcut to Qt's shortcut system that watches for the given
11869 \a key sequence in the given \a context. If the \a context is
11870 Qt::ApplicationShortcut, the shortcut applies to the application as a
11871 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11872 or to the window itself, Qt::WindowShortcut.
11873
11874 If the same \a key sequence has been grabbed by several widgets,
11875 when the \a key sequence occurs a QEvent::Shortcut event is sent
11876 to all the widgets to which it applies in a non-deterministic
11877 order, but with the ``ambiguous'' flag set to true.
11878
11879 \warning You should not normally need to use this function;
11880 instead create \l{QAction}s with the shortcut key sequences you
11881 require (if you also want equivalent menu options and toolbar
11882 buttons), or create \l{QShortcut}s if you just need key sequences.
11883 Both QAction and QShortcut handle all the event filtering for you,
11884 and provide signals which are triggered when the user triggers the
11885 key sequence, so are much easier to use than this low-level
11886 function.
11887
11888 \sa releaseShortcut(), setShortcutEnabled()
11889*/
11890int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11891{
11892 Q_ASSERT(qApp);
11893 if (key.isEmpty())
11894 return 0;
11895 setAttribute(attribute: Qt::WA_GrabbedShortcut);
11896 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(owner: this, key, context, matcher: qWidgetShortcutContextMatcher);
11897}
11898
11899/*!
11900 Removes the shortcut with the given \a id from Qt's shortcut
11901 system. The widget will no longer receive QEvent::Shortcut events
11902 for the shortcut's key sequence (unless it has other shortcuts
11903 with the same key sequence).
11904
11905 \warning You should not normally need to use this function since
11906 Qt's shortcut system removes shortcuts automatically when their
11907 parent widget is destroyed. It is best to use QAction or
11908 QShortcut to handle shortcuts, since they are easier to use than
11909 this low-level function. Note also that this is an expensive
11910 operation.
11911
11912 \sa grabShortcut(), setShortcutEnabled()
11913*/
11914void QWidget::releaseShortcut(int id)
11915{
11916 Q_ASSERT(qApp);
11917 if (id)
11918 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, owner: this, key: 0);
11919}
11920
11921/*!
11922 If \a enable is true, the shortcut with the given \a id is
11923 enabled; otherwise the shortcut is disabled.
11924
11925 \warning You should not normally need to use this function since
11926 Qt's shortcut system enables/disables shortcuts automatically as
11927 widgets become hidden/visible and gain or lose focus. It is best
11928 to use QAction or QShortcut to handle shortcuts, since they are
11929 easier to use than this low-level function.
11930
11931 \sa grabShortcut(), releaseShortcut()
11932*/
11933void QWidget::setShortcutEnabled(int id, bool enable)
11934{
11935 Q_ASSERT(qApp);
11936 if (id)
11937 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, owner: this, key: 0);
11938}
11939
11940/*!
11941 \since 4.2
11942
11943 If \a enable is true, auto repeat of the shortcut with the
11944 given \a id is enabled; otherwise it is disabled.
11945
11946 \sa grabShortcut(), releaseShortcut()
11947*/
11948void QWidget::setShortcutAutoRepeat(int id, bool enable)
11949{
11950 Q_ASSERT(qApp);
11951 if (id)
11952 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on: enable, id, owner: this, key: 0);
11953}
11954#endif // QT_NO_SHORTCUT
11955
11956/*!
11957 Updates the widget's micro focus and informs input methods
11958 that the state specified by \a query has changed.
11959*/
11960void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
11961{
11962 if (this == QGuiApplication::focusObject())
11963 QGuiApplication::inputMethod()->update(queries: query);
11964}
11965
11966/*!
11967 Raises this widget to the top of the parent widget's stack.
11968
11969 After this call the widget will be visually in front of any
11970 overlapping sibling widgets.
11971
11972 \note When using activateWindow(), you can call this function to
11973 ensure that the window is stacked on top.
11974
11975 \sa lower(), stackUnder()
11976*/
11977
11978void QWidget::raise()
11979{
11980 Q_D(QWidget);
11981 if (!isWindow()) {
11982 QWidget *p = parentWidget();
11983 const int parentChildCount = p->d_func()->children.size();
11984 if (parentChildCount < 2)
11985 return;
11986 const int from = p->d_func()->children.indexOf(t: this);
11987 Q_ASSERT(from >= 0);
11988 // Do nothing if the widget is already in correct stacking order _and_ created.
11989 if (from != parentChildCount -1)
11990 p->d_func()->children.move(from, to: parentChildCount - 1);
11991 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
11992 create();
11993 else if (from == parentChildCount - 1)
11994 return;
11995
11996 QRegion region(rect());
11997 d->subtractOpaqueSiblings(sourceRegion&: region);
11998 d->invalidateBackingStore(region);
11999 }
12000 if (testAttribute(attribute: Qt::WA_WState_Created))
12001 d->raise_sys();
12002
12003 if (d->extra && d->extra->hasWindowContainer)
12004 QWindowContainer::parentWasRaised(parent: this);
12005
12006 QEvent e(QEvent::ZOrderChange);
12007 QCoreApplication::sendEvent(receiver: this, event: &e);
12008}
12009
12010void QWidgetPrivate::raise_sys()
12011{
12012 Q_Q(QWidget);
12013 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12014 q->windowHandle()->raise();
12015 } else if (renderToTexture) {
12016 if (QWidget *p = q->parentWidget()) {
12017 setDirtyOpaqueRegion();
12018 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12019 }
12020 }
12021}
12022
12023/*!
12024 Lowers the widget to the bottom of the parent widget's stack.
12025
12026 After this call the widget will be visually behind (and therefore
12027 obscured by) any overlapping sibling widgets.
12028
12029 \sa raise(), stackUnder()
12030*/
12031
12032void QWidget::lower()
12033{
12034 Q_D(QWidget);
12035 if (!isWindow()) {
12036 QWidget *p = parentWidget();
12037 const int parentChildCount = p->d_func()->children.size();
12038 if (parentChildCount < 2)
12039 return;
12040 const int from = p->d_func()->children.indexOf(t: this);
12041 Q_ASSERT(from >= 0);
12042 // Do nothing if the widget is already in correct stacking order _and_ created.
12043 if (from != 0)
12044 p->d_func()->children.move(from, to: 0);
12045 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12046 create();
12047 else if (from == 0)
12048 return;
12049 }
12050 if (testAttribute(attribute: Qt::WA_WState_Created))
12051 d->lower_sys();
12052
12053 if (d->extra && d->extra->hasWindowContainer)
12054 QWindowContainer::parentWasLowered(parent: this);
12055
12056 QEvent e(QEvent::ZOrderChange);
12057 QCoreApplication::sendEvent(receiver: this, event: &e);
12058}
12059
12060void QWidgetPrivate::lower_sys()
12061{
12062 Q_Q(QWidget);
12063 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12064 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12065 q->windowHandle()->lower();
12066 } else if (QWidget *p = q->parentWidget()) {
12067 setDirtyOpaqueRegion();
12068 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12069 }
12070}
12071
12072/*!
12073 Places the widget under \a w in the parent widget's stack.
12074
12075 To make this work, the widget itself and \a w must be siblings.
12076
12077 \sa raise(), lower()
12078*/
12079void QWidget::stackUnder(QWidget* w)
12080{
12081 Q_D(QWidget);
12082 QWidget *p = parentWidget();
12083 if (!w || isWindow() || p != w->parentWidget() || this == w)
12084 return;
12085 if (p) {
12086 int from = p->d_func()->children.indexOf(t: this);
12087 int to = p->d_func()->children.indexOf(t: w);
12088 Q_ASSERT(from >= 0);
12089 Q_ASSERT(to >= 0);
12090 if (from < to)
12091 --to;
12092 // Do nothing if the widget is already in correct stacking order _and_ created.
12093 if (from != to)
12094 p->d_func()->children.move(from, to);
12095 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12096 create();
12097 else if (from == to)
12098 return;
12099 }
12100 if (testAttribute(attribute: Qt::WA_WState_Created))
12101 d->stackUnder_sys(w);
12102
12103 QEvent e(QEvent::ZOrderChange);
12104 QCoreApplication::sendEvent(receiver: this, event: &e);
12105}
12106
12107void QWidgetPrivate::stackUnder_sys(QWidget*)
12108{
12109 Q_Q(QWidget);
12110 if (QWidget *p = q->parentWidget()) {
12111 setDirtyOpaqueRegion();
12112 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12113 }
12114}
12115
12116/*!
12117 \fn bool QWidget::isTopLevel() const
12118 \deprecated
12119
12120 Use isWindow() instead.
12121*/
12122
12123/*!
12124 \fn bool QWidget::isRightToLeft() const
12125 \internal
12126*/
12127
12128/*!
12129 \fn bool QWidget::isLeftToRight() const
12130 \internal
12131*/
12132
12133/*!
12134 \macro QWIDGETSIZE_MAX
12135 \relates QWidget
12136
12137 Defines the maximum size for a QWidget object.
12138
12139 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12140 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12141
12142 \sa QWidget::setMaximumSize()
12143*/
12144
12145/*!
12146 \fn QWidget::setupUi(QWidget *widget)
12147
12148 Sets up the user interface for the specified \a widget.
12149
12150 \note This function is available with widgets that derive from user
12151 interface descriptions created using \l{uic}.
12152
12153 \sa {Using a Designer UI File in Your Application}
12154*/
12155
12156QRect QWidgetPrivate::frameStrut() const
12157{
12158 Q_Q(const QWidget);
12159 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
12160 // x2 = x1 + w - 1, so w/h = 1
12161 return QRect(0, 0, 1, 1);
12162 }
12163
12164 if (data.fstrut_dirty
12165 // ### Fix properly for 4.3
12166 && q->isVisible()
12167 && q->testAttribute(attribute: Qt::WA_WState_Created))
12168 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12169
12170 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12171}
12172
12173void QWidgetPrivate::updateFrameStrut()
12174{
12175 Q_Q(QWidget);
12176 if (q->data->fstrut_dirty) {
12177 if (QTLWExtra *te = maybeTopData()) {
12178 if (te->window && te->window->handle()) {
12179 const QMargins margins = te->window->frameMargins();
12180 if (!margins.isNull()) {
12181 te->frameStrut.setCoords(xp1: margins.left(), yp1: margins.top(), xp2: margins.right(), yp2: margins.bottom());
12182 q->data->fstrut_dirty = false;
12183 }
12184 }
12185 }
12186 }
12187}
12188
12189#ifdef QT_KEYPAD_NAVIGATION
12190/*!
12191 \internal
12192
12193 Changes the focus from the current focusWidget to a widget in
12194 the \a direction.
12195
12196 Returns \c true, if there was a widget in that direction
12197*/
12198bool QWidgetPrivate::navigateToDirection(Direction direction)
12199{
12200 QWidget *targetWidget = widgetInNavigationDirection(direction);
12201 if (targetWidget)
12202 targetWidget->setFocus();
12203 return (targetWidget != 0);
12204}
12205
12206/*!
12207 \internal
12208
12209 Searches for a widget that is positioned in the \a direction, starting
12210 from the current focusWidget.
12211
12212 Returns the pointer to a found widget or \nullptr, if there was no widget
12213 in that direction.
12214*/
12215QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12216{
12217 const QWidget *sourceWidget = QApplication::focusWidget();
12218 if (!sourceWidget)
12219 return nullptr;
12220 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12221 const int sourceX =
12222 (direction == DirectionNorth || direction == DirectionSouth) ?
12223 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12224 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12225 const int sourceY =
12226 (direction == DirectionEast || direction == DirectionWest) ?
12227 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12228 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12229 const QPoint sourcePoint(sourceX, sourceY);
12230 const QPoint sourceCenter = sourceRect.center();
12231 const QWidget *sourceWindow = sourceWidget->window();
12232
12233 QWidget *targetWidget = nullptr;
12234 int shortestDistance = INT_MAX;
12235
12236 const auto targetCandidates = QApplication::allWidgets();
12237 for (QWidget *targetCandidate : targetCandidates) {
12238
12239 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12240
12241 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12242 // but the owner of the proxy cannot.
12243 // Additionally, empty widgets should be ignored.
12244 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12245 continue;
12246
12247 // Only navigate to a target widget that...
12248 if ( targetCandidate != sourceWidget
12249 // ...takes the focus,
12250 && targetCandidate->focusPolicy() & Qt::TabFocus
12251 // ...is above if DirectionNorth,
12252 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12253 // ...is on the right if DirectionEast,
12254 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12255 // ...is below if DirectionSouth,
12256 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12257 // ...is on the left if DirectionWest,
12258 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12259 // ...is enabled,
12260 && targetCandidate->isEnabled()
12261 // ...is visible,
12262 && targetCandidate->isVisible()
12263 // ...is in the same window,
12264 && targetCandidate->window() == sourceWindow) {
12265 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12266 const QRect &targetCandidateRect) {
12267 int dx = 0;
12268 int dy = 0;
12269 if (p.x() < r.left())
12270 dx = r.left() - p.x();
12271 else if (p.x() > r.right())
12272 dx = p.x() - r.right();
12273 if (p.y() < r.top())
12274 dy = r.top() - p.y();
12275 else if (p.y() > r.bottom())
12276 dy = p.y() - r.bottom();
12277 return dx + dy;
12278 }();
12279 if (targetCandidateDistance < shortestDistance) {
12280 shortestDistance = targetCandidateDistance;
12281 targetWidget = targetCandidate;
12282 }
12283 }
12284 }
12285 return targetWidget;
12286}
12287
12288/*!
12289 \internal
12290
12291 Tells us if it there is currently a reachable widget by keypad navigation in
12292 a certain \a orientation.
12293 If no navigation is possible, occurring key events in that \a orientation may
12294 be used to interact with the value in the focused widget, even though it
12295 currently has not the editFocus.
12296
12297 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12298*/
12299bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12300{
12301 return orientation == Qt::Horizontal?
12302 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12303 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12304 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12305 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12306}
12307/*!
12308 \internal
12309
12310 Checks, if the \a widget is inside a QTabWidget. If is is inside
12311 one, left/right key events will be used to switch between tabs in keypad
12312 navigation. If there is no QTabWidget, the horizontal key events can be used
12313to
12314 interact with the value in the focused widget, even though it currently has
12315 not the editFocus.
12316
12317 \sa QWidget::hasEditFocus()
12318*/
12319bool QWidgetPrivate::inTabWidget(QWidget *widget)
12320{
12321 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12322 if (qobject_cast<const QTabWidget*>(tabWidget))
12323 return true;
12324 return false;
12325}
12326#endif
12327
12328/*!
12329 \since 5.0
12330 \internal
12331
12332 Sets the backing store to be the \a store specified.
12333 The QWidget will take ownership of the \a store.
12334*/
12335void QWidget::setBackingStore(QBackingStore *store)
12336{
12337 // ### createWinId() ??
12338
12339 if (!isWindow())
12340 return;
12341
12342 Q_D(QWidget);
12343
12344 QTLWExtra *topData = d->topData();
12345 if (topData->backingStore == store)
12346 return;
12347
12348 QBackingStore *oldStore = topData->backingStore;
12349 delete topData->backingStore;
12350 topData->backingStore = store;
12351
12352 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12353 if (!repaintManager)
12354 return;
12355
12356 if (isWindow()) {
12357 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12358 delete repaintManager->backingStore();
12359 repaintManager->setBackingStore(store);
12360 }
12361}
12362
12363/*!
12364 \since 5.0
12365
12366 Returns the QBackingStore this widget will be drawn into.
12367*/
12368QBackingStore *QWidget::backingStore() const
12369{
12370 Q_D(const QWidget);
12371 QTLWExtra *extra = d->maybeTopData();
12372 if (extra && extra->backingStore)
12373 return extra->backingStore;
12374
12375 if (!isWindow())
12376 return window()->backingStore();
12377
12378 return nullptr;
12379}
12380
12381void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12382{
12383 if (left)
12384 *left = (int)leftLayoutItemMargin;
12385 if (top)
12386 *top = (int)topLayoutItemMargin;
12387 if (right)
12388 *right = (int)rightLayoutItemMargin;
12389 if (bottom)
12390 *bottom = (int)bottomLayoutItemMargin;
12391}
12392
12393void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12394{
12395 if (leftLayoutItemMargin == left
12396 && topLayoutItemMargin == top
12397 && rightLayoutItemMargin == right
12398 && bottomLayoutItemMargin == bottom)
12399 return;
12400
12401 Q_Q(QWidget);
12402 leftLayoutItemMargin = (signed char)left;
12403 topLayoutItemMargin = (signed char)top;
12404 rightLayoutItemMargin = (signed char)right;
12405 bottomLayoutItemMargin = (signed char)bottom;
12406 q->updateGeometry();
12407}
12408
12409void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12410{
12411 Q_Q(QWidget);
12412 QStyleOption myOpt;
12413 if (!opt) {
12414 myOpt.initFrom(w: q);
12415 myOpt.rect.setRect(ax: 0, ay: 0, aw: 32768, ah: 32768); // arbitrary
12416 opt = &myOpt;
12417 }
12418
12419 QRect liRect = q->style()->subElementRect(subElement: element, option: opt, widget: q);
12420 if (liRect.isValid()) {
12421 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12422 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12423 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12424 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12425 } else {
12426 leftLayoutItemMargin = 0;
12427 topLayoutItemMargin = 0;
12428 rightLayoutItemMargin = 0;
12429 bottomLayoutItemMargin = 0;
12430 }
12431}
12432// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12433void QWidgetPrivate::adjustQuitOnCloseAttribute()
12434{
12435 Q_Q(QWidget);
12436
12437 if (!q->parentWidget()) {
12438 Qt::WindowType type = q->windowType();
12439 if (type == Qt::Widget || type == Qt::SubWindow)
12440 type = Qt::Window;
12441 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12442 q->setAttribute(attribute: Qt::WA_QuitOnClose, on: false);
12443 }
12444}
12445
12446void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12447{
12448 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12449 if (!wd->textureChildSeen)
12450 return;
12451 if (end)
12452 wd->endCompose();
12453 else
12454 wd->beginCompose();
12455 for (int i = 0; i < wd->children.size(); ++i) {
12456 w = qobject_cast<QWidget *>(o: wd->children.at(i));
12457 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12458 sendComposeStatus(w, end);
12459 }
12460}
12461
12462Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12463{
12464 return widget->data;
12465}
12466
12467Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12468{
12469 return widget->d_func();
12470}
12471
12472
12473#if QT_CONFIG(graphicsview)
12474/*!
12475 \since 4.5
12476
12477 Returns the proxy widget for the corresponding embedded widget in a graphics
12478 view; otherwise returns \nullptr.
12479
12480 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12481 QGraphicsScene::addWidget()
12482 */
12483QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12484{
12485 Q_D(const QWidget);
12486 if (d->extra) {
12487 return d->extra->proxyWidget;
12488 }
12489 return nullptr;
12490}
12491#endif
12492
12493#ifndef QT_NO_GESTURES
12494/*!
12495 Subscribes the widget to a given \a gesture with specific \a flags.
12496
12497 \sa ungrabGesture(), QGestureEvent
12498 \since 4.6
12499*/
12500void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12501{
12502 Q_D(QWidget);
12503 d->gestureContext.insert(key: gesture, value: flags);
12504 (void)QGestureManager::instance(); // create a gesture manager
12505}
12506
12507/*!
12508 Unsubscribes the widget from a given \a gesture type
12509
12510 \sa grabGesture(), QGestureEvent
12511 \since 4.6
12512*/
12513void QWidget::ungrabGesture(Qt::GestureType gesture)
12514{
12515 // if you modify this function, check the inlined version in ~QWidget, too
12516 Q_D(QWidget);
12517 if (d->gestureContext.remove(key: gesture)) {
12518 if (QGestureManager *manager = QGestureManager::instance())
12519 manager->cleanupCachedGestures(target: this, type: gesture);
12520 }
12521}
12522#endif // QT_NO_GESTURES
12523
12524/*!
12525 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12526
12527 Frees up window system resources. Destroys the widget window if \a
12528 destroyWindow is true.
12529
12530 destroy() calls itself recursively for all the child widgets,
12531 passing \a destroySubWindows for the \a destroyWindow parameter.
12532 To have more control over destruction of subwidgets, destroy
12533 subwidgets selectively first.
12534
12535 This function is usually called from the QWidget destructor.
12536*/
12537void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12538{
12539 Q_D(QWidget);
12540
12541 d->aboutToDestroy();
12542 if (!isWindow() && parentWidget())
12543 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(rect: geometry()));
12544 d->deactivateWidgetCleanup();
12545
12546 if ((windowType() == Qt::Popup) && qApp)
12547 qApp->d_func()->closePopup(popup: this);
12548
12549 if (this == qApp->activeWindow())
12550 QApplicationPrivate::setActiveWindow(nullptr);
12551 if (QWidget::mouseGrabber() == this)
12552 releaseMouse();
12553 if (QWidget::keyboardGrabber() == this)
12554 releaseKeyboard();
12555
12556 setAttribute(attribute: Qt::WA_WState_Created, on: false);
12557
12558 if (windowType() != Qt::Desktop) {
12559 if (destroySubWindows) {
12560 QObjectList childList(children());
12561 for (int i = 0; i < childList.size(); i++) {
12562 QWidget *widget = qobject_cast<QWidget *>(o: childList.at(i));
12563 if (widget && widget->testAttribute(attribute: Qt::WA_NativeWindow)) {
12564 if (widget->windowHandle()) {
12565 widget->destroy();
12566 }
12567 }
12568 }
12569 }
12570 if (destroyWindow) {
12571 d->deleteTLSysExtra();
12572 } else {
12573 if (parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_WState_Created)) {
12574 d->hide_sys();
12575 }
12576 }
12577
12578 d->setWinId(0);
12579 }
12580}
12581
12582/*!
12583 \fn QPaintEngine *QWidget::paintEngine() const
12584
12585 Returns the widget's paint engine.
12586
12587 Note that this function should not be called explicitly by the
12588 user, since it's meant for reimplementation purposes only. The
12589 function is called by Qt internally, and the default
12590 implementation may not always return a valid pointer.
12591*/
12592QPaintEngine *QWidget::paintEngine() const
12593{
12594 qWarning(msg: "QWidget::paintEngine: Should no longer be called");
12595
12596#ifdef Q_OS_WIN
12597 // We set this bit which is checked in setAttribute for
12598 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12599 //
12600 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12601 // Windows which would mean suddenly their widgets stop working.
12602 //
12603 // 2. Users set paint on screen and subclass paintEngine() to
12604 // return 0, in which case we have a "hole" in the backingstore
12605 // allowing use of GDI or DirectX directly.
12606 //
12607 // 1 is WRONG, but to minimize silent failures, we have set this
12608 // bit to ignore the setAttribute call. 2. needs to be
12609 // supported because its our only means of embedding native
12610 // graphics stuff.
12611 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12612#endif
12613
12614 return nullptr; //##### @@@
12615}
12616
12617// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12618static inline bool canMapPosition(QWindow *window)
12619{
12620 return window->handle() && !qt_window_private(window)->resizeEventPending;
12621}
12622
12623#if QT_CONFIG(graphicsview)
12624static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12625{
12626 QGraphicsProxyWidget *result = nullptr;
12627 const QWidgetPrivate *d = qt_widget_private(widget: const_cast<QWidget *>(w));
12628 if (d->extra)
12629 result = d->extra->proxyWidget;
12630 return result;
12631}
12632#endif // QT_CONFIG(graphicsview)
12633
12634struct MapToGlobalTransformResult {
12635 QTransform transform;
12636 QWindow *window;
12637};
12638
12639static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12640{
12641 MapToGlobalTransformResult result;
12642 result.window = nullptr;
12643 for ( ; w ; w = w->parentWidget()) {
12644#if QT_CONFIG(graphicsview)
12645 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12646 if (const QGraphicsScene *scene = qgpw->scene()) {
12647 const QList <QGraphicsView *> views = scene->views();
12648 if (!views.isEmpty()) {
12649 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(widget: views.constFirst()));
12650 result.transform *= viewP->mapToViewTransform(item: qgpw);
12651 w = views.first()->viewport();
12652 }
12653 }
12654 }
12655#endif // QT_CONFIG(graphicsview)
12656 QWindow *window = w->windowHandle();
12657 if (window && canMapPosition(window)) {
12658 result.window = window;
12659 break;
12660 }
12661
12662 const auto &geometry = w->geometry();
12663 result.transform *= QTransform::fromTranslate(dx: geometry.x(), dy: geometry.y());
12664 if (w->isWindow())
12665 break;
12666 }
12667 return result;
12668}
12669
12670/*!
12671 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12672
12673 Translates the widget coordinate \a pos to global screen
12674 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12675 the global coordinates of the top-left pixel of the widget.
12676
12677 \sa mapFromGlobal(), mapTo(), mapToParent()
12678 \since 6.0
12679*/
12680QPointF QWidget::mapToGlobal(const QPointF &pos) const
12681{
12682 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12683 const QPointF g = t.transform.map(p: pos);
12684 return t.window ? t.window->mapToGlobal(pos: g) : g;
12685}
12686
12687/*!
12688 \overload
12689*/
12690QPoint QWidget::mapToGlobal(const QPoint &pos) const
12691{
12692 return mapToGlobal(pos: QPointF(pos)).toPoint();
12693}
12694
12695/*!
12696 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12697
12698 Translates the global screen coordinate \a pos to widget
12699 coordinates.
12700
12701 \sa mapToGlobal(), mapFrom(), mapFromParent()
12702 \since 6.0
12703*/
12704QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12705{
12706 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12707 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12708 return t.transform.inverted().map(p: windowLocal);
12709}
12710
12711/*!
12712 \overload
12713*/
12714QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12715{
12716 return mapFromGlobal(pos: QPointF(pos)).toPoint();
12717}
12718
12719QWidget *qt_pressGrab = nullptr;
12720QWidget *qt_mouseGrb = nullptr;
12721static bool mouseGrabWithCursor = false;
12722static QWidget *keyboardGrb = nullptr;
12723
12724static inline QWindow *grabberWindow(const QWidget *w)
12725{
12726 QWindow *window = w->windowHandle();
12727 if (!window)
12728 if (const QWidget *nativeParent = w->nativeParentWidget())
12729 window = nativeParent->windowHandle();
12730 return window;
12731}
12732
12733#ifndef QT_NO_CURSOR
12734static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12735#else
12736static void grabMouseForWidget(QWidget *widget)
12737#endif
12738{
12739 if (qt_mouseGrb)
12740 qt_mouseGrb->releaseMouse();
12741
12742 mouseGrabWithCursor = false;
12743 if (QWindow *window = grabberWindow(w: widget)) {
12744#ifndef QT_NO_CURSOR
12745 if (cursor) {
12746 mouseGrabWithCursor = true;
12747 QGuiApplication::setOverrideCursor(*cursor);
12748 }
12749#endif // !QT_NO_CURSOR
12750 window->setMouseGrabEnabled(true);
12751 }
12752
12753 qt_mouseGrb = widget;
12754 qt_pressGrab = nullptr;
12755}
12756
12757static void releaseMouseGrabOfWidget(QWidget *widget)
12758{
12759 if (qt_mouseGrb == widget) {
12760 if (QWindow *window = grabberWindow(w: widget)) {
12761#ifndef QT_NO_CURSOR
12762 if (mouseGrabWithCursor) {
12763 QGuiApplication::restoreOverrideCursor();
12764 mouseGrabWithCursor = false;
12765 }
12766#endif // !QT_NO_CURSOR
12767 window->setMouseGrabEnabled(false);
12768 }
12769 }
12770 qt_mouseGrb = nullptr;
12771}
12772
12773/*!
12774 \fn void QWidget::grabMouse()
12775
12776 Grabs the mouse input.
12777
12778 This widget receives all mouse events until releaseMouse() is
12779 called; other widgets get no mouse events at all. Keyboard
12780 events are not affected. Use grabKeyboard() if you want to grab
12781 that.
12782
12783 \warning Bugs in mouse-grabbing applications very often lock the
12784 terminal. Use this function with extreme caution, and consider
12785 using the \c -nograb command line option while debugging.
12786
12787 It is seldom necessary to grab the mouse when using Qt, as
12788 Qt grabs and releases it sensibly. In particular, Qt grabs the
12789 mouse when a mouse button is pressed and keeps it until the last
12790 button is released.
12791
12792 \note Only visible widgets can grab mouse input. If isVisible()
12793 returns \c false for a widget, that widget cannot call grabMouse().
12794
12795 \note On Windows, grabMouse() only works when the mouse is inside a window
12796 owned by the process.
12797 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12798
12799 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12800*/
12801void QWidget::grabMouse()
12802{
12803 grabMouseForWidget(widget: this);
12804}
12805
12806/*!
12807 \fn void QWidget::grabMouse(const QCursor &cursor)
12808 \overload grabMouse()
12809
12810 Grabs the mouse input and changes the cursor shape.
12811
12812 The cursor will assume shape \a cursor (for as long as the mouse
12813 focus is grabbed) and this widget will be the only one to receive
12814 mouse events until releaseMouse() is called().
12815
12816 \warning Grabbing the mouse might lock the terminal.
12817
12818 \note See the note in QWidget::grabMouse().
12819
12820 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12821*/
12822#ifndef QT_NO_CURSOR
12823void QWidget::grabMouse(const QCursor &cursor)
12824{
12825 grabMouseForWidget(widget: this, cursor: &cursor);
12826}
12827#endif
12828
12829bool QWidgetPrivate::stealMouseGrab(bool grab)
12830{
12831 // This is like a combination of grab/releaseMouse() but with error checking
12832 // and it has no effect on the result of mouseGrabber().
12833 Q_Q(QWidget);
12834 QWindow *window = grabberWindow(w: q);
12835 return window ? window->setMouseGrabEnabled(grab) : false;
12836}
12837
12838/*!
12839 \fn void QWidget::releaseMouse()
12840
12841 Releases the mouse grab.
12842
12843 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12844*/
12845void QWidget::releaseMouse()
12846{
12847 releaseMouseGrabOfWidget(widget: this);
12848}
12849
12850/*!
12851 \fn void QWidget::grabKeyboard()
12852
12853 Grabs the keyboard input.
12854
12855 This widget receives all keyboard events until releaseKeyboard()
12856 is called; other widgets get no keyboard events at all. Mouse
12857 events are not affected. Use grabMouse() if you want to grab that.
12858
12859 The focus widget is not affected, except that it doesn't receive
12860 any keyboard events. setFocus() moves the focus as usual, but the
12861 new focus widget receives keyboard events only after
12862 releaseKeyboard() is called.
12863
12864 If a different widget is currently grabbing keyboard input, that
12865 widget's grab is released first.
12866
12867 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12868*/
12869void QWidget::grabKeyboard()
12870{
12871 if (keyboardGrb)
12872 keyboardGrb->releaseKeyboard();
12873 if (QWindow *window = grabberWindow(w: this))
12874 window->setKeyboardGrabEnabled(true);
12875 keyboardGrb = this;
12876}
12877
12878bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12879{
12880 // This is like a combination of grab/releaseKeyboard() but with error
12881 // checking and it has no effect on the result of keyboardGrabber().
12882 Q_Q(QWidget);
12883 QWindow *window = grabberWindow(w: q);
12884 return window ? window->setKeyboardGrabEnabled(grab) : false;
12885}
12886
12887/*!
12888 \fn void QWidget::releaseKeyboard()
12889
12890 Releases the keyboard grab.
12891
12892 \sa grabKeyboard(), grabMouse(), releaseMouse()
12893*/
12894void QWidget::releaseKeyboard()
12895{
12896 if (keyboardGrb == this) {
12897 if (QWindow *window = grabberWindow(w: this))
12898 window->setKeyboardGrabEnabled(false);
12899 keyboardGrb = nullptr;
12900 }
12901}
12902
12903/*!
12904 \fn QWidget *QWidget::mouseGrabber()
12905
12906 Returns the widget that is currently grabbing the mouse input.
12907
12908 If no widget in this application is currently grabbing the mouse,
12909 \nullptr is returned.
12910
12911 \sa grabMouse(), keyboardGrabber()
12912*/
12913QWidget *QWidget::mouseGrabber()
12914{
12915 if (qt_mouseGrb)
12916 return qt_mouseGrb;
12917 return qt_pressGrab;
12918}
12919
12920/*!
12921 \fn QWidget *QWidget::keyboardGrabber()
12922
12923 Returns the widget that is currently grabbing the keyboard input.
12924
12925 If no widget in this application is currently grabbing the
12926 keyboard, \nullptr is returned.
12927
12928 \sa grabMouse(), mouseGrabber()
12929*/
12930QWidget *QWidget::keyboardGrabber()
12931{
12932 return keyboardGrb;
12933}
12934
12935/*!
12936 \fn void QWidget::activateWindow()
12937
12938 Sets the top-level widget containing this widget to be the active
12939 window.
12940
12941 An active window is a visible top-level window that has the
12942 keyboard input focus.
12943
12944 This function performs the same operation as clicking the mouse on
12945 the title bar of a top-level window. On X11, the result depends on
12946 the Window Manager. If you want to ensure that the window is
12947 stacked on top as well you should also call raise(). Note that the
12948 window must be visible, otherwise activateWindow() has no effect.
12949
12950 On Windows, if you are calling this when the application is not
12951 currently the active one then it will not make it the active
12952 window. It will change the color of the taskbar entry to indicate
12953 that the window has changed in some way. This is because Microsoft
12954 does not allow an application to interrupt what the user is currently
12955 doing in another application.
12956
12957 \sa isActiveWindow(), window(), show()
12958*/
12959void QWidget::activateWindow()
12960{
12961 QWindow *const wnd = window()->windowHandle();
12962
12963 if (wnd)
12964 wnd->requestActivate();
12965}
12966
12967/*!
12968
12969 Internal implementation of the virtual QPaintDevice::metric()
12970 function.
12971
12972 \a m is the metric to get.
12973*/
12974int QWidget::metric(PaintDeviceMetric m) const
12975{
12976 QScreen *screen = this->screen();
12977
12978 if (!screen) {
12979 if (m == PdmDpiX || m == PdmDpiY)
12980 return 72;
12981 return QPaintDevice::metric(metric: m);
12982 }
12983
12984 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12985
12986 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12987 static bool downscale = qEnvironmentVariableIntValue(varName: "QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12988 QWindow *window = this->window()->windowHandle();
12989 if (window)
12990 return downscale ? std::ceil(x: window->devicePixelRatio()) : window->devicePixelRatio();
12991 return screen->devicePixelRatio();
12992 };
12993
12994 switch (m) {
12995 case PdmWidth:
12996 return data->crect.width();
12997 case PdmWidthMM:
12998 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12999 case PdmHeight:
13000 return data->crect.height();
13001 case PdmHeightMM:
13002 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13003 case PdmDepth:
13004 return screen->depth();
13005 case PdmDpiX:
13006 for (const QWidget *p = this; p; p = p->parentWidget()) {
13007 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13008 return p->d_func()->extra->customDpiX;
13009 }
13010 return qRound(d: screen->logicalDotsPerInchX());
13011 case PdmDpiY:
13012 for (const QWidget *p = this; p; p = p->parentWidget()) {
13013 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13014 return p->d_func()->extra->customDpiY;
13015 }
13016 return qRound(d: screen->logicalDotsPerInchY());
13017 case PdmPhysicalDpiX:
13018 return qRound(d: screen->physicalDotsPerInchX());
13019 case PdmPhysicalDpiY:
13020 return qRound(d: screen->physicalDotsPerInchY());
13021 case PdmDevicePixelRatio:
13022 return resolveDevicePixelRatio();
13023 case PdmDevicePixelRatioScaled:
13024 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13025 case PdmDevicePixelRatioF_EncodedA:
13026 Q_FALLTHROUGH();
13027 case PdmDevicePixelRatioF_EncodedB:
13028 return QPaintDevice::encodeMetricF(metric: m, value: resolveDevicePixelRatio());
13029 default:
13030 break;
13031 }
13032 return QPaintDevice::metric(metric: m);
13033}
13034
13035/*!
13036 Initializes the \a painter pen, background and font to the same as
13037 the given widget's. This function is called automatically when the
13038 painter is opened on a QWidget.
13039*/
13040void QWidget::initPainter(QPainter *painter) const
13041{
13042 const QPalette &pal = palette();
13043 painter->d_func()->state->pen = QPen(pal.brush(cr: foregroundRole()), 1);
13044 painter->d_func()->state->bgBrush = pal.brush(cr: backgroundRole());
13045 QFont f(font(), const_cast<QWidget *>(this));
13046 painter->d_func()->state->deviceFont = f;
13047 painter->d_func()->state->font = f;
13048}
13049
13050/*!
13051 \internal
13052
13053 Do PaintDevice rendering with the specified \a offset.
13054*/
13055QPaintDevice *QWidget::redirected(QPoint *offset) const
13056{
13057 return d_func()->redirected(offset);
13058}
13059
13060/*!
13061 \internal
13062
13063 A painter that is shared among other instances of QPainter.
13064*/
13065QPainter *QWidget::sharedPainter() const
13066{
13067 // Someone sent a paint event directly to the widget
13068 if (!d_func()->redirectDev)
13069 return nullptr;
13070
13071 QPainter *sp = d_func()->sharedPainter();
13072 if (!sp || !sp->isActive())
13073 return nullptr;
13074
13075 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13076 return nullptr;
13077
13078 return sp;
13079}
13080
13081/*!
13082 \fn void QWidget::setMask(const QRegion &region)
13083 \overload
13084
13085 Causes only the parts of the widget which overlap \a region to be
13086 visible. If the region includes pixels outside the rect() of the
13087 widget, window system controls in that area may or may not be
13088 visible, depending on the platform.
13089
13090 Since QRegion allows arbitrarily complex regions to be created, widget
13091 masks can be made to suit the most unconventionally-shaped windows, and
13092 even allow widgets to be displayed with holes in them. Note that this
13093 effect can be slow if the region is particularly complex.
13094
13095 Widget masks are used to hint to the window system that the application
13096 does not want mouse events for areas outside the mask. On most systems,
13097 they also result in coarse visual clipping. To get smooth window edges, use
13098 translucent background and anti-aliased painting instead, as shown in the
13099 \l{Translucent Background} example.
13100
13101 \sa windowOpacity
13102*/
13103void QWidget::setMask(const QRegion &newMask)
13104{
13105 Q_D(QWidget);
13106
13107 d->createExtra();
13108 if (newMask == d->extra->mask)
13109 return;
13110
13111#ifndef QT_NO_BACKINGSTORE
13112 const QRegion oldMask(d->extra->mask);
13113#endif
13114
13115 d->extra->mask = newMask;
13116 d->extra->hasMask = !newMask.isEmpty();
13117
13118 if (!testAttribute(attribute: Qt::WA_WState_Created))
13119 return;
13120
13121 d->setMask_sys(newMask);
13122
13123#ifndef QT_NO_BACKINGSTORE
13124 if (!isVisible())
13125 return;
13126
13127 if (!d->extra->hasMask) {
13128 // Mask was cleared; update newly exposed area.
13129 QRegion expose(rect());
13130 expose -= oldMask;
13131 if (!expose.isEmpty()) {
13132 d->setDirtyOpaqueRegion();
13133 update(rgn: expose);
13134 }
13135 return;
13136 }
13137
13138 if (!isWindow()) {
13139 // Update newly exposed area on the parent widget.
13140 QRegion parentExpose(rect());
13141 parentExpose -= newMask;
13142 if (!parentExpose.isEmpty()) {
13143 d->setDirtyOpaqueRegion();
13144 parentExpose.translate(p: data->crect.topLeft());
13145 parentWidget()->update(rgn: parentExpose);
13146 }
13147
13148 // Update newly exposed area on this widget
13149 if (!oldMask.isEmpty())
13150 update(rgn: newMask - oldMask);
13151 }
13152#endif
13153}
13154
13155void QWidgetPrivate::setMask_sys(const QRegion &region)
13156{
13157 Q_Q(QWidget);
13158 if (QWindow *window = q->windowHandle())
13159 window->setMask(region);
13160}
13161
13162/*!
13163 \fn void QWidget::setMask(const QBitmap &bitmap)
13164
13165 Causes only the pixels of the widget for which \a bitmap has a
13166 corresponding 1 bit to be visible. If the region includes pixels
13167 outside the rect() of the widget, window system controls in that
13168 area may or may not be visible, depending on the platform.
13169
13170 Note that this effect can be slow if the region is particularly
13171 complex.
13172
13173 The following code shows how an image with an alpha channel can be
13174 used to generate a mask for a widget:
13175
13176 \snippet widget-mask/main.cpp 0
13177
13178 The label shown by this code is masked using the image it contains,
13179 giving the appearance that an irregularly-shaped image is being drawn
13180 directly onto the screen.
13181
13182 Masked widgets receive mouse events only on their visible
13183 portions.
13184
13185 \sa clearMask(), windowOpacity()
13186*/
13187void QWidget::setMask(const QBitmap &bitmap)
13188{
13189 setMask(QRegion(bitmap));
13190}
13191
13192/*!
13193 \fn void QWidget::clearMask()
13194
13195 Removes any mask set by setMask().
13196
13197 \sa setMask()
13198*/
13199void QWidget::clearMask()
13200{
13201 Q_D(QWidget);
13202 if (!d->extra || !d->extra->hasMask)
13203 return;
13204 setMask(QRegion());
13205}
13206
13207void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13208{
13209 Q_ASSERT(widgetAsObject->isWidgetType());
13210 Q_ASSERT(!newParent || newParent->isWidgetType());
13211 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13212 widget->setParent(static_cast<QWidget*>(newParent));
13213}
13214
13215std::string QWidgetPrivate::flagsForDumping() const
13216{
13217 Q_Q(const QWidget);
13218 std::string flags = QObjectPrivate::flagsForDumping();
13219 if (QApplication::focusWidget() == q)
13220 flags += 'F';
13221 if (q->isVisible()) {
13222 std::stringstream s;
13223 s << '<'
13224 << q->width() << 'x' << q->height()
13225 << std::showpos << q->x() << q->y()
13226 << '>';
13227 flags += s.str();
13228 } else {
13229 flags += 'I';
13230 }
13231 return flags;
13232}
13233
13234void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13235{
13236#if QT_CONFIG(xcb)
13237 Q_Q(QWidget);
13238
13239 if (!q->windowHandle())
13240 return;
13241
13242 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13243 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDesktop))
13244 wmWindowType |= QXcbWindow::Desktop;
13245 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDock))
13246 wmWindowType |= QXcbWindow::Dock;
13247 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolBar))
13248 wmWindowType |= QXcbWindow::Toolbar;
13249 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeMenu))
13250 wmWindowType |= QXcbWindow::Menu;
13251 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeUtility))
13252 wmWindowType |= QXcbWindow::Utility;
13253 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeSplash))
13254 wmWindowType |= QXcbWindow::Splash;
13255 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDialog))
13256 wmWindowType |= QXcbWindow::Dialog;
13257 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDropDownMenu))
13258 wmWindowType |= QXcbWindow::DropDownMenu;
13259 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypePopupMenu))
13260 wmWindowType |= QXcbWindow::PopupMenu;
13261 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolTip))
13262 wmWindowType |= QXcbWindow::Tooltip;
13263 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeNotification))
13264 wmWindowType |= QXcbWindow::Notification;
13265 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeCombo))
13266 wmWindowType |= QXcbWindow::Combo;
13267 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDND))
13268 wmWindowType |= QXcbWindow::Dnd;
13269
13270 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13271 return;
13272
13273 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13274 xcbWindow->setWindowType(wmWindowType);
13275#else
13276 Q_UNUSED(skipIfMissing);
13277#endif
13278}
13279
13280/*!
13281 \internal
13282 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13283 Return false otherwise.
13284 */
13285bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13286{
13287 Q_Q(const QWidget);
13288 const QWidgetList &children = q->findChildren<QWidget *>(options: Qt::FindChildrenRecursively);
13289 for (const auto *child : children) {
13290 if (child->focusPolicy() == policy && child->isEnabled()
13291 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13292 return true;
13293 }
13294 }
13295 return false;
13296}
13297
13298#ifndef QT_NO_DEBUG_STREAM
13299
13300namespace {
13301QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13302{
13303 const QDebugStateSaver saver(debug);
13304 debug.nospace();
13305 debug << '[';
13306 if (const QWidget *widget = attributes.widget) {
13307 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13308 const QMetaEnum me = qtMo->enumerator(index: qtMo->indexOfEnumerator(name: "WidgetAttribute"));
13309 int count = 0;
13310 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13311 if (widget->testAttribute(attribute: static_cast<Qt::WidgetAttribute>(a))) {
13312 if (count++)
13313 debug << ',';
13314 debug << me.valueToKey(value: a);
13315 }
13316 }
13317 }
13318 debug << ']';
13319 return debug;
13320}
13321}
13322
13323QDebug operator<<(QDebug debug, const QWidget *widget)
13324{
13325 const QDebugStateSaver saver(debug);
13326 debug.nospace();
13327 if (widget) {
13328 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13329 if (!widget->objectName().isEmpty())
13330 debug << ", name=" << widget->objectName();
13331 if (debug.verbosity() > 2) {
13332 const QRect geometry = widget->geometry();
13333 const QRect frameGeometry = widget->frameGeometry();
13334 if (widget->isVisible())
13335 debug << ", visible";
13336 if (!widget->isEnabled())
13337 debug << ", disabled";
13338 debug << ", states=" << widget->windowState()
13339 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13340 debug << ", attributes=" << WidgetAttributes{.widget: widget};
13341 if (widget->isWindow())
13342 debug << ", window";
13343 debug << ", " << geometry.width() << 'x' << geometry.height()
13344 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13345 if (frameGeometry != geometry) {
13346 const QMargins margins(geometry.x() - frameGeometry.x(),
13347 geometry.y() - frameGeometry.y(),
13348 frameGeometry.right() - geometry.right(),
13349 frameGeometry.bottom() - geometry.bottom());
13350 debug << ", margins=" << margins;
13351 }
13352 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13353 if (const WId wid = widget->internalWinId())
13354 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13355 }
13356 debug << ')';
13357 } else {
13358 debug << "QWidget(0x0)";
13359 }
13360 return debug;
13361}
13362#endif // !QT_NO_DEBUG_STREAM
13363
13364
13365// *************************** Focus abstraction ************************************
13366
13367#define FOCUS_NEXT(w) w->d_func()->focus_next
13368#define FOCUS_PREV(w) w->d_func()->focus_prev
13369
13370/*!
13371 \internal
13372 \return next or previous element in the focus chain, depending on
13373 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13374 */
13375QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13376{
13377 Q_Q(const QWidget);
13378 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13379}
13380
13381/*!
13382 \internal
13383 Removes a widget from the focus chain, respecting the flags set in \param rules.
13384 \list
13385 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13386 in the focus chain, depending on \param direction.
13387 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13388 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13389 \endlist
13390 \return \c true if the widget has been removed, otherwise \c false.
13391 */
13392bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13393{
13394 Q_Q(QWidget);
13395 if (!isFocusChainConsistent()) {
13396#ifdef QT_DEBUG
13397 if (rules.testFlag(flag: FocusChainRemovalRule::AssertConsistency))
13398 qFatal() << q << "has inconsistent focus chain.";
13399#endif
13400 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13401 return false;
13402 }
13403
13404 if (!isInFocusChain()) {
13405 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13406 return false;
13407 }
13408
13409 if (rules.testFlag(flag: FocusChainRemovalRule::EnsureFocusOut))
13410 q->focusNextPrevChild(next: direction == FocusDirection::Next);
13411
13412 FOCUS_NEXT(FOCUS_PREV(q)) = FOCUS_NEXT(q);
13413 FOCUS_PREV(FOCUS_NEXT(q)) = FOCUS_PREV(q);
13414 initFocusChain();
13415 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13416 return true;
13417}
13418
13419/*!
13420 \internal
13421 Initialises the focus chain by making the widget point to itself.
13422 */
13423void QWidgetPrivate::initFocusChain()
13424{
13425 Q_Q(QWidget);
13426 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13427 FOCUS_PREV(q) = q;
13428 FOCUS_NEXT(q) = q;
13429}
13430
13431/*!
13432 \internal
13433 Reads QWidget children, which are not part of a focus chain yet.
13434 Inserts them into the focus chain before or after the widget,
13435 depending on \param direction and in the order of their creation.
13436 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13437 */
13438void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13439{
13440 Q_Q(QWidget);
13441
13442 // separate the focus chain into new (children of myself) and old (the rest)
13443 QWidget *firstOld = nullptr;
13444 QWidget *lastOld = nullptr; // last in the old list
13445 QWidget *lastNew = q; // last in the new list
13446 bool prevWasNew = true;
13447 QWidget *widget = nextPrevElementInFocusChain(direction);
13448
13449 // For efficiency, do not maintain the list invariant inside the loop.
13450 // Append items to the relevant list, and we optimize by not changing pointers,
13451 // when subsequent items are going into the same list.
13452 while (widget != q) {
13453 bool currentIsNew = q->isAncestorOf(child: widget);
13454 if (currentIsNew) {
13455 if (!prevWasNew) {
13456 // previous was old => append to new list
13457 FOCUS_NEXT(lastNew) = widget;
13458 FOCUS_PREV(widget) = lastNew;
13459 }
13460 lastNew = widget;
13461 } else {
13462 if (prevWasNew) {
13463 // prev was new => append to old list, if it exists
13464 if (lastOld) {
13465 FOCUS_NEXT(lastOld) = widget;
13466 FOCUS_PREV(widget) = lastOld;
13467 } else {
13468 // start the old list
13469 firstOld = widget;
13470 }
13471 }
13472 lastOld = widget;
13473 }
13474 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13475 prevWasNew = currentIsNew;
13476 }
13477
13478 // repair old list:
13479 if (firstOld) {
13480 FOCUS_NEXT(lastOld) = firstOld;
13481 FOCUS_PREV(firstOld) = lastOld;
13482 }
13483
13484 if (!q->isWindow()) {
13485 QWidget *topLevel = q->window();
13486 // insert new chain into toplevel's chain
13487 QWidget *prev = FOCUS_PREV(topLevel);
13488 FOCUS_PREV(topLevel) = lastNew;
13489 FOCUS_NEXT(prev) = q;
13490 FOCUS_PREV(q) = prev;
13491 FOCUS_NEXT(lastNew) = topLevel;
13492 } else {
13493 // repair new list
13494 FOCUS_NEXT(lastNew) = q;
13495 FOCUS_PREV(q) = lastNew;
13496 }
13497}
13498
13499/*!
13500 \internal
13501 Inserts a widget into the focus chain before or after \param position, depending on
13502 \param direction.
13503 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13504 */
13505bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13506{
13507 Q_Q(QWidget);
13508 Q_ASSERT(position);
13509 QWidget *next = FOCUS_NEXT(q);
13510 QWidget *previous = FOCUS_PREV(q);
13511
13512 switch (direction) {
13513 case FocusDirection::Next:
13514 if (previous == position) {
13515 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13516 return false;
13517 }
13518
13519 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13520
13521 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13522 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13523 FOCUS_NEXT(position) = q;
13524 FOCUS_PREV(q) = position;
13525 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13526 break;
13527
13528 case FocusDirection::Previous:
13529 if (next == position) {
13530 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13531 return false;
13532 }
13533
13534 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13535
13536 FOCUS_PREV(q) = FOCUS_PREV(position);
13537 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13538 FOCUS_PREV(position) = q;
13539 FOCUS_NEXT(q) = position;
13540 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13541 break;
13542 }
13543
13544 Q_ASSERT(isFocusChainConsistent());
13545 return true;
13546}
13547
13548/*!
13549 \internal
13550 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13551 before or after \param position, depending on \param direction.
13552 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13553 \note
13554 \param toBeInserted must be a consistent focus chain.
13555 */
13556bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13557 FocusDirection direction, QWidget *position)
13558{
13559 if (toBeInserted.isEmpty()) {
13560 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13561 return false;
13562 }
13563
13564 Q_ASSERT_X(!toBeInserted.contains(position),
13565 Q_FUNC_INFO,
13566 "Coding error: toBeInserted contains position");
13567
13568 QWidget *first = toBeInserted.constFirst();
13569 QWidget *last = toBeInserted.constLast();
13570
13571 // Call QWidget override to log accordingly
13572 if (toBeInserted.count() == 1)
13573 return first->d_func()->insertIntoFocusChain(direction, position);
13574
13575 Q_ASSERT(first != last);
13576 switch (direction) {
13577 case FocusDirection::Previous:
13578 if (FOCUS_PREV(position) == last) {
13579 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13580 << position;
13581 return false;
13582 }
13583 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13584 FOCUS_PREV(first) = FOCUS_PREV(position);
13585 FOCUS_NEXT(last) = position;
13586 FOCUS_PREV(position) = last;
13587 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13588 break;
13589 case FocusDirection::Next:
13590 if (FOCUS_PREV(position) == last) {
13591 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13592 << position;
13593 return false;
13594 }
13595 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13596 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13597 FOCUS_PREV(first) = position;
13598 FOCUS_NEXT(position) = first;
13599 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13600 break;
13601 }
13602
13603 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13604 return true;
13605}
13606
13607/*!
13608 \internal
13609 \return a QWidgetList, representing the part of the focus chain,
13610 starting with \param from and ending with \param to, in \param direction.
13611 */
13612QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13613{
13614 QWidgetList path({from});
13615 if (from == to)
13616 return path;
13617
13618 QWidget *current = from;
13619 do {
13620 switch (direction) {
13621 case QWidgetPrivate::FocusDirection::Previous:
13622 current = current->previousInFocusChain();
13623 break;
13624 case QWidgetPrivate::FocusDirection::Next:
13625 current = current->nextInFocusChain();
13626 break;
13627 }
13628 if (path.contains(t: current))
13629 return QWidgetList();
13630 path << current;
13631 } while (current != to);
13632
13633 return path;
13634}
13635
13636/*!
13637 \internal
13638 Removes the part from the focus chain starting with \param from and ending with \param to,
13639 in \param direction.
13640 \return removed part as a QWidgetList.
13641 */
13642QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13643 QWidget *to,
13644 FocusDirection direction)
13645{
13646 // Check if there is a path from->to in direction
13647 const QWidgetList path = focusPath(from, to , direction);
13648 if (path.isEmpty()) {
13649 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13650 return QWidgetList();
13651 }
13652
13653 QWidget *first = path.constFirst();
13654 QWidget *last = path.constLast();
13655 if (first == last) {
13656 first->d_func()->removeFromFocusChain();
13657 return QWidgetList({first});
13658 }
13659
13660 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13661 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13662 FOCUS_PREV(first) = last;
13663 FOCUS_NEXT(last) = first;
13664 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13665 return path;
13666}
13667
13668/*!
13669 \internal
13670 \return The last focus child of the widget, traversing the focus chain no further than
13671 \param noFurtherThan.
13672 */
13673QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13674{
13675 Q_Q(QWidget);
13676 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13677 // that determines the last focus child for a widget, taking proxies and compound widgets into
13678 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13679 // to a child), 'lastFocusChild' will be set to the target itself.
13680 QWidget *lastFocusChild = q;
13681
13682 QWidget *focusProxy = deepestFocusProxy();
13683 if (!focusProxy) {
13684 // QTBUG-81097: Another case is possible here. We can have a child
13685 // widget, that sets its focusProxy() to the parent (target).
13686 // An example of such widget is a QLineEdit, nested into
13687 // a QAbstractSpinBox. In this case such widget should be considered
13688 // the last focus child.
13689 for (auto *object : std::as_const(t: q->children())) {
13690 QWidget *w = qobject_cast<QWidget *>(o: object);
13691 if (w && w->focusProxy() == q) {
13692 lastFocusChild = w;
13693 break;
13694 }
13695 }
13696 } else if (q->isAncestorOf(child: focusProxy)) {
13697 lastFocusChild = focusProxy;
13698 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13699 focusNext != focusProxy && q->isAncestorOf(child: focusNext)
13700 && focusNext->window() == focusProxy->window();
13701 focusNext = focusNext->nextInFocusChain()) {
13702 if (focusNext == noFurtherThan)
13703 break;
13704 if (focusNext->focusPolicy() != Qt::NoFocus)
13705 lastFocusChild = focusNext;
13706 }
13707 }
13708 return lastFocusChild;
13709};
13710
13711/*!
13712 \internal
13713 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13714 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13715 are pointing to the widget itself.
13716
13717 \note
13718 This method doesn't check the consistency of the focus chain.
13719 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13720 isInFocusChain() will return \c true for all of those widgets, even if they represent
13721 an inconsistent focus chain.
13722 */
13723bool QWidgetPrivate::isInFocusChain() const
13724{
13725 Q_Q(const QWidget);
13726 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13727}
13728
13729/*!
13730 \internal
13731 A focus chain is consistent, when it is circular: Following the chain in either direction
13732 has to return to the beginning. This is why a newly constructed widget points to itself,
13733 when the focus chain has been initialized. A newly constructed widget is considered to have
13734 a consistent focus chain, while not being part of a focus chain.
13735
13736 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13737 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13738 It returns \c false, if one of the following is detected:
13739 \list
13740 \li nullptr found in a previous/next pointer.
13741 \li broken chain: widget A is B's previous, but B isn't A's next.
13742 \li chain isn't closed: starting at A doesn't lead back to A.
13743 \endlist
13744 It return \c true, if none of the above is observed.
13745
13746 \note
13747 The focus chain is checked only in forward direction.
13748 This is sufficient, because the check for a broken chain asserts consistent paths
13749 in both directions.
13750 */
13751bool QWidgetPrivate::isFocusChainConsistent() const
13752{
13753 Q_Q(const QWidget);
13754 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13755 if (skip)
13756 return true;
13757
13758 if (!isInFocusChain())
13759 return true;
13760
13761 const QWidget *position = q;
13762
13763 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13764 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13765 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13766 << "Previous pointing to" << FOCUS_PREV(position)
13767 << "Next pointing to" << FOCUS_NEXT(position);
13768 return false;
13769 }
13770 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13771 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13772 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13773 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13774 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13775 return false;
13776 }
13777 position = FOCUS_NEXT(position);
13778 if (position == q)
13779 return true;
13780
13781 }
13782
13783 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13784 return false;
13785}
13786
13787#undef FOCUS_NEXT
13788#undef FOCUS_PREV
13789
13790
13791QT_END_NAMESPACE
13792
13793#include "moc_qwidget.cpp"
13794#include "moc_qwidget_p.cpp"
13795

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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