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 "qevent.h"
10#include "qlayout.h"
11#if QT_CONFIG(menu)
12#include "qmenu.h"
13#endif
14#include "qmetaobject.h"
15#include "qpixmap.h"
16#include "qpointer.h"
17#include "qstack.h"
18#include "qstyle.h"
19#include "qstylefactory.h"
20#include "qvariant.h"
21#include "qwidget.h"
22#include "qstyleoption.h"
23#include "qstylehints.h"
24#if QT_CONFIG(accessibility)
25# include "qaccessible.h"
26#endif
27#include <qpa/qplatformwindow.h>
28#include <qpa/qplatformwindow_p.h>
29#include "private/qwidgetwindow_p.h"
30#include "qpainter.h"
31#if QT_CONFIG(tooltip)
32#include "qtooltip.h"
33#endif
34#if QT_CONFIG(whatsthis)
35#include "qwhatsthis.h"
36#endif
37#include "qdebug.h"
38#include "private/qstylesheetstyle_p.h"
39#include "private/qstyle_p.h"
40#include "qfileinfo.h"
41#include "qscopeguard.h"
42#include <QtGui/private/qhighdpiscaling_p.h>
43#include <QtGui/qinputmethod.h>
44
45#if QT_CONFIG(graphicseffect)
46#include <private/qgraphicseffect_p.h>
47#endif
48#include <qbackingstore.h>
49#include <private/qwidgetrepaintmanager_p.h>
50#include <private/qpaintengine_raster_p.h>
51
52#include "qwidget_p.h"
53#include <QtGui/private/qwindow_p.h>
54#if QT_CONFIG(action)
55# include "QtGui/private/qaction_p.h"
56#endif
57#include "qlayout_p.h"
58#if QT_CONFIG(graphicsview)
59#include "QtWidgets/qgraphicsproxywidget.h"
60#include "QtWidgets/qgraphicsscene.h"
61#include "private/qgraphicsproxywidget_p.h"
62#endif
63#include "QtWidgets/qabstractscrollarea.h"
64#include "private/qabstractscrollarea_p.h"
65#include "private/qevent_p.h"
66
67#include "private/qgesturemanager_p.h"
68
69#ifdef QT_KEYPAD_NAVIGATION
70#if QT_CONFIG(tabwidget)
71#include "qtabwidget.h" // Needed in inTabWidget()
72#endif
73#endif // QT_KEYPAD_NAVIGATION
74
75#include "qwindowcontainer_p.h"
76
77#include <sstream>
78
79QT_BEGIN_NAMESPACE
80
81using namespace QNativeInterface::Private;
82using namespace Qt::StringLiterals;
83
84Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
85
86static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
87{
88 return (qMax(a: r1.left(), b: r2.left()) <= qMin(a: r1.right(), b: r2.right()) &&
89 qMax(a: r1.top(), b: r2.top()) <= qMin(a: r1.bottom(), b: r2.bottom()));
90}
91
92extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
93
94QWidgetPrivate::QWidgetPrivate(int version)
95 : QObjectPrivate(version)
96 , focus_next(nullptr)
97 , focus_prev(nullptr)
98 , focus_child(nullptr)
99 , layout(nullptr)
100 , needsFlush(nullptr)
101 , redirectDev(nullptr)
102 , widgetItem(nullptr)
103 , extraPaintEngine(nullptr)
104 , polished(nullptr)
105 , graphicsEffect(nullptr)
106#if !defined(QT_NO_IM)
107 , imHints(Qt::ImhNone)
108#endif
109#if QT_CONFIG(tooltip)
110 , toolTipDuration(-1)
111#endif
112 , directFontResolveMask(0)
113 , inheritedFontResolveMask(0)
114 , directPaletteResolveMask(0)
115 , inheritedPaletteResolveMask(0)
116 , leftmargin(0)
117 , topmargin(0)
118 , rightmargin(0)
119 , bottommargin(0)
120 , leftLayoutItemMargin(0)
121 , topLayoutItemMargin(0)
122 , rightLayoutItemMargin(0)
123 , bottomLayoutItemMargin(0)
124 , hd(nullptr)
125 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
126 , fg_role(QPalette::NoRole)
127 , bg_role(QPalette::NoRole)
128 , dirtyOpaqueChildren(1)
129 , isOpaque(0)
130 , retainSizeWhenHiddenChanged(0)
131 , inDirtyList(0)
132 , isScrolled(0)
133 , isMoved(0)
134 , usesDoubleBufferedGLContext(0)
135 , mustHaveWindowHandle(0)
136 , renderToTexture(0)
137 , textureChildSeen(0)
138#ifndef QT_NO_IM
139 , inheritsInputMethodHints(0)
140#endif
141 , renderToTextureReallyDirty(1)
142 , usesRhiFlush(0)
143 , childrenHiddenByWState(0)
144 , childrenShownByExpose(0)
145#if defined(Q_OS_WIN)
146 , noPaintOnScreen(0)
147#endif
148{
149 if (Q_UNLIKELY(!qApp)) {
150 qFatal(msg: "QWidget: Must construct a QApplication before a QWidget");
151 return;
152 }
153
154#ifdef QT_BUILD_INTERNAL
155 // Don't check the version parameter in internal builds.
156 // This allows incompatible versions to be loaded, possibly for testing.
157 Q_UNUSED(version);
158#else
159 if (Q_UNLIKELY(version != QObjectPrivateVersion))
160 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
161 version, QObjectPrivateVersion);
162#endif
163
164 willBeWidget = true; // used in QObject's ctor
165 memset(s: high_attributes, c: 0, n: sizeof(high_attributes));
166
167#ifdef QWIDGET_EXTRA_DEBUG
168 static int count = 0;
169 qDebug() << "widgets" << ++count;
170#endif
171}
172
173
174QWidgetPrivate::~QWidgetPrivate()
175{
176 if (widgetItem)
177 widgetItem->wid = nullptr;
178
179 if (extra)
180 deleteExtra();
181}
182
183/*!
184 \internal
185*/
186void QWidgetPrivate::scrollChildren(int dx, int dy)
187{
188 Q_Q(QWidget);
189 if (q->children().size() > 0) { // scroll children
190 QPoint pd(dx, dy);
191 QObjectList childObjects = q->children();
192 for (int i = 0; i < childObjects.size(); ++i) { // move all children
193 QWidget *w = qobject_cast<QWidget*>(o: childObjects.at(i));
194 if (w && !w->isWindow()) {
195 QPoint oldp = w->pos();
196 QRect r(w->pos() + pd, w->size());
197 w->data->crect = r;
198 if (w->testAttribute(attribute: Qt::WA_WState_Created))
199 w->d_func()->setWSGeometry();
200 w->d_func()->setDirtyOpaqueRegion();
201 QMoveEvent e(r.topLeft(), oldp);
202 QCoreApplication::sendEvent(receiver: w, event: &e);
203 }
204 }
205 }
206}
207
208void QWidgetPrivate::setWSGeometry()
209{
210 Q_Q(QWidget);
211 if (QWindow *window = q->windowHandle())
212 window->setGeometry(data.crect);
213}
214
215void QWidgetPrivate::updateWidgetTransform(QEvent *event)
216{
217 Q_Q(QWidget);
218 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
219 QTransform t;
220 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
221 t.translate(dx: p.x(), dy: p.y());
222 QGuiApplication::inputMethod()->setInputItemTransform(t);
223 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
224 QGuiApplication::inputMethod()->update(queries: Qt::ImInputItemClipRectangle);
225 }
226}
227
228#ifdef QT_KEYPAD_NAVIGATION
229QPointer<QWidget> QWidgetPrivate::editingWidget;
230
231/*!
232 Returns \c true if this widget currently has edit focus; otherwise false.
233
234 This feature is only available in Qt for Embedded Linux.
235
236 \sa setEditFocus(), QApplication::navigationMode()
237*/
238bool QWidget::hasEditFocus() const
239{
240 const QWidget* w = this;
241 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
242 w = w->d_func()->extra->focus_proxy;
243 return QWidgetPrivate::editingWidget == w;
244}
245
246/*!
247 \fn void QWidget::setEditFocus(bool enable)
248
249 If \a enable is true, make this widget have edit focus, in which
250 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
251 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
252 change focus.
253
254 This feature is only available in Qt for Embedded Linux.
255
256 \sa hasEditFocus(), QApplication::navigationMode()
257*/
258void QWidget::setEditFocus(bool on)
259{
260 QWidget *f = this;
261 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
262 f = f->d_func()->extra->focus_proxy;
263
264 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
265 QWidgetPrivate::editingWidget->setEditFocus(false);
266
267 if (on && !f->hasFocus())
268 f->setFocus();
269
270 if ((!on && !QWidgetPrivate::editingWidget)
271 || (on && QWidgetPrivate::editingWidget == f)) {
272 return;
273 }
274
275 if (!on && QWidgetPrivate::editingWidget == f) {
276 QWidgetPrivate::editingWidget = 0;
277 QEvent event(QEvent::LeaveEditFocus);
278 QCoreApplication::sendEvent(f, &event);
279 QCoreApplication::sendEvent(f->style(), &event);
280 } else if (on) {
281 QWidgetPrivate::editingWidget = f;
282 QEvent event(QEvent::EnterEditFocus);
283 QCoreApplication::sendEvent(f, &event);
284 QCoreApplication::sendEvent(f->style(), &event);
285 }
286}
287#endif
288
289/*!
290 \property QWidget::autoFillBackground
291 \brief whether the widget background is filled automatically
292 \since 4.1
293
294 If enabled, this property will cause Qt to fill the background of the
295 widget before invoking the paint event. The color used is defined by the
296 QPalette::Window color role from the widget's \l{QPalette}{palette}.
297
298 In addition, Windows are always filled with QPalette::Window, unless the
299 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
300
301 This property cannot be turned off (i.e., set to false) if a widget's
302 parent has a static gradient for its background.
303
304 \warning Use this property with caution in conjunction with
305 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
306 background or a border-image, this property is automatically disabled.
307
308 By default, this property is \c false.
309
310 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
311 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
312*/
313bool QWidget::autoFillBackground() const
314{
315 Q_D(const QWidget);
316 return d->extra && d->extra->autoFillBackground;
317}
318
319void QWidget::setAutoFillBackground(bool enabled)
320{
321 Q_D(QWidget);
322 if (!d->extra)
323 d->createExtra();
324 if (d->extra->autoFillBackground == enabled)
325 return;
326
327 d->extra->autoFillBackground = enabled;
328 d->updateIsOpaque();
329 update();
330 d->updateIsOpaque();
331}
332
333/*!
334 \class QWidget
335 \brief The QWidget class is the base class of all user interface objects.
336
337 \ingroup basicwidgets
338 \inmodule QtWidgets
339
340 The widget is the atom of the user interface: it receives mouse, keyboard
341 and other events from the window system, and paints a representation of
342 itself on the screen. Every widget is rectangular, and they are sorted in a
343 Z-order. A widget is clipped by its parent and by the widgets in front of
344 it.
345
346 A widget that is not embedded in a parent widget is called a window.
347 Usually, windows have a frame and a title bar, although it is also possible
348 to create windows without such decoration using suitable
349 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
350 subclasses of QDialog are the most common window types.
351
352 Every widget's constructor accepts one or two standard arguments:
353
354 \list 1
355 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
356 If it is \nullptr (the default), the new widget will be a window.
357 If not, it will be a child of \e parent, and be constrained by
358 \e parent's geometry (unless you specify Qt::Window as window flag).
359 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
360 the default is suitable for almost all widgets, but to get, for
361 example, a window without a window system frame, you must use
362 special flags.
363 \endlist
364
365 QWidget has many member functions, but some of them have little direct
366 functionality; for example, QWidget has a font property, but never uses
367 this itself. There are many subclasses which provide real functionality,
368 such as QLabel, QPushButton, QListWidget, and QTabWidget.
369
370
371 \section1 Top-Level and Child Widgets
372
373 A widget without a parent widget is always an independent window (top-level
374 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
375 title bar and icon respectively.
376
377 Non-window widgets are child widgets, displayed within their parent
378 widgets. Most widgets in Qt are mainly useful as child widgets. For
379 example, it is possible to display a button as a top-level window, but most
380 people prefer to put their buttons inside other widgets, such as QDialog.
381
382 \image parent-child-widgets.png A parent widget containing various child widgets.
383
384 The diagram above shows a QGroupBox widget being used to hold various child
385 widgets in a layout provided by QGridLayout. The QLabel child widgets have
386 been outlined to indicate their full sizes.
387
388 If you want to use a QWidget to hold child widgets you will usually want to
389 add a layout to the parent QWidget. See \l{Layout Management} for more
390 information.
391
392
393 \section1 Composite Widgets
394
395 When a widget is used as a container to group a number of child widgets, it
396 is known as a composite widget. These can be created by constructing a
397 widget with the required visual properties - a QFrame, for example - and
398 adding child widgets to it, usually managed by a layout. The above diagram
399 shows such a composite widget that was created using Qt Designer.
400
401 Composite widgets can also be created by subclassing a standard widget,
402 such as QWidget or QFrame, and adding the necessary layout and child
403 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
404 {examples provided with Qt} use this approach, and it is also covered in
405 the Qt \l{Widgets Tutorial}.
406
407
408 \section1 Custom Widgets and Painting
409
410 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
411 display custom content that is composed using a series of painting
412 operations with an instance of the QPainter class. This approach contrasts
413 with the canvas-style approach used by the \l{Graphics View}
414 {Graphics View Framework} where items are added to a scene by the
415 application and are rendered by the framework itself.
416
417 Each widget performs all painting operations from within its paintEvent()
418 function. This is called whenever the widget needs to be redrawn, either
419 as a result of some external change or when requested by the application.
420
421 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
422 can handle paint events.
423
424
425 \section1 Size Hints and Size Policies
426
427 When implementing a new widget, it is almost always useful to reimplement
428 sizeHint() to provide a reasonable default size for the widget and to set
429 the correct size policy with setSizePolicy().
430
431 By default, composite widgets which do not provide a size hint will be
432 sized according to the space requirements of their child widgets.
433
434 The size policy lets you supply good default behavior for the layout
435 management system, so that other widgets can contain and manage yours
436 easily. The default size policy indicates that the size hint represents
437 the preferred size of the widget, and this is often good enough for many
438 widgets.
439
440 \note The size of top-level widgets are constrained to 2/3 of the desktop's
441 height and width. You can resize() the widget manually if these bounds are
442 inadequate.
443
444
445 \section1 Events
446
447 Widgets respond to events that are typically caused by user actions. Qt
448 delivers events to widgets by calling specific event handler functions with
449 instances of QEvent subclasses containing information about each event.
450
451 If your widget only contains child widgets, you probably do not need to
452 implement any event handlers. If you want to detect a mouse click in a
453 child widget call the child's underMouse() function inside the widget's
454 mousePressEvent().
455
456 The \l{widgets/scribble}{Scribble example} implements a wider set of
457 events to handle mouse movement, button presses, and window resizing.
458
459 You will need to supply the behavior and content for your own widgets, but
460 here is a brief overview of the events that are relevant to QWidget,
461 starting with the most common ones:
462
463 \list
464 \li paintEvent() is called whenever the widget needs to be repainted.
465 Every widget displaying custom content must implement it. Painting
466 using a QPainter can only take place in a paintEvent() or a
467 function called by a paintEvent().
468 \li resizeEvent() is called when the widget has been resized.
469 \li mousePressEvent() is called when a mouse button is pressed while
470 the mouse cursor is inside the widget, or when the widget has
471 grabbed the mouse using grabMouse(). Pressing the mouse without
472 releasing it is effectively the same as calling grabMouse().
473 \li mouseReleaseEvent() is called when a mouse button is released. A
474 widget receives mouse release events when it has received the
475 corresponding mouse press event. This means that if the user
476 presses the mouse inside \e your widget, then drags the mouse
477 somewhere else before releasing the mouse button, \e your widget
478 receives the release event. There is one exception: if a popup menu
479 appears while the mouse button is held down, this popup immediately
480 steals the mouse events.
481 \li mouseDoubleClickEvent() is called when the user double-clicks in
482 the widget. If the user double-clicks, the widget receives a mouse
483 press event, a mouse release event, (a mouse click event,) a second
484 mouse press, this event and finally a second mouse release event.
485 (Some mouse move events may also be
486 received if the mouse is not held steady during this operation.) It
487 is \e{not possible} to distinguish a click from a double-click
488 until the second click arrives. (This is one reason why most GUI
489 books recommend that double-clicks be an extension of
490 single-clicks, rather than trigger a different action.)
491 \endlist
492
493 Widgets that accept keyboard input need to reimplement a few more event
494 handlers:
495
496 \list
497 \li keyPressEvent() is called whenever a key is pressed, and again when
498 a key has been held down long enough for it to auto-repeat. The
499 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
500 they are not used by the focus-change mechanisms. To force those
501 keys to be processed by your widget, you must reimplement
502 QWidget::event().
503 \li focusInEvent() is called when the widget gains keyboard focus
504 (assuming you have called setFocusPolicy()). Well-behaved widgets
505 indicate that they own the keyboard focus in a clear but discreet
506 way.
507 \li focusOutEvent() is called when the widget loses keyboard focus.
508 \endlist
509
510 You may be required to also reimplement some of the less common event
511 handlers:
512
513 \list
514 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
515 button is held down. This can be useful during drag and drop
516 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
517 you get mouse move events even when no buttons are held down.
518 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
519 \li keyReleaseEvent() is called whenever a key is released and while it
520 is held down (if the key is auto-repeating). In that case, the
521 widget will receive a pair of key release and key press event for
522 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
523 to the widget if they are not used by the focus-change mechanisms.
524 To force those keys to be processed by your widget, you must
525 reimplement QWidget::event().
526 \li wheelEvent() is called whenever the user turns the mouse wheel
527 while the widget has the focus.
528 \li enterEvent() is called when the mouse enters the widget's screen
529 space. (This excludes screen space owned by any of the widget's
530 children.)
531 \li leaveEvent() is called when the mouse leaves the widget's screen
532 space. If the mouse enters a child widget it will not cause a
533 leaveEvent().
534 \li moveEvent() is called when the widget has been moved relative to
535 its parent.
536 \li closeEvent() is called when the user closes the widget (or when
537 close() is called).
538 \endlist
539
540 There are also some rather obscure events described in the documentation
541 for QEvent::Type. To handle these events, you need to reimplement event()
542 directly.
543
544 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
545 (to move the keyboard focus), and passes on most of the other events to
546 one of the more specialized handlers above.
547
548 Events and the mechanism used to deliver them are covered in
549 \l{The Event System}.
550
551 \section1 Groups of Functions and Properties
552
553 \table
554 \header \li Context \li Functions and Properties
555
556 \row \li Window functions \li
557 show(),
558 hide(),
559 raise(),
560 lower(),
561 close().
562
563 \row \li Top-level windows \li
564 \l windowModified, \l windowTitle, \l windowIcon,
565 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
566 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
567 showNormal().
568
569 \row \li Window contents \li
570 update(),
571 repaint(),
572 scroll().
573
574 \row \li Geometry \li
575 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
576 \l sizePolicy, sizeHint(), minimumSizeHint(),
577 updateGeometry(), layout(),
578 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
579 adjustSize(),
580 mapFromGlobal(), mapToGlobal(),
581 mapFromParent(), mapToParent(),
582 \l maximumSize, \l minimumSize, \l sizeIncrement,
583 \l baseSize, setFixedSize()
584
585 \row \li Mode \li
586 \l visible, isVisibleTo(),
587 \l enabled, isEnabledTo(),
588 \l modal,
589 isWindow(),
590 \l mouseTracking,
591 \l updatesEnabled,
592 visibleRegion().
593
594 \row \li Look and feel \li
595 style(),
596 setStyle(),
597 \l styleSheet,
598 \l cursor,
599 \l font,
600 \l palette,
601 backgroundRole(), setBackgroundRole(),
602 fontInfo(), fontMetrics().
603
604 \row \li Keyboard focus functions \li
605 \l focus, \l focusPolicy,
606 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
607 focusNextChild(), focusPreviousChild().
608
609 \row \li Mouse and keyboard grabbing \li
610 grabMouse(), releaseMouse(),
611 grabKeyboard(), releaseKeyboard(),
612 mouseGrabber(), keyboardGrabber().
613
614 \row \li Event handlers \li
615 event(),
616 mousePressEvent(),
617 mouseReleaseEvent(),
618 mouseDoubleClickEvent(),
619 mouseMoveEvent(),
620 keyPressEvent(),
621 keyReleaseEvent(),
622 focusInEvent(),
623 focusOutEvent(),
624 wheelEvent(),
625 enterEvent(),
626 leaveEvent(),
627 paintEvent(),
628 moveEvent(),
629 resizeEvent(),
630 closeEvent(),
631 dragEnterEvent(),
632 dragMoveEvent(),
633 dragLeaveEvent(),
634 dropEvent(),
635 childEvent(),
636 showEvent(),
637 hideEvent(),
638 customEvent().
639 changeEvent(),
640
641 \row \li System functions \li
642 parentWidget(), window(), setParent(), winId(),
643 find(), metric().
644
645 \row \li Context menu \li
646 contextMenuPolicy, contextMenuEvent(),
647 customContextMenuRequested(), actions()
648
649 \row \li Interactive help \li
650 setToolTip(), setWhatsThis()
651
652 \endtable
653
654
655 \section1 Widget Style Sheets
656
657 In addition to the standard widget styles for each platform, widgets can
658 also be styled according to rules specified in a \l{styleSheet}
659 {style sheet}. This feature enables you to customize the appearance of
660 specific widgets to provide visual cues to users about their purpose. For
661 example, a button could be styled in a particular way to indicate that it
662 performs a destructive action.
663
664 The use of widget style sheets is described in more detail in the
665 \l{Qt Style Sheets} document.
666
667
668 \section1 Transparency and Double Buffering
669
670 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
671 is no need to write double-buffering code in paintEvent() to avoid
672 flicker.
673
674 Since Qt 4.1, the contents of parent widgets are propagated by
675 default to each of their children as long as Qt::WA_PaintOnScreen is not
676 set. Custom widgets can be written to take advantage of this feature by
677 updating irregular regions (to create non-rectangular child widgets), or
678 painting with colors that have less than full alpha component. The
679 following diagram shows how attributes and properties of a custom widget
680 can be fine-tuned to achieve different effects.
681
682 \image propagation-custom.png
683
684 In the above diagram, a semi-transparent rectangular child widget with an
685 area removed is constructed and added to a parent widget (a QLabel showing
686 a pixmap). Then, different properties and widget attributes are set to
687 achieve different effects:
688
689 \list
690 \li The left widget has no additional properties or widget attributes
691 set. This default state suits most custom widgets using
692 transparency, are irregularly-shaped, or do not paint over their
693 entire area with an opaque brush.
694 \li The center widget has the \l autoFillBackground property set. This
695 property is used with custom widgets that rely on the widget to
696 supply a default background, and do not paint over their entire
697 area with an opaque brush.
698 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
699 set. This indicates that the widget will paint over its entire area
700 with opaque colors. The widget's area will initially be
701 \e{uninitialized}, represented in the diagram with a red diagonal
702 grid pattern that shines through the overpainted area. The
703 Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
704 paint their own specialized contents quickly and do not need a
705 default filled background.
706 \endlist
707
708 To rapidly update custom widgets with simple background colors, such as
709 real-time plotting or graphing widgets, it is better to define a suitable
710 background color (using setBackgroundRole() with the
711 QPalette::Window role), set the \l autoFillBackground property, and only
712 implement the necessary drawing functionality in the widget's paintEvent().
713
714 To rapidly update custom widgets that constantly paint over their entire
715 areas with opaque content, e.g., video streaming widgets, it is better to
716 set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
717 associated with repainting the widget's background.
718
719 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
720 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
721 attribute takes precedence. Depending on your requirements, you should
722 choose either one of them.
723
724 Since Qt 4.1, the contents of parent widgets are also propagated to
725 standard Qt widgets. This can lead to some unexpected results if the
726 parent widget is decorated in a non-standard way, as shown in the diagram
727 below.
728
729 \image propagation-standard.png
730
731 The scope for customizing the painting behavior of standard Qt widgets,
732 without resorting to subclassing, is slightly less than that possible for
733 custom widgets. Usually, the desired appearance of a standard widget can be
734 achieved by setting its \l autoFillBackground property.
735
736
737 \section1 Creating Translucent Windows
738
739 Since Qt 4.5, it has been possible to create windows with translucent regions
740 on window systems that support compositing.
741
742 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
743 attribute with setAttribute() and ensure that its background is painted with
744 non-opaque colors in the regions you want to be partially transparent.
745
746 Platform notes:
747
748 \list
749 \li X11: This feature relies on the use of an X server that supports ARGB visuals
750 and a compositing window manager.
751 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
752 for the translucency to work.
753 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
754 for the translucency to work.
755 \endlist
756
757
758 \section1 Native Widgets vs Alien Widgets
759
760 Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
761 system. They do not have a native window handle associated with them. This
762 feature significantly speeds up widget painting, resizing, and removes flicker.
763
764 Should you require the old behavior with native windows, you can choose
765 one of the following options:
766
767 \list 1
768 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
769 \li Set the Qt::AA_NativeWindows attribute on your application. All
770 widgets will be native widgets.
771 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
772 and all of its ancestors will become native (unless
773 Qt::WA_DontCreateNativeAncestors is set).
774 \li Call QWidget::winId to enforce a native window (this implies 3).
775 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
776 (this implies 3).
777 \endlist
778
779 \sa QEvent, QPainter, QGridLayout, QBoxLayout
780
781*/
782
783QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
784QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
785
786
787/*****************************************************************************
788 QWidget member functions
789 *****************************************************************************/
790
791/*
792 Widget state flags:
793 \list
794 \li Qt::WA_WState_Created The widget has a valid winId().
795 \li Qt::WA_WState_Visible The widget is currently visible.
796 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
797 become visible unless you call show() on it. Qt::WA_WState_Hidden
798 implies !Qt::WA_WState_Visible.
799 \li Qt::WA_WState_CompressKeys Compress keyboard events.
800 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
801 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
802 \li Qt::WA_WState_Reparented The widget has been reparented.
803 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
804 \endlist
805*/
806
807struct QWidgetExceptionCleaner
808{
809 /* this cleans up when the constructor throws an exception */
810 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
811 {
812#ifdef QT_NO_EXCEPTIONS
813 Q_UNUSED(that);
814 Q_UNUSED(d);
815#else
816 QWidgetPrivate::allWidgets->remove(that);
817 if (d->focus_next != that) {
818 if (d->focus_next)
819 d->focus_next->d_func()->focus_prev = d->focus_prev;
820 if (d->focus_prev)
821 d->focus_prev->d_func()->focus_next = d->focus_next;
822 }
823#endif
824 }
825};
826
827/*!
828 Constructs a widget which is a child of \a parent, with widget
829 flags set to \a f.
830
831 If \a parent is \nullptr, the new widget becomes a window. If
832 \a parent is another widget, this widget becomes a child window
833 inside \a parent. The new widget is deleted when its \a parent is
834 deleted.
835
836 The widget flags argument, \a f, is normally 0, but it can be set
837 to customize the frame of a window (i.e. \a parent must be
838 \nullptr). To customize the frame, use a value composed
839 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
840
841 If you add a child widget to an already visible widget you must
842 explicitly show the child to make it visible.
843
844 Note that the X11 version of Qt may not be able to deliver all
845 combinations of style flags on all systems. This is because on
846 X11, Qt can only ask the window manager, and the window manager
847 can override the application's settings. On Windows, Qt can set
848 whatever flags you want.
849
850 \sa windowFlags
851*/
852QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
853 : QObject(*new QWidgetPrivate, nullptr), QPaintDevice()
854{
855 QT_TRY {
856 d_func()->init(desktopWidget: parent, f);
857 } QT_CATCH(...) {
858 QWidgetExceptionCleaner::cleanup(that: this, d: d_func());
859 QT_RETHROW;
860 }
861}
862
863
864/*! \internal
865*/
866QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
867 : QObject(dd, nullptr), QPaintDevice()
868{
869 Q_D(QWidget);
870 QT_TRY {
871 d->init(desktopWidget: parent, f);
872 } QT_CATCH(...) {
873 QWidgetExceptionCleaner::cleanup(that: this, d: d_func());
874 QT_RETHROW;
875 }
876}
877
878/*!
879 \internal
880*/
881int QWidget::devType() const
882{
883 return QInternal::Widget;
884}
885
886
887//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
888void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
889{
890 bool customize = (flags & (Qt::CustomizeWindowHint
891 | Qt::FramelessWindowHint
892 | Qt::WindowTitleHint
893 | Qt::WindowSystemMenuHint
894 | Qt::WindowMinimizeButtonHint
895 | Qt::WindowMaximizeButtonHint
896 | Qt::WindowCloseButtonHint
897 | Qt::WindowContextHelpButtonHint));
898
899 uint type = (flags & Qt::WindowType_Mask);
900
901 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
902 type = Qt::Window;
903 flags |= Qt::Window;
904 }
905
906 if (flags & Qt::CustomizeWindowHint) {
907 // modify window flags to make them consistent.
908 // Only enable this on non-Mac platforms. Since the old way of doing this would
909 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
910 // we can't just add this in.
911 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
912# ifdef Q_OS_WIN
913 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
914# endif
915 ) {
916 flags |= Qt::WindowSystemMenuHint;
917 flags |= Qt::WindowTitleHint;
918 flags &= ~Qt::FramelessWindowHint;
919 }
920 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
921 // if any of the window hints that affect the titlebar are set
922 // and the window is supposed to have frame, we add a titlebar
923 // and system menu by default.
924 flags |= Qt::WindowSystemMenuHint;
925 flags |= Qt::WindowTitleHint;
926 }
927 if (!customize) { // don't modify window flags if the user explicitly set them.
928 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
929 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
930 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
931 }
932 if (w->testAttribute(attribute: Qt::WA_TransparentForMouseEvents))
933 flags |= Qt::WindowTransparentForInput;
934}
935
936void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
937{
938 Q_Q(QWidget);
939 isWidget = true;
940 wasWidget = true;
941
942 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
943
944 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
945 qFatal(msg: "QWidget: Cannot create a QWidget without QApplication");
946
947 Q_ASSERT(allWidgets);
948 if (allWidgets)
949 allWidgets->insert(value: q);
950
951 q->data = &data;
952
953#if QT_CONFIG(thread)
954 if (!parent) {
955 Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
956 "Widgets must be created in the GUI thread.");
957 }
958#endif
959
960 data.fstrut_dirty = true;
961
962 data.winid = 0;
963 data.widget_attributes = 0;
964 data.window_flags = f;
965 data.window_state = 0;
966 data.focus_policy = 0;
967 data.context_menu_policy = Qt::DefaultContextMenu;
968 data.window_modality = Qt::NonModal;
969
970 data.sizehint_forced = 0;
971 data.is_closing = false;
972 data.in_show = 0;
973 data.in_set_window_state = 0;
974 data.in_destructor = false;
975
976 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
977 if (f & Qt::MSWindowsOwnDC) {
978 mustHaveWindowHandle = 1;
979 q->setAttribute(Qt::WA_NativeWindow);
980 }
981
982 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
983 adjustQuitOnCloseAttribute();
984
985 q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
986 q->setAttribute(Qt::WA_WState_Hidden);
987
988 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
989 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
990 focus_next = focus_prev = q;
991
992 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
993 q->create();
994 else if (parentWidget)
995 q->setParent(parent: parentWidget, f: data.window_flags);
996 else {
997 adjustFlags(flags&: data.window_flags, w: q);
998 resolveLayoutDirection();
999 // opaque system background?
1000 const QBrush &background = q->palette().brush(cr: QPalette::Window);
1001 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1002 }
1003 data.fnt = QFont(data.fnt, q);
1004
1005 q->setAttribute(Qt::WA_PendingMoveEvent);
1006 q->setAttribute(Qt::WA_PendingResizeEvent);
1007
1008 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1009 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1010
1011 QEvent e(QEvent::Create);
1012 QCoreApplication::sendEvent(receiver: q, event: &e);
1013 QCoreApplication::postEvent(receiver: q, event: new QEvent(QEvent::PolishRequest));
1014
1015 extraPaintEngine = nullptr;
1016}
1017
1018void QWidgetPrivate::createRecursively()
1019{
1020 Q_Q(QWidget);
1021 q->create(0, initializeWindow: true, destroyOldWindow: true);
1022 for (int i = 0; i < children.size(); ++i) {
1023 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
1024 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(attribute: Qt::WA_WState_Created))
1025 child->d_func()->createRecursively();
1026 }
1027}
1028
1029QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1030{
1031 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1032 if (QTLWExtra *x = maybeTopData()) {
1033 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1034 return x->window;
1035 }
1036 }
1037 if (mode == WindowHandleMode::Closest) {
1038 if (auto nativeParent = q_func()->nativeParentWidget()) {
1039 if (auto window = nativeParent->windowHandle())
1040 return window;
1041 }
1042 }
1043 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1044 if (auto topLevel = q_func()->topLevelWidget()) {
1045 if (auto window = topLevel ->windowHandle())
1046 return window;
1047 }
1048 }
1049 return nullptr;
1050}
1051
1052/*!
1053 \internal
1054
1055 Used by clients outside of widgets to get a handle to the
1056 closest QWindow without having to link to widgets.
1057*/
1058QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1059{
1060 return windowHandle(mode: QWidgetPrivate::WindowHandleMode::Closest);
1061}
1062
1063QScreen *QWidgetPrivate::associatedScreen() const
1064{
1065#if QT_CONFIG(graphicsview)
1066 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1067 if (nearestGraphicsProxyWidget(origin: q_func()))
1068 return nullptr;
1069#endif
1070 if (auto window = windowHandle(mode: WindowHandleMode::Closest))
1071 return window->screen();
1072 return nullptr;
1073}
1074
1075// finds the first rhiconfig in the hierarchy that has enable==true
1076static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1077{
1078 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1079 if (config.isEnabled()) {
1080 if (outConfig)
1081 *outConfig = config;
1082 if (outType)
1083 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1084 return true;
1085 }
1086 for (const QObject *child : w->children()) {
1087 if (const QWidget *childWidget = qobject_cast<const QWidget *>(o: child)) {
1088 if (q_evaluateRhiConfigRecursive(w: childWidget, outConfig, outType))
1089 return true;
1090 }
1091 }
1092 return false;
1093}
1094
1095bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1096{
1097 // First, check env.vars. or other means that force the usage of rhi-based
1098 // flushing with a specific graphics API. This takes precedence over what
1099 // the widgets themselves declare. This is global, applying to all
1100 // top-levels.
1101 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1102 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1103 return true;
1104 }
1105
1106 // Otherwise, check the widget hierarchy to see if there is a child (or
1107 // ourselves) that declare the need for rhi-based composition.
1108 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1109 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1110 return true;
1111 }
1112
1113 return false;
1114}
1115
1116// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1117
1118/*!
1119 Creates a new widget window.
1120
1121 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1122 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1123 QWindow wrapping a foreign window and pass it to
1124 QWidget::createWindowContainer() instead.
1125
1126 \sa createWindowContainer(), QWindow::fromWinId()
1127*/
1128
1129void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1130{
1131 Q_UNUSED(initializeWindow);
1132 Q_UNUSED(destroyOldWindow);
1133
1134 Q_D(QWidget);
1135 if (Q_UNLIKELY(window))
1136 qWarning(msg: "QWidget::create(): Parameter 'window' does not have any effect.");
1137 if (testAttribute(attribute: Qt::WA_WState_Created) && window == 0 && internalWinId())
1138 return;
1139
1140 if (d->data.in_destructor)
1141 return;
1142
1143 Qt::WindowType type = windowType();
1144 Qt::WindowFlags &flags = data->window_flags;
1145
1146 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1147 type = Qt::Window;
1148 flags |= Qt::Window;
1149 }
1150
1151 if (QWidget *parent = parentWidget()) {
1152 if (type & Qt::Window) {
1153 if (!parent->testAttribute(attribute: Qt::WA_WState_Created))
1154 parent->createWinId();
1155 } else if (testAttribute(attribute: Qt::WA_NativeWindow) && !parent->internalWinId()
1156 && !testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
1157 // We're about to create a native child widget that doesn't have a native parent;
1158 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1159 // attribute is set.
1160 d->createWinId();
1161 // Nothing more to do.
1162 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1163 Q_ASSERT(internalWinId());
1164 return;
1165 }
1166 }
1167
1168
1169 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue(varName: "QT_ONSCREEN_PAINT") > 0;
1170 if (paintOnScreenEnv)
1171 setAttribute(Qt::WA_PaintOnScreen);
1172
1173 if (QApplicationPrivate::testAttribute(flag: Qt::AA_NativeWindows))
1174 setAttribute(Qt::WA_NativeWindow);
1175
1176 d->updateIsOpaque();
1177
1178 setAttribute(Qt::WA_WState_Created); // set created flag
1179 d->create();
1180
1181 // A real toplevel window needs a paint manager
1182 if (isWindow() && windowType() != Qt::Desktop)
1183 d->topData()->repaintManager.reset(p: new QWidgetRepaintManager(this));
1184
1185 d->setModal_sys();
1186
1187 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered))
1188 setAttribute(Qt::WA_DropSiteRegistered, on: true);
1189
1190 // need to force the resting of the icon after changing parents
1191 if (testAttribute(attribute: Qt::WA_SetWindowIcon))
1192 d->setWindowIcon_sys();
1193
1194 if (isWindow() && !d->topData()->iconText.isEmpty())
1195 d->setWindowIconText_helper(d->topData()->iconText);
1196 if (isWindow() && !d->topData()->caption.isEmpty())
1197 d->setWindowTitle_helper(d->topData()->caption);
1198 if (isWindow() && !d->topData()->filePath.isEmpty())
1199 d->setWindowFilePath_helper(d->topData()->filePath);
1200 if (windowType() != Qt::Desktop) {
1201 d->updateSystemBackground();
1202
1203 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon))
1204 d->setWindowIcon_sys();
1205 }
1206
1207 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1208 // as those force native window creation on their ancestors before they are shown.
1209 // If the strut is not updated, any subsequent move of the top level window before show
1210 // will cause window frame to be ignored when positioning the window.
1211 // Note that this only helps on platforms that handle window creation synchronously.
1212 d->updateFrameStrut();
1213}
1214
1215void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1216{
1217 QObjectList children = parentWidget->children();
1218 for (int i = 0; i < children.size(); i++) {
1219 if (children.at(i)->isWidgetType()) {
1220 const QWidget *childWidget = qobject_cast<const QWidget *>(object: children.at(i));
1221 if (childWidget) { // should not be necessary
1222 if (childWidget->testAttribute(attribute: Qt::WA_NativeWindow)) {
1223 if (!childWidget->internalWinId())
1224 childWidget->winId();
1225 if (childWidget->windowHandle()) {
1226 if (childWidget->isWindow()) {
1227 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1228 } else {
1229 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1230 }
1231 }
1232 } else {
1233 q_createNativeChildrenAndSetParent(parentWidget: childWidget);
1234 }
1235 }
1236 }
1237 }
1238
1239}
1240
1241void QWidgetPrivate::create()
1242{
1243 Q_Q(QWidget);
1244
1245 if (!q->testAttribute(attribute: Qt::WA_NativeWindow) && !q->isWindow())
1246 return; // we only care about real toplevels
1247
1248 QWidgetWindow *win = topData()->window;
1249 // topData() ensures the extra is created but does not ensure 'window' is non-null
1250 // in case the extra was already valid.
1251 if (!win) {
1252 createTLSysExtra();
1253 Q_ASSERT(topData()->window);
1254 win = topData()->window;
1255 }
1256
1257 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1258 for (const QByteArray &propertyName : dynamicPropertyNames) {
1259 if (!qstrncmp(str1: propertyName, str2: "_q_platform_", len: 12))
1260 win->setProperty(name: propertyName, value: q->property(name: propertyName));
1261 }
1262
1263 Qt::WindowFlags &flags = data.window_flags;
1264
1265#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
1266 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1267 flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1268#endif
1269
1270 if (q->testAttribute(attribute: Qt::WA_ShowWithoutActivating))
1271 win->setProperty(name: "_q_showWithoutActivating", value: QVariant(true));
1272 if (q->testAttribute(attribute: Qt::WA_MacAlwaysShowToolWindow))
1273 win->setProperty(name: "_q_macAlwaysShowToolWindow", value: QVariant(true));
1274 win->setFlags(flags);
1275 fixPosIncludesFrame();
1276 if (q->testAttribute(attribute: Qt::WA_Moved)
1277 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
1278 win->setGeometry(q->geometry());
1279 else
1280 win->resize(newSize: q->size());
1281 if (win->isTopLevel()) {
1282 QScreen *targetScreen = topData()->initialScreen;
1283 topData()->initialScreen = nullptr;
1284 if (!targetScreen) {
1285 targetScreen = q->windowType() != Qt::Desktop
1286 ? q->screen() : nullptr;
1287 }
1288 win->setScreen(targetScreen);
1289 }
1290
1291 QSurfaceFormat format = win->requestedFormat();
1292 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1293 && q->testAttribute(attribute: Qt::WA_TranslucentBackground)) {
1294 format.setAlphaBufferSize(8);
1295 }
1296 win->setFormat(format);
1297
1298 if (QWidget *nativeParent = q->nativeParentWidget()) {
1299 if (nativeParent->windowHandle()) {
1300 if (flags & Qt::Window) {
1301 win->setTransientParent(nativeParent->window()->windowHandle());
1302 win->setParent(nullptr);
1303 } else {
1304 win->setTransientParent(nullptr);
1305 win->setParent(nativeParent->windowHandle());
1306 }
1307 }
1308 }
1309
1310 qt_window_private(window: win)->positionPolicy = topData()->posIncludesFrame ?
1311 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1312
1313 if (q->windowType() != Qt::Desktop || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
1314 win->create();
1315 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1316 if (QPlatformWindow *platformWindow = win->handle())
1317 platformWindow->setFrameStrutEventsEnabled(true);
1318 }
1319
1320 data.window_flags = win->flags();
1321 if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1322 data.window_flags &= ~Qt::ForeignWindow;
1323
1324#if QT_CONFIG(xcb)
1325 if (!topData()->role.isNull()) {
1326 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1327 xcbWindow->setWindowRole(topData()->role);
1328 }
1329#endif
1330
1331 // Android doesn't allow to re-use the backing store.
1332 // => force creation of a new one.
1333#ifdef Q_OS_ANDROID
1334 QBackingStore *store = nullptr;
1335#else
1336 QBackingStore *store = q->backingStore();
1337#endif
1338 usesRhiFlush = false;
1339
1340 if (!store) {
1341 if (q->windowType() != Qt::Desktop) {
1342 if (q->isWindow()) {
1343 q->setBackingStore(new QBackingStore(win));
1344 QPlatformBackingStoreRhiConfig rhiConfig;
1345 usesRhiFlush = q_evaluateRhiConfig(w: q, outConfig: &rhiConfig, outType: nullptr);
1346 topData()->backingStore->handle()->setRhiConfig(rhiConfig);
1347 }
1348 } else {
1349 q->setAttribute(Qt::WA_PaintOnScreen, on: true);
1350 }
1351 } else if (win->handle()) {
1352 usesRhiFlush = q_evaluateRhiConfig(w: q, outConfig: nullptr, outType: nullptr);
1353 }
1354
1355 setWindowModified_helper();
1356
1357 if (win->handle()) {
1358 WId id = win->winId();
1359 // See the QPlatformWindow::winId() documentation
1360 Q_ASSERT(id != WId(0));
1361 setWinId(id);
1362 }
1363 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1364
1365 // Check children and create windows for them if necessary
1366 q_createNativeChildrenAndSetParent(parentWidget: q);
1367
1368 if (extra && !extra->mask.isEmpty())
1369 setMask_sys(extra->mask);
1370
1371 if (data.crect.width() == 0 || data.crect.height() == 0) {
1372 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
1373 } else if (q->isVisible()) {
1374 // If widget is already shown, set window visible, too
1375 win->setNativeWindowVisibility(true);
1376 }
1377}
1378
1379#ifdef Q_OS_WIN
1380static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1381#endif
1382
1383void QWidgetPrivate::createTLSysExtra()
1384{
1385 Q_Q(QWidget);
1386 if (!extra->topextra->window && (q->testAttribute(attribute: Qt::WA_NativeWindow) || q->isWindow())) {
1387 extra->topextra->window = new QWidgetWindow(q);
1388 if (extra->minw || extra->minh)
1389 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1390 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1391 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1392 if (extra->topextra->opacity != 255 && q->isWindow())
1393 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1394
1395 const bool isTipLabel = q->inherits(classname: "QTipLabel");
1396 const bool isAlphaWidget = !isTipLabel && q->inherits(classname: "QAlphaWidget");
1397#ifdef Q_OS_WIN
1398 // Pass on native parent handle for Widget embedded into Active X.
1399 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1400 if (activeXNativeParentHandle.isValid())
1401 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1402 if (isTipLabel || isAlphaWidget)
1403 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1404#endif
1405 if (isTipLabel || isAlphaWidget || q->inherits(classname: "QRollEffect"))
1406 qt_window_private(window: extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1407
1408 updateIsTranslucent();
1409 }
1410
1411}
1412
1413/*!
1414 Destroys the widget.
1415
1416 All this widget's children are deleted first. The application
1417 exits if this widget is the main widget.
1418*/
1419
1420QWidget::~QWidget()
1421{
1422 Q_D(QWidget);
1423 d->data.in_destructor = true;
1424
1425#if defined (QT_CHECK_STATE)
1426 if (Q_UNLIKELY(paintingActive()))
1427 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1428#endif
1429
1430#ifndef QT_NO_GESTURES
1431 if (QGestureManager *manager = QGestureManager::instance(ic: QGestureManager::DontForceCreation)) {
1432 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1433 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1434 manager->cleanupCachedGestures(target: this, type: *it);
1435 }
1436 d->gestureContext.clear();
1437#endif
1438
1439#ifndef QT_NO_ACTION
1440 // remove all actions from this widget
1441 for (auto action : std::as_const(t&: d->actions)) {
1442 QActionPrivate *apriv = action->d_func();
1443 apriv->associatedObjects.removeAll(t: this);
1444 }
1445 d->actions.clear();
1446#endif
1447
1448#ifndef QT_NO_SHORTCUT
1449 // Remove all shortcuts grabbed by this
1450 // widget, unless application is closing
1451 if (!QApplicationPrivate::is_app_closing && testAttribute(attribute: Qt::WA_GrabbedShortcut))
1452 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id: 0, owner: this, key: QKeySequence());
1453#endif
1454
1455 // delete layout while we still are a valid widget
1456 delete d->layout;
1457 d->layout = nullptr;
1458 // Remove myself from focus list
1459
1460 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1461 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1462
1463 if (d->focus_next != this) {
1464 d->focus_next->d_func()->focus_prev = d->focus_prev;
1465 d->focus_prev->d_func()->focus_next = d->focus_next;
1466 d->focus_next = d->focus_prev = nullptr;
1467 }
1468
1469
1470 QT_TRY {
1471#if QT_CONFIG(graphicsview)
1472 const QWidget* w = this;
1473 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1474 w = w->d_func()->extra->focus_proxy;
1475 QWidget *window = w->window();
1476 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1477 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1478#endif
1479 clearFocus();
1480 } QT_CATCH(...) {
1481 // swallow this problem because we are in a destructor
1482 }
1483
1484 d->setDirtyOpaqueRegion();
1485
1486 if (isWindow() && isVisible() && internalWinId()) {
1487 QT_TRY {
1488 d->close();
1489 } QT_CATCH(...) {
1490 // if we're out of memory, at least hide the window.
1491 QT_TRY {
1492 hide();
1493 } QT_CATCH(...) {
1494 // and if that also doesn't work, then give up
1495 }
1496 }
1497 } else if (isVisible()) {
1498 qApp->d_func()->sendSyntheticEnterLeave(widget: this);
1499 }
1500
1501 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1502 repaintManager->removeDirtyWidget(w: this);
1503 if (testAttribute(attribute: Qt::WA_StaticContents))
1504 repaintManager->removeStaticWidget(widget: this);
1505 }
1506
1507 delete d->needsFlush;
1508 d->needsFlush = nullptr;
1509
1510 // The next 20 lines are duplicated from QObject, but required here
1511 // since QWidget deletes is children itself
1512 bool blocked = d->blockSig;
1513 d->blockSig = 0; // unblock signals so we always emit destroyed()
1514
1515 if (d->isSignalConnected(signalIdx: 0)) {
1516 QT_TRY {
1517 emit destroyed(this);
1518 } QT_CATCH(...) {
1519 // all the signal/slots connections are still in place - if we don't
1520 // quit now, we will crash pretty soon.
1521 qWarning(msg: "Detected an unexpected exception in ~QWidget while emitting destroyed().");
1522 QT_RETHROW;
1523 }
1524 }
1525
1526 if (d->declarativeData) {
1527 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1528 if (QAbstractDeclarativeData::destroyed)
1529 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1530 d->declarativeData = nullptr; // don't activate again in ~QObject
1531 d->wasDeleted = false;
1532 }
1533
1534 d->blockSig = blocked;
1535
1536 if (!d->children.isEmpty())
1537 d->deleteChildren();
1538
1539 QCoreApplication::removePostedEvents(receiver: this);
1540
1541 QT_TRY {
1542 destroy(); // platform-dependent cleanup
1543 } QT_CATCH(...) {
1544 // if this fails we can't do anything about it but at least we are not allowed to throw.
1545 }
1546 --QWidgetPrivate::instanceCounter;
1547
1548 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1549 QWidgetPrivate::allWidgets->remove(value: this);
1550
1551 QT_TRY {
1552 QEvent e(QEvent::Destroy);
1553 QCoreApplication::sendEvent(receiver: this, event: &e);
1554 } QT_CATCH(const std::exception&) {
1555 // if this fails we can't do anything about it but at least we are not allowed to throw.
1556 }
1557
1558#if QT_CONFIG(graphicseffect)
1559 delete d->graphicsEffect;
1560#endif
1561
1562 d->isWidget = false;
1563}
1564
1565int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1566int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1567
1568void QWidgetPrivate::setWinId(WId id) // set widget identifier
1569{
1570 Q_Q(QWidget);
1571 if (mapper && data.winid) {
1572 mapper->remove(key: data.winid);
1573 }
1574
1575 const WId oldWinId = data.winid;
1576
1577 data.winid = id;
1578 if (mapper && id) {
1579 mapper->insert(key: data.winid, value: q);
1580 }
1581
1582 if (oldWinId != id) {
1583 QEvent e(QEvent::WinIdChange);
1584 QCoreApplication::sendEvent(receiver: q, event: &e);
1585 }
1586}
1587
1588void QWidgetPrivate::createTLExtra()
1589{
1590 if (!extra)
1591 createExtra();
1592 if (!extra->topextra) {
1593 extra->topextra = std::make_unique<QTLWExtra>();
1594 QTLWExtra* x = extra->topextra.get();
1595 x->backingStore = nullptr;
1596 x->sharedPainter = nullptr;
1597 x->incw = x->inch = 0;
1598 x->basew = x->baseh = 0;
1599 x->frameStrut.setCoords(xp1: 0, yp1: 0, xp2: 0, yp2: 0);
1600 x->normalGeometry = QRect(0,0,-1,-1);
1601 x->savedFlags = { };
1602 x->opacity = 255;
1603 x->posIncludesFrame = 0;
1604 x->sizeAdjusted = false;
1605 x->embedded = 0;
1606 x->window = nullptr;
1607 x->initialScreen = nullptr;
1608
1609#ifdef QWIDGET_EXTRA_DEBUG
1610 static int count = 0;
1611 qDebug() << "tlextra" << ++count;
1612#endif
1613 }
1614}
1615
1616/*!
1617 \internal
1618 Creates the widget extra data.
1619*/
1620
1621void QWidgetPrivate::createExtra()
1622{
1623 if (!extra) { // if not exists
1624 extra = std::make_unique<QWExtra>();
1625 extra->glContext = nullptr;
1626#if QT_CONFIG(graphicsview)
1627 extra->proxyWidget = nullptr;
1628#endif
1629 extra->minw = 0;
1630 extra->minh = 0;
1631 extra->maxw = QWIDGETSIZE_MAX;
1632 extra->maxh = QWIDGETSIZE_MAX;
1633 extra->customDpiX = 0;
1634 extra->customDpiY = 0;
1635 extra->explicitMinSize = 0;
1636 extra->explicitMaxSize = 0;
1637 extra->autoFillBackground = 0;
1638 extra->nativeChildrenForced = 0;
1639 extra->inRenderWithPainter = 0;
1640 extra->hasWindowContainer = false;
1641 extra->hasMask = 0;
1642 createSysExtra();
1643#ifdef QWIDGET_EXTRA_DEBUG
1644 static int count = 0;
1645 qDebug() << "extra" << ++count;
1646#endif
1647 }
1648}
1649
1650void QWidgetPrivate::createSysExtra()
1651{
1652}
1653
1654/*!
1655 \internal
1656 Deletes the widget extra data.
1657*/
1658
1659void QWidgetPrivate::deleteExtra()
1660{
1661 if (extra) { // if exists
1662 deleteSysExtra();
1663#ifndef QT_NO_STYLE_STYLESHEET
1664 // dereference the stylesheet style
1665 if (QStyleSheetStyle *proxy = qt_styleSheet(style: extra->style))
1666 proxy->deref();
1667#endif
1668 if (extra->topextra) {
1669 deleteTLSysExtra();
1670 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1671 }
1672 // extra->xic destroyed in QWidget::destroy()
1673 extra.reset();
1674 }
1675}
1676
1677void QWidgetPrivate::deleteSysExtra()
1678{
1679}
1680
1681static void deleteBackingStore(QWidgetPrivate *d)
1682{
1683 QTLWExtra *topData = d->topData();
1684
1685 delete topData->backingStore;
1686 topData->backingStore = nullptr;
1687}
1688
1689void QWidgetPrivate::deleteTLSysExtra()
1690{
1691 if (extra && extra->topextra) {
1692 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1693 //needs to be deleted first.
1694
1695 extra->topextra->repaintManager.reset(p: nullptr);
1696 deleteBackingStore(d: this);
1697 extra->topextra->widgetTextures.clear();
1698
1699 //the toplevel might have a context with a "qglcontext associated with it. We need to
1700 //delete the qglcontext before we delete the qplatformopenglcontext.
1701 //One unfortunate thing about this is that we potentially create a glContext just to
1702 //delete it straight afterwards.
1703 if (extra->topextra->window) {
1704 extra->topextra->window->destroy();
1705 }
1706 delete extra->topextra->window;
1707 extra->topextra->window = nullptr;
1708
1709 }
1710}
1711
1712/*
1713 Returns \c region of widgets above this which overlap with
1714 \a rect, which is in parent's coordinate system (same as crect).
1715*/
1716
1717QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1718{
1719 Q_Q(const QWidget);
1720
1721 const QWidget *w = q;
1722 QRect r = rect;
1723 QPoint p;
1724 QRegion region;
1725 while (w) {
1726 if (w->isWindow())
1727 break;
1728 QWidgetPrivate *pd = w->parentWidget()->d_func();
1729 bool above = false;
1730 for (int i = 0; i < pd->children.size(); ++i) {
1731 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
1732 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1733 continue;
1734 if (!above) {
1735 above = (sibling == w);
1736 continue;
1737 }
1738
1739 const QRect siblingRect = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
1740 if (qRectIntersects(r1: siblingRect, r2: r)) {
1741 const auto &siblingExtra = sibling->d_func()->extra;
1742 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1743 && !siblingExtra->mask.translated(p: sibling->data->crect.topLeft()).intersects(r)) {
1744 continue;
1745 }
1746 region += siblingRect.translated(p: -p);
1747 if (breakAfterFirst)
1748 break;
1749 }
1750 }
1751 w = w->parentWidget();
1752 r.translate(p: pd->data.crect.topLeft());
1753 p += pd->data.crect.topLeft();
1754 }
1755 return region;
1756}
1757
1758void QWidgetPrivate::syncBackingStore()
1759{
1760 if (shouldPaintOnScreen()) {
1761 paintOnScreen(rgn: dirty);
1762 dirty = QRegion();
1763 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1764 repaintManager->sync();
1765 }
1766}
1767
1768void QWidgetPrivate::syncBackingStore(const QRegion &region)
1769{
1770 if (shouldPaintOnScreen())
1771 paintOnScreen(rgn: region);
1772 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1773 repaintManager->sync(exposedWidget: q_func(), exposedRegion: region);
1774 }
1775}
1776
1777void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1778{
1779 if (data.in_destructor)
1780 return;
1781
1782 if (shouldDiscardSyncRequest())
1783 return;
1784
1785 Q_Q(QWidget);
1786 if (q->testAttribute(attribute: Qt::WA_StaticContents)) {
1787 if (!extra)
1788 createExtra();
1789 extra->staticContentsSize = data.crect.size();
1790 }
1791
1792 QPaintEngine *engine = q->paintEngine();
1793
1794 // QGLWidget does not support partial updates if:
1795 // 1) The context is double buffered
1796 // 2) The context is single buffered and auto-fill background is enabled.
1797 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1798 || engine->type() == QPaintEngine::OpenGL2))
1799 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1800 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1801
1802 toBePainted &= clipRect();
1803 clipToEffectiveMask(region&: toBePainted);
1804 if (toBePainted.isEmpty())
1805 return; // Nothing to repaint.
1806
1807 drawWidget(pdev: q, rgn: toBePainted, offset: QPoint(), flags: QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, sharedPainter: nullptr);
1808
1809 if (Q_UNLIKELY(q->paintingActive()))
1810 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1811}
1812
1813void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1814{
1815 Q_Q(QWidget);
1816
1817 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1818 return; // nothing we can do
1819
1820 if (enable != q->testAttribute(attribute: Qt::WA_UpdatesDisabled))
1821 return; // nothing to do
1822
1823 q->setAttribute(Qt::WA_UpdatesDisabled, on: !enable);
1824 if (enable)
1825 q->update();
1826
1827 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1828 for (int i = 0; i < children.size(); ++i) {
1829 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
1830 if (w && !w->isWindow() && !w->testAttribute(attribute))
1831 w->d_func()->setUpdatesEnabled_helper(enable);
1832 }
1833}
1834
1835/*!
1836 \internal
1837
1838 Propagate this widget's palette to all children, except style sheet
1839 widgets, and windows that don't enable window propagation (palettes don't
1840 normally propagate to windows).
1841*/
1842void QWidgetPrivate::propagatePaletteChange()
1843{
1844 Q_Q(QWidget);
1845 // Propagate a new inherited mask to all children.
1846#if QT_CONFIG(graphicsview)
1847 if (!q->parentWidget() && extra && extra->proxyWidget) {
1848 QGraphicsProxyWidget *p = extra->proxyWidget;
1849 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1850 } else
1851#endif // QT_CONFIG(graphicsview)
1852 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
1853 inheritedPaletteResolveMask = 0;
1854 }
1855
1856 directPaletteResolveMask = data.pal.resolveMask();
1857 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1858
1859 const bool useStyleSheetPropagationInWidgetStyles =
1860 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1861
1862 QEvent pc(QEvent::PaletteChange);
1863 QCoreApplication::sendEvent(receiver: q, event: &pc);
1864 for (int i = 0; i < children.size(); ++i) {
1865 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
1866 if (w && (!w->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1867 && (!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
1868 QWidgetPrivate *wd = w->d_func();
1869 wd->inheritedPaletteResolveMask = mask;
1870 wd->resolvePalette();
1871 }
1872 }
1873}
1874
1875/*
1876 Returns the widget's clipping rectangle.
1877*/
1878QRect QWidgetPrivate::clipRect() const
1879{
1880 Q_Q(const QWidget);
1881 const QWidget * w = q;
1882 if (!w->isVisible())
1883 return QRect();
1884 QRect r = effectiveRectFor(rect: q->rect());
1885 int ox = 0;
1886 int oy = 0;
1887 while (w
1888 && w->isVisible()
1889 && !w->isWindow()
1890 && w->parentWidget()) {
1891 ox -= w->x();
1892 oy -= w->y();
1893 w = w->parentWidget();
1894 r &= QRect(ox, oy, w->width(), w->height());
1895 }
1896 return r;
1897}
1898
1899/*
1900 Returns the widget's clipping region (without siblings).
1901*/
1902QRegion QWidgetPrivate::clipRegion() const
1903{
1904 Q_Q(const QWidget);
1905 if (!q->isVisible())
1906 return QRegion();
1907 QRegion r(q->rect());
1908 const QWidget * w = q;
1909 const QWidget *ignoreUpTo;
1910 int ox = 0;
1911 int oy = 0;
1912 while (w
1913 && w->isVisible()
1914 && !w->isWindow()
1915 && w->parentWidget()) {
1916 ox -= w->x();
1917 oy -= w->y();
1918 ignoreUpTo = w;
1919 w = w->parentWidget();
1920 r &= QRegion(ox, oy, w->width(), w->height());
1921
1922 int i = 0;
1923 while(w->d_func()->children.at(i: i++) != static_cast<const QObject *>(ignoreUpTo))
1924 ;
1925 for ( ; i < w->d_func()->children.size(); ++i) {
1926 if (QWidget *sibling = qobject_cast<QWidget *>(o: w->d_func()->children.at(i))) {
1927 if (sibling->isVisible() && !sibling->isWindow()) {
1928 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1929 sibling->width(), sibling->height());
1930 if (qRectIntersects(r1: siblingRect, r2: q->rect()))
1931 r -= QRegion(siblingRect);
1932 }
1933 }
1934 }
1935 }
1936 return r;
1937}
1938
1939void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1940{
1941// Transform the system clip region from device-independent pixels to device pixels
1942 QTransform scaleTransform;
1943 scaleTransform.scale(sx: devicePixelRatio, sy: devicePixelRatio);
1944
1945 paintEngine->d_func()->baseSystemClip = region;
1946 paintEngine->d_func()->setSystemTransform(scaleTransform);
1947
1948}
1949
1950#if QT_CONFIG(graphicseffect)
1951void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1952{
1953 Q_Q(QWidget);
1954 QWidget *w = q;
1955 do {
1956 if (w->graphicsEffect()) {
1957 QWidgetEffectSourcePrivate *sourced =
1958 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1959 if (!sourced->updateDueToGraphicsEffect)
1960 w->graphicsEffect()->source()->d_func()->invalidateCache();
1961 }
1962 w = w->parentWidget();
1963 } while (w);
1964}
1965#endif // QT_CONFIG(graphicseffect)
1966
1967void QWidgetPrivate::setDirtyOpaqueRegion()
1968{
1969 Q_Q(QWidget);
1970
1971 dirtyOpaqueChildren = true;
1972
1973#if QT_CONFIG(graphicseffect)
1974 invalidateGraphicsEffectsRecursively();
1975#endif // QT_CONFIG(graphicseffect)
1976
1977 if (q->isWindow())
1978 return;
1979
1980 QWidget *parent = q->parentWidget();
1981 if (!parent)
1982 return;
1983
1984 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1985 QWidgetPrivate *pd = parent->d_func();
1986 if (!pd->dirtyOpaqueChildren)
1987 pd->setDirtyOpaqueRegion();
1988}
1989
1990const QRegion &QWidgetPrivate::getOpaqueChildren() const
1991{
1992 if (!dirtyOpaqueChildren)
1993 return opaqueChildren;
1994
1995 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
1996 that->opaqueChildren = QRegion();
1997
1998 for (int i = 0; i < children.size(); ++i) {
1999 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
2000 if (!child || !child->isVisible() || child->isWindow())
2001 continue;
2002
2003 const QPoint offset = child->geometry().topLeft();
2004 QWidgetPrivate *childd = child->d_func();
2005 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2006 if (childd->extra && childd->extra->hasMask)
2007 r &= childd->extra->mask;
2008 if (r.isEmpty())
2009 continue;
2010 r.translate(p: offset);
2011 that->opaqueChildren += r;
2012 }
2013
2014 that->opaqueChildren &= q_func()->rect();
2015 that->dirtyOpaqueChildren = false;
2016
2017 return that->opaqueChildren;
2018}
2019
2020void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2021{
2022 if (children.isEmpty() || clipRect.isEmpty())
2023 return;
2024
2025 const QRegion &r = getOpaqueChildren();
2026 if (!r.isEmpty())
2027 source -= (r & clipRect);
2028}
2029
2030//subtract any relatives that are higher up than me --- this is too expensive !!!
2031void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2032 bool alsoNonOpaque) const
2033{
2034 Q_Q(const QWidget);
2035 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue(varName: "QT_NO_SUBTRACTOPAQUESIBLINGS");
2036 if (disableSubtractOpaqueSiblings || q->isWindow())
2037 return;
2038
2039 QRect clipBoundingRect;
2040 bool dirtyClipBoundingRect = true;
2041
2042 QRegion parentClip;
2043 bool dirtyParentClip = true;
2044
2045 QPoint parentOffset = data.crect.topLeft();
2046
2047 const QWidget *w = q;
2048
2049 while (w) {
2050 if (w->isWindow())
2051 break;
2052 QWidgetPrivate *pd = w->parentWidget()->d_func();
2053 const int myIndex = pd->children.indexOf(t: const_cast<QWidget *>(w));
2054 const QRect widgetGeometry = w->d_func()->effectiveRectFor(rect: w->data->crect);
2055 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2056 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
2057 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2058 continue;
2059
2060 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
2061 if (!qRectIntersects(r1: siblingGeometry, r2: widgetGeometry))
2062 continue;
2063
2064 if (dirtyClipBoundingRect) {
2065 clipBoundingRect = sourceRegion.boundingRect();
2066 dirtyClipBoundingRect = false;
2067 }
2068
2069 if (!qRectIntersects(r1: siblingGeometry, r2: clipBoundingRect.translated(p: parentOffset)))
2070 continue;
2071
2072 if (dirtyParentClip) {
2073 parentClip = sourceRegion.translated(p: parentOffset);
2074 dirtyParentClip = false;
2075 }
2076
2077 const QPoint siblingPos(sibling->data->crect.topLeft());
2078 const QRect siblingClipRect(sibling->d_func()->clipRect());
2079 QRegion siblingDirty(parentClip);
2080 siblingDirty &= (siblingClipRect.translated(p: siblingPos));
2081 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2082 && !sibling->d_func()->graphicsEffect;
2083 if (hasMask)
2084 siblingDirty &= sibling->d_func()->extra->mask.translated(p: siblingPos);
2085 if (siblingDirty.isEmpty())
2086 continue;
2087
2088 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2089 if (hasMask) {
2090 siblingDirty.translate(p: -parentOffset);
2091 sourceRegion -= siblingDirty;
2092 } else {
2093 sourceRegion -= siblingGeometry.translated(p: -parentOffset);
2094 }
2095 } else {
2096 if (hasDirtySiblingsAbove)
2097 *hasDirtySiblingsAbove = true;
2098 if (sibling->d_func()->children.isEmpty())
2099 continue;
2100 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2101 opaqueSiblingChildren.translate(p: -parentOffset + siblingPos);
2102 sourceRegion -= opaqueSiblingChildren;
2103 }
2104 if (sourceRegion.isEmpty())
2105 return;
2106
2107 dirtyClipBoundingRect = true;
2108 dirtyParentClip = true;
2109 }
2110
2111 w = w->parentWidget();
2112 parentOffset += pd->data.crect.topLeft();
2113 dirtyParentClip = true;
2114 }
2115}
2116
2117void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2118{
2119 Q_Q(const QWidget);
2120
2121 const QWidget *w = q;
2122 QPoint offset;
2123
2124#if QT_CONFIG(graphicseffect)
2125 if (graphicsEffect) {
2126 w = q->parentWidget();
2127 offset -= data.crect.topLeft();
2128 }
2129#endif // QT_CONFIG(graphicseffect)
2130
2131 while (w) {
2132 const QWidgetPrivate *wd = w->d_func();
2133 if (wd->extra && wd->extra->hasMask)
2134 region &= (w != q) ? wd->extra->mask.translated(p: offset) : wd->extra->mask;
2135 if (w->isWindow())
2136 return;
2137 offset -= wd->data.crect.topLeft();
2138 w = w->parentWidget();
2139 }
2140}
2141
2142bool QWidgetPrivate::shouldPaintOnScreen() const
2143{
2144#if defined(QT_NO_BACKINGSTORE)
2145 return true;
2146#else
2147 Q_Q(const QWidget);
2148 if (q->testAttribute(attribute: Qt::WA_PaintOnScreen)
2149 || (!q->isWindow() && q->window()->testAttribute(attribute: Qt::WA_PaintOnScreen))) {
2150 return true;
2151 }
2152
2153 return false;
2154#endif
2155}
2156
2157void QWidgetPrivate::updateIsOpaque()
2158{
2159 // hw: todo: only needed if opacity actually changed
2160 setDirtyOpaqueRegion();
2161
2162#if QT_CONFIG(graphicseffect)
2163 if (graphicsEffect) {
2164 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2165 setOpaque(false);
2166 return;
2167 }
2168#endif // QT_CONFIG(graphicseffect)
2169
2170 Q_Q(QWidget);
2171 if (q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) || q->testAttribute(attribute: Qt::WA_PaintOnScreen)) {
2172 setOpaque(true);
2173 return;
2174 }
2175
2176 const QPalette &pal = q->palette();
2177
2178 if (q->autoFillBackground()) {
2179 const QBrush &autoFillBrush = pal.brush(cr: q->backgroundRole());
2180 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2181 setOpaque(true);
2182 return;
2183 }
2184 }
2185
2186 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
2187 const QBrush &windowBrush = q->palette().brush(cr: QPalette::Window);
2188 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2189 setOpaque(true);
2190 return;
2191 }
2192 }
2193 setOpaque(false);
2194}
2195
2196void QWidgetPrivate::setOpaque(bool opaque)
2197{
2198 if (isOpaque != opaque) {
2199 isOpaque = opaque;
2200 updateIsTranslucent();
2201 }
2202}
2203
2204void QWidgetPrivate::updateIsTranslucent()
2205{
2206 Q_Q(QWidget);
2207 if (QWindow *window = q->windowHandle()) {
2208 QSurfaceFormat format = window->format();
2209 const int oldAlpha = format.alphaBufferSize();
2210 const int newAlpha = q->testAttribute(attribute: Qt::WA_TranslucentBackground) ? 8 : -1;
2211 if (oldAlpha != newAlpha) {
2212 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2213 //
2214 // If that is not the case, then the setFormat() is not just futile
2215 // but downright dangerous. Futile because the format matters only
2216 // when creating the native window, no point in changing it
2217 // afterwards. Dangerous because a QOpenGLContext or something else
2218 // may eventually query the QWindow's format(), in order to ensure
2219 // compatibility (in terms of native concepts such as pixel format,
2220 // EGLConfig, etc.), and if we change it here, then the returned
2221 // format does not describe reality anymore. (reality being the
2222 // settings with which the native resource was created).
2223 //
2224 // Whereas if one does a destroy()-create() then this all here
2225 // won't matter because the format is updated in
2226 // QWidgetPrivate::create() again.
2227 //
2228 if (!window->handle()) {
2229 format.setAlphaBufferSize(newAlpha);
2230 window->setFormat(format);
2231 }
2232 }
2233 }
2234}
2235
2236static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2237{
2238 Q_ASSERT(painter);
2239
2240 if (brush.style() == Qt::TexturePattern) {
2241 const QRect rect(rgn.boundingRect());
2242 painter->setClipRegion(rgn);
2243 painter->drawTiledPixmap(rect, pm: brush.texture(), offset: rect.topLeft());
2244 } else if (brush.gradient()
2245 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2246 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2247 painter->save();
2248 painter->setClipRegion(rgn);
2249 painter->fillRect(x: 0, y: 0, w: painter->device()->width(), h: painter->device()->height(), b: brush);
2250 painter->restore();
2251 } else {
2252 for (const QRect &rect : rgn)
2253 painter->fillRect(rect, brush);
2254 }
2255}
2256
2257bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2258{
2259#if QT_CONFIG(scrollarea)
2260 Q_Q(const QWidget);
2261 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2262 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2263 return false;
2264 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(object: parent);
2265 if (scrollArea && scrollArea->viewport() == q) {
2266 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2267 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2268 painter->setBrushOrigin(-priv->contentsOffset());
2269 }
2270#endif // QT_CONFIG(scrollarea)
2271 return true;
2272}
2273
2274void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2275{
2276 Q_Q(const QWidget);
2277
2278 bool brushOriginSet = false;
2279 const QBrush autoFillBrush = q->palette().brush(cr: q->backgroundRole());
2280
2281 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2282 const QBrush bg = q->palette().brush(cr: QPalette::Window);
2283 if (!brushOriginSet)
2284 brushOriginSet = updateBrushOrigin(painter, brush: bg);
2285 if (!(flags & DontSetCompositionMode)) {
2286 //copy alpha straight in
2287 QPainter::CompositionMode oldMode = painter->compositionMode();
2288 painter->setCompositionMode(QPainter::CompositionMode_Source);
2289 fillRegion(painter, rgn, brush: bg);
2290 painter->setCompositionMode(oldMode);
2291 } else {
2292 fillRegion(painter, rgn, brush: bg);
2293 }
2294 }
2295
2296 if (q->autoFillBackground()) {
2297 if (!brushOriginSet)
2298 brushOriginSet = updateBrushOrigin(painter, brush: autoFillBrush);
2299 fillRegion(painter, rgn, brush: autoFillBrush);
2300 }
2301
2302 if (q->testAttribute(attribute: Qt::WA_StyledBackground)) {
2303 painter->setClipRegion(rgn);
2304 QStyleOption opt;
2305 opt.initFrom(w: q);
2306 q->style()->drawPrimitive(pe: QStyle::PE_Widget, opt: &opt, p: painter, w: q);
2307 }
2308}
2309
2310/*
2311 \internal
2312 This function is called when a widget is hidden or destroyed.
2313 It resets some application global pointers that should only refer active,
2314 visible widgets.
2315*/
2316
2317extern QWidget *qt_button_down;
2318
2319void QWidgetPrivate::deactivateWidgetCleanup()
2320{
2321 Q_Q(QWidget);
2322 // If this was the active application window, reset it
2323 if (QApplication::activeWindow() == q)
2324 QApplicationPrivate::setActiveWindow(nullptr);
2325 // If the is the active mouse press widget, reset it
2326 if (q == qt_button_down)
2327 qt_button_down = nullptr;
2328}
2329
2330
2331/*!
2332 Returns a pointer to the widget with window identifier/handle \a
2333 id.
2334
2335 The window identifier type depends on the underlying window
2336 system, see \c qwindowdefs.h for the actual definition. If there
2337 is no widget with this identifier, \nullptr is returned.
2338*/
2339
2340QWidget *QWidget::find(WId id)
2341{
2342 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(key: id, defaultValue: 0) : nullptr;
2343}
2344
2345
2346
2347/*!
2348 \fn WId QWidget::internalWinId() const
2349 \internal
2350 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2351
2352*/
2353
2354/*!
2355 \fn WId QWidget::winId() const
2356
2357 Returns the window system identifier of the widget.
2358
2359 Portable in principle, but if you use it you are probably about to
2360 do something non-portable. Be careful.
2361
2362 If a widget is non-native (alien) and winId() is invoked on it, that widget
2363 will be provided a native handle.
2364
2365 This value may change at run-time. An event with type QEvent::WinIdChange
2366 will be sent to the widget following a change in window system identifier.
2367
2368 \sa find()
2369*/
2370WId QWidget::winId() const
2371{
2372 if (!data->in_destructor
2373 && (!testAttribute(attribute: Qt::WA_WState_Created) || !internalWinId()))
2374 {
2375 QWidget *that = const_cast<QWidget*>(this);
2376 that->setAttribute(Qt::WA_NativeWindow);
2377 that->d_func()->createWinId();
2378 return that->data->winid;
2379 }
2380 return data->winid;
2381}
2382
2383void QWidgetPrivate::createWinId()
2384{
2385 Q_Q(QWidget);
2386
2387 const bool forceNativeWindow = q->testAttribute(attribute: Qt::WA_NativeWindow);
2388 if (!q->testAttribute(attribute: Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2389 if (!q->isWindow()) {
2390 QWidget *parent = q->parentWidget();
2391 QWidgetPrivate *pd = parent->d_func();
2392 if (forceNativeWindow && !q->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors))
2393 parent->setAttribute(Qt::WA_NativeWindow);
2394 if (!parent->internalWinId()) {
2395 pd->createWinId();
2396 }
2397
2398 for (int i = 0; i < pd->children.size(); ++i) {
2399 QWidget *w = qobject_cast<QWidget *>(o: pd->children.at(i));
2400 if (w && !w->isWindow() && (!w->testAttribute(attribute: Qt::WA_WState_Created)
2401 || (!w->internalWinId() && w->testAttribute(attribute: Qt::WA_NativeWindow)))) {
2402 w->create();
2403 }
2404 }
2405 } else {
2406 q->create();
2407 }
2408 }
2409}
2410
2411/*!
2412\internal
2413Ensures that the widget is set on the screen point is on. This is handy getting a correct
2414size hint before a resize in e.g QMenu and QToolTip.
2415Returns if the screen was changed.
2416*/
2417
2418bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2419{
2420 Q_Q(QWidget);
2421 if (!q->isWindow())
2422 return false;
2423 // Find the screen for pos and make the widget understand it is on that screen.
2424 return setScreen(QGuiApplication::screenAt(point: pos));
2425}
2426
2427/*!
2428\internal
2429Ensures that the widget's QWindow is set to be on the given \a screen.
2430Returns true if the screen was changed.
2431*/
2432
2433bool QWidgetPrivate::setScreen(QScreen *screen)
2434{
2435 Q_Q(QWidget);
2436 if (!screen || !q->isWindow())
2437 return false;
2438 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2439 if (currentScreen != screen) {
2440 topData()->initialScreen = screen;
2441 if (windowHandle())
2442 windowHandle()->setScreen(screen);
2443 return true;
2444 }
2445 return false;
2446}
2447
2448/*!
2449\internal
2450Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2451
2452*/
2453
2454void QWidget::createWinId()
2455{
2456 Q_D(QWidget);
2457 d->createWinId();
2458}
2459
2460/*!
2461 \since 4.4
2462
2463 Returns the effective window system identifier of the widget, i.e. the
2464 native parent's window system identifier.
2465
2466 If the widget is native, this function returns the native widget ID.
2467 Otherwise, the window ID of the first native parent widget, i.e., the
2468 top-level widget that contains this widget, is returned.
2469
2470 \note We recommend that you do not store this value as it is likely to
2471 change at run-time.
2472
2473 \sa nativeParentWidget()
2474*/
2475WId QWidget::effectiveWinId() const
2476{
2477 const WId id = internalWinId();
2478 if (id || !testAttribute(attribute: Qt::WA_WState_Created))
2479 return id;
2480 if (const QWidget *realParent = nativeParentWidget())
2481 return realParent->internalWinId();
2482 return 0;
2483}
2484
2485/*!
2486 If this is a native widget, return the associated QWindow.
2487 Otherwise return null.
2488
2489 Native widgets include toplevel widgets, QGLWidget, and child widgets
2490 on which winId() was called.
2491
2492 \since 5.0
2493
2494 \sa winId(), screen()
2495*/
2496QWindow *QWidget::windowHandle() const
2497{
2498 Q_D(const QWidget);
2499 return d->windowHandle();
2500}
2501
2502/*!
2503 Returns the screen the widget is on.
2504
2505 \since 5.14
2506
2507 \sa windowHandle()
2508*/
2509QScreen *QWidget::screen() const
2510{
2511 Q_D(const QWidget);
2512 if (auto associatedScreen = d->associatedScreen())
2513 return associatedScreen;
2514 if (auto topLevel = window()) {
2515 if (auto topData = qt_widget_private(widget: topLevel)->topData()) {
2516 if (topData->initialScreen)
2517 return topData->initialScreen;
2518 }
2519 if (auto screenByPos = QGuiApplication::screenAt(point: topLevel->geometry().center()))
2520 return screenByPos;
2521 }
2522 return QGuiApplication::primaryScreen();
2523}
2524
2525/*!
2526 Sets the screen on which the widget should be shown to \a screen.
2527
2528 Setting the screen only makes sense for windows. If necessary, the widget's
2529 window will get recreated on \a screen.
2530
2531 \note If the screen is part of a virtual desktop of multiple screens,
2532 the window will not move automatically to \a screen. To place the
2533 window relative to the screen, use the screen's topLeft() position.
2534
2535 \sa QWindow::setScreen()
2536*/
2537void QWidget::setScreen(QScreen *screen)
2538{
2539 Q_D(QWidget);
2540 d->setScreen(screen);
2541}
2542
2543#ifndef QT_NO_STYLE_STYLESHEET
2544
2545/*!
2546 \property QWidget::styleSheet
2547 \brief the widget's style sheet
2548 \since 4.2
2549
2550 The style sheet contains a textual description of customizations to the
2551 widget's style, as described in the \l{Qt Style Sheets} document.
2552
2553 Since Qt 4.5, Qt style sheets fully supports \macos.
2554
2555 \warning Qt style sheets are currently not supported for custom QStyle
2556 subclasses. We plan to address this in some future release.
2557
2558 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2559*/
2560QString QWidget::styleSheet() const
2561{
2562 Q_D(const QWidget);
2563 if (!d->extra)
2564 return QString();
2565 return d->extra->styleSheet;
2566}
2567
2568void QWidget::setStyleSheet(const QString& styleSheet)
2569{
2570 Q_D(QWidget);
2571 if (data->in_destructor)
2572 return;
2573 d->createExtra();
2574
2575 QStyleSheetStyle *proxy = qt_styleSheet(style: d->extra->style);
2576 d->extra->styleSheet = styleSheet;
2577 if (styleSheet.isEmpty()) { // stylesheet removed
2578 if (!proxy)
2579 return;
2580
2581 d->inheritStyle();
2582 return;
2583 }
2584
2585 if (proxy) { // style sheet update
2586 bool repolish = d->polished;
2587 if (!repolish) {
2588 const auto childWidgets = findChildren<QWidget*>();
2589 for (auto child : childWidgets) {
2590 repolish = child->d_func()->polished;
2591 if (repolish)
2592 break;
2593 }
2594 }
2595 if (repolish)
2596 proxy->repolish(widget: this);
2597 return;
2598 }
2599
2600 if (testAttribute(attribute: Qt::WA_SetStyle)) {
2601 d->setStyle_helper(newStyle: new QStyleSheetStyle(d->extra->style), propagate: true);
2602 } else {
2603 d->setStyle_helper(newStyle: new QStyleSheetStyle(nullptr), propagate: true);
2604 }
2605}
2606
2607#endif // QT_NO_STYLE_STYLESHEET
2608
2609/*!
2610 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2611*/
2612
2613QStyle *QWidget::style() const
2614{
2615 Q_D(const QWidget);
2616
2617 if (d->extra && d->extra->style)
2618 return d->extra->style;
2619 return QApplication::style();
2620}
2621
2622/*!
2623 Sets the widget's GUI style to \a style. The ownership of the style
2624 object is not transferred.
2625
2626 If no style is set, the widget uses the application's style,
2627 QApplication::style() instead.
2628
2629 Setting a widget's style has no effect on existing or future child
2630 widgets.
2631
2632 \warning This function is particularly useful for demonstration
2633 purposes, where you want to show Qt's styling capabilities. Real
2634 applications should avoid it and use one consistent GUI style
2635 instead.
2636
2637 \warning Qt style sheets are currently not supported for custom QStyle
2638 subclasses. We plan to address this in some future release.
2639
2640 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2641*/
2642
2643void QWidget::setStyle(QStyle *style)
2644{
2645 Q_D(QWidget);
2646 setAttribute(Qt::WA_SetStyle, on: style != nullptr);
2647 d->createExtra();
2648#ifndef QT_NO_STYLE_STYLESHEET
2649 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2650 //if for some reason someone try to set a QStyleSheetStyle, ref it
2651 //(this may happen for example in QButtonDialogBox which propagates its style)
2652 styleSheetStyle->ref();
2653 d->setStyle_helper(newStyle: style, propagate: false);
2654 } else if (qt_styleSheet(style: d->extra->style) || !qApp->styleSheet().isEmpty()) {
2655 // if we have an application stylesheet or have a proxy already, propagate
2656 d->setStyle_helper(newStyle: new QStyleSheetStyle(style), propagate: true);
2657 } else
2658#endif
2659 d->setStyle_helper(newStyle: style, propagate: false);
2660}
2661
2662void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2663{
2664 Q_Q(QWidget);
2665 QStyle *oldStyle = q->style();
2666
2667 createExtra();
2668
2669#ifndef QT_NO_STYLE_STYLESHEET
2670 QPointer<QStyle> origStyle = extra->style;
2671#endif
2672 extra->style = newStyle;
2673
2674 // repolish
2675 if (polished && q->windowType() != Qt::Desktop) {
2676 oldStyle->unpolish(widget: q);
2677 q->style()->polish(widget: q);
2678 }
2679
2680 if (propagate) {
2681 // We copy the list because the order may be modified
2682 const QObjectList childrenList = children;
2683 for (int i = 0; i < childrenList.size(); ++i) {
2684 QWidget *c = qobject_cast<QWidget*>(o: childrenList.at(i));
2685 if (c)
2686 c->d_func()->inheritStyle();
2687 }
2688 }
2689
2690#ifndef QT_NO_STYLE_STYLESHEET
2691 if (!qt_styleSheet(style: newStyle)) {
2692 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(style: origStyle)) {
2693 cssStyle->clearWidgetFont(w: q);
2694 }
2695 }
2696#endif
2697
2698 QEvent e(QEvent::StyleChange);
2699 QCoreApplication::sendEvent(receiver: q, event: &e);
2700
2701#ifndef QT_NO_STYLE_STYLESHEET
2702 // dereference the old stylesheet style
2703 if (QStyleSheetStyle *proxy = qt_styleSheet(style: origStyle))
2704 proxy->deref();
2705#endif
2706}
2707
2708// Inherits style from the current parent and propagates it as necessary
2709void QWidgetPrivate::inheritStyle()
2710{
2711#ifndef QT_NO_STYLE_STYLESHEET
2712 Q_Q(QWidget);
2713
2714 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2715
2716 QStyleSheetStyle *proxy = qt_styleSheet(style: extraStyle);
2717
2718 if (!q->styleSheet().isEmpty()) {
2719 Q_ASSERT(proxy);
2720 proxy->repolish(widget: q);
2721 return;
2722 }
2723
2724 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2725 QWidget *parent = q->parentWidget();
2726 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2727 // If we have stylesheet on app or parent has stylesheet style, we need
2728 // to be running a proxy
2729 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(style: parentStyle)) {
2730 QStyle *newStyle = parentStyle;
2731 if (q->testAttribute(attribute: Qt::WA_SetStyle))
2732 newStyle = new QStyleSheetStyle(origStyle);
2733 else if (QStyleSheetStyle *newProxy = qt_styleSheet(style: parentStyle))
2734 newProxy->ref();
2735
2736 setStyle_helper(newStyle, propagate: true);
2737 return;
2738 }
2739
2740 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2741 // we just need our original style back
2742 if (origStyle == extraStyle) // is it any different?
2743 return;
2744
2745 // We could have inherited the proxy from our parent (which has a custom style)
2746 // In such a case we need to start following the application style (i.e revert
2747 // the propagation behavior of QStyleSheetStyle)
2748 if (!q->testAttribute(attribute: Qt::WA_SetStyle))
2749 origStyle = nullptr;
2750
2751 setStyle_helper(newStyle: origStyle, propagate: true);
2752#endif // QT_NO_STYLE_STYLESHEET
2753}
2754
2755
2756/*!
2757 \fn bool QWidget::isWindow() const
2758
2759 Returns \c true if the widget is an independent window, otherwise
2760 returns \c false.
2761
2762 A window is a widget that isn't visually the child of any other
2763 widget and that usually has a frame and a
2764 \l{QWidget::setWindowTitle()}{window title}.
2765
2766 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2767 It will then be grouped with its parent and deleted when the
2768 parent is deleted, minimized when the parent is minimized etc. If
2769 supported by the window manager, it will also have a common
2770 taskbar entry with its parent.
2771
2772 QDialog and QMainWindow widgets are by default windows, even if a
2773 parent widget is specified in the constructor. This behavior is
2774 specified by the Qt::Window flag.
2775
2776 \sa window(), isModal(), parentWidget()
2777*/
2778
2779/*!
2780 \property QWidget::modal
2781 \brief whether the widget is a modal widget
2782
2783 This property only makes sense for windows. A modal widget
2784 prevents widgets in all other windows from getting any input.
2785
2786 By default, this property is \c false.
2787
2788 \sa isWindow(), windowModality, QDialog
2789*/
2790
2791/*!
2792 \property QWidget::windowModality
2793 \brief which windows are blocked by the modal widget
2794 \since 4.1
2795
2796 This property only makes sense for windows. A modal widget
2797 prevents widgets in other windows from getting input. The value of
2798 this property controls which windows are blocked when the widget
2799 is visible. Changing this property while the window is visible has
2800 no effect; you must hide() the widget first, then show() it again.
2801
2802 By default, this property is Qt::NonModal.
2803
2804 \sa isWindow(), QWidget::modal, QDialog
2805*/
2806
2807Qt::WindowModality QWidget::windowModality() const
2808{
2809 return static_cast<Qt::WindowModality>(data->window_modality);
2810}
2811
2812void QWidget::setWindowModality(Qt::WindowModality windowModality)
2813{
2814 data->window_modality = windowModality;
2815 // setModal_sys() will be called by setAttribute()
2816 setAttribute(Qt::WA_ShowModal, on: (data->window_modality != Qt::NonModal));
2817 setAttribute(Qt::WA_SetWindowModality, on: true);
2818}
2819
2820void QWidgetPrivate::setModal_sys()
2821{
2822 Q_Q(QWidget);
2823 if (q->windowHandle())
2824 q->windowHandle()->setModality(q->windowModality());
2825}
2826
2827/*!
2828 \fn bool QWidget::underMouse() const
2829
2830 Returns \c true if the widget is under the mouse cursor; otherwise
2831 returns \c false.
2832
2833 This value is not updated properly during drag and drop
2834 operations.
2835
2836 \sa enterEvent(), leaveEvent()
2837*/
2838
2839/*!
2840 \property QWidget::minimized
2841 \brief whether this widget is minimized (iconified)
2842
2843 This property is only relevant for windows.
2844
2845 By default, this property is \c false.
2846
2847 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2848*/
2849bool QWidget::isMinimized() const
2850{ return data->window_state & Qt::WindowMinimized; }
2851
2852/*!
2853 Shows the widget minimized, as an icon.
2854
2855 Calling this function only affects \l{isWindow()}{windows}.
2856
2857 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2858 isMinimized()
2859*/
2860void QWidget::showMinimized()
2861{
2862 bool isMin = isMinimized();
2863 if (isMin && isVisible())
2864 return;
2865
2866 ensurePolished();
2867
2868 if (!isMin)
2869 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2870 setVisible(true);
2871}
2872
2873/*!
2874 \property QWidget::maximized
2875 \brief whether this widget is maximized
2876
2877 This property is only relevant for windows.
2878
2879 \note Due to limitations on some window systems, this does not always
2880 report the expected results (e.g., if the user on X11 maximizes the
2881 window via the window manager, Qt has no way of distinguishing this
2882 from any other resize). This is expected to improve as window manager
2883 protocols evolve.
2884
2885 By default, this property is \c false.
2886
2887 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2888*/
2889bool QWidget::isMaximized() const
2890{ return data->window_state & Qt::WindowMaximized; }
2891
2892
2893
2894/*!
2895 Returns the current window state. The window state is a OR'ed
2896 combination of Qt::WindowState: Qt::WindowMinimized,
2897 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2898
2899 \sa Qt::WindowState, setWindowState()
2900 */
2901Qt::WindowStates QWidget::windowState() const
2902{
2903 return Qt::WindowStates(data->window_state);
2904}
2905
2906/*!\internal
2907
2908 The function sets the window state on child widgets similar to
2909 setWindowState(). The difference is that the window state changed
2910 event has the isOverride() flag set. It exists mainly to keep
2911 QWorkspace working.
2912 */
2913void QWidget::overrideWindowState(Qt::WindowStates newstate)
2914{
2915 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2916 data->window_state = newstate;
2917 QCoreApplication::sendEvent(receiver: this, event: &e);
2918}
2919
2920/*!
2921 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2922
2923 Sets the window state to \a windowState. The window state is a OR'ed
2924 combination of Qt::WindowState: Qt::WindowMinimized,
2925 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2926
2927 If the window is not visible (i.e. isVisible() returns \c false), the
2928 window state will take effect when show() is called. For visible
2929 windows, the change is immediate. For example, to toggle between
2930 full-screen and normal mode, use the following code:
2931
2932 \snippet code/src_gui_kernel_qwidget.cpp 0
2933
2934 In order to restore and activate a minimized window (while
2935 preserving its maximized and/or full-screen state), use the following:
2936
2937 \snippet code/src_gui_kernel_qwidget.cpp 1
2938
2939 Calling this function will hide the widget. You must call show() to make
2940 the widget visible again.
2941
2942 \note On some window systems Qt::WindowActive is not immediate, and may be
2943 ignored in certain cases.
2944
2945 When the window state changes, the widget receives a changeEvent()
2946 of type QEvent::WindowStateChange.
2947
2948 \sa Qt::WindowState, windowState()
2949*/
2950void QWidget::setWindowState(Qt::WindowStates newstate)
2951{
2952 Q_D(QWidget);
2953 Qt::WindowStates oldstate = windowState();
2954 if (newstate.testFlag(flag: Qt::WindowMinimized)) // QTBUG-46763
2955 newstate.setFlag(flag: Qt::WindowActive, on: false);
2956 if (oldstate == newstate)
2957 return;
2958 if (isWindow() && !testAttribute(attribute: Qt::WA_WState_Created))
2959 create();
2960
2961 data->window_state = newstate;
2962 data->in_set_window_state = 1;
2963 if (isWindow()) {
2964 // Ensure the initial size is valid, since we store it as normalGeometry below.
2965 if (!testAttribute(attribute: Qt::WA_Resized) && !isVisible())
2966 adjustSize();
2967
2968 d->createTLExtra();
2969 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2970 d->topData()->normalGeometry = geometry();
2971
2972 Q_ASSERT(windowHandle());
2973 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2974 }
2975 data->in_set_window_state = 0;
2976
2977 if (newstate & Qt::WindowActive)
2978 activateWindow();
2979
2980 QWindowStateChangeEvent e(oldstate);
2981 QCoreApplication::sendEvent(receiver: this, event: &e);
2982}
2983
2984/*!
2985 \property QWidget::fullScreen
2986 \brief whether the widget is shown in full screen mode
2987
2988 A widget in full screen mode occupies the whole screen area and does not
2989 display window decorations, such as a title bar.
2990
2991 By default, this property is \c false.
2992
2993 \sa windowState(), minimized, maximized
2994*/
2995bool QWidget::isFullScreen() const
2996{ return data->window_state & Qt::WindowFullScreen; }
2997
2998/*!
2999 Shows the widget in full-screen mode.
3000
3001 Calling this function only affects \l{isWindow()}{windows}.
3002
3003 To return from full-screen mode, call showNormal() or close().
3004
3005 \note Full-screen mode works fine under Windows, but has certain
3006 problems under X. These problems are due to limitations of the
3007 ICCCM protocol that specifies the communication between X11
3008 clients and the window manager. ICCCM simply does not understand
3009 the concept of non-decorated full-screen windows. Therefore, the
3010 best we can do is to request a borderless window and place and
3011 resize it to fill the entire screen. Depending on the window
3012 manager, this may or may not work. The borderless window is
3013 requested using MOTIF hints, which are at least partially
3014 supported by virtually all modern window managers.
3015
3016 An alternative would be to bypass the window manager entirely and
3017 create a window with the Qt::X11BypassWindowManagerHint flag. This
3018 has other severe problems though, like totally broken keyboard focus
3019 and very strange effects on desktop changes or when the user raises
3020 other windows.
3021
3022 X11 window managers that follow modern post-ICCCM specifications
3023 support full-screen mode properly.
3024
3025 On macOS, showing a window full screen puts the entire application in
3026 full-screen mode, providing it with a dedicated desktop. Showing another
3027 window while the application runs in full-screen mode might automatically
3028 make that window full screen as well. To prevent that, exit full-screen
3029 mode by calling showNormal() or by close() on the full screen window
3030 before showing another window.
3031
3032 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3033*/
3034void QWidget::showFullScreen()
3035{
3036 ensurePolished();
3037
3038 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3039 | Qt::WindowFullScreen);
3040 setVisible(true);
3041#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3042 // activating it here before libscreen activates it causes problems
3043 activateWindow();
3044#endif
3045}
3046
3047/*!
3048 Shows the widget maximized.
3049
3050 Calling this function only affects \l{isWindow()}{windows}.
3051
3052 On X11, this function may not work properly with certain window
3053 managers. See the \l{Window Geometry} documentation for an explanation.
3054
3055 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3056*/
3057void QWidget::showMaximized()
3058{
3059 ensurePolished();
3060
3061 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3062 | Qt::WindowMaximized);
3063 setVisible(true);
3064}
3065
3066/*!
3067 Restores the widget after it has been maximized or minimized.
3068
3069 Calling this function only affects \l{isWindow()}{windows}.
3070
3071 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3072*/
3073void QWidget::showNormal()
3074{
3075 ensurePolished();
3076
3077 setWindowState(windowState() & ~(Qt::WindowMinimized
3078 | Qt::WindowMaximized
3079 | Qt::WindowFullScreen));
3080 setVisible(true);
3081}
3082
3083/*!
3084 Returns \c true if this widget would become enabled if \a ancestor is
3085 enabled; otherwise returns \c false.
3086
3087
3088
3089 This is the case if neither the widget itself nor every parent up
3090 to but excluding \a ancestor has been explicitly disabled.
3091
3092 isEnabledTo(0) returns false if this widget or any if its ancestors
3093 was explicitly disabled.
3094
3095 The word ancestor here means a parent widget within the same window.
3096
3097 Therefore isEnabledTo(0) stops at this widget's window, unlike
3098 isEnabled() which also takes parent windows into considerations.
3099
3100 \sa setEnabled(), enabled
3101*/
3102
3103bool QWidget::isEnabledTo(const QWidget *ancestor) const
3104{
3105 const QWidget * w = this;
3106 while (!w->testAttribute(attribute: Qt::WA_ForceDisabled)
3107 && !w->isWindow()
3108 && w->parentWidget()
3109 && w->parentWidget() != ancestor)
3110 w = w->parentWidget();
3111 return !w->testAttribute(attribute: Qt::WA_ForceDisabled);
3112}
3113
3114#ifndef QT_NO_ACTION
3115/*!
3116 Appends the action \a action to this widget's list of actions.
3117
3118 All QWidgets have a list of \l{QAction}s, however they can be
3119 represented graphically in many different ways. The default use of
3120 the QAction list (as returned by actions()) is to create a context
3121 QMenu.
3122
3123 A QWidget should only have one of each action and adding an action
3124 it already has will not cause the same action to be in the widget twice.
3125
3126 The ownership of \a action is not transferred to this QWidget.
3127
3128 \sa removeAction(), insertAction(), actions(), QMenu
3129*/
3130void QWidget::addAction(QAction *action)
3131{
3132 insertAction(before: nullptr, action);
3133}
3134
3135/*!
3136 Appends the actions \a actions to this widget's list of actions.
3137
3138 \sa removeAction(), QMenu, addAction()
3139*/
3140void QWidget::addActions(const QList<QAction *> &actions)
3141{
3142 for(int i = 0; i < actions.size(); i++)
3143 insertAction(before: nullptr, action: actions.at(i));
3144}
3145
3146/*!
3147 Inserts the action \a action to this widget's list of actions,
3148 before the action \a before. It appends the action if \a before is \nullptr or
3149 \a before is not a valid action for this widget.
3150
3151 A QWidget should only have one of each action.
3152
3153 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3154*/
3155void QWidget::insertAction(QAction *before, QAction *action)
3156{
3157 if (Q_UNLIKELY(!action)) {
3158 qWarning(msg: "QWidget::insertAction: Attempt to insert null action");
3159 return;
3160 }
3161
3162 Q_D(QWidget);
3163 if (d->actions.contains(t: action))
3164 removeAction(action);
3165
3166 int pos = d->actions.indexOf(t: before);
3167 if (pos < 0) {
3168 before = nullptr;
3169 pos = d->actions.size();
3170 }
3171 d->actions.insert(i: pos, t: action);
3172
3173 QActionPrivate *apriv = action->d_func();
3174 apriv->associatedObjects.append(t: this);
3175
3176 QActionEvent e(QEvent::ActionAdded, action, before);
3177 QCoreApplication::sendEvent(receiver: this, event: &e);
3178}
3179
3180/*!
3181 Inserts the actions \a actions to this widget's list of actions,
3182 before the action \a before. It appends the action if \a before is \nullptr or
3183 \a before is not a valid action for this widget.
3184
3185 A QWidget can have at most one of each action.
3186
3187 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3188*/
3189void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3190{
3191 for(int i = 0; i < actions.size(); ++i)
3192 insertAction(before, action: actions.at(i));
3193}
3194
3195/*!
3196 Removes the action \a action from this widget's list of actions.
3197 \sa insertAction(), actions(), insertAction()
3198*/
3199void QWidget::removeAction(QAction *action)
3200{
3201 if (!action)
3202 return;
3203
3204 Q_D(QWidget);
3205
3206 QActionPrivate *apriv = action->d_func();
3207 apriv->associatedObjects.removeAll(t: this);
3208
3209 if (d->actions.removeAll(t: action)) {
3210 QActionEvent e(QEvent::ActionRemoved, action);
3211 QCoreApplication::sendEvent(receiver: this, event: &e);
3212 }
3213}
3214
3215/*!
3216 Returns the (possibly empty) list of this widget's actions.
3217
3218 \sa contextMenuPolicy, insertAction(), removeAction()
3219*/
3220QList<QAction*> QWidget::actions() const
3221{
3222 Q_D(const QWidget);
3223 return d->actions;
3224}
3225
3226/*!
3227 \fn QAction *QWidget::addAction(const QString &text);
3228 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3229 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3230 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3231
3232 \since 6.3
3233
3234 These convenience functions create a new action with text \a text,
3235 icon \a icon and shortcut \a shortcut, if any.
3236
3237 The functions add the newly created action to the widget's
3238 list of actions, and return it.
3239
3240 QWidget takes ownership of the returned QAction.
3241*/
3242QAction *QWidget::addAction(const QString &text)
3243{
3244 QAction *ret = new QAction(text, this);
3245 addAction(action: ret);
3246 return ret;
3247}
3248
3249QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3250{
3251 QAction *ret = new QAction(icon, text, this);
3252 addAction(action: ret);
3253 return ret;
3254}
3255
3256#if QT_CONFIG(shortcut)
3257QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3258{
3259 QAction *ret = addAction(text);
3260 ret->setShortcut(shortcut);
3261 return ret;
3262}
3263
3264QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3265{
3266 QAction *ret = addAction(icon, text);
3267 ret->setShortcut(shortcut);
3268 return ret;
3269}
3270#endif
3271
3272/*!
3273 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3274 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3275 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3276 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3277
3278 \overload
3279 \since 6.3
3280
3281 This convenience function creates a new action with the text \a
3282 text, icon \a icon, and shortcut \a shortcut, if any.
3283
3284 The action's \l{QAction::triggered()}{triggered()} signal is connected
3285 to the \a receiver's \a member slot. The function adds the newly created
3286 action to the widget's list of actions and returns it.
3287
3288 QWidget takes ownership of the returned QAction.
3289*/
3290QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3291 Qt::ConnectionType type)
3292{
3293 QAction *action = addAction(text);
3294 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3295 return action;
3296}
3297
3298QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3299 const QObject *receiver, const char* member,
3300 Qt::ConnectionType type)
3301{
3302 QAction *action = addAction(icon, text);
3303 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3304 return action;
3305}
3306
3307#if QT_CONFIG(shortcut)
3308QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3309 const QObject *receiver, const char* member,
3310 Qt::ConnectionType type)
3311{
3312 QAction *action = addAction(text, receiver, member, type);
3313 action->setShortcut(shortcut);
3314 return action;
3315}
3316
3317QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3318 const QObject *receiver, const char* member,
3319 Qt::ConnectionType type)
3320{
3321 QAction *action = addAction(icon, text, receiver, member, type);
3322 action->setShortcut(shortcut);
3323 return action;
3324}
3325#endif // QT_CONFIG(shortcut)
3326
3327/*!
3328 \fn template<typename...Args> QAction *QWidget::addAction(const QString &text, Args&&...args)
3329 \fn template<typename...Args> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3330 \fn template<typename...Args> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3331 \fn template<typename...Args> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3332
3333 \since 6.3
3334 \overload
3335
3336 These convenience functions create a new action with the text \a text,
3337 icon \a icon, and shortcut \a shortcut, if any.
3338
3339 The action's \l{QAction::triggered()}{triggered()} signal is connected
3340 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3341 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3342
3343 The function adds the newly created action to the widget's list of
3344 actions and returns it.
3345
3346 QWidget takes ownership of the returned QAction.
3347*/
3348#endif // QT_NO_ACTION
3349
3350/*!
3351 \property QWidget::enabled
3352 \brief whether the widget is enabled
3353
3354 In general an enabled widget handles keyboard and mouse events; a disabled
3355 widget does not. An exception is made with \l{QAbstractButton}.
3356
3357 Some widgets display themselves differently when they are
3358 disabled. For example a button might draw its label grayed out. If
3359 your widget needs to know when it becomes enabled or disabled, you
3360 can use the changeEvent() with type QEvent::EnabledChange.
3361
3362 Disabling a widget implicitly disables all its children. Enabling
3363 respectively enables all child widgets unless they have been
3364 explicitly disabled. It it not possible to explicitly enable a child
3365 widget which is not a window while its parent widget remains disabled.
3366
3367 By default, this property is \c true.
3368
3369 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3370*/
3371void QWidget::setEnabled(bool enable)
3372{
3373 Q_D(QWidget);
3374 setAttribute(Qt::WA_ForceDisabled, on: !enable);
3375 d->setEnabled_helper(enable);
3376}
3377
3378void QWidgetPrivate::setEnabled_helper(bool enable)
3379{
3380 Q_Q(QWidget);
3381
3382 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3383 return; // nothing we can do
3384
3385 if (enable != q->testAttribute(attribute: Qt::WA_Disabled))
3386 return; // nothing to do
3387
3388 q->setAttribute(Qt::WA_Disabled, on: !enable);
3389 updateSystemBackground();
3390
3391 if (!enable && q->window()->focusWidget() == q) {
3392 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3393 if (!parentIsEnabled || !q->focusNextChild())
3394 q->clearFocus();
3395 }
3396
3397 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3398 for (int i = 0; i < children.size(); ++i) {
3399 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
3400 if (w && !w->testAttribute(attribute))
3401 w->d_func()->setEnabled_helper(enable);
3402 }
3403#ifndef QT_NO_CURSOR
3404 if (q->testAttribute(attribute: Qt::WA_SetCursor) || q->isWindow()) {
3405 // enforce the windows behavior of clearing the cursor on
3406 // disabled widgets
3407 qt_qpa_set_cursor(w: q, force: false);
3408 }
3409#endif
3410#ifndef QT_NO_IM
3411 if (q->testAttribute(attribute: Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3412 QWidget *focusWidget = effectiveFocusWidget();
3413
3414 if (enable) {
3415 if (focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled))
3416 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3417 } else {
3418 QGuiApplication::inputMethod()->commit();
3419 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3420 }
3421 }
3422#endif //QT_NO_IM
3423 QEvent e(QEvent::EnabledChange);
3424 QCoreApplication::sendEvent(receiver: q, event: &e);
3425}
3426
3427/*!
3428 \property QWidget::acceptDrops
3429 \brief whether drop events are enabled for this widget
3430
3431 Setting this property to true announces to the system that this
3432 widget \e may be able to accept drop events.
3433
3434 If the widget is the desktop (windowType() == Qt::Desktop), this may
3435 fail if another application is using the desktop; you can call
3436 acceptDrops() to test if this occurs.
3437
3438 \warning Do not modify this property in a drag and drop event handler.
3439
3440 By default, this property is \c false.
3441
3442 \sa {Drag and Drop in Qt}{Drag and Drop}
3443*/
3444bool QWidget::acceptDrops() const
3445{
3446 return testAttribute(attribute: Qt::WA_AcceptDrops);
3447}
3448
3449void QWidget::setAcceptDrops(bool on)
3450{
3451 setAttribute(Qt::WA_AcceptDrops, on);
3452
3453}
3454
3455/*!
3456 Disables widget input events if \a disable is true; otherwise
3457 enables input events.
3458
3459 See the \l enabled documentation for more information.
3460
3461 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3462*/
3463void QWidget::setDisabled(bool disable)
3464{
3465 setEnabled(!disable);
3466}
3467
3468/*!
3469 \property QWidget::frameGeometry
3470 \brief geometry of the widget relative to its parent including any
3471 window frame
3472
3473 See the \l{Window Geometry} documentation for an overview of geometry
3474 issues with windows.
3475
3476 By default, this property contains a value that depends on the user's
3477 platform and screen geometry.
3478
3479 \sa geometry(), x(), y(), pos()
3480*/
3481QRect QWidget::frameGeometry() const
3482{
3483 Q_D(const QWidget);
3484 if (isWindow() && ! (windowType() == Qt::Popup)) {
3485 QRect fs = d->frameStrut();
3486 return QRect(data->crect.x() - fs.left(),
3487 data->crect.y() - fs.top(),
3488 data->crect.width() + fs.left() + fs.right(),
3489 data->crect.height() + fs.top() + fs.bottom());
3490 }
3491 return data->crect;
3492}
3493
3494/*!
3495 \property QWidget::x
3496
3497 \brief the x coordinate of the widget relative to its parent including
3498 any window frame
3499
3500 See the \l{Window Geometry} documentation for an overview of geometry
3501 issues with windows.
3502
3503 By default, this property has a value of 0.
3504
3505 \sa frameGeometry, y, pos
3506*/
3507int QWidget::x() const
3508{
3509 Q_D(const QWidget);
3510 if (isWindow() && ! (windowType() == Qt::Popup))
3511 return data->crect.x() - d->frameStrut().left();
3512 return data->crect.x();
3513}
3514
3515/*!
3516 \property QWidget::y
3517 \brief the y coordinate of the widget relative to its parent and
3518 including any window frame
3519
3520 See the \l{Window Geometry} documentation for an overview of geometry
3521 issues with windows.
3522
3523 By default, this property has a value of 0.
3524
3525 \sa frameGeometry, x, pos
3526*/
3527int QWidget::y() const
3528{
3529 Q_D(const QWidget);
3530 if (isWindow() && ! (windowType() == Qt::Popup))
3531 return data->crect.y() - d->frameStrut().top();
3532 return data->crect.y();
3533}
3534
3535/*!
3536 \property QWidget::pos
3537 \brief the position of the widget within its parent widget
3538
3539 If the widget is a window, the position is that of the widget on
3540 the desktop, including its frame.
3541
3542 When changing the position, the widget, if visible, receives a
3543 move event (moveEvent()) immediately. If the widget is not
3544 currently visible, it is guaranteed to receive an event before it
3545 is shown.
3546
3547 By default, this property contains a position that refers to the
3548 origin.
3549
3550 \warning Calling move() or setGeometry() inside moveEvent() can
3551 lead to infinite recursion.
3552
3553 See the \l{Window Geometry} documentation for an overview of geometry
3554 issues with windows.
3555
3556 \note Not all windowing systems support setting or querying top level window positions.
3557 On such a system, programmatically moving windows may not have any effect, and artificial
3558 values may be returned for the current positions, such as \c QPoint(0, 0).
3559
3560 \sa frameGeometry, size, x(), y()
3561*/
3562QPoint QWidget::pos() const
3563{
3564 Q_D(const QWidget);
3565 QPoint result = data->crect.topLeft();
3566 if (isWindow() && ! (windowType() == Qt::Popup))
3567 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3568 result -= d->frameStrut().topLeft();
3569 return result;
3570}
3571
3572/*!
3573 \property QWidget::geometry
3574 \brief the geometry of the widget relative to its parent and
3575 excluding the window frame
3576
3577 When changing the geometry, the widget, if visible, receives a
3578 move event (moveEvent()) and/or a resize event (resizeEvent())
3579 immediately. If the widget is not currently visible, it is
3580 guaranteed to receive appropriate events before it is shown.
3581
3582 The size component is adjusted if it lies outside the range
3583 defined by minimumSize() and maximumSize().
3584
3585 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3586 can lead to infinite recursion.
3587
3588 See the \l{Window Geometry} documentation for an overview of geometry
3589 issues with windows.
3590
3591 By default, this property contains a value that depends on the user's
3592 platform and screen geometry.
3593
3594 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3595 resizeEvent(), minimumSize(), maximumSize()
3596*/
3597
3598/*!
3599 \property QWidget::size
3600 \brief the size of the widget excluding any window frame
3601
3602 If the widget is visible when it is being resized, it receives a resize event
3603 (resizeEvent()) immediately. If the widget is not currently
3604 visible, it is guaranteed to receive an event before it is shown.
3605
3606 The size is adjusted if it lies outside the range defined by
3607 minimumSize() and maximumSize().
3608
3609 By default, this property contains a value that depends on the user's
3610 platform and screen geometry.
3611
3612 \warning Calling resize() or setGeometry() inside resizeEvent() can
3613 lead to infinite recursion.
3614
3615 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3616 appear on screen. This also applies to windows.
3617
3618 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3619*/
3620
3621/*!
3622 \property QWidget::width
3623 \brief the width of the widget excluding any window frame
3624
3625 See the \l{Window Geometry} documentation for an overview of geometry
3626 issues with windows.
3627
3628 \note Do not use this function to find the width of a screen on
3629 a multi-screen desktop. See QScreen for details.
3630
3631 By default, this property contains a value that depends on the user's
3632 platform and screen geometry.
3633
3634 \sa geometry, height, size
3635*/
3636
3637/*!
3638 \property QWidget::height
3639 \brief the height of the widget excluding any window frame
3640
3641 See the \l{Window Geometry} documentation for an overview of geometry
3642 issues with windows.
3643
3644 By default, this property contains a value that depends on the user's
3645 platform and \l{QScreen::geometry}{screen geometry}.
3646
3647 \sa geometry, width, size
3648*/
3649
3650/*!
3651 \property QWidget::rect
3652 \brief the internal geometry of the widget excluding any window
3653 frame
3654
3655 The rect property equals QRect(0, 0, width(), height()).
3656
3657 See the \l{Window Geometry} documentation for an overview of geometry
3658 issues with windows.
3659
3660 By default, this property contains a value that depends on the user's
3661 platform and screen geometry.
3662
3663 \sa size
3664*/
3665
3666/*!
3667 \property QWidget::normalGeometry
3668
3669 \brief the geometry of the widget as it will appear when shown as
3670 a normal (not maximized or full screen) top-level widget
3671
3672 If the widget is already in this state the normal geometry will
3673 reflect the widget's current geometry().
3674
3675 For child widgets this property always holds an empty rectangle.
3676
3677 By default, this property contains an empty rectangle.
3678
3679 \sa QWidget::windowState(), QWidget::geometry
3680*/
3681QRect QWidget::normalGeometry() const
3682{
3683 Q_D(const QWidget);
3684 if (!isWindow())
3685 return QRect();
3686
3687 if (!isMaximized() && !isFullScreen())
3688 return geometry();
3689
3690 return d->topData()->normalGeometry;
3691}
3692
3693
3694/*!
3695 \property QWidget::childrenRect
3696 \brief the bounding rectangle of the widget's children
3697
3698 Hidden children are excluded.
3699
3700 By default, for a widget with no children, this property contains a
3701 rectangle with zero width and height located at the origin.
3702
3703 \sa childrenRegion(), geometry()
3704*/
3705
3706QRect QWidget::childrenRect() const
3707{
3708 Q_D(const QWidget);
3709 QRect r(0, 0, 0, 0);
3710 for (int i = 0; i < d->children.size(); ++i) {
3711 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3712 if (w && !w->isWindow() && !w->isHidden())
3713 r |= w->geometry();
3714 }
3715 return r;
3716}
3717
3718/*!
3719 \property QWidget::childrenRegion
3720 \brief the combined region occupied by the widget's children
3721
3722 Hidden children are excluded.
3723
3724 By default, for a widget with no children, this property contains an
3725 empty region.
3726
3727 \sa childrenRect(), geometry(), mask()
3728*/
3729
3730QRegion QWidget::childrenRegion() const
3731{
3732 Q_D(const QWidget);
3733 QRegion r;
3734 for (int i = 0; i < d->children.size(); ++i) {
3735 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3736 if (w && !w->isWindow() && !w->isHidden()) {
3737 QRegion mask = w->mask();
3738 if (mask.isEmpty())
3739 r |= w->geometry();
3740 else
3741 r |= mask.translated(p: w->pos());
3742 }
3743 }
3744 return r;
3745}
3746
3747
3748/*!
3749 \property QWidget::minimumSize
3750 \brief the widget's minimum size
3751
3752 The widget cannot be resized to a smaller size than the minimum
3753 widget size. The widget's size is forced to the minimum size if
3754 the current size is smaller.
3755
3756 The minimum size set by this function will override the minimum size
3757 defined by QLayout. In order to unset the minimum size, use a
3758 value of \c{QSize(0, 0)}.
3759
3760 By default, this property contains a size with zero width and height.
3761
3762 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3763*/
3764
3765QSize QWidget::minimumSize() const
3766{
3767 Q_D(const QWidget);
3768 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3769}
3770
3771/*!
3772 \property QWidget::maximumSize
3773 \brief the widget's maximum size in pixels
3774
3775 The widget cannot be resized to a larger size than the maximum
3776 widget size.
3777
3778 By default, this property contains a size in which both width and height
3779 have values of 16777215.
3780
3781 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3782 of widgets.
3783
3784 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3785*/
3786
3787QSize QWidget::maximumSize() const
3788{
3789 Q_D(const QWidget);
3790 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3791 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3792}
3793
3794
3795/*!
3796 \property QWidget::minimumWidth
3797 \brief the widget's minimum width in pixels
3798
3799 This property corresponds to the width held by the \l minimumSize property.
3800
3801 By default, this property has a value of 0.
3802
3803 \sa minimumSize, minimumHeight
3804*/
3805
3806/*!
3807 \property QWidget::minimumHeight
3808 \brief the widget's minimum height in pixels
3809
3810 This property corresponds to the height held by the \l minimumSize property.
3811
3812 By default, this property has a value of 0.
3813
3814 \sa minimumSize, minimumWidth
3815*/
3816
3817/*!
3818 \property QWidget::maximumWidth
3819 \brief the widget's maximum width in pixels
3820
3821 This property corresponds to the width held by the \l maximumSize property.
3822
3823 By default, this property contains a value of 16777215.
3824
3825 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3826 of widgets.
3827
3828 \sa maximumSize, maximumHeight
3829*/
3830
3831/*!
3832 \property QWidget::maximumHeight
3833 \brief the widget's maximum height in pixels
3834
3835 This property corresponds to the height held by the \l maximumSize property.
3836
3837 By default, this property contains a value of 16777215.
3838
3839 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3840 of widgets.
3841
3842 \sa maximumSize, maximumWidth
3843*/
3844
3845/*!
3846 \property QWidget::sizeIncrement
3847 \brief the size increment of the widget
3848
3849 When the user resizes the window, the size will move in steps of
3850 sizeIncrement().width() pixels horizontally and
3851 sizeIncrement.height() pixels vertically, with baseSize() as the
3852 basis. Preferred widget sizes are for non-negative integers \e i
3853 and \e j:
3854 \snippet code/src_gui_kernel_qwidget.cpp 2
3855
3856 Note that while you can set the size increment for all widgets, it
3857 only affects windows.
3858
3859 By default, this property contains a size with zero width and height.
3860
3861 \warning The size increment has no effect under Windows, and may
3862 be disregarded by the window manager on X11.
3863
3864 \sa size, minimumSize, maximumSize
3865*/
3866QSize QWidget::sizeIncrement() const
3867{
3868 Q_D(const QWidget);
3869 return (d->extra && d->extra->topextra)
3870 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3871 : QSize(0, 0);
3872}
3873
3874/*!
3875 \property QWidget::baseSize
3876 \brief the base size of the widget
3877
3878 The base size is used to calculate a proper widget size if the
3879 widget defines sizeIncrement().
3880
3881 By default, for a newly-created widget, this property contains a size with
3882 zero width and height.
3883
3884 \sa setSizeIncrement()
3885*/
3886
3887QSize QWidget::baseSize() const
3888{
3889 Q_D(const QWidget);
3890 return (d->extra && d->extra->topextra)
3891 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3892 : QSize(0, 0);
3893}
3894
3895bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3896{
3897 Q_Q(QWidget);
3898
3899 int mw = minw, mh = minh;
3900 if (mw == QWIDGETSIZE_MAX)
3901 mw = 0;
3902 if (mh == QWIDGETSIZE_MAX)
3903 mh = 0;
3904 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3905 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) "
3906 "The largest allowed size is (%d,%d)",
3907 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3908 QWIDGETSIZE_MAX);
3909 minw = mw = qMin<int>(a: minw, QWIDGETSIZE_MAX);
3910 minh = mh = qMin<int>(a: minh, QWIDGETSIZE_MAX);
3911 }
3912 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3913 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3914 "are not possible",
3915 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3916 minw = mw = qMax(a: minw, b: 0);
3917 minh = mh = qMax(a: minh, b: 0);
3918 }
3919 createExtra();
3920 if (extra->minw == mw && extra->minh == mh)
3921 return false;
3922 extra->minw = mw;
3923 extra->minh = mh;
3924 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3925 return true;
3926}
3927
3928void QWidgetPrivate::setConstraints_sys()
3929{
3930 Q_Q(QWidget);
3931 if (extra && q->windowHandle()) {
3932 QWindow *win = q->windowHandle();
3933 QWindowPrivate *winp = qt_window_private(window: win);
3934
3935 winp->minimumSize = QSize(extra->minw, extra->minh);
3936 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3937
3938 if (extra->topextra) {
3939 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3940 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3941 }
3942
3943 if (winp->platformWindow) {
3944 fixPosIncludesFrame();
3945 winp->platformWindow->propagateSizeHints();
3946 }
3947 }
3948}
3949
3950/*!
3951 \overload
3952
3953 This function corresponds to setMinimumSize(QSize(minw, minh)).
3954 Sets the minimum width to \a minw and the minimum height to \a
3955 minh.
3956*/
3957
3958void QWidget::setMinimumSize(int minw, int minh)
3959{
3960 Q_D(QWidget);
3961 if (!d->setMinimumSize_helper(minw, minh))
3962 return;
3963
3964 if (isWindow())
3965 d->setConstraints_sys();
3966 if (minw > width() || minh > height()) {
3967 bool resized = testAttribute(attribute: Qt::WA_Resized);
3968 bool maximized = isMaximized();
3969 resize(w: qMax(a: minw,b: width()), h: qMax(a: minh,b: height()));
3970 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
3971 if (maximized)
3972 data->window_state = data->window_state | Qt::WindowMaximized;
3973 }
3974#if QT_CONFIG(graphicsview)
3975 if (d->extra) {
3976 if (d->extra->proxyWidget)
3977 d->extra->proxyWidget->setMinimumSize(aw: minw, ah: minh);
3978 }
3979#endif
3980 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3981}
3982
3983bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3984{
3985 Q_Q(QWidget);
3986 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3987 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) "
3988 "The largest allowed size is (%d,%d)",
3989 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3990 QWIDGETSIZE_MAX);
3991 maxw = qMin<int>(a: maxw, QWIDGETSIZE_MAX);
3992 maxh = qMin<int>(a: maxh, QWIDGETSIZE_MAX);
3993 }
3994 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
3995 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
3996 "are not possible",
3997 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
3998 maxw = qMax(a: maxw, b: 0);
3999 maxh = qMax(a: maxh, b: 0);
4000 }
4001 createExtra();
4002 if (extra->maxw == maxw && extra->maxh == maxh)
4003 return false;
4004 extra->maxw = maxw;
4005 extra->maxh = maxh;
4006 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4007 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4008 return true;
4009}
4010
4011/*!
4012 \overload
4013
4014 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4015 maxh)). Sets the maximum width to \a maxw and the maximum height
4016 to \a maxh.
4017*/
4018void QWidget::setMaximumSize(int maxw, int maxh)
4019{
4020 Q_D(QWidget);
4021 if (!d->setMaximumSize_helper(maxw, maxh))
4022 return;
4023
4024 if (isWindow())
4025 d->setConstraints_sys();
4026 if (maxw < width() || maxh < height()) {
4027 bool resized = testAttribute(attribute: Qt::WA_Resized);
4028 resize(w: qMin(a: maxw,b: width()), h: qMin(a: maxh,b: height()));
4029 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
4030 }
4031
4032#if QT_CONFIG(graphicsview)
4033 if (d->extra) {
4034 if (d->extra->proxyWidget)
4035 d->extra->proxyWidget->setMaximumSize(aw: maxw, ah: maxh);
4036 }
4037#endif
4038
4039 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4040}
4041
4042/*!
4043 \overload
4044
4045 Sets the x (width) size increment to \a w and the y (height) size
4046 increment to \a h.
4047*/
4048void QWidget::setSizeIncrement(int w, int h)
4049{
4050 Q_D(QWidget);
4051 d->createTLExtra();
4052 QTLWExtra* x = d->topData();
4053 if (x->incw == w && x->inch == h)
4054 return;
4055 x->incw = w;
4056 x->inch = h;
4057 if (isWindow())
4058 d->setConstraints_sys();
4059}
4060
4061/*!
4062 \overload
4063
4064 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4065 the widgets base size to width \a basew and height \a baseh.
4066*/
4067void QWidget::setBaseSize(int basew, int baseh)
4068{
4069 Q_D(QWidget);
4070 d->createTLExtra();
4071 QTLWExtra* x = d->topData();
4072 if (x->basew == basew && x->baseh == baseh)
4073 return;
4074 x->basew = basew;
4075 x->baseh = baseh;
4076 if (isWindow())
4077 d->setConstraints_sys();
4078}
4079
4080/*!
4081 Sets both the minimum and maximum sizes of the widget to \a s,
4082 thereby preventing it from ever growing or shrinking.
4083
4084 This will override the default size constraints set by QLayout.
4085
4086 To remove constraints, set the size to QWIDGETSIZE_MAX.
4087
4088 Alternatively, if you want the widget to have a
4089 fixed size based on its contents, you can call
4090 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4091
4092 \sa maximumSize, minimumSize
4093*/
4094
4095void QWidget::setFixedSize(const QSize & s)
4096{
4097 setFixedSize(w: s.width(), h: s.height());
4098}
4099
4100
4101/*!
4102 \fn void QWidget::setFixedSize(int w, int h)
4103 \overload
4104
4105 Sets the width of the widget to \a w and the height to \a h.
4106*/
4107
4108void QWidget::setFixedSize(int w, int h)
4109{
4110 Q_D(QWidget);
4111 bool minSizeSet = d->setMinimumSize_helper(minw&: w, minh&: h);
4112 bool maxSizeSet = d->setMaximumSize_helper(maxw&: w, maxh&: h);
4113 if (!minSizeSet && !maxSizeSet)
4114 return;
4115
4116 if (isWindow())
4117 d->setConstraints_sys();
4118 else
4119 d->updateGeometry_helper(forceUpdate: true);
4120
4121 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4122 resize(w, h);
4123}
4124
4125void QWidget::setMinimumWidth(int w)
4126{
4127 Q_D(QWidget);
4128 d->createExtra();
4129 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4130 setMinimumSize(minw: w, minh: minimumSize().height());
4131 d->extra->explicitMinSize = expl;
4132}
4133
4134void QWidget::setMinimumHeight(int h)
4135{
4136 Q_D(QWidget);
4137 d->createExtra();
4138 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4139 setMinimumSize(minw: minimumSize().width(), minh: h);
4140 d->extra->explicitMinSize = expl;
4141}
4142
4143void QWidget::setMaximumWidth(int w)
4144{
4145 Q_D(QWidget);
4146 d->createExtra();
4147 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4148 setMaximumSize(maxw: w, maxh: maximumSize().height());
4149 d->extra->explicitMaxSize = expl;
4150}
4151
4152void QWidget::setMaximumHeight(int h)
4153{
4154 Q_D(QWidget);
4155 d->createExtra();
4156 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4157 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4158 d->extra->explicitMaxSize = expl;
4159}
4160
4161/*!
4162 Sets both the minimum and maximum width of the widget to \a w
4163 without changing the heights. Provided for convenience.
4164
4165 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4166*/
4167
4168void QWidget::setFixedWidth(int w)
4169{
4170 Q_D(QWidget);
4171 d->createExtra();
4172 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4173 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4174 setMinimumSize(minw: w, minh: minimumSize().height());
4175 setMaximumSize(maxw: w, maxh: maximumSize().height());
4176 d->extra->explicitMinSize = explMin;
4177 d->extra->explicitMaxSize = explMax;
4178}
4179
4180
4181/*!
4182 Sets both the minimum and maximum heights of the widget to \a h
4183 without changing the widths. Provided for convenience.
4184
4185 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4186*/
4187
4188void QWidget::setFixedHeight(int h)
4189{
4190 Q_D(QWidget);
4191 d->createExtra();
4192 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4193 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4194 setMinimumSize(minw: minimumSize().width(), minh: h);
4195 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4196 d->extra->explicitMinSize = explMin;
4197 d->extra->explicitMaxSize = explMax;
4198}
4199
4200
4201/*!
4202 Translates the widget coordinate \a pos to the coordinate system
4203 of \a parent. The \a parent must not be \nullptr and must be a parent
4204 of the calling widget.
4205
4206 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4207 \since 6.0
4208*/
4209
4210QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4211{
4212 QPointF p = pos;
4213 if (parent) {
4214 const QWidget * w = this;
4215 while (w != parent) {
4216 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPointF &pos)",
4217 "parent must be in parent hierarchy");
4218 p = w->mapToParent(p);
4219 w = w->parentWidget();
4220 }
4221 }
4222 return p;
4223}
4224
4225/*!
4226 \overload
4227*/
4228QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4229{
4230 return mapTo(parent, pos: QPointF(pos)).toPoint();
4231}
4232
4233/*!
4234 Translates the widget coordinate \a pos from the coordinate system
4235 of \a parent to this widget's coordinate system. The \a parent
4236 must not be \nullptr and must be a parent of the calling widget.
4237
4238 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4239 \since 6.0
4240*/
4241
4242QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4243{
4244 QPointF p(pos);
4245 if (parent) {
4246 const QWidget * w = this;
4247 while (w != parent) {
4248 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4249 "parent must be in parent hierarchy");
4250
4251 p = w->mapFromParent(p);
4252 w = w->parentWidget();
4253 }
4254 }
4255 return p;
4256}
4257
4258/*!
4259 \overload
4260*/
4261QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4262{
4263 return mapFrom(parent, pos: QPointF(pos)).toPoint();
4264}
4265
4266/*!
4267 Translates the widget coordinate \a pos to a coordinate in the
4268 parent widget.
4269
4270 Same as mapToGlobal() if the widget has no parent.
4271
4272 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4273 \since 6.0
4274*/
4275
4276QPointF QWidget::mapToParent(const QPointF &pos) const
4277{
4278 return pos + QPointF(data->crect.topLeft());
4279}
4280
4281/*!
4282 \overload
4283*/
4284QPoint QWidget::mapToParent(const QPoint &pos) const
4285{
4286 return pos + data->crect.topLeft();
4287}
4288
4289/*!
4290 Translates the parent widget coordinate \a pos to widget
4291 coordinates.
4292
4293 Same as mapFromGlobal() if the widget has no parent.
4294
4295 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4296 \since 6.0
4297*/
4298
4299QPointF QWidget::mapFromParent(const QPointF &pos) const
4300{
4301 return pos - QPointF(data->crect.topLeft());
4302}
4303
4304/*!
4305 \overload
4306*/
4307QPoint QWidget::mapFromParent(const QPoint &pos) const
4308{
4309 return pos - data->crect.topLeft();
4310}
4311
4312
4313/*!
4314 Returns the window for this widget, i.e. the next ancestor widget
4315 that has (or could have) a window-system frame.
4316
4317 If the widget is a window, the widget itself is returned.
4318
4319 Typical usage is changing the window title:
4320
4321 \snippet code/src_gui_kernel_qwidget.cpp 3
4322
4323 \sa isWindow()
4324*/
4325
4326QWidget *QWidget::window() const
4327{
4328 QWidget *w = const_cast<QWidget *>(this);
4329 QWidget *p = w->parentWidget();
4330 while (!w->isWindow() && p) {
4331 w = p;
4332 p = p->parentWidget();
4333 }
4334 return w;
4335}
4336
4337/*!
4338 \since 4.4
4339
4340 Returns the native parent for this widget, i.e. the next ancestor widget
4341 that has a system identifier, or \nullptr if it does not have any native
4342 parent.
4343
4344 \sa effectiveWinId()
4345*/
4346QWidget *QWidget::nativeParentWidget() const
4347{
4348 QWidget *parent = parentWidget();
4349 while (parent && !parent->internalWinId())
4350 parent = parent->parentWidget();
4351 return parent;
4352}
4353
4354/*! \fn QWidget *QWidget::topLevelWidget() const
4355 \deprecated
4356
4357 Use window() instead.
4358*/
4359
4360
4361
4362/*!
4363 Returns the background role of the widget.
4364
4365 The background role defines the brush from the widget's \l palette that
4366 is used to render the background.
4367
4368 If no explicit background role is set, the widget inherts its parent
4369 widget's background role.
4370
4371 \sa setBackgroundRole(), foregroundRole()
4372 */
4373QPalette::ColorRole QWidget::backgroundRole() const
4374{
4375
4376 const QWidget *w = this;
4377 do {
4378 QPalette::ColorRole role = w->d_func()->bg_role;
4379 if (role != QPalette::NoRole)
4380 return role;
4381 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4382 break;
4383 w = w->parentWidget();
4384 } while (w);
4385 return QPalette::Window;
4386}
4387
4388/*!
4389 Sets the background role of the widget to \a role.
4390
4391 The background role defines the brush from the widget's \l palette that
4392 is used to render the background.
4393
4394 If \a role is QPalette::NoRole, then the widget inherits its
4395 parent's background role.
4396
4397 Note that styles are free to choose any color from the palette.
4398 You can modify the palette or set a style sheet if you don't
4399 achieve the result you want with setBackgroundRole().
4400
4401 \sa backgroundRole(), foregroundRole()
4402 */
4403
4404void QWidget::setBackgroundRole(QPalette::ColorRole role)
4405{
4406 Q_D(QWidget);
4407 d->bg_role = role;
4408 d->updateSystemBackground();
4409 d->propagatePaletteChange();
4410 d->updateIsOpaque();
4411}
4412
4413/*!
4414 Returns the foreground role.
4415
4416 The foreground role defines the color from the widget's \l palette that
4417 is used to draw the foreground.
4418
4419 If no explicit foreground role is set, the function returns a role
4420 that contrasts with the background role.
4421
4422 \sa setForegroundRole(), backgroundRole()
4423 */
4424QPalette::ColorRole QWidget::foregroundRole() const
4425{
4426 Q_D(const QWidget);
4427 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4428 if (rl != QPalette::NoRole)
4429 return rl;
4430 QPalette::ColorRole role = QPalette::WindowText;
4431 switch (backgroundRole()) {
4432 case QPalette::Button:
4433 role = QPalette::ButtonText;
4434 break;
4435 case QPalette::Base:
4436 role = QPalette::Text;
4437 break;
4438 case QPalette::Dark:
4439 case QPalette::Shadow:
4440 role = QPalette::Light;
4441 break;
4442 case QPalette::Highlight:
4443 role = QPalette::HighlightedText;
4444 break;
4445 case QPalette::ToolTipBase:
4446 role = QPalette::ToolTipText;
4447 break;
4448 default:
4449 ;
4450 }
4451 return role;
4452}
4453
4454/*!
4455 Sets the foreground role of the widget to \a role.
4456
4457 The foreground role defines the color from the widget's \l palette that
4458 is used to draw the foreground.
4459
4460 If \a role is QPalette::NoRole, the widget uses a foreground role
4461 that contrasts with the background role.
4462
4463 Note that styles are free to choose any color from the palette.
4464 You can modify the palette or set a style sheet if you don't
4465 achieve the result you want with setForegroundRole().
4466
4467 \sa foregroundRole(), backgroundRole()
4468 */
4469void QWidget::setForegroundRole(QPalette::ColorRole role)
4470{
4471 Q_D(QWidget);
4472 d->fg_role = role;
4473 d->updateSystemBackground();
4474 d->propagatePaletteChange();
4475}
4476
4477/*!
4478 \property QWidget::palette
4479 \brief the widget's palette
4480
4481 This property describes the widget's palette. The palette is used by the
4482 widget's style when rendering standard components, and is available as a
4483 means to ensure that custom widgets can maintain consistency with the
4484 native platform's look and feel. It's common that different platforms, or
4485 different styles, have different palettes.
4486
4487 When you assign a new palette to a widget, the color roles from this
4488 palette are combined with the widget's default palette to form the
4489 widget's final palette. The palette entry for the widget's background role
4490 is used to fill the widget's background (see QWidget::autoFillBackground),
4491 and the foreground role initializes QPainter's pen.
4492
4493 The default depends on the system environment. QApplication maintains a
4494 system/theme palette which serves as a default for all widgets. There may
4495 also be special palette defaults for certain types of widgets (e.g., on
4496 Windows Vista, all classes that derive from QMenuBar have a special
4497 default palette). You can also define default palettes for widgets
4498 yourself by passing a custom palette and the name of a widget to
4499 QApplication::setPalette(). Finally, the style always has the option of
4500 polishing the palette as it's assigned (see QStyle::polish()).
4501
4502 QWidget propagates explicit palette roles from parent to child. If you
4503 assign a brush or color to a specific role on a palette and assign that
4504 palette to a widget, that role will propagate to all the widget's
4505 children, overriding any system defaults for that role. Note that palettes
4506 by default don't propagate to windows (see isWindow()) unless the
4507 Qt::WA_WindowPropagation attribute is enabled.
4508
4509 QWidget's palette propagation is similar to its font propagation.
4510
4511 The current style, which is used to render the content of all standard Qt
4512 widgets, is free to choose colors and brushes from the widget palette, or
4513 in some cases, to ignore the palette (partially, or completely). In
4514 particular, certain styles like GTK style, Mac style, and Windows Vista
4515 style, depend on third party APIs to render the content of widgets,
4516 and these styles typically do not follow the palette. Because of this,
4517 assigning roles to a widget's palette is not guaranteed to change the
4518 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4519
4520 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4521 When using style sheets, the palette of a widget can be customized using
4522 the "color", "background-color", "selection-color",
4523 "selection-background-color" and "alternate-background-color".
4524
4525 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4526*/
4527const QPalette &QWidget::palette() const
4528{
4529 if (!isEnabled()) {
4530 data->pal.setCurrentColorGroup(QPalette::Disabled);
4531 } else if ((!isVisible() || isActiveWindow())
4532#if defined(Q_OS_WIN)
4533 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4534#endif
4535 ) {
4536 data->pal.setCurrentColorGroup(QPalette::Active);
4537 } else {
4538 data->pal.setCurrentColorGroup(QPalette::Inactive);
4539 }
4540 return data->pal;
4541}
4542
4543void QWidget::setPalette(const QPalette &palette)
4544{
4545 Q_D(QWidget);
4546 setAttribute(Qt::WA_SetPalette, on: palette.resolveMask() != 0);
4547
4548 // Determine which palette is inherited from this widget's ancestors and
4549 // QApplication::palette, resolve this against \a palette (attributes from
4550 // the inherited palette are copied over this widget's palette). Then
4551 // propagate this palette to this widget's children.
4552 QPalette naturalPalette = d->naturalWidgetPalette(inheritedMask: d->inheritedPaletteResolveMask);
4553 QPalette resolvedPalette = palette.resolve(other: naturalPalette);
4554 d->setPalette_helper(resolvedPalette);
4555}
4556
4557/*!
4558 \internal
4559
4560 Returns the palette that the widget \a w inherits from its ancestors and
4561 QApplication::palette. \a inheritedMask is the combination of the widget's
4562 ancestors palette request masks (i.e., which attributes from the parent
4563 widget's palette are implicitly imposed on this widget by the user). Note
4564 that this font does not take into account the palette set on \a w itself.
4565*/
4566QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4567{
4568 Q_Q(const QWidget);
4569
4570 const bool useStyleSheetPropagationInWidgetStyles =
4571 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4572
4573 QPalette naturalPalette = QApplication::palette(q);
4574 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4575 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4576#if QT_CONFIG(graphicsview)
4577 || (extra && extra->proxyWidget)
4578#endif // QT_CONFIG(graphicsview)
4579 )) {
4580 if (QWidget *p = q->parentWidget()) {
4581 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4582 if (!naturalPalette.isCopyOf(p: QGuiApplication::palette())) {
4583 QPalette inheritedPalette = p->palette();
4584 inheritedPalette.setResolveMask(inheritedMask);
4585 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4586 } else {
4587 naturalPalette = p->palette();
4588 }
4589 }
4590 }
4591#if QT_CONFIG(graphicsview)
4592 else if (extra && extra->proxyWidget) {
4593 QPalette inheritedPalette = extra->proxyWidget->palette();
4594 inheritedPalette.setResolveMask(inheritedMask);
4595 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4596 }
4597#endif // QT_CONFIG(graphicsview)
4598 }
4599 naturalPalette.setResolveMask(0);
4600 return naturalPalette;
4601}
4602/*!
4603 \internal
4604
4605 Determine which palette is inherited from this widget's ancestors and
4606 QApplication::palette, resolve this against this widget's palette
4607 (attributes from the inherited palette are copied over this widget's
4608 palette). Then propagate this palette to this widget's children.
4609*/
4610void QWidgetPrivate::resolvePalette()
4611{
4612 QPalette naturalPalette = naturalWidgetPalette(inheritedMask: inheritedPaletteResolveMask);
4613 QPalette resolvedPalette = data.pal.resolve(other: naturalPalette);
4614 setPalette_helper(resolvedPalette);
4615}
4616
4617void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4618{
4619 Q_Q(QWidget);
4620 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4621 return;
4622 data.pal = palette;
4623 updateSystemBackground();
4624 propagatePaletteChange();
4625 updateIsOpaque();
4626 q->update();
4627 updateIsOpaque();
4628}
4629
4630void QWidgetPrivate::updateSystemBackground()
4631{
4632}
4633
4634/*!
4635 \property QWidget::font
4636 \brief the font currently set for the widget
4637
4638 This property describes the widget's requested font. The font is used by
4639 the widget's style when rendering standard components, and is available as
4640 a means to ensure that custom widgets can maintain consistency with the
4641 native platform's look and feel. It's common that different platforms, or
4642 different styles, define different fonts for an application.
4643
4644 When you assign a new font to a widget, the properties from this font are
4645 combined with the widget's default font to form the widget's final
4646 font. You can call fontInfo() to get a copy of the widget's final
4647 font. The final font is also used to initialize QPainter's font.
4648
4649 The default depends on the system environment. QApplication maintains a
4650 system/theme font which serves as a default for all widgets. There may
4651 also be special font defaults for certain types of widgets. You can also
4652 define default fonts for widgets yourself by passing a custom font and the
4653 name of a widget to QApplication::setFont(). Finally, the font is matched
4654 against Qt's font database to find the best match.
4655
4656 QWidget propagates explicit font properties from parent to child. If you
4657 change a specific property on a font and assign that font to a widget,
4658 that property will propagate to all the widget's children, overriding any
4659 system defaults for that property. Note that fonts by default don't
4660 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4661 attribute is enabled.
4662
4663 QWidget's font propagation is similar to its palette propagation.
4664
4665 The current style, which is used to render the content of all standard Qt
4666 widgets, is free to choose to use the widget font, or in some cases, to
4667 ignore it (partially, or completely). In particular, certain styles like
4668 GTK style, Mac style, and Windows Vista style, apply special
4669 modifications to the widget font to match the platform's native look and
4670 feel. Because of this, assigning properties to a widget's font is not
4671 guaranteed to change the appearance of the widget. Instead, you may choose
4672 to apply a \l styleSheet.
4673
4674 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4675 style sheets will take precedence if the settings conflict.
4676
4677 \sa fontInfo(), fontMetrics()
4678*/
4679
4680void QWidget::setFont(const QFont &font)
4681{
4682 Q_D(QWidget);
4683
4684#ifndef QT_NO_STYLE_STYLESHEET
4685 const QStyleSheetStyle* style;
4686 if (d->extra && (style = qt_styleSheet(style: d->extra->style)))
4687 style->saveWidgetFont(w: this, font);
4688#endif
4689
4690 setAttribute(Qt::WA_SetFont, on: font.resolveMask() != 0);
4691
4692 // Determine which font is inherited from this widget's ancestors and
4693 // QApplication::font, resolve this against \a font (attributes from the
4694 // inherited font are copied over). Then propagate this font to this
4695 // widget's children.
4696 QFont naturalFont = d->naturalWidgetFont(inheritedMask: d->inheritedFontResolveMask);
4697 QFont resolvedFont = font.resolve(naturalFont);
4698 d->setFont_helper(resolvedFont);
4699}
4700
4701/*
4702 \internal
4703
4704 Returns the font that the widget \a w inherits from its ancestors and
4705 QApplication::font. \a inheritedMask is the combination of the widget's
4706 ancestors font request masks (i.e., which attributes from the parent
4707 widget's font are implicitly imposed on this widget by the user). Note
4708 that this font does not take into account the font set on \a w itself.
4709
4710 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4711 is applied, fonts are not propagated anymore
4712*/
4713QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4714{
4715 Q_Q(const QWidget);
4716
4717 const bool useStyleSheetPropagationInWidgetStyles =
4718 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4719
4720 QFont naturalFont = QApplication::font(q);
4721 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4722 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4723#if QT_CONFIG(graphicsview)
4724 || (extra && extra->proxyWidget)
4725#endif // QT_CONFIG(graphicsview)
4726 )) {
4727 if (QWidget *p = q->parentWidget()) {
4728 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4729 if (!naturalFont.isCopyOf(QApplication::font())) {
4730 if (inheritedMask != 0) {
4731 QFont inheritedFont = p->font();
4732 inheritedFont.setResolveMask(inheritedMask);
4733 naturalFont = inheritedFont.resolve(naturalFont);
4734 } // else nothing to do (naturalFont = naturalFont)
4735 } else {
4736 naturalFont = p->font();
4737 }
4738 }
4739 }
4740#if QT_CONFIG(graphicsview)
4741 else if (extra && extra->proxyWidget) {
4742 if (inheritedMask != 0) {
4743 QFont inheritedFont = extra->proxyWidget->font();
4744 inheritedFont.setResolveMask(inheritedMask);
4745 naturalFont = inheritedFont.resolve(naturalFont);
4746 } // else nothing to do (naturalFont = naturalFont)
4747 }
4748#endif // QT_CONFIG(graphicsview)
4749 }
4750 naturalFont.setResolveMask(0);
4751 return naturalFont;
4752}
4753
4754/*!
4755 \internal
4756
4757 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4758*/
4759QFont QWidgetPrivate::localFont() const
4760{
4761 QFont localfont = data.fnt;
4762 localfont.setResolveMask(directFontResolveMask);
4763 return localfont;
4764}
4765
4766/*!
4767 \internal
4768
4769 Determine which font is implicitly imposed on this widget by its ancestors
4770 and QApplication::font, resolve this against its own font (attributes from
4771 the implicit font are copied over). Then propagate this font to this
4772 widget's children.
4773*/
4774void QWidgetPrivate::resolveFont()
4775{
4776 QFont naturalFont = naturalWidgetFont(inheritedMask: inheritedFontResolveMask);
4777 QFont resolvedFont = localFont().resolve(naturalFont);
4778 setFont_helper(resolvedFont);
4779}
4780
4781/*!
4782 \internal
4783
4784 Assign \a font to this widget, and propagate it to all children, except
4785 style sheet widgets (handled differently) and windows that don't enable
4786 window propagation. \a implicitMask is the union of all ancestor widgets'
4787 font request masks, and determines which attributes from this widget's
4788 font should propagate.
4789*/
4790void QWidgetPrivate::updateFont(const QFont &font)
4791{
4792 Q_Q(QWidget);
4793#ifndef QT_NO_STYLE_STYLESHEET
4794 const QStyleSheetStyle* cssStyle;
4795 cssStyle = extra ? qt_styleSheet(style: extra->style) : nullptr;
4796 const bool useStyleSheetPropagationInWidgetStyles =
4797 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4798#endif
4799
4800 data.fnt = QFont(font, q);
4801
4802 // Combine new mask with natural mask and propagate to children.
4803#if QT_CONFIG(graphicsview)
4804 if (!q->parentWidget() && extra && extra->proxyWidget) {
4805 QGraphicsProxyWidget *p = extra->proxyWidget;
4806 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4807 } else
4808#endif // QT_CONFIG(graphicsview)
4809 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
4810 inheritedFontResolveMask = 0;
4811 }
4812 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4813 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4814 // isn't all weak information, but save the original mask to be able to let new changes on the
4815 // parent widget font propagate correctly.
4816 directFontResolveMask = data.fnt.resolveMask();
4817 data.fnt.setResolveMask(newMask);
4818
4819 for (int i = 0; i < children.size(); ++i) {
4820 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4821 if (w) {
4822 if (0) {
4823#ifndef QT_NO_STYLE_STYLESHEET
4824 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(attribute: Qt::WA_StyleSheet)) {
4825 // Style sheets follow a different font propagation scheme.
4826 if (cssStyle)
4827 cssStyle->updateStyleSheetFont(w);
4828#endif
4829 } else if ((!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
4830 // Propagate font changes.
4831 QWidgetPrivate *wd = w->d_func();
4832 wd->inheritedFontResolveMask = newMask;
4833 wd->resolveFont();
4834 }
4835 }
4836 }
4837
4838#ifndef QT_NO_STYLE_STYLESHEET
4839 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4840 cssStyle->updateStyleSheetFont(w: q);
4841 }
4842#endif
4843
4844 QEvent e(QEvent::FontChange);
4845 QCoreApplication::sendEvent(receiver: q, event: &e);
4846}
4847
4848void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4849{
4850 Q_Q(QWidget);
4851
4852 if ( (direction == Qt::RightToLeft) == q->testAttribute(attribute: Qt::WA_RightToLeft))
4853 return;
4854 q->setAttribute(Qt::WA_RightToLeft, on: (direction == Qt::RightToLeft));
4855 if (!children.isEmpty()) {
4856 for (int i = 0; i < children.size(); ++i) {
4857 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4858 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4859 w->d_func()->setLayoutDirection_helper(direction);
4860 }
4861 }
4862 QEvent e(QEvent::LayoutDirectionChange);
4863 QCoreApplication::sendEvent(receiver: q, event: &e);
4864}
4865
4866void QWidgetPrivate::resolveLayoutDirection()
4867{
4868 Q_Q(const QWidget);
4869 if (!q->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4870 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4871}
4872
4873/*!
4874 \property QWidget::layoutDirection
4875
4876 \brief the layout direction for this widget.
4877
4878 \note This method no longer affects text layout direction since Qt 4.7.
4879
4880 By default, this property is set to Qt::LeftToRight.
4881
4882 When the layout direction is set on a widget, it will propagate to
4883 the widget's children, but not to a child that is a window and not
4884 to a child for which setLayoutDirection() has been explicitly
4885 called. Also, child widgets added \e after setLayoutDirection()
4886 has been called for the parent do not inherit the parent's layout
4887 direction.
4888
4889
4890 \sa QApplication::layoutDirection
4891*/
4892void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4893{
4894 Q_D(QWidget);
4895
4896 if (direction == Qt::LayoutDirectionAuto) {
4897 unsetLayoutDirection();
4898 return;
4899 }
4900
4901 setAttribute(Qt::WA_SetLayoutDirection);
4902 d->setLayoutDirection_helper(direction);
4903}
4904
4905Qt::LayoutDirection QWidget::layoutDirection() const
4906{
4907 return testAttribute(attribute: Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4908}
4909
4910void QWidget::unsetLayoutDirection()
4911{
4912 Q_D(QWidget);
4913 setAttribute(Qt::WA_SetLayoutDirection, on: false);
4914 d->resolveLayoutDirection();
4915}
4916
4917/*!
4918 \fn QFontMetrics QWidget::fontMetrics() const
4919
4920 Returns the font metrics for the widget's current font.
4921 Equivalent to \c QFontMetrics(widget->font()).
4922
4923 \sa font(), fontInfo(), setFont()
4924*/
4925
4926/*!
4927 \fn QFontInfo QWidget::fontInfo() const
4928
4929 Returns the font info for the widget's current font.
4930 Equivalent to \c QFontInfo(widget->font()).
4931
4932 \sa font(), fontMetrics(), setFont()
4933*/
4934
4935
4936/*!
4937 \property QWidget::cursor
4938 \brief the cursor shape for this widget
4939
4940 The mouse cursor will assume this shape when it's over this
4941 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4942
4943 An editor widget might use an I-beam cursor:
4944 \snippet code/src_gui_kernel_qwidget.cpp 6
4945
4946 If no cursor has been set, or after a call to unsetCursor(), the
4947 parent's cursor is used.
4948
4949 By default, this property contains a cursor with the Qt::ArrowCursor
4950 shape.
4951
4952 Some underlying window implementations will reset the cursor if it
4953 leaves a widget even if the mouse is grabbed. If you want to have
4954 a cursor set for all widgets, even when outside the window, consider
4955 QGuiApplication::setOverrideCursor().
4956
4957 \sa QGuiApplication::setOverrideCursor()
4958*/
4959
4960#ifndef QT_NO_CURSOR
4961QCursor QWidget::cursor() const
4962{
4963 Q_D(const QWidget);
4964 if (testAttribute(attribute: Qt::WA_SetCursor))
4965 return (d->extra && d->extra->curs)
4966 ? *d->extra->curs
4967 : QCursor(Qt::ArrowCursor);
4968 if (isWindow() || !parentWidget())
4969 return QCursor(Qt::ArrowCursor);
4970 return parentWidget()->cursor();
4971}
4972
4973void QWidget::setCursor(const QCursor &cursor)
4974{
4975 Q_D(QWidget);
4976 if (cursor.shape() != Qt::ArrowCursor
4977 || (d->extra && d->extra->curs))
4978 {
4979 d->createExtra();
4980 d->extra->curs = std::make_unique<QCursor>(args: cursor);
4981 }
4982 setAttribute(Qt::WA_SetCursor);
4983 d->setCursor_sys(cursor);
4984
4985 QEvent event(QEvent::CursorChange);
4986 QCoreApplication::sendEvent(receiver: this, event: &event);
4987}
4988
4989void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4990{
4991 Q_UNUSED(cursor);
4992 Q_Q(QWidget);
4993 qt_qpa_set_cursor(w: q, force: false);
4994}
4995
4996void QWidget::unsetCursor()
4997{
4998 Q_D(QWidget);
4999 if (d->extra)
5000 d->extra->curs.reset();
5001 if (!isWindow())
5002 setAttribute(Qt::WA_SetCursor, on: false);
5003 d->unsetCursor_sys();
5004
5005 QEvent event(QEvent::CursorChange);
5006 QCoreApplication::sendEvent(receiver: this, event: &event);
5007}
5008
5009void QWidgetPrivate::unsetCursor_sys()
5010{
5011 Q_Q(QWidget);
5012 qt_qpa_set_cursor(w: q, force: false);
5013}
5014
5015static inline void applyCursor(QWidget *w, const QCursor &c)
5016{
5017 if (QWindow *window = w->windowHandle())
5018 window->setCursor(c);
5019}
5020
5021static inline void unsetCursor(QWidget *w)
5022{
5023 if (QWindow *window = w->windowHandle())
5024 window->unsetCursor();
5025}
5026
5027void qt_qpa_set_cursor(QWidget *w, bool force)
5028{
5029 if (!w->testAttribute(attribute: Qt::WA_WState_Created))
5030 return;
5031
5032 static QPointer<QWidget> lastUnderMouse = nullptr;
5033 if (force) {
5034 lastUnderMouse = w;
5035 } else if (lastUnderMouse) {
5036 const WId lastWinId = lastUnderMouse->effectiveWinId();
5037 const WId winId = w->effectiveWinId();
5038 if (lastWinId && lastWinId == winId)
5039 w = lastUnderMouse;
5040 } else if (!w->internalWinId()) {
5041 return; // The mouse is not under this widget, and it's not native, so don't change it.
5042 }
5043
5044 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5045 && !w->testAttribute(attribute: Qt::WA_SetCursor))
5046 w = w->parentWidget();
5047
5048 QWidget *nativeParent = w;
5049 if (!w->internalWinId())
5050 nativeParent = w->nativeParentWidget();
5051 if (!nativeParent || !nativeParent->internalWinId())
5052 return;
5053
5054 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_SetCursor)) {
5055 if (w->isEnabled())
5056 applyCursor(w: nativeParent, c: w->cursor());
5057 else
5058 // Enforce the windows behavior of clearing the cursor on
5059 // disabled widgets.
5060 unsetCursor(w: nativeParent);
5061 } else {
5062 unsetCursor(w: nativeParent);
5063 }
5064}
5065#endif
5066
5067/*!
5068 \enum QWidget::RenderFlag
5069
5070 This enum describes how to render the widget when calling QWidget::render().
5071
5072 \value DrawWindowBackground If you enable this option, the widget's background
5073 is rendered into the target even if autoFillBackground is not set. By default,
5074 this option is enabled.
5075
5076 \value DrawChildren If you enable this option, the widget's children
5077 are rendered recursively into the target. By default, this option is enabled.
5078
5079 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5080 is ignored when rendering into the target. By default, this option is disabled.
5081
5082 \since 4.3
5083*/
5084
5085/*!
5086 \since 4.3
5087
5088 Renders the \a sourceRegion of this widget into the \a target
5089 using \a renderFlags to determine how to render. Rendering
5090 starts at \a targetOffset in the \a target. For example:
5091
5092 \snippet code/src_gui_kernel_qwidget.cpp 7
5093
5094 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5095 the region, i.e. the entire widget.
5096
5097 Ensure that you call QPainter::end() for the \a target device's
5098 active painter (if any) before rendering. For example:
5099
5100 \snippet code/src_gui_kernel_qwidget.cpp 8
5101
5102 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5103 instead.
5104*/
5105void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5106 const QRegion &sourceRegion, RenderFlags renderFlags)
5107{
5108 QPainter p(target);
5109 render(painter: &p, targetOffset, sourceRegion, renderFlags);
5110}
5111
5112/*!
5113 \overload
5114
5115 Renders the widget into the \a painter's QPainter::device().
5116
5117 Transformations and settings applied to the \a painter will be used
5118 when rendering.
5119
5120 \note The \a painter must be active. On \macos the widget will be
5121 rendered into a QPixmap and then drawn by the \a painter.
5122
5123 \sa QPainter::device()
5124*/
5125void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5126 const QRegion &sourceRegion, RenderFlags renderFlags)
5127{
5128 if (Q_UNLIKELY(!painter)) {
5129 qWarning(msg: "QWidget::render: Null pointer to painter");
5130 return;
5131 }
5132
5133 if (Q_UNLIKELY(!painter->isActive())) {
5134 qWarning(msg: "QWidget::render: Cannot render with an inactive painter");
5135 return;
5136 }
5137
5138 const qreal opacity = painter->opacity();
5139 if (qFuzzyIsNull(d: opacity))
5140 return; // Fully transparent.
5141
5142 Q_D(QWidget);
5143 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5144 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(region: sourceRegion, renderFlags)
5145 : sourceRegion;
5146 if (toBePainted.isEmpty())
5147 return;
5148
5149 if (!d->extra)
5150 d->createExtra();
5151 d->extra->inRenderWithPainter = true;
5152
5153 QPaintEngine *engine = painter->paintEngine();
5154 Q_ASSERT(engine);
5155 QPaintEnginePrivate *enginePriv = engine->d_func();
5156 Q_ASSERT(enginePriv);
5157 QPaintDevice *target = engine->paintDevice();
5158 Q_ASSERT(target);
5159
5160 // Render via a pixmap when dealing with non-opaque painters or printers.
5161 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5162 d->render_helper(painter, targetOffset, sourceRegion: toBePainted, renderFlags);
5163 d->extra->inRenderWithPainter = inRenderWithPainter;
5164 return;
5165 }
5166
5167 // Set new shared painter.
5168 QPainter *oldPainter = d->sharedPainter();
5169 d->setSharedPainter(painter);
5170
5171 // Save current system clip, viewport and transform,
5172 const QTransform oldTransform = enginePriv->systemTransform;
5173 const QRegion oldSystemClip = enginePriv->systemClip;
5174 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5175 const QRegion oldSystemViewport = enginePriv->systemViewport;
5176
5177 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5178 if (painter->hasClipping()) {
5179 const QRegion painterClip = painter->deviceTransform().map(r: painter->clipRegion());
5180 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5181 } else {
5182 enginePriv->setSystemViewport(oldSystemClip);
5183 }
5184
5185 d->render(target, targetOffset, sourceRegion: toBePainted, renderFlags);
5186
5187 // Restore system clip, viewport and transform.
5188 enginePriv->baseSystemClip = oldBaseClip;
5189 enginePriv->setSystemTransformAndViewport(xform: oldTransform, region: oldSystemViewport);
5190 enginePriv->systemStateChanged();
5191
5192 // Restore shared painter.
5193 d->setSharedPainter(oldPainter);
5194
5195 d->extra->inRenderWithPainter = inRenderWithPainter;
5196}
5197
5198static void sendResizeEvents(QWidget *target)
5199{
5200 QResizeEvent e(target->size(), QSize());
5201 QCoreApplication::sendEvent(receiver: target, event: &e);
5202
5203 const QObjectList children = target->children();
5204 for (int i = 0; i < children.size(); ++i) {
5205 if (!children.at(i)->isWidgetType())
5206 continue;
5207 QWidget *child = static_cast<QWidget*>(children.at(i));
5208 if (!child->isWindow() && child->testAttribute(attribute: Qt::WA_PendingResizeEvent))
5209 sendResizeEvents(target: child);
5210 }
5211}
5212
5213/*!
5214 \since 5.0
5215
5216 Renders the widget into a pixmap restricted by the
5217 given \a rectangle. If the widget has any children, then
5218 they are also painted in the appropriate positions.
5219
5220 If a rectangle with an invalid size is specified (the default),
5221 the entire widget is painted.
5222
5223 \sa render(), QPixmap
5224*/
5225QPixmap QWidget::grab(const QRect &rectangle)
5226{
5227 Q_D(QWidget);
5228 if (testAttribute(attribute: Qt::WA_PendingResizeEvent) || !testAttribute(attribute: Qt::WA_WState_Created))
5229 sendResizeEvents(target: this);
5230
5231 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5232
5233 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5234 QRect r(rectangle);
5235 if (r.width() < 0 || r.height() < 0) {
5236 // For grabbing widgets that haven't been shown yet,
5237 // we trigger the layouting mechanism to determine the widget's size.
5238 r = d->prepareToRender(region: QRegion(), renderFlags).boundingRect();
5239 r.setTopLeft(rectangle.topLeft());
5240 }
5241
5242 if (!r.intersects(r: rect()))
5243 return QPixmap();
5244
5245 const qreal dpr = devicePixelRatio();
5246 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5247 res.setDevicePixelRatio(dpr);
5248 if (!d->isOpaque)
5249 res.fill(fillColor: Qt::transparent);
5250 d->render(target: &res, targetOffset: QPoint(), sourceRegion: QRegion(r), renderFlags);
5251
5252 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5253 return res;
5254}
5255
5256/*!
5257 \brief The graphicsEffect function returns a pointer to the
5258 widget's graphics effect.
5259
5260 If the widget has no graphics effect, \nullptr is returned.
5261
5262 \since 4.6
5263
5264 \sa setGraphicsEffect()
5265*/
5266#if QT_CONFIG(graphicseffect)
5267QGraphicsEffect *QWidget::graphicsEffect() const
5268{
5269 Q_D(const QWidget);
5270 return d->graphicsEffect;
5271}
5272#endif // QT_CONFIG(graphicseffect)
5273
5274/*!
5275
5276 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5277
5278 Sets \a effect as the widget's effect. If there already is an effect installed
5279 on this widget, QWidget will delete the existing effect before installing
5280 the new \a effect.
5281
5282 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5283 the effect from the widget and install it on this widget.
5284
5285 QWidget takes ownership of \a effect.
5286
5287 \note This function will apply the effect on itself and all its children.
5288
5289 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5290 QOpenGLWidget and QQuickWidget.
5291
5292 \since 4.6
5293
5294 \sa graphicsEffect()
5295*/
5296#if QT_CONFIG(graphicseffect)
5297void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5298{
5299 Q_D(QWidget);
5300 if (d->graphicsEffect == effect)
5301 return;
5302
5303 if (d->graphicsEffect) {
5304 d->invalidateBackingStore(rect());
5305 delete d->graphicsEffect;
5306 d->graphicsEffect = nullptr;
5307 }
5308
5309 if (effect) {
5310 // Set new effect.
5311 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5312 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5313 d->graphicsEffect = effect;
5314 effect->d_func()->setGraphicsEffectSource(source);
5315 update();
5316 }
5317
5318 d->updateIsOpaque();
5319}
5320#endif // QT_CONFIG(graphicseffect)
5321
5322bool QWidgetPrivate::isAboutToShow() const
5323{
5324 if (data.in_show)
5325 return true;
5326
5327 Q_Q(const QWidget);
5328 if (q->isHidden())
5329 return false;
5330
5331 // The widget will be shown if any of its ancestors are about to show.
5332 QWidget *parent = q->parentWidget();
5333 return parent ? parent->d_func()->isAboutToShow() : false;
5334}
5335
5336QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5337{
5338 Q_Q(QWidget);
5339 const bool isVisible = q->isVisible();
5340
5341 // Make sure the widget is laid out correctly.
5342 if (!isVisible && !isAboutToShow()) {
5343 QWidget *topLevel = q->window();
5344 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5345 topLevel->ensurePolished();
5346
5347 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5348 // they're not explicitly hidden.
5349 QWidget *widget = q;
5350 QWidgetList hiddenWidgets;
5351 while (widget) {
5352 if (widget->isHidden()) {
5353 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
5354 hiddenWidgets.append(t: widget);
5355 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5356 widget->d_func()->updateGeometry_helper(forceUpdate: true);
5357 }
5358 widget = widget->parentWidget();
5359 }
5360
5361 // Activate top-level layout.
5362 if (topLevel->d_func()->layout)
5363 topLevel->d_func()->layout->activate();
5364
5365 // Adjust size if necessary.
5366 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5367 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5368 && !topLevel->testAttribute(attribute: Qt::WA_Resized)) {
5369 topLevel->adjustSize();
5370 topLevel->setAttribute(Qt::WA_Resized, on: false);
5371 }
5372
5373 // Activate child layouts.
5374 topLevel->d_func()->activateChildLayoutsRecursively();
5375
5376 // We're not cheating with WA_WState_Hidden anymore.
5377 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5378 QWidget *widget = hiddenWidgets.at(i);
5379 widget->setAttribute(Qt::WA_WState_Hidden);
5380 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5381 widget->parentWidget()->d_func()->layout->invalidate();
5382 }
5383 } else if (isVisible) {
5384 q->window()->d_func()->sendPendingMoveAndResizeEvents(recursive: true, disableUpdates: true);
5385 }
5386
5387 // Calculate the region to be painted.
5388 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5389 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5390 toBePainted &= extra->mask;
5391 return toBePainted;
5392}
5393
5394void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5395 QWidget::RenderFlags renderFlags)
5396{
5397 Q_ASSERT(painter);
5398 Q_ASSERT(!toBePainted.isEmpty());
5399
5400 Q_Q(QWidget);
5401 const QTransform originalTransform = painter->worldTransform();
5402 const bool useDeviceCoordinates = originalTransform.isScaling();
5403 if (!useDeviceCoordinates) {
5404 // Render via a pixmap.
5405 const QRect rect = toBePainted.boundingRect();
5406 const QSize size = rect.size();
5407 if (size.isNull())
5408 return;
5409
5410 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5411 QPixmap pixmap(size * pixmapDevicePixelRatio);
5412 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5413
5414 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5415 pixmap.fill(fillColor: Qt::transparent);
5416 q->render(target: &pixmap, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5417
5418 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5419 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: true);
5420
5421 painter->drawPixmap(p: targetOffset, pm: pixmap);
5422
5423 if (restore)
5424 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: false);
5425
5426 } else {
5427 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5428 QTransform transform = originalTransform;
5429 transform.translate(dx: targetOffset.x(), dy: targetOffset.y());
5430
5431 QPaintDevice *device = painter->device();
5432 Q_ASSERT(device);
5433
5434 // Calculate device rect.
5435 const QRectF rect(toBePainted.boundingRect());
5436 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5437 deviceRect &= QRect(0, 0, device->width(), device->height());
5438
5439 QPixmap pixmap(deviceRect.size());
5440 pixmap.fill(fillColor: Qt::transparent);
5441
5442 // Create a pixmap device coordinate painter.
5443 QPainter pixmapPainter(&pixmap);
5444 pixmapPainter.setRenderHints(hints: painter->renderHints());
5445 transform *= QTransform::fromTranslate(dx: -deviceRect.x(), dy: -deviceRect.y());
5446 pixmapPainter.setTransform(transform);
5447
5448 q->render(painter: &pixmapPainter, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5449 pixmapPainter.end();
5450
5451 // And then draw the pixmap.
5452 painter->setTransform(transform: QTransform());
5453 painter->drawPixmap(p: deviceRect.topLeft(), pm: pixmap);
5454 painter->setTransform(transform: originalTransform);
5455 }
5456}
5457
5458void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5459 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5460{
5461 if (rgn.isEmpty())
5462 return;
5463
5464 Q_Q(QWidget);
5465
5466 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5467 << "into paint device" << pdev << "with" << flags;
5468
5469 const bool asRoot = flags & DrawAsRoot;
5470 bool onScreen = shouldPaintOnScreen();
5471
5472#if QT_CONFIG(graphicseffect)
5473 if (graphicsEffect && graphicsEffect->isEnabled()) {
5474 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5475 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5476 (source->d_func());
5477 if (!sourced->context) {
5478 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5479 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5480 sourced->context = &context;
5481 if (!sharedPainter) {
5482 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: effectRgn.translated(p: offset));
5483 QPainter p(pdev);
5484 p.translate(offset);
5485 context.painter = &p;
5486 graphicsEffect->draw(painter: &p);
5487 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5488 } else {
5489 context.painter = sharedPainter;
5490 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5491 sourced->invalidateCache();
5492 sourced->lastEffectTransform = sharedPainter->worldTransform();
5493 }
5494 sharedPainter->save();
5495 sharedPainter->translate(offset);
5496 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: sharedPainter->device()->devicePixelRatio(), region: effectRgn.translated(p: offset));
5497 graphicsEffect->draw(painter: sharedPainter);
5498 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: 1, region: QRegion());
5499 sharedPainter->restore();
5500 }
5501 sourced->context = nullptr;
5502
5503 if (repaintManager)
5504 repaintManager->markNeedsFlush(widget: q, region: effectRgn, topLevelOffset: offset);
5505
5506 return;
5507 }
5508 }
5509#endif // QT_CONFIG(graphicseffect)
5510 flags = flags & ~UseEffectRegionBounds;
5511
5512 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5513 const bool recursive = flags & DrawRecursive;
5514 const bool alsoInvisible = flags & DrawInvisible;
5515
5516 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5517
5518 QRegion toBePainted(rgn);
5519 if (asRoot && !alsoInvisible)
5520 toBePainted &= clipRect(); //(rgn & visibleRegion());
5521 if (!(flags & DontSubtractOpaqueChildren))
5522 subtractOpaqueChildren(source&: toBePainted, clipRect: q->rect());
5523
5524 if (!toBePainted.isEmpty()) {
5525 if (!onScreen || alsoOnScreen) {
5526 //update the "in paint event" flag
5527 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5528 qWarning(msg: "QWidget::repaint: Recursive repaint detected");
5529 q->setAttribute(Qt::WA_WState_InPaintEvent);
5530
5531 //clip away the new area
5532 QPaintEngine *paintEngine = pdev->paintEngine();
5533 if (paintEngine) {
5534 setRedirected(replacement: pdev, offset: -offset);
5535
5536 if (sharedPainter)
5537 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted);
5538 else
5539 paintEngine->d_func()->systemRect = q->data->crect;
5540
5541 //paint the background
5542 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(attribute: Qt::WA_StyledBackground))
5543 && !q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
5544 beginBackingStorePainting();
5545 QPainter p(q);
5546 p.setRenderHint(hint: QPainter::SmoothPixmapTransform);
5547 paintBackground(painter: &p, rgn: toBePainted, flags: (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5548 endBackingStorePainting();
5549 }
5550
5551 if (!sharedPainter)
5552 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted.translated(p: offset));
5553
5554 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(attribute: Qt::WA_TintedBackground)) {
5555 beginBackingStorePainting();
5556 QPainter p(q);
5557 QColor tint = q->palette().window().color();
5558 tint.setAlphaF(.6f);
5559 p.fillRect(toBePainted.boundingRect(), color: tint);
5560 endBackingStorePainting();
5561 }
5562 }
5563
5564#if 0
5565 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5566 qDebug() << "clipping to" << toBePainted << "location == " << offset
5567 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5568#endif
5569
5570 bool skipPaintEvent = false;
5571 if (renderToTexture) {
5572 // This widget renders into a texture which is composed later. We just need to
5573 // punch a hole in the backingstore, so the texture will be visible.
5574 beginBackingStorePainting();
5575 if (!q->testAttribute(attribute: Qt::WA_AlwaysStackOnTop) && repaintManager) {
5576 QPainter p(q);
5577 p.setCompositionMode(QPainter::CompositionMode_Source);
5578 p.fillRect(r: q->rect(), c: Qt::transparent);
5579 } else if (!repaintManager) {
5580 // We are not drawing to a backingstore: fall back to QImage
5581 QImage img = grabFramebuffer();
5582 // grabFramebuffer() always sets the format to RGB32
5583 // regardless of whether it is transparent or not.
5584 if (img.format() == QImage::Format_RGB32)
5585 img.reinterpretAsFormat(f: QImage::Format_ARGB32_Premultiplied);
5586 QPainter p(q);
5587 p.drawImage(r: q->rect(), image: img);
5588 skipPaintEvent = true;
5589 }
5590 endBackingStorePainting();
5591 if (renderToTextureReallyDirty)
5592 renderToTextureReallyDirty = 0;
5593 else
5594 skipPaintEvent = true;
5595 }
5596
5597 if (!skipPaintEvent) {
5598 //actually send the paint event
5599 sendPaintEvent(toBePainted);
5600 }
5601
5602 if (repaintManager)
5603 repaintManager->markNeedsFlush(widget: q, region: toBePainted, topLevelOffset: offset);
5604
5605 //restore
5606 if (paintEngine) {
5607 restoreRedirected();
5608 if (!sharedPainter)
5609 paintEngine->d_func()->systemRect = QRect();
5610 else
5611 paintEngine->d_func()->currentClipDevice = nullptr;
5612
5613 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5614 }
5615 q->setAttribute(Qt::WA_WState_InPaintEvent, on: false);
5616 if (Q_UNLIKELY(q->paintingActive()))
5617 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5618
5619 if (paintEngine && paintEngine->autoDestruct()) {
5620 delete paintEngine;
5621 }
5622 } else if (q->isWindow()) {
5623 QPaintEngine *engine = pdev->paintEngine();
5624 if (engine) {
5625 QPainter p(pdev);
5626 p.setClipRegion(toBePainted);
5627 const QBrush bg = q->palette().brush(cr: QPalette::Window);
5628 if (bg.style() == Qt::TexturePattern)
5629 p.drawTiledPixmap(rect: q->rect(), pm: bg.texture());
5630 else
5631 p.fillRect(q->rect(), bg);
5632
5633 if (engine->autoDestruct())
5634 delete engine;
5635 }
5636 }
5637 }
5638
5639 if (recursive && !children.isEmpty()) {
5640 paintSiblingsRecursive(pdev, children, index: children.size() - 1, rgn, offset, flags: flags & ~DrawAsRoot,
5641 sharedPainter, repaintManager);
5642 }
5643}
5644
5645void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5646{
5647 Q_Q(QWidget);
5648 QPaintEvent e(toBePainted);
5649 QCoreApplication::sendSpontaneousEvent(receiver: q, event: &e);
5650
5651 if (renderToTexture)
5652 resolveSamples();
5653}
5654
5655void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5656 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5657{
5658 if (Q_UNLIKELY(!target)) {
5659 qWarning(msg: "QWidget::render: null pointer to paint device");
5660 return;
5661 }
5662
5663 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5664 QRegion paintRegion = !inRenderWithPainter
5665 ? prepareToRender(region: sourceRegion, renderFlags)
5666 : sourceRegion;
5667 if (paintRegion.isEmpty())
5668 return;
5669
5670 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5671
5672 // Use the target's shared painter if set (typically set when doing
5673 // "other->render(widget);" in the widget's paintEvent.
5674 if (target->devType() == QInternal::Widget) {
5675 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5676 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5677 QPainter *targetPainter = targetPrivate->sharedPainter();
5678 if (targetPainter && targetPainter->isActive())
5679 setSharedPainter(targetPainter);
5680 }
5681 }
5682
5683 // Use the target's redirected device if set and adjust offset and paint
5684 // region accordingly. This is typically the case when people call render
5685 // from the paintEvent.
5686 QPoint offset = targetOffset;
5687 offset -= paintRegion.boundingRect().topLeft();
5688 QPoint redirectionOffset;
5689 QPaintDevice *redirected = nullptr;
5690
5691 if (target->devType() == QInternal::Widget)
5692 redirected = static_cast<QWidget *>(target)->d_func()->redirected(offset: &redirectionOffset);
5693
5694 if (redirected) {
5695 target = redirected;
5696 offset -= redirectionOffset;
5697 }
5698
5699 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5700 if (QPaintEngine *targetEngine = target->paintEngine()) {
5701 const QRegion targetSystemClip = targetEngine->systemClip();
5702 if (!targetSystemClip.isEmpty())
5703 paintRegion &= targetSystemClip.translated(p: -offset);
5704 }
5705 }
5706
5707 // Set backingstore flags.
5708 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5709 if (renderFlags & QWidget::DrawWindowBackground)
5710 flags |= DrawAsRoot;
5711
5712 if (renderFlags & QWidget::DrawChildren)
5713 flags |= DrawRecursive;
5714 else
5715 flags |= DontSubtractOpaqueChildren;
5716
5717 flags |= DontSetCompositionMode;
5718
5719 // Render via backingstore.
5720 drawWidget(pdev: target, rgn: paintRegion, offset, flags, sharedPainter: sharedPainter());
5721
5722 // Restore shared painter.
5723 if (oldSharedPainter)
5724 setSharedPainter(oldSharedPainter);
5725}
5726
5727void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5728 const QPoint &offset, DrawWidgetFlags flags
5729 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5730{
5731 QWidget *w = nullptr;
5732 QRect boundingRect;
5733 bool dirtyBoundingRect = true;
5734 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5735 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5736
5737 do {
5738 QWidget *x = qobject_cast<QWidget*>(o: siblings.at(i: index));
5739 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5740 && !(excludeNativeChildren && x->internalWinId())) {
5741 if (dirtyBoundingRect) {
5742 boundingRect = rgn.boundingRect();
5743 dirtyBoundingRect = false;
5744 }
5745
5746 if (qRectIntersects(r1: boundingRect, r2: x->d_func()->effectiveRectFor(rect: x->data->crect))) {
5747 w = x;
5748 break;
5749 }
5750 }
5751 --index;
5752 } while (index >= 0);
5753
5754 if (!w)
5755 return;
5756
5757 QWidgetPrivate *wd = w->d_func();
5758 const QPoint widgetPos(w->data->crect.topLeft());
5759 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5760 if (index > 0) {
5761 QRegion wr(rgn);
5762 if (wd->isOpaque)
5763 wr -= hasMask ? wd->extra->mask.translated(p: widgetPos) : w->data->crect;
5764 paintSiblingsRecursive(pdev, siblings, index: --index, rgn: wr, offset, flags,
5765 sharedPainter, repaintManager);
5766 }
5767
5768 if (w->updatesEnabled()
5769#if QT_CONFIG(graphicsview)
5770 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5771#endif // QT_CONFIG(graphicsview)
5772 ) {
5773 QRegion wRegion(rgn);
5774 wRegion &= wd->effectiveRectFor(rect: w->data->crect);
5775 wRegion.translate(p: -widgetPos);
5776 if (hasMask)
5777 wRegion &= wd->extra->mask;
5778 wd->drawWidget(pdev, rgn: wRegion, offset: offset + widgetPos, flags, sharedPainter, repaintManager);
5779 }
5780}
5781
5782#if QT_CONFIG(graphicseffect)
5783QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5784{
5785 if (system != Qt::DeviceCoordinates)
5786 return m_widget->rect();
5787
5788 if (Q_UNLIKELY(!context)) {
5789 // Device coordinates without context not yet supported.
5790 qWarning(msg: "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5791 return QRectF();
5792 }
5793
5794 return context->painter->worldTransform().mapRect(m_widget->rect());
5795}
5796
5797void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5798{
5799 if (!context || context->painter != painter) {
5800 m_widget->render(painter);
5801 return;
5802 }
5803
5804 // The region saved in the context is neither clipped to the rect
5805 // nor the mask, so we have to clip it here before calling drawWidget.
5806 QRegion toBePainted = context->rgn;
5807 toBePainted &= m_widget->rect();
5808 QWidgetPrivate *wd = qt_widget_private(widget: m_widget);
5809 if (wd->extra && wd->extra->hasMask)
5810 toBePainted &= wd->extra->mask;
5811
5812 wd->drawWidget(pdev: context->pdev, rgn: toBePainted, offset: context->offset, flags: context->flags,
5813 sharedPainter: context->sharedPainter, repaintManager: context->repaintManager);
5814}
5815
5816QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5817 QGraphicsEffect::PixmapPadMode mode) const
5818{
5819 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5820 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5821 // Device coordinates without context not yet supported.
5822 qWarning(msg: "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5823 return QPixmap();
5824 }
5825
5826 QPoint pixmapOffset;
5827 QRectF sourceRect = m_widget->rect();
5828
5829 if (deviceCoordinates) {
5830 const QTransform &painterTransform = context->painter->worldTransform();
5831 sourceRect = painterTransform.mapRect(sourceRect);
5832 pixmapOffset = painterTransform.map(p: pixmapOffset);
5833 }
5834
5835 QRect effectRect;
5836
5837 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5838 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5839 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5840 effectRect = sourceRect.adjusted(xp1: -1, yp1: -1, xp2: 1, yp2: 1).toAlignedRect();
5841 else
5842 effectRect = sourceRect.toAlignedRect();
5843
5844 if (offset)
5845 *offset = effectRect.topLeft();
5846
5847 pixmapOffset -= effectRect.topLeft();
5848
5849 qreal dpr(1.0);
5850 if (const auto *paintDevice = context->painter->device())
5851 dpr = paintDevice->devicePixelRatio();
5852 else
5853 qWarning(msg: "QWidgetEffectSourcePrivate::pixmap: Painter not active");
5854 QPixmap pixmap(effectRect.size() * dpr);
5855 pixmap.setDevicePixelRatio(dpr);
5856
5857 pixmap.fill(fillColor: Qt::transparent);
5858 m_widget->render(target: &pixmap, targetOffset: pixmapOffset, sourceRegion: QRegion(), renderFlags: QWidget::DrawChildren);
5859 return pixmap;
5860}
5861#endif // QT_CONFIG(graphicseffect)
5862
5863#if QT_CONFIG(graphicsview)
5864/*!
5865 \internal
5866
5867 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5868 widget and its ancestors. The search starts at \a origin (inclusive).
5869 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5870 embedded widget was found.
5871*/
5872QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5873{
5874 if (origin) {
5875 const auto &extra = origin->d_func()->extra;
5876 if (extra && extra->proxyWidget)
5877 return extra->proxyWidget;
5878 return nearestGraphicsProxyWidget(origin: origin->parentWidget());
5879 }
5880 return nullptr;
5881}
5882#endif
5883
5884/*!
5885 \property QWidget::locale
5886 \brief the widget's locale
5887 \since 4.3
5888
5889 As long as no special locale has been set, this is either
5890 the parent's locale or (if this widget is a top level widget),
5891 the default locale.
5892
5893 If the widget displays dates or numbers, these should be formatted
5894 using the widget's locale.
5895
5896 \sa QLocale, QLocale::setDefault()
5897*/
5898
5899void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5900{
5901 Q_Q(QWidget);
5902 if (locale == loc && !forceUpdate)
5903 return;
5904
5905 locale = loc;
5906
5907 if (!children.isEmpty()) {
5908 for (int i = 0; i < children.size(); ++i) {
5909 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
5910 if (!w)
5911 continue;
5912 if (w->testAttribute(attribute: Qt::WA_SetLocale))
5913 continue;
5914 if (w->isWindow() && !w->testAttribute(attribute: Qt::WA_WindowPropagation))
5915 continue;
5916 w->d_func()->setLocale_helper(loc, forceUpdate);
5917 }
5918 }
5919 QEvent e(QEvent::LocaleChange);
5920 QCoreApplication::sendEvent(receiver: q, event: &e);
5921}
5922
5923void QWidget::setLocale(const QLocale &locale)
5924{
5925 Q_D(QWidget);
5926
5927 setAttribute(Qt::WA_SetLocale);
5928 d->setLocale_helper(loc: locale);
5929}
5930
5931QLocale QWidget::locale() const
5932{
5933 Q_D(const QWidget);
5934
5935 return d->locale;
5936}
5937
5938void QWidgetPrivate::resolveLocale()
5939{
5940 Q_Q(const QWidget);
5941
5942 if (!q->testAttribute(attribute: Qt::WA_SetLocale)) {
5943 QWidget *parent = q->parentWidget();
5944 setLocale_helper(loc: !parent || (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation))
5945 ? QLocale() : parent->locale());
5946 }
5947}
5948
5949void QWidget::unsetLocale()
5950{
5951 Q_D(QWidget);
5952 setAttribute(Qt::WA_SetLocale, on: false);
5953 d->resolveLocale();
5954}
5955
5956/*!
5957 \property QWidget::windowTitle
5958 \brief the window title (caption)
5959
5960 This property only makes sense for top-level widgets, such as
5961 windows and dialogs. If no caption has been set, the title is based of the
5962 \l windowFilePath. If neither of these is set, then the title is
5963 an empty string.
5964
5965 If you use the \l windowModified mechanism, the window title must
5966 contain a "[*]" placeholder, which indicates where the '*' should
5967 appear. Normally, it should appear right after the file name
5968 (e.g., "document1.txt[*] - Text Editor"). If the \l
5969 windowModified property is \c false (the default), the placeholder
5970 is simply removed.
5971
5972 On some desktop platforms (including Windows and Unix), the application name
5973 (from QGuiApplication::applicationDisplayName) is added at the end of the
5974 window title, if set. This is done by the QPA plugin, so it is shown to the
5975 user, but isn't part of the windowTitle string.
5976
5977 \sa windowIcon, windowModified, windowFilePath
5978*/
5979QString QWidget::windowTitle() const
5980{
5981 Q_D(const QWidget);
5982 if (d->extra && d->extra->topextra) {
5983 if (!d->extra->topextra->caption.isEmpty())
5984 return d->extra->topextra->caption;
5985 if (!d->extra->topextra->filePath.isEmpty())
5986 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
5987 }
5988 return QString();
5989}
5990
5991/*!
5992 Returns a modified window title with the [*] place holder
5993 replaced according to the rules described in QWidget::setWindowTitle
5994
5995 This function assumes that "[*]" can be quoted by another
5996 "[*]", so it will replace two place holders by one and
5997 a single last one by either "*" or nothing depending on
5998 the modified flag.
5999
6000 \internal
6001*/
6002QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6003{
6004 Q_ASSERT(widget);
6005
6006 QString cap = title;
6007 if (cap.isEmpty())
6008 return cap;
6009
6010 const auto placeHolder = "[*]"_L1;
6011 int index = cap.indexOf(s: placeHolder);
6012
6013 // here the magic begins
6014 while (index != -1) {
6015 index += placeHolder.size();
6016 int count = 1;
6017 while (cap.indexOf(s: placeHolder, from: index) == index) {
6018 ++count;
6019 index += placeHolder.size();
6020 }
6021
6022 if (count%2) { // odd number of [*] -> replace last one
6023 int lastIndex = cap.lastIndexOf(s: placeHolder, from: index - 1);
6024 if (widget->isWindowModified()
6025 && widget->style()->styleHint(stylehint: QStyle::SH_TitleBar_ModifyNotification, opt: nullptr, widget))
6026 cap.replace(i: lastIndex, len: 3, after: QWidget::tr(s: "*"));
6027 else
6028 cap.remove(i: lastIndex, len: 3);
6029 }
6030
6031 index = cap.indexOf(s: placeHolder, from: index);
6032 }
6033
6034 cap.replace(before: "[*][*]"_L1, after: placeHolder);
6035
6036 return cap;
6037}
6038
6039void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6040{
6041 Q_Q(QWidget);
6042 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6043 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6044}
6045
6046void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6047{
6048 Q_Q(QWidget);
6049 if (!q->isWindow())
6050 return;
6051
6052 if (QWindow *window = q->windowHandle())
6053 window->setTitle(caption);
6054
6055}
6056
6057void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6058{
6059 Q_Q(QWidget);
6060 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6061 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6062}
6063
6064void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6065{
6066#if QT_CONFIG(xcb)
6067 Q_Q(QWidget);
6068 // ### The QWidget property is deprecated, but the XCB window function is not.
6069 // It should remain available for the rare application that needs it.
6070 if (QWindow *window = q->windowHandle()) {
6071 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6072 xcbWindow->setWindowIconText(iconText);
6073 }
6074#else
6075 Q_UNUSED(iconText);
6076#endif
6077}
6078
6079/*!
6080 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6081
6082 This signal is emitted when the window's icon text has changed, with the
6083 new \a iconText as an argument.
6084
6085 \since 5.2
6086 \deprecated
6087
6088 This signal is deprecated.
6089*/
6090
6091void QWidget::setWindowIconText(const QString &iconText)
6092{
6093 if (QWidget::windowIconText() == iconText)
6094 return;
6095
6096 Q_D(QWidget);
6097 d->topData()->iconText = iconText;
6098 d->setWindowIconText_helper(iconText);
6099
6100 QEvent e(QEvent::IconTextChange);
6101 QCoreApplication::sendEvent(receiver: this, event: &e);
6102
6103 emit windowIconTextChanged(iconText);
6104}
6105
6106/*!
6107 \fn void QWidget::windowTitleChanged(const QString &title)
6108
6109 This signal is emitted when the window's title has changed, with the
6110 new \a title as an argument.
6111
6112 \since 5.2
6113*/
6114
6115void QWidget::setWindowTitle(const QString &title)
6116{
6117 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6118 return;
6119
6120 Q_D(QWidget);
6121 d->topData()->caption = title;
6122 d->setWindowTitle_helper(title);
6123
6124 QEvent e(QEvent::WindowTitleChange);
6125 QCoreApplication::sendEvent(receiver: this, event: &e);
6126
6127 emit windowTitleChanged(title);
6128}
6129
6130
6131/*!
6132 \property QWidget::windowIcon
6133 \brief the widget's icon
6134
6135 This property only makes sense for windows. If no icon
6136 has been set, windowIcon() returns the application icon
6137 (QApplication::windowIcon()).
6138
6139 \note On \macos, window icons represent the active document,
6140 and will not be displayed unless a file path has also been
6141 set using setWindowFilePath.
6142
6143 \sa windowTitle, setWindowFilePath
6144*/
6145QIcon QWidget::windowIcon() const
6146{
6147 const QWidget *w = this;
6148 while (w) {
6149 const QWidgetPrivate *d = w->d_func();
6150 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6151 return *d->extra->topextra->icon;
6152 w = w->parentWidget();
6153 }
6154 return QApplication::windowIcon();
6155}
6156
6157void QWidgetPrivate::setWindowIcon_helper()
6158{
6159 Q_Q(QWidget);
6160 QEvent e(QEvent::WindowIconChange);
6161
6162 // Do not send the event if the widget is a top level.
6163 // In that case, setWindowIcon_sys does it, and event propagation from
6164 // QWidgetWindow to the top level QWidget ensures that the event reaches
6165 // the top level anyhow
6166 if (!q->windowHandle())
6167 QCoreApplication::sendEvent(receiver: q, event: &e);
6168 for (int i = 0; i < children.size(); ++i) {
6169 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
6170 if (w && !w->isWindow())
6171 QCoreApplication::sendEvent(receiver: w, event: &e);
6172 }
6173}
6174
6175/*!
6176 \fn void QWidget::windowIconChanged(const QIcon &icon)
6177
6178 This signal is emitted when the window's icon has changed, with the
6179 new \a icon as an argument.
6180
6181 \since 5.2
6182*/
6183
6184void QWidget::setWindowIcon(const QIcon &icon)
6185{
6186 Q_D(QWidget);
6187
6188 setAttribute(Qt::WA_SetWindowIcon, on: !icon.isNull());
6189 d->createTLExtra();
6190
6191 if (!d->extra->topextra->icon)
6192 d->extra->topextra->icon = std::make_unique<QIcon>(args: icon);
6193 else
6194 *d->extra->topextra->icon = icon;
6195
6196 d->setWindowIcon_sys();
6197 d->setWindowIcon_helper();
6198
6199 emit windowIconChanged(icon);
6200}
6201
6202void QWidgetPrivate::setWindowIcon_sys()
6203{
6204 Q_Q(QWidget);
6205 if (QWindow *window = q->windowHandle())
6206 window->setIcon(q->windowIcon());
6207}
6208
6209/*!
6210 \property QWidget::windowIconText
6211 \brief the text to be displayed on the icon of a minimized window
6212
6213 This property only makes sense for windows. If no icon
6214 text has been set, this accessor returns an empty string.
6215 It is only implemented on the X11 platform, and only certain
6216 window managers use this window property.
6217
6218 \deprecated
6219 This property is deprecated.
6220
6221 \sa windowIcon, windowTitle
6222*/
6223
6224QString QWidget::windowIconText() const
6225{
6226 Q_D(const QWidget);
6227 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6228}
6229
6230/*!
6231 \property QWidget::windowFilePath
6232 \since 4.4
6233 \brief the file path associated with a widget
6234
6235 This property only makes sense for windows. It associates a file path with
6236 a window. If you set the file path, but have not set the window title, Qt
6237 sets the window title to the file name of the specified path, obtained using
6238 QFileInfo::fileName().
6239
6240 If the window title is set at any point, then the window title takes precedence and
6241 will be shown instead of the file path string.
6242
6243 Additionally, on \macos, this has an added benefit that it sets the
6244 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6245 for the window, assuming that the file path exists.
6246
6247 If no file path is set, this property contains an empty string.
6248
6249 By default, this property contains an empty string.
6250
6251 \sa windowTitle, windowIcon
6252*/
6253
6254QString QWidget::windowFilePath() const
6255{
6256 Q_D(const QWidget);
6257 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6258}
6259
6260void QWidget::setWindowFilePath(const QString &filePath)
6261{
6262 if (filePath == windowFilePath())
6263 return;
6264
6265 Q_D(QWidget);
6266
6267 d->createTLExtra();
6268 d->extra->topextra->filePath = filePath;
6269 d->setWindowFilePath_helper(filePath);
6270}
6271
6272void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6273{
6274 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6275#ifdef Q_OS_MAC
6276 setWindowTitle_helper(QFileInfo(filePath).fileName());
6277#else
6278 Q_Q(QWidget);
6279 Q_UNUSED(filePath);
6280 setWindowTitle_helper(q->windowTitle());
6281#endif
6282 }
6283#ifdef Q_OS_MAC
6284 setWindowFilePath_sys(filePath);
6285#endif
6286}
6287
6288void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6289{
6290 Q_Q(QWidget);
6291 if (!q->isWindow())
6292 return;
6293
6294 if (QWindow *window = q->windowHandle())
6295 window->setFilePath(filePath);
6296}
6297
6298/*!
6299 Returns the window's role, or an empty string.
6300
6301 \sa windowIcon, windowTitle
6302*/
6303
6304QString QWidget::windowRole() const
6305{
6306 Q_D(const QWidget);
6307 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6308}
6309
6310/*!
6311 Sets the window's role to \a role. This only makes sense for
6312 windows on X11.
6313*/
6314void QWidget::setWindowRole(const QString &role)
6315{
6316#if QT_CONFIG(xcb)
6317 Q_D(QWidget);
6318 d->createTLExtra();
6319 d->topData()->role = role;
6320 if (windowHandle()) {
6321 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6322 xcbWindow->setWindowRole(role);
6323 }
6324#else
6325 Q_UNUSED(role);
6326#endif
6327}
6328
6329/*!
6330 \property QWidget::mouseTracking
6331 \brief whether mouse tracking is enabled for the widget
6332
6333 If mouse tracking is disabled (the default), the widget only
6334 receives mouse move events when at least one mouse button is
6335 pressed while the mouse is being moved.
6336
6337 If mouse tracking is enabled, the widget receives mouse move
6338 events even if no buttons are pressed.
6339
6340 \sa mouseMoveEvent()
6341*/
6342
6343/*!
6344 \property QWidget::tabletTracking
6345 \brief whether tablet tracking is enabled for the widget
6346 \since 5.9
6347
6348 If tablet tracking is disabled (the default), the widget only
6349 receives tablet move events when the stylus is in contact with
6350 the tablet, or at least one stylus button is pressed,
6351 while the stylus is being moved.
6352
6353 If tablet tracking is enabled, the widget receives tablet move
6354 events even while hovering in proximity. This is useful for
6355 monitoring position as well as the auxiliary properties such
6356 as rotation and tilt, and providing feedback in the UI.
6357
6358 \sa tabletEvent()
6359*/
6360
6361
6362/*!
6363 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6364 function resets this widget to have no focus proxy.
6365
6366 Some widgets can "have focus", but create a child widget, such as
6367 QLineEdit, to actually handle the focus. In this case, the widget
6368 can set the line edit to be its focus proxy.
6369
6370 setFocusProxy() sets the widget which will actually get focus when
6371 "this widget" gets it. If there is a focus proxy, setFocus() and
6372 hasFocus() operate on the focus proxy. If "this widget" is the focus
6373 widget, then setFocusProxy() moves focus to the new focus proxy.
6374
6375 \sa focusProxy()
6376*/
6377
6378void QWidget::setFocusProxy(QWidget * w)
6379{
6380 Q_D(QWidget);
6381 if (!w && !d->extra)
6382 return;
6383
6384 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6385 if (Q_UNLIKELY(fp == this)) {
6386 qWarning(msg: "QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6387 return;
6388 }
6389 }
6390
6391 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6392
6393 d->createExtra();
6394 d->extra->focus_proxy = w;
6395
6396 if (w && isAncestorOf(child: w)) {
6397 // If the focus proxy is a child of this (so this is a compound widget), then
6398 // we need to make sure that this widget is immediately in front of its own children
6399 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6400 // widgets that are positioned between this compound widget, and its proxy in
6401 // the focus chain.
6402 const QWidget *parentOfW = w->parentWidget();
6403 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6404 QWidget *firstChild = nullptr;
6405 const auto childList = children();
6406 for (QObject *child : childList) {
6407 if ((firstChild = qobject_cast<QWidget *>(o: child)))
6408 break;
6409 }
6410 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6411 QWidget *oldNext = d->focus_next;
6412 QWidget *oldPrev = d->focus_prev;
6413 oldNext->d_func()->focus_prev = oldPrev;
6414 oldPrev->d_func()->focus_next = oldNext;
6415
6416 oldPrev = firstChild->d_func()->focus_prev;
6417 d->focus_next = firstChild;
6418 d->focus_prev = oldPrev;
6419 oldPrev->d_func()->focus_next = this;
6420 firstChild->d_func()->focus_prev = this;
6421 } else if (w && w->isAncestorOf(child: this)) {
6422 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6423 // remove it from the chain and insert this into the focus chain after its parent
6424
6425 // is this the case already?
6426 QWidget *parentsNext = w->d_func()->focus_next;
6427 if (parentsNext == this) {
6428 // nothing to do.
6429 Q_ASSERT(d->focus_prev == w);
6430 } else {
6431 // Remove 'this' from the focus chain by making prev and next point directly to each other
6432 QWidget *myOldNext = d->focus_next;
6433 QWidget *myOldPrev = d->focus_prev;
6434 if (myOldNext && myOldPrev) {
6435 myOldNext->d_func()->focus_prev = myOldPrev;
6436 myOldPrev->d_func()->focus_next = myOldNext;
6437 }
6438
6439 // Insert 'this' behind the parent
6440 w->d_func()->focus_next = this;
6441 d->focus_prev = w;
6442 d->focus_next = parentsNext;
6443 parentsNext->d_func()->focus_prev = this;
6444 }
6445 }
6446
6447 if (moveFocusToProxy)
6448 setFocus(Qt::OtherFocusReason);
6449}
6450
6451
6452/*!
6453 Returns the focus proxy, or \nullptr if there is no focus proxy.
6454
6455 \sa setFocusProxy()
6456*/
6457
6458QWidget *QWidget::focusProxy() const
6459{
6460 Q_D(const QWidget);
6461 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6462}
6463
6464
6465/*!
6466 \property QWidget::focus
6467 \brief whether this widget (or its focus proxy) has the keyboard
6468 input focus
6469
6470 By default, this property is \c false.
6471
6472 \note Obtaining the value of this property for a widget is effectively equivalent
6473 to checking whether QApplication::focusWidget() refers to the widget.
6474
6475 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6476*/
6477bool QWidget::hasFocus() const
6478{
6479 const QWidget* w = this;
6480 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6481 w = w->d_func()->extra->focus_proxy;
6482#if QT_CONFIG(graphicsview)
6483 if (QWidget *window = w->window()) {
6484 const auto &e = window->d_func()->extra;
6485 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6486 return true;
6487 }
6488#endif // QT_CONFIG(graphicsview)
6489 return (QApplication::focusWidget() == w);
6490}
6491
6492/*!
6493 Gives the keyboard input focus to this widget (or its focus
6494 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6495 be passed into any focus event sent from this function, it is used
6496 to give an explanation of what caused the widget to get focus.
6497 If the window is not active, the widget will be given the focus when
6498 the window becomes active.
6499
6500 First, a focus about to change event is sent to the focus widget (if any) to
6501 tell it that it is about to lose the focus. Then focus is changed, a
6502 focus out event is sent to the previous focus item and a focus in event is sent
6503 to the new item to tell it that it just received the focus.
6504 (Nothing happens if the focus in and focus out widgets are the
6505 same.)
6506
6507 \note On embedded platforms, setFocus() will not cause an input panel
6508 to be opened by the input method. If you want this to happen, you
6509 have to send a QEvent::RequestSoftwareInputPanel event to the
6510 widget yourself.
6511
6512 setFocus() gives focus to a widget regardless of its focus policy,
6513 but does not clear any keyboard grab (see grabKeyboard()).
6514
6515 Be aware that if the widget is hidden, it will not accept focus
6516 until it is shown.
6517
6518 \warning If you call setFocus() in a function which may itself be
6519 called from focusOutEvent() or focusInEvent(), you may get an
6520 infinite recursion.
6521
6522 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6523 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6524 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6525*/
6526
6527void QWidget::setFocus(Qt::FocusReason reason)
6528{
6529 if (!isEnabled())
6530 return;
6531
6532 QWidget *f = d_func()->deepestFocusProxy();
6533 if (!f)
6534 f = this;
6535
6536 if (QApplication::focusWidget() == f)
6537 return;
6538
6539#if QT_CONFIG(graphicsview)
6540 QWidget *previousProxyFocus = nullptr;
6541 if (const auto &topData = window()->d_func()->extra) {
6542 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6543 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6544 if (previousProxyFocus && previousProxyFocus->focusProxy())
6545 previousProxyFocus = previousProxyFocus->focusProxy();
6546 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6547 return;
6548 }
6549 }
6550#endif
6551
6552#if QT_CONFIG(graphicsview)
6553 // Update proxy state
6554 if (const auto &topData = window()->d_func()->extra) {
6555 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6556 f->d_func()->updateFocusChild();
6557 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6558 topData->proxyWidget->setFocus(reason);
6559 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6560 }
6561 }
6562#endif
6563
6564 if (f->isActiveWindow()) {
6565 QWidget *prev = QApplicationPrivate::focus_widget;
6566 if (prev) {
6567 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6568 && prev->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
6569 QGuiApplication::inputMethod()->commit();
6570 }
6571
6572 if (reason != Qt::NoFocusReason) {
6573 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6574 QCoreApplication::sendEvent(receiver: prev, event: &focusAboutToChange);
6575 }
6576 }
6577
6578 f->d_func()->updateFocusChild();
6579
6580 QApplicationPrivate::setFocusWidget(focus: f, reason);
6581#if QT_CONFIG(accessibility)
6582 // menus update the focus manually and this would create bogus events
6583 if (!(f->inherits(classname: "QMenuBar") || f->inherits(classname: "QMenu") || f->inherits(classname: "QMenuItem")))
6584 {
6585 QAccessibleEvent event(f, QAccessible::Focus);
6586 QAccessible::updateAccessibility(event: &event);
6587 }
6588#endif
6589#if QT_CONFIG(graphicsview)
6590 if (const auto &topData = window()->d_func()->extra) {
6591 if (topData->proxyWidget) {
6592 if (previousProxyFocus && previousProxyFocus != f) {
6593 // Send event to self
6594 QFocusEvent event(QEvent::FocusOut, reason);
6595 QPointer<QWidget> that = previousProxyFocus;
6596 QCoreApplication::sendEvent(receiver: previousProxyFocus, event: &event);
6597 if (that)
6598 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6599 }
6600 if (!isHidden()) {
6601#if QT_CONFIG(graphicsview)
6602 // Update proxy state
6603 if (const auto &topData = window()->d_func()->extra)
6604 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6605 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6606#endif
6607 // Send event to self
6608 QFocusEvent event(QEvent::FocusIn, reason);
6609 QPointer<QWidget> that = f;
6610 QCoreApplication::sendEvent(receiver: f, event: &event);
6611 if (that)
6612 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6613 }
6614 }
6615 }
6616#endif
6617 } else {
6618 f->d_func()->updateFocusChild();
6619 }
6620}
6621
6622
6623/*!\internal
6624 * A focus proxy can have its own focus proxy, which can have its own
6625 * proxy, and so on. This helper function returns the widget that sits
6626 * at the bottom of the proxy chain, and therefore the one that should
6627 * normally get focus if this widget receives a focus request.
6628 */
6629QWidget *QWidgetPrivate::deepestFocusProxy() const
6630{
6631 Q_Q(const QWidget);
6632
6633 QWidget *focusProxy = q->focusProxy();
6634 if (!focusProxy)
6635 return nullptr;
6636
6637 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6638 focusProxy = nextFocusProxy;
6639
6640 return focusProxy;
6641}
6642
6643static inline bool isEmbedded(const QWindow *w)
6644{
6645 const auto platformWindow = w->handle();
6646 return platformWindow && platformWindow->isEmbedded();
6647}
6648
6649void QWidgetPrivate::setFocus_sys()
6650{
6651 Q_Q(QWidget);
6652 // Embedded native widget may have taken the focus; get it back to toplevel
6653 // if that is the case (QTBUG-25852)
6654 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6655 // unless the application is embedded (QTBUG-71991).
6656 if (QWindow *nativeWindow = q->testAttribute(attribute: Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6657 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6658 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6659 || QCoreApplication::testAttribute(attribute: Qt::AA_PluginApplication)
6660 || isEmbedded(w: nativeWindow))) {
6661 nativeWindow->requestActivate();
6662 }
6663 }
6664}
6665
6666// updates focus_child on parent widgets to point into this widget
6667void QWidgetPrivate::updateFocusChild()
6668{
6669 Q_Q(QWidget);
6670
6671 QWidget *w = q;
6672 if (q->isHidden()) {
6673 while (w && w->isHidden()) {
6674 w->d_func()->focus_child = q;
6675 w = w->isWindow() ? nullptr : w->parentWidget();
6676 }
6677 } else {
6678 while (w) {
6679 w->d_func()->focus_child = q;
6680 w = w->isWindow() ? nullptr : w->parentWidget();
6681 }
6682 }
6683
6684 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6685 if (extra->window)
6686 emit extra->window->focusObjectChanged(object: q);
6687 }
6688}
6689
6690/*!
6691 \fn void QWidget::setFocus()
6692 \overload
6693
6694 Gives the keyboard input focus to this widget (or its focus
6695 proxy) if this widget or one of its parents is the
6696 \l{isActiveWindow()}{active window}.
6697*/
6698
6699/*!
6700 Takes keyboard input focus from the widget.
6701
6702 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6703 lost the focus.
6704
6705 This widget must enable focus setting in order to get the keyboard
6706 input focus, i.e. it must call setFocusPolicy().
6707
6708 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6709 setFocusPolicy(), QApplication::focusWidget()
6710*/
6711
6712void QWidget::clearFocus()
6713{
6714 if (hasFocus()) {
6715 if (testAttribute(attribute: Qt::WA_InputMethodEnabled))
6716 QGuiApplication::inputMethod()->commit();
6717
6718 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6719 QCoreApplication::sendEvent(receiver: this, event: &focusAboutToChange);
6720 }
6721
6722 QTLWExtra *extra = window()->d_func()->maybeTopData();
6723 QObject *originalFocusObject = nullptr;
6724 if (extra && extra->window) {
6725 originalFocusObject = extra->window->focusObject();
6726 // the window's focus object might already be nullptr if we are in the destructor, but we still
6727 // need to update QGuiApplication and input context if we have a focus widget.
6728 if (!originalFocusObject)
6729 originalFocusObject = focusWidget();
6730 }
6731
6732 QWidget *w = this;
6733 while (w) {
6734 // Just like setFocus(), we update (clear) the focus_child of our parents
6735 if (w->d_func()->focus_child == this)
6736 w->d_func()->focus_child = nullptr;
6737 w = w->parentWidget();
6738 }
6739
6740 // We've potentially cleared the focus_child of our parents, so we need
6741 // to report this to the rest of Qt. Note that the focus_child is not the same
6742 // thing as the application's focusWidget, which is why this piece of code is
6743 // not inside a hasFocus() block.
6744 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6745 emit extra->window->focusObjectChanged(object: extra->window->focusObject());
6746
6747#if QT_CONFIG(graphicsview)
6748 const auto &topData = d_func()->extra;
6749 if (topData && topData->proxyWidget)
6750 topData->proxyWidget->clearFocus();
6751#endif
6752
6753 if (hasFocus()) {
6754 // Update proxy state
6755 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::OtherFocusReason);
6756#if QT_CONFIG(accessibility)
6757 QAccessibleEvent event(this, QAccessible::Focus);
6758 QAccessible::updateAccessibility(event: &event);
6759#endif
6760 }
6761}
6762
6763
6764/*!
6765 \fn bool QWidget::focusNextChild()
6766
6767 Finds a new widget to give the keyboard focus to, as appropriate
6768 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6769 false if it can't.
6770
6771 \sa focusPreviousChild()
6772*/
6773
6774/*!
6775 \fn bool QWidget::focusPreviousChild()
6776
6777 Finds a new widget to give the keyboard focus to, as appropriate
6778 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6779 or false if it can't.
6780
6781 \sa focusNextChild()
6782*/
6783
6784/*!
6785 Finds a new widget to give the keyboard focus to, as appropriate
6786 for Tab and Shift+Tab, and returns \c true if it can find a new
6787 widget, or false if it can't.
6788
6789 If \a next is true, this function searches forward, if \a next
6790 is false, it searches backward.
6791
6792 Sometimes, you will want to reimplement this function. For
6793 example, a web browser might reimplement it to move its "current
6794 active link" forward or backward, and call
6795 focusNextPrevChild() only when it reaches the last or
6796 first link on the "page".
6797
6798 Child widgets call focusNextPrevChild() on their parent widgets,
6799 but only the window that contains the child widgets decides where
6800 to redirect focus. By reimplementing this function for an object,
6801 you thus gain control of focus traversal for all child widgets.
6802
6803 \sa focusNextChild(), focusPreviousChild()
6804*/
6805
6806bool QWidget::focusNextPrevChild(bool next)
6807{
6808 QWidget* p = parentWidget();
6809 bool isSubWindow = (windowType() == Qt::SubWindow);
6810 if (!isWindow() && !isSubWindow && p)
6811 return p->focusNextPrevChild(next);
6812#if QT_CONFIG(graphicsview)
6813 Q_D(QWidget);
6814 if (d->extra && d->extra->proxyWidget)
6815 return d->extra->proxyWidget->focusNextPrevChild(next);
6816#endif
6817
6818 bool wrappingOccurred = false;
6819 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(toplevel: this, next,
6820 wrappingOccurred: &wrappingOccurred);
6821 if (!w) return false;
6822
6823 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6824
6825 /* If we are about to wrap the focus chain, give the platform
6826 * implementation a chance to alter the wrapping behavior. This is
6827 * especially needed when the window is embedded in a window created by
6828 * another process.
6829 */
6830 if (wrappingOccurred) {
6831 QWindow *window = windowHandle();
6832 if (window != nullptr) {
6833 QWindowPrivate *winp = qt_window_private(window);
6834
6835 if (winp->platformWindow != nullptr) {
6836 QFocusEvent event(QEvent::FocusIn, reason);
6837 event.ignore();
6838 winp->platformWindow->windowEvent(event: &event);
6839 if (event.isAccepted()) return true;
6840 }
6841 }
6842 }
6843
6844 w->setFocus(reason);
6845 return true;
6846}
6847
6848/*!
6849 Returns the last child of this widget that setFocus had been
6850 called on. For top level widgets this is the widget that will get
6851 focus in case this window gets activated
6852
6853 This is not the same as QApplication::focusWidget(), which returns
6854 the focus widget in the currently active window.
6855*/
6856
6857QWidget *QWidget::focusWidget() const
6858{
6859 return const_cast<QWidget *>(d_func()->focus_child);
6860}
6861
6862QObject *QWidgetPrivate::focusObject()
6863{
6864 Q_Q(QWidget);
6865 QWidget *proxy = deepestFocusProxy();
6866 return proxy ? proxy : q;
6867}
6868
6869/*!
6870 Returns the next widget in this widget's focus chain.
6871
6872 \sa previousInFocusChain()
6873*/
6874QWidget *QWidget::nextInFocusChain() const
6875{
6876 return const_cast<QWidget *>(d_func()->focus_next);
6877}
6878
6879/*!
6880 \brief The previousInFocusChain function returns the previous
6881 widget in this widget's focus chain.
6882
6883 \sa nextInFocusChain()
6884
6885 \since 4.6
6886*/
6887QWidget *QWidget::previousInFocusChain() const
6888{
6889 return const_cast<QWidget *>(d_func()->focus_prev);
6890}
6891
6892/*!
6893 \property QWidget::isActiveWindow
6894 \brief whether this widget's window is the active window
6895
6896 The active window is the window that contains the widget that has
6897 keyboard focus (The window may still have focus if it has no
6898 widgets or none of its widgets accepts keyboard focus).
6899
6900 When popup windows are visible, this property is \c true for both the
6901 active window \e and for the popup.
6902
6903 By default, this property is \c false.
6904
6905 \sa activateWindow(), QApplication::activeWindow()
6906*/
6907bool QWidget::isActiveWindow() const
6908{
6909 QWidget *tlw = window();
6910 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6911 return true;
6912
6913#if QT_CONFIG(graphicsview)
6914 if (const auto &tlwExtra = tlw->d_func()->extra) {
6915 if (isVisible() && tlwExtra->proxyWidget)
6916 return tlwExtra->proxyWidget->isActiveWindow();
6917 }
6918#endif
6919
6920 if (style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: this)) {
6921 if (tlw->windowType() == Qt::Tool &&
6922 !tlw->isModal() &&
6923 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6924 return true;
6925 QWidget *w = QApplication::activeWindow();
6926 while(w && tlw->windowType() == Qt::Tool &&
6927 !w->isModal() && w->parentWidget()) {
6928 w = w->parentWidget()->window();
6929 if (w == tlw)
6930 return true;
6931 }
6932 }
6933
6934 // Check for an active window container
6935 if (QWindow *ww = QGuiApplication::focusWindow()) {
6936 while (ww) {
6937 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(object: ww);
6938 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(object: qww->widget()) : 0;
6939 if (qwc && qwc->topLevelWidget() == tlw)
6940 return true;
6941 ww = ww->parent();
6942 }
6943 }
6944
6945 // Check if platform adaptation thinks the window is active. This is necessary for
6946 // example in case of ActiveQt servers that are embedded into another application.
6947 // Those are separate processes that are not part of the parent application Qt window/widget
6948 // hierarchy, so they need to rely on native methods to determine if they are part of the
6949 // active window.
6950 if (const QWindow *w = tlw->windowHandle()) {
6951 if (w->handle())
6952 return w->handle()->isActive();
6953 }
6954
6955 return false;
6956}
6957
6958/*!
6959 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6960 \overload
6961 \since 6.6
6962
6963 Sets the tab order for the widgets in the \a widgets list by calling
6964 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6965 pair of widgets.
6966
6967 Instead of setting up each pair manually like this:
6968
6969 \snippet code/src_gui_kernel_qwidget.cpp 9
6970
6971 you can call:
6972
6973 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6974
6975 The call does not create a closed tab focus loop. If there are more widgets
6976 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
6977 of those widgets, not back to \c{a}.
6978
6979 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6980*/
6981
6982/*!
6983 Puts the \a second widget after the \a first widget in the focus order.
6984
6985 It effectively removes the \a second widget from its focus chain and
6986 inserts it after the \a first widget.
6987
6988 Note that since the tab order of the \a second widget is changed, you
6989 should order a chain like this:
6990
6991 \snippet code/src_gui_kernel_qwidget.cpp 9
6992
6993 \e not like this:
6994
6995 \snippet code/src_gui_kernel_qwidget.cpp 10
6996
6997 If \a first or \a second has a focus proxy, setTabOrder()
6998 correctly substitutes the proxy.
6999
7000 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7001 a compound widget. When setting a tab order between one or two compound widgets, the
7002 local tab order inside each will be preserved. This means that if both widgets are
7003 compound widgets, the resulting tab order will be from the last child inside
7004 \a first, to the first child inside \a second.
7005
7006 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7007*/
7008void QWidget::setTabOrder(QWidget* first, QWidget *second)
7009{
7010 if (!first || !second || first == second
7011 || first->focusPolicy() == Qt::NoFocus
7012 || second->focusPolicy() == Qt::NoFocus)
7013 return;
7014
7015 if (Q_UNLIKELY(first->window() != second->window())) {
7016 qWarning(msg: "QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7017 return;
7018 }
7019
7020 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7021 {
7022 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7023 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7024 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7025 // 'lastFocusChild' will be set to the target itself.
7026 QWidget *lastFocusChild = target;
7027
7028 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7029 if (!focusProxy) {
7030 // QTBUG-81097: Another case is possible here. We can have a child
7031 // widget, that sets its focusProxy() to the parent (target).
7032 // An example of such widget is a QLineEdit, nested into
7033 // a QAbstractSpinBox. In this case such widget should be considered
7034 // the last focus child.
7035 for (auto *object : target->children()) {
7036 QWidget *w = qobject_cast<QWidget*>(o: object);
7037 if (w && w->focusProxy() == target) {
7038 lastFocusChild = w;
7039 break;
7040 }
7041 }
7042 } else if (target->isAncestorOf(child: focusProxy)) {
7043 lastFocusChild = focusProxy;
7044 for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
7045 focusNext != focusProxy && target->isAncestorOf(child: focusNext) && focusNext->window() == focusProxy->window();
7046 focusNext = focusNext->d_func()->focus_next) {
7047 if (focusNext == noFurtherThan)
7048 break;
7049 if (focusNext->focusPolicy() != Qt::NoFocus)
7050 lastFocusChild = focusNext;
7051 }
7052 }
7053 return lastFocusChild;
7054 };
7055 auto setPrev = [](QWidget *w, QWidget *prev) {
7056 w->d_func()->focus_prev = prev;
7057 };
7058 auto setNext = [](QWidget *w, QWidget *next) {
7059 w->d_func()->focus_next = next;
7060 };
7061
7062 // detect inflection in case we have compound widgets
7063 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7064 if (lastFocusChildOfFirst == second)
7065 lastFocusChildOfFirst = first;
7066 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7067 if (lastFocusChildOfSecond == first)
7068 lastFocusChildOfSecond = second;
7069
7070 // remove the second widget from the chain
7071 {
7072 QWidget *oldPrev = second->d_func()->focus_prev;
7073 QWidget *prevWithFocus = oldPrev;
7074 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7075 prevWithFocus = prevWithFocus->d_func()->focus_prev;
7076 // only widgets between first and second -> all is fine
7077 if (prevWithFocus == first)
7078 return;
7079 QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
7080 setPrev(oldNext, oldPrev);
7081 setNext(oldPrev, oldNext);
7082 }
7083
7084 // insert the second widget into the chain
7085 {
7086 QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
7087 setPrev(second, lastFocusChildOfFirst);
7088 setNext(lastFocusChildOfFirst, second);
7089 setPrev(oldNext, lastFocusChildOfSecond);
7090 setNext(lastFocusChildOfSecond, oldNext);
7091 }
7092}
7093
7094void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7095{
7096 QWidget *prev = nullptr;
7097 for (const auto &widget : widgets) {
7098 if (!prev) {
7099 prev = widget;
7100 } else {
7101 QWidget::setTabOrder(first: prev, second: widget);
7102 prev = widget;
7103 }
7104 }
7105}
7106
7107
7108/*!\internal
7109
7110 Moves the relevant subwidgets of this widget from the \a oldtlw's
7111 tab chain to that of the new parent, if there's anything to move and
7112 we're really moving
7113
7114 This function is called from QWidget::reparent() *after* the widget
7115 has been reparented.
7116
7117 \sa reparent()
7118*/
7119
7120void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7121{
7122 Q_Q(QWidget);
7123 if (oldtlw == q->window())
7124 return; // nothing to do
7125
7126 if (focus_child)
7127 focus_child->clearFocus();
7128
7129 // separate the focus chain into new (children of myself) and old (the rest)
7130 QWidget *firstOld = nullptr;
7131 //QWidget *firstNew = q; //invariant
7132 QWidget *o = nullptr; // last in the old list
7133 QWidget *n = q; // last in the new list
7134
7135 bool prevWasNew = true;
7136 QWidget *w = focus_next;
7137
7138 //Note: for efficiency, we do not maintain the list invariant inside the loop
7139 //we append items to the relevant list, and we optimize by not changing pointers
7140 //when subsequent items are going into the same list.
7141 while (w != q) {
7142 bool currentIsNew = q->isAncestorOf(child: w);
7143 if (currentIsNew) {
7144 if (!prevWasNew) {
7145 //prev was old -- append to new list
7146 n->d_func()->focus_next = w;
7147 w->d_func()->focus_prev = n;
7148 }
7149 n = w;
7150 } else {
7151 if (prevWasNew) {
7152 //prev was new -- append to old list, if there is one
7153 if (o) {
7154 o->d_func()->focus_next = w;
7155 w->d_func()->focus_prev = o;
7156 } else {
7157 // "create" the old list
7158 firstOld = w;
7159 }
7160 }
7161 o = w;
7162 }
7163 w = w->d_func()->focus_next;
7164 prevWasNew = currentIsNew;
7165 }
7166
7167 //repair the old list:
7168 if (firstOld) {
7169 o->d_func()->focus_next = firstOld;
7170 firstOld->d_func()->focus_prev = o;
7171 }
7172
7173 if (!q->isWindow()) {
7174 QWidget *topLevel = q->window();
7175 //insert new chain into toplevel's chain
7176
7177 QWidget *prev = topLevel->d_func()->focus_prev;
7178
7179 topLevel->d_func()->focus_prev = n;
7180 prev->d_func()->focus_next = q;
7181
7182 focus_prev = prev;
7183 n->d_func()->focus_next = topLevel;
7184 } else {
7185 //repair the new list
7186 n->d_func()->focus_next = q;
7187 focus_prev = n;
7188 }
7189
7190}
7191
7192/*!
7193 \property QWidget::frameSize
7194 \brief the size of the widget including any window frame
7195
7196 By default, this property contains a value that depends on the user's
7197 platform and screen geometry.
7198*/
7199QSize QWidget::frameSize() const
7200{
7201 Q_D(const QWidget);
7202 if (isWindow() && !(windowType() == Qt::Popup)) {
7203 QRect fs = d->frameStrut();
7204 return QSize(data->crect.width() + fs.left() + fs.right(),
7205 data->crect.height() + fs.top() + fs.bottom());
7206 }
7207 return data->crect.size();
7208}
7209
7210/*! \fn void QWidget::move(int x, int y)
7211
7212 \overload
7213
7214 This corresponds to move(QPoint(\a x, \a y)).
7215*/
7216
7217void QWidget::move(const QPoint &p)
7218{
7219 Q_D(QWidget);
7220 setAttribute(Qt::WA_Moved);
7221 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7222 if (isWindow())
7223 d->topData()->posIncludesFrame = false;
7224 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7225 p.y() + geometry().y() - QWidget::y(),
7226 width(), height(), true);
7227 d->setDirtyOpaqueRegion();
7228 } else {
7229 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7230 if (isWindow())
7231 d->topData()->posIncludesFrame = true;
7232 data->crect.moveTopLeft(p); // no frame yet
7233 setAttribute(Qt::WA_PendingMoveEvent);
7234 }
7235
7236 if (d->extra && d->extra->hasWindowContainer)
7237 QWindowContainer::parentWasMoved(parent: this);
7238}
7239
7240// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7241// unknown), that is, crect has a position including the frame.
7242// If we can determine the frame strut, fix that and clear the flag.
7243// FIXME: This does not play well with window states other than
7244// Qt::WindowNoState, as we depend on calling setGeometry() on the
7245// platform window after fixing up the position so that the new
7246// geometry is reflected in the platform window, but when the frame
7247// comes in after the window has been shown (e.g. maximized), we're
7248// not in a position to do that kind of fixup.
7249void QWidgetPrivate::fixPosIncludesFrame()
7250{
7251 Q_Q(QWidget);
7252 if (QTLWExtra *te = maybeTopData()) {
7253 if (te->posIncludesFrame) {
7254 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7255 // example, in QGraphicsProxyWidget).
7256 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
7257 te->posIncludesFrame = 0;
7258 } else {
7259 if (q->windowHandle() && q->windowHandle()->handle()) {
7260 updateFrameStrut();
7261 if (!q->data->fstrut_dirty) {
7262 data.crect.translate(dx: te->frameStrut.x(), dy: te->frameStrut.y());
7263 te->posIncludesFrame = 0;
7264 }
7265 } // windowHandle()
7266 } // !WA_DontShowOnScreen
7267 } // posIncludesFrame
7268 } // QTLWExtra
7269}
7270
7271/*! \fn void QWidget::resize(int w, int h)
7272 \overload
7273
7274 This corresponds to resize(QSize(\a w, \a h)).
7275*/
7276
7277void QWidget::resize(const QSize &s)
7278{
7279 Q_D(QWidget);
7280 setAttribute(Qt::WA_Resized);
7281 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7282 d->fixPosIncludesFrame();
7283 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7284 d->setDirtyOpaqueRegion();
7285 } else {
7286 const auto oldRect = data->crect;
7287 data->crect.setSize(s.boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7288 if (oldRect != data->crect)
7289 setAttribute(Qt::WA_PendingResizeEvent);
7290 }
7291}
7292
7293void QWidget::setGeometry(const QRect &r)
7294{
7295 Q_D(QWidget);
7296 setAttribute(Qt::WA_Resized);
7297 setAttribute(Qt::WA_Moved);
7298 if (isWindow())
7299 d->topData()->posIncludesFrame = 0;
7300 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7301 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7302 d->setDirtyOpaqueRegion();
7303 } else {
7304 const auto oldRect = data->crect;
7305 data->crect.setTopLeft(r.topLeft());
7306 data->crect.setSize(r.size().boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7307 if (oldRect != data->crect) {
7308 setAttribute(Qt::WA_PendingMoveEvent);
7309 setAttribute(Qt::WA_PendingResizeEvent);
7310 }
7311 }
7312
7313 if (d->extra && d->extra->hasWindowContainer)
7314 QWindowContainer::parentWasMoved(parent: this);
7315}
7316
7317void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7318{
7319 Q_Q(QWidget);
7320 if (extra) { // any size restrictions?
7321 w = qMin(a: w,b: extra->maxw);
7322 h = qMin(a: h,b: extra->maxh);
7323 w = qMax(a: w,b: extra->minw);
7324 h = qMax(a: h,b: extra->minh);
7325 }
7326
7327 if (q->isWindow() && q->windowHandle()) {
7328 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7329 if (!integration->hasCapability(cap: QPlatformIntegration::NonFullScreenWindows)) {
7330 x = 0;
7331 y = 0;
7332 w = q->windowHandle()->width();
7333 h = q->windowHandle()->height();
7334 }
7335 }
7336
7337 QPoint oldp = q->geometry().topLeft();
7338 QSize olds = q->size();
7339 QRect r(x, y, w, h);
7340
7341 bool isResize = olds != r.size();
7342 if (!isMove)
7343 isMove = oldp != r.topLeft();
7344
7345
7346 // We only care about stuff that changes the geometry, or may
7347 // cause the window manager to change its state
7348 if (r.size() == olds && oldp == r.topLeft())
7349 return;
7350
7351 if (!data.in_set_window_state) {
7352 q->data->window_state &= ~Qt::WindowMaximized;
7353 q->data->window_state &= ~Qt::WindowFullScreen;
7354 if (q->isWindow())
7355 topData()->normalGeometry = QRect(0, 0, -1, -1);
7356 }
7357
7358 QPoint oldPos = q->pos();
7359 data.crect = r;
7360
7361 bool needsShow = false;
7362
7363 if (q->isWindow() || q->windowHandle()) {
7364 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7365 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
7366 if (q->isVisible())
7367 hide_sys();
7368 data.crect = QRect(x, y, w, h);
7369 } else if (q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7370 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
7371 needsShow = true;
7372 }
7373 }
7374
7375 if (q->isVisible()) {
7376 if (!q->testAttribute(attribute: Qt::WA_DontShowOnScreen) && !q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7377 if (QWindow *win = q->windowHandle()) {
7378 if (q->isWindow()) {
7379 if (isResize && !isMove)
7380 win->resize(w, h);
7381 else if (isMove && !isResize)
7382 win->setPosition(posx: x, posy: y);
7383 else
7384 win->setGeometry(q->geometry());
7385 } else {
7386 QPoint posInNativeParent = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
7387 win->setGeometry(QRect(posInNativeParent,r.size()));
7388 }
7389
7390 if (needsShow)
7391 show_sys();
7392 }
7393
7394 if (!q->isWindow()) {
7395 if (renderToTexture) {
7396 QRegion updateRegion(q->geometry());
7397 updateRegion += QRect(oldPos, olds);
7398 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7399 } else if (isMove && !isResize) {
7400 moveRect(QRect(oldPos, olds), dx: x - oldPos.x(), dy: y - oldPos.y());
7401 } else {
7402 invalidateBackingStore_resizeHelper(oldPos, oldSize: olds);
7403 }
7404 }
7405 }
7406
7407 if (isMove) {
7408 QMoveEvent e(q->pos(), oldPos);
7409 QCoreApplication::sendEvent(receiver: q, event: &e);
7410 }
7411 if (isResize) {
7412 QResizeEvent e(r.size(), olds);
7413 QCoreApplication::sendEvent(receiver: q, event: &e);
7414 if (q->windowHandle())
7415 q->update();
7416 }
7417 } else { // not visible
7418 if (isMove && q->pos() != oldPos)
7419 q->setAttribute(Qt::WA_PendingMoveEvent, on: true);
7420 if (isResize)
7421 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7422 }
7423
7424}
7425
7426/*!
7427 \since 4.2
7428 Saves the current geometry and state for top-level widgets.
7429
7430 To save the geometry when the window closes, you can
7431 implement a close event like this:
7432
7433 \snippet code/src_gui_kernel_qwidget.cpp 11
7434
7435 See the \l{Window Geometry} documentation for an overview of geometry
7436 issues with windows.
7437
7438 Use QMainWindow::saveState() to save the geometry and the state of
7439 toolbars and dock widgets.
7440
7441 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7442*/
7443QByteArray QWidget::saveGeometry() const
7444{
7445 QByteArray array;
7446 QDataStream stream(&array, QIODevice::WriteOnly);
7447 stream.setVersion(QDataStream::Qt_4_0);
7448 const quint32 magicNumber = 0x1D9D0CB;
7449 // Version history:
7450 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7451 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7452 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7453 quint16 majorVersion = 3;
7454 quint16 minorVersion = 0;
7455 const int screenNumber = QGuiApplication::screens().indexOf(t: screen());
7456 stream << magicNumber
7457 << majorVersion
7458 << minorVersion
7459 << frameGeometry()
7460 << normalGeometry()
7461 << qint32(screenNumber)
7462 << quint8(windowState() & Qt::WindowMaximized)
7463 << quint8(windowState() & Qt::WindowFullScreen)
7464 << qint32(screen()->geometry().width()) // added in 2.0
7465 << geometry(); // added in 3.0
7466 return array;
7467}
7468
7469/*!
7470 \internal
7471
7472 Check a if \a restoredGeometry fits into \a availableGeometry
7473 This method is used to verify that a widget is restored to a geometry, which
7474 fits into the target screen.
7475
7476 \param frameHeight represents the height of the widget's title bar, which is expected
7477 to be on its top.
7478
7479 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7480 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7481 be full screen.
7482
7483 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7484 \a restoredGeometry will be moved
7485 \list
7486 \li down if its top is off screen
7487 \li up if its bottom is off screen
7488 \li right if its left edge is off screen
7489 \li left if its right edge is off screen
7490 \endlist
7491 */
7492void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7493 int frameHeight)
7494{
7495 // compare with restored geometry's height increased by frameHeight
7496 const int height = restoredGeometry->height() + frameHeight;
7497
7498 // Step 1: Resize if necessary:
7499 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7500 if (availableGeometry.height() <= height)
7501 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7502 if (availableGeometry.width() <= restoredGeometry->width())
7503 restoredGeometry->setWidth(availableGeometry.width() - 2);
7504
7505 // Step 2: Move if necessary:
7506 // Construct a rectangle from restored Geometry adjusted by frameHeight
7507 const QRect restored = restoredGeometry->adjusted(xp1: 0, yp1: -frameHeight, xp2: 0, yp2: 0);
7508
7509 // Return if restoredGeometry (including frame) fits into screen
7510 if (availableGeometry.contains(r: restored))
7511 return;
7512
7513 // (size is correct, but at least one edge is off screen)
7514
7515 // Top out of bounds => move down
7516 if (restored.top() <= availableGeometry.top()) {
7517 restoredGeometry->moveTop(pos: availableGeometry.top() + 1 + frameHeight);
7518 } else if (restored.bottom() >= availableGeometry.bottom()) {
7519 // Bottom out of bounds => move up
7520 restoredGeometry->moveBottom(pos: availableGeometry.bottom() - 1);
7521 }
7522
7523 // Left edge out of bounds => move right
7524 if (restored.left() <= availableGeometry.left()) {
7525 restoredGeometry->moveLeft(pos: availableGeometry.left() + 1);
7526 } else if (restored.right() >= availableGeometry.right()) {
7527 // Right edge out of bounds => move left
7528 restoredGeometry->moveRight(pos: availableGeometry.right() - 1);
7529 }
7530}
7531
7532/*!
7533 \since 4.2
7534
7535 Restores the geometry and state of top-level widgets stored in the
7536 byte array \a geometry. Returns \c true on success; otherwise
7537 returns \c false.
7538
7539 If the restored geometry is off-screen, it will be modified to be
7540 inside the available screen geometry.
7541
7542 To restore geometry saved using QSettings, you can use code like
7543 this:
7544
7545 \snippet code/src_gui_kernel_qwidget.cpp 12
7546
7547 See the \l{Window Geometry} documentation for an overview of geometry
7548 issues with windows.
7549
7550 Use QMainWindow::restoreState() to restore the geometry and the
7551 state of toolbars and dock widgets.
7552
7553 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7554*/
7555bool QWidget::restoreGeometry(const QByteArray &geometry)
7556{
7557 if (geometry.size() < 4)
7558 return false;
7559 QDataStream stream(geometry);
7560 stream.setVersion(QDataStream::Qt_4_0);
7561
7562 const quint32 magicNumber = 0x1D9D0CB;
7563 quint32 storedMagicNumber;
7564 stream >> storedMagicNumber;
7565 if (storedMagicNumber != magicNumber)
7566 return false;
7567
7568 const quint16 currentMajorVersion = 3;
7569 quint16 majorVersion = 0;
7570 quint16 minorVersion = 0;
7571
7572 stream >> majorVersion >> minorVersion;
7573
7574 if (majorVersion > currentMajorVersion)
7575 return false;
7576 // (Allow all minor versions.)
7577
7578 QRect restoredFrameGeometry;
7579 QRect restoredGeometry;
7580 QRect restoredNormalGeometry;
7581 qint32 restoredScreenNumber;
7582 quint8 maximized;
7583 quint8 fullScreen;
7584 qint32 restoredScreenWidth = 0;
7585
7586 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7587 >> restoredNormalGeometry
7588 >> restoredScreenNumber
7589 >> maximized
7590 >> fullScreen;
7591
7592 if (majorVersion > 1)
7593 stream >> restoredScreenWidth;
7594 if (majorVersion > 2)
7595 stream >> restoredGeometry;
7596
7597 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7598
7599 if (restoredScreenNumber >= qMax(a: QGuiApplication::screens().size(), b: 1))
7600 restoredScreenNumber = 0;
7601 const QScreen *restoredScreen = QGuiApplication::screens().value(i: restoredScreenNumber, defaultValue: nullptr);
7602 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7603 // Sanity check bailing out when large variations of screen sizes occur due to
7604 // high DPI scaling or different levels of DPI awareness.
7605 if (restoredScreenWidth) {
7606 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7607 if (factor < 0.8 || factor > 1.25)
7608 return false;
7609 } else {
7610 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7611 // unless the size will be adapted by maximized or fullscreen.
7612 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7613 return false;
7614 }
7615
7616 const int frameHeight = QApplication::style()
7617 ? QApplication::style()->pixelMetric(metric: QStyle::PM_TitleBarHeight)
7618 : 20;
7619
7620 if (!restoredNormalGeometry.isValid())
7621 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7622 if (!restoredNormalGeometry.isValid()) {
7623 // use the widget's adjustedSize if the sizeHint() doesn't help
7624 restoredNormalGeometry.setSize(restoredNormalGeometry
7625 .size()
7626 .expandedTo(otherSize: d_func()->adjustedSize()));
7627 }
7628
7629 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7630 : QRect();
7631
7632 // Modify the restored geometry if we are about to restore to coordinates
7633 // that would make the window "lost". This happens if:
7634 // - The restored geometry is completely or partly oustside the available geometry
7635 // - The title bar is outside the available geometry.
7636
7637 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredGeometry, frameHeight);
7638 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredNormalGeometry, frameHeight);
7639
7640 if (maximized || fullScreen) {
7641 // set geometry before setting the window state to make
7642 // sure the window is maximized to the right screen.
7643 Qt::WindowStates ws = windowState();
7644#ifndef Q_OS_WIN
7645 setGeometry(restoredNormalGeometry);
7646#else
7647 if (ws & Qt::WindowFullScreen) {
7648 // Full screen is not a real window state on Windows.
7649 move(availableGeometry.topLeft());
7650 } else if (ws & Qt::WindowMaximized) {
7651 // Setting a geometry on an already maximized window causes this to be
7652 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7653 // Move the window in normal state if needed.
7654 if (restoredScreen != screen()) {
7655 setWindowState(Qt::WindowNoState);
7656 setGeometry(restoredNormalGeometry);
7657 }
7658 } else {
7659 setGeometry(restoredNormalGeometry);
7660 }
7661#endif // Q_OS_WIN
7662 if (maximized)
7663 ws |= Qt::WindowMaximized;
7664 if (fullScreen)
7665 ws |= Qt::WindowFullScreen;
7666 setWindowState(ws);
7667 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7668 } else {
7669 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7670
7671 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7672 if (majorVersion > 2)
7673 setGeometry(restoredGeometry);
7674 else
7675 setGeometry(restoredNormalGeometry);
7676 }
7677 return true;
7678}
7679
7680/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7681 \overload
7682
7683 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7684*/
7685
7686/*!
7687 Sets the margins around the contents of the widget to have the sizes
7688 \a left, \a top, \a right, and \a bottom. The margins are used by
7689 the layout system, and may be used by subclasses to specify the area
7690 to draw in (e.g. excluding the frame).
7691
7692 Changing the margins will trigger a resizeEvent().
7693
7694 \sa contentsRect(), contentsMargins()
7695*/
7696void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7697{
7698 Q_D(QWidget);
7699 if (left == d->leftmargin && top == d->topmargin
7700 && right == d->rightmargin && bottom == d->bottommargin)
7701 return;
7702 d->leftmargin = left;
7703 d->topmargin = top;
7704 d->rightmargin = right;
7705 d->bottommargin = bottom;
7706
7707 d->updateContentsRect();
7708}
7709
7710/*!
7711 \overload
7712 \since 4.6
7713
7714 \brief The setContentsMargins function sets the margins around the
7715 widget's contents.
7716
7717 Sets the margins around the contents of the widget to have the
7718 sizes determined by \a margins. The margins are
7719 used by the layout system, and may be used by subclasses to
7720 specify the area to draw in (e.g. excluding the frame).
7721
7722 Changing the margins will trigger a resizeEvent().
7723
7724 \sa contentsRect(), contentsMargins()
7725*/
7726void QWidget::setContentsMargins(const QMargins &margins)
7727{
7728 setContentsMargins(left: margins.left(), top: margins.top(),
7729 right: margins.right(), bottom: margins.bottom());
7730}
7731
7732void QWidgetPrivate::updateContentsRect()
7733{
7734 Q_Q(QWidget);
7735
7736 if (layout)
7737 layout->update(); //force activate; will do updateGeometry
7738 else
7739 q->updateGeometry();
7740
7741 if (q->isVisible()) {
7742 q->update();
7743 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7744 QCoreApplication::sendEvent(receiver: q, event: &e);
7745 } else {
7746 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7747 }
7748
7749 QEvent e(QEvent::ContentsRectChange);
7750 QCoreApplication::sendEvent(receiver: q, event: &e);
7751}
7752
7753/*!
7754 \since 4.6
7755
7756 \brief The contentsMargins function returns the widget's contents margins.
7757
7758 \sa setContentsMargins(), contentsRect()
7759 */
7760QMargins QWidget::contentsMargins() const
7761{
7762 Q_D(const QWidget);
7763 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7764 return testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea) ?
7765 userMargins | d->safeAreaMargins() : userMargins;
7766}
7767
7768/*!
7769 Returns the area inside the widget's margins.
7770
7771 \sa setContentsMargins(), contentsMargins()
7772*/
7773QRect QWidget::contentsRect() const
7774{
7775 return rect() - contentsMargins();
7776}
7777
7778QMargins QWidgetPrivate::safeAreaMargins() const
7779{
7780 Q_Q(const QWidget);
7781 QWidget *nativeWidget = q->window();
7782 if (!nativeWidget->windowHandle())
7783 return QMargins();
7784
7785 QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7786 if (!platformWindow)
7787 return QMargins();
7788
7789 QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7790
7791 if (!q->isWindow()) {
7792 // In theory the native parent widget already has a contents rect reflecting
7793 // the safe area of that widget, but we can't be sure that the widget or child
7794 // widgets of that widget have respected the contents rect when setting their
7795 // geometry, so we need to manually compute the safe area.
7796
7797 // Unless the native widget doesn't have any margins, in which case there's
7798 // nothing for us to compute.
7799 if (safeAreaMargins.isNull())
7800 return QMargins();
7801
7802 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7803 // set, then we know that the layout has already taken care of placing us inside the
7804 // safe area, by taking the contents rect of its parent widget into account.
7805 const QWidget *assumedSafeWidget = nullptr;
7806 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7807 QWidget *parentWidget = w->parentWidget();
7808 if (parentWidget->testAttribute(attribute: Qt::WA_LayoutOnEntireRect))
7809 continue; // Layout not going to help us
7810
7811 QLayout *layout = parentWidget->layout();
7812 if (!layout)
7813 continue;
7814
7815 if (layout->geometry().isNull())
7816 continue; // Layout hasn't been activated yet
7817
7818 if (layout->indexOf(w) < 0)
7819 continue; // Widget is not in layout
7820
7821 assumedSafeWidget = w;
7822 break;
7823 }
7824
7825#if !defined(QT_DEBUG)
7826 if (assumedSafeWidget) {
7827 // We found a layout that we assume will take care of keeping us within the safe area
7828 // For debug builds we still map the safe area using the fallback logic, so that we
7829 // can detect any misbehaving layouts.
7830 return QMargins();
7831 }
7832#endif
7833
7834 // In all other cases we need to map the safe area of the native parent to the widget.
7835 // This depends on the widget being positioned and sized already, which means the initial
7836 // layout will be wrong, but the layout will then adjust itself.
7837 QPoint topLeftMargins = q->mapFrom(parent: nativeWidget, pos: QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7838 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7839 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(parent: nativeWidget,
7840 pos: nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7841
7842 // Margins should never be negative
7843 safeAreaMargins = QMargins(qMax(a: 0, b: topLeftMargins.x()), qMax(a: 0, b: topLeftMargins.y()),
7844 qMax(a: 0, b: bottomRightMargins.x()), qMax(a: 0, b: bottomRightMargins.y()));
7845
7846 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7847 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7848 qWarning() << layout << "is laying out" << assumedSafeWidget
7849 << "outside of the contents rect of" << layout->parentWidget();
7850 return QMargins(); // Return empty margin to visually highlight the error
7851 }
7852 }
7853
7854 return safeAreaMargins;
7855}
7856
7857/*!
7858 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7859
7860 This signal is emitted when the widget's \l contextMenuPolicy is
7861 Qt::CustomContextMenu, and the user has requested a context menu on
7862 the widget. The position \a pos is the position of the context menu
7863 event that the widget receives. Normally this is in widget
7864 coordinates. The exception to this rule is QAbstractScrollArea and
7865 its subclasses that map the context menu event to coordinates of the
7866 \l{QAbstractScrollArea::viewport()}{viewport()}.
7867
7868
7869 \sa mapToGlobal(), QMenu, contextMenuPolicy
7870*/
7871
7872
7873/*!
7874 \property QWidget::contextMenuPolicy
7875 \brief how the widget shows a context menu
7876
7877 The default value of this property is Qt::DefaultContextMenu,
7878 which means the contextMenuEvent() handler is called. Other values
7879 are Qt::NoContextMenu, Qt::PreventContextMenu,
7880 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7881 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7882 emitted.
7883
7884 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7885*/
7886
7887Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7888{
7889 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7890}
7891
7892void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7893{
7894 data->context_menu_policy = (uint) policy;
7895}
7896
7897/*!
7898 \property QWidget::focusPolicy
7899 \brief the way the widget accepts keyboard focus
7900
7901 The policy is Qt::TabFocus if the widget accepts keyboard
7902 focus by tabbing, Qt::ClickFocus if the widget accepts
7903 focus by clicking, Qt::StrongFocus if it accepts both, and
7904 Qt::NoFocus (the default) if it does not accept focus at
7905 all.
7906
7907 You must enable keyboard focus for a widget if it processes
7908 keyboard events. This is normally done from the widget's
7909 constructor. For instance, the QLineEdit constructor calls
7910 setFocusPolicy(Qt::StrongFocus).
7911
7912 If the widget has a focus proxy, then the focus policy will
7913 be propagated to it.
7914
7915 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7916*/
7917
7918
7919Qt::FocusPolicy QWidget::focusPolicy() const
7920{
7921 return (Qt::FocusPolicy)data->focus_policy;
7922}
7923
7924void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7925{
7926 data->focus_policy = (uint) policy;
7927 Q_D(QWidget);
7928 if (d->extra && d->extra->focus_proxy)
7929 d->extra->focus_proxy->setFocusPolicy(policy);
7930}
7931
7932/*!
7933 \property QWidget::updatesEnabled
7934 \brief whether updates are enabled
7935
7936 An updates enabled widget receives paint events and has a system
7937 background; a disabled widget does not. This also implies that
7938 calling update() and repaint() has no effect if updates are
7939 disabled.
7940
7941 By default, this property is \c true.
7942
7943 setUpdatesEnabled() is normally used to disable updates for a
7944 short period of time, for instance to avoid screen flicker during
7945 large changes. In Qt, widgets normally do not generate screen
7946 flicker, but on X11 the server might erase regions on the screen
7947 when widgets get hidden before they can be replaced by other
7948 widgets. Disabling updates solves this.
7949
7950 Example:
7951 \snippet code/src_gui_kernel_qwidget.cpp 13
7952
7953 Disabling a widget implicitly disables all its children. Enabling a widget
7954 enables all child widgets \e except top-level widgets or those that
7955 have been explicitly disabled. Re-enabling updates implicitly calls
7956 update() on the widget.
7957
7958 \sa paintEvent()
7959*/
7960void QWidget::setUpdatesEnabled(bool enable)
7961{
7962 Q_D(QWidget);
7963 setAttribute(Qt::WA_ForceUpdatesDisabled, on: !enable);
7964 d->setUpdatesEnabled_helper(enable);
7965}
7966
7967/*!
7968 Shows the widget and its child widgets.
7969
7970 This is equivalent to calling showFullScreen(), showMaximized(), or setVisible(true),
7971 depending on the platform's default behavior for the window flags.
7972
7973 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7974 showNormal(), isVisible(), windowFlags()
7975*/
7976void QWidget::show()
7977{
7978 Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
7979 if (defaultState == Qt::WindowFullScreen)
7980 showFullScreen();
7981 else if (defaultState == Qt::WindowMaximized)
7982 showMaximized();
7983 else
7984 setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7985}
7986
7987/*! \internal
7988
7989 Makes the widget visible in the isVisible() meaning of the word.
7990 It is only called for toplevels or widgets with visible parents.
7991 */
7992void QWidgetPrivate::show_recursive()
7993{
7994 Q_Q(QWidget);
7995 // polish if necessary
7996
7997 if (!q->testAttribute(attribute: Qt::WA_WState_Created))
7998 createRecursively();
7999 q->ensurePolished();
8000
8001 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
8002 q->parentWidget()->d_func()->layout->activate();
8003 // activate our layout before we and our children become visible
8004 if (layout)
8005 layout->activate();
8006
8007 show_helper();
8008}
8009
8010void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
8011{
8012 Q_Q(QWidget);
8013
8014 disableUpdates = disableUpdates && q->updatesEnabled();
8015 if (disableUpdates)
8016 q->setAttribute(Qt::WA_UpdatesDisabled);
8017
8018 if (q->testAttribute(attribute: Qt::WA_PendingMoveEvent)) {
8019 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
8020 QCoreApplication::sendEvent(receiver: q, event: &e);
8021 q->setAttribute(Qt::WA_PendingMoveEvent, on: false);
8022 }
8023
8024 if (q->testAttribute(attribute: Qt::WA_PendingResizeEvent)) {
8025 QResizeEvent e(data.crect.size(), QSize());
8026 QCoreApplication::sendEvent(receiver: q, event: &e);
8027 q->setAttribute(Qt::WA_PendingResizeEvent, on: false);
8028 }
8029
8030 if (disableUpdates)
8031 q->setAttribute(Qt::WA_UpdatesDisabled, on: false);
8032
8033 if (!recursive)
8034 return;
8035
8036 for (int i = 0; i < children.size(); ++i) {
8037 if (QWidget *child = qobject_cast<QWidget *>(o: children.at(i)))
8038 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8039 }
8040}
8041
8042void QWidgetPrivate::activateChildLayoutsRecursively()
8043{
8044 sendPendingMoveAndResizeEvents(recursive: false, disableUpdates: true);
8045
8046 for (int i = 0; i < children.size(); ++i) {
8047 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
8048 if (!child || child->isHidden() || child->isWindow())
8049 continue;
8050
8051 child->ensurePolished();
8052
8053 // Activate child's layout
8054 QWidgetPrivate *childPrivate = child->d_func();
8055 if (childPrivate->layout)
8056 childPrivate->layout->activate();
8057
8058 // Pretend we're visible.
8059 const bool wasVisible = child->isVisible();
8060 if (!wasVisible)
8061 child->setAttribute(Qt::WA_WState_Visible);
8062
8063 // Do the same for all my children.
8064 childPrivate->activateChildLayoutsRecursively();
8065
8066 // We're not cheating anymore.
8067 if (!wasVisible)
8068 child->setAttribute(Qt::WA_WState_Visible, on: false);
8069 }
8070}
8071
8072void QWidgetPrivate::show_helper()
8073{
8074 Q_Q(QWidget);
8075 data.in_show = true; // qws optimization
8076 // make sure we receive pending move and resize events
8077 sendPendingMoveAndResizeEvents();
8078
8079 // become visible before showing all children
8080 q->setAttribute(Qt::WA_WState_Visible);
8081
8082 // finally show all children recursively
8083 showChildren(spontaneous: false);
8084
8085
8086
8087 const bool isWindow = q->isWindow();
8088#if QT_CONFIG(graphicsview)
8089 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8090#else
8091 bool isEmbedded = false;
8092#endif
8093
8094 // popup handling: new popups and tools need to be raised, and
8095 // existing popups must be closed. Also propagate the current
8096 // windows's KeyboardFocusChange status.
8097 if (isWindow && !isEmbedded) {
8098 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8099 q->raise();
8100 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(attribute: Qt::WA_KeyboardFocusChange))
8101 q->setAttribute(Qt::WA_KeyboardFocusChange);
8102 } else {
8103 while (QApplication::activePopupWidget()) {
8104 if (!QApplication::activePopupWidget()->close())
8105 break;
8106 }
8107 }
8108 }
8109
8110 // Automatic embedding of child windows of widgets already embedded into
8111 // QGraphicsProxyWidget when they are shown the first time.
8112#if QT_CONFIG(graphicsview)
8113 if (isWindow) {
8114 if (!isEmbedded && !bypassGraphicsProxyWidget(p: q)) {
8115 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(origin: q->parentWidget());
8116 if (ancestorProxy) {
8117 isEmbedded = true;
8118 ancestorProxy->d_func()->embedSubWindow(q);
8119 }
8120 }
8121 }
8122#else
8123 Q_UNUSED(isEmbedded);
8124#endif
8125
8126 // send the show event before showing the window
8127 QShowEvent showEvent;
8128 QCoreApplication::sendEvent(receiver: q, event: &showEvent);
8129
8130 show_sys();
8131
8132 if (!isEmbedded && q->windowType() == Qt::Popup)
8133 qApp->d_func()->openPopup(popup: q);
8134
8135#if QT_CONFIG(accessibility)
8136 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8137 QAccessibleEvent event(q, QAccessible::ObjectShow);
8138 QAccessible::updateAccessibility(event: &event);
8139 }
8140#endif
8141
8142 if (QApplicationPrivate::hidden_focus_widget == q) {
8143 QApplicationPrivate::hidden_focus_widget = nullptr;
8144 q->setFocus(Qt::OtherFocusReason);
8145 }
8146
8147 // Process events when showing a Qt::SplashScreen widget before the event loop
8148 // is spinnning; otherwise it might not show up on particular platforms.
8149 // This makes QSplashScreen behave the same on all platforms.
8150 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8151 QCoreApplication::processEvents();
8152
8153 data.in_show = false; // reset qws optimization
8154}
8155
8156void QWidgetPrivate::show_sys()
8157{
8158 Q_Q(QWidget);
8159
8160 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8161
8162 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8163 invalidateBackingStore(q->rect());
8164 q->setAttribute(Qt::WA_Mapped);
8165 // add our window the modal window list (native dialogs)
8166 if (window && q->isWindow()
8167#if QT_CONFIG(graphicsview)
8168 && (!extra || !extra->proxyWidget)
8169#endif
8170 && q->windowModality() != Qt::NonModal) {
8171 QGuiApplicationPrivate::showModalWindow(window);
8172 }
8173 return;
8174 }
8175
8176 if (renderToTexture && !q->isWindow())
8177 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QUpdateLaterEvent(q->geometry()));
8178 else
8179 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(q->rect()));
8180
8181 if ((!q->isWindow() && !q->testAttribute(attribute: Qt::WA_NativeWindow))
8182 || q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
8183 return;
8184 }
8185
8186 if (window) {
8187 if (q->isWindow())
8188 fixPosIncludesFrame();
8189 QRect geomRect = q->geometry();
8190 if (!q->isWindow()) {
8191 QPoint topLeftOfWindow = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
8192 geomRect.moveTopLeft(p: topLeftOfWindow);
8193 }
8194 const QRect windowRect = window->geometry();
8195 if (windowRect != geomRect) {
8196 if (q->testAttribute(attribute: Qt::WA_Moved)
8197 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
8198 window->setGeometry(geomRect);
8199 else
8200 window->resize(newSize: geomRect.size());
8201 }
8202
8203#ifndef QT_NO_CURSOR
8204 qt_qpa_set_cursor(w: q, force: false); // Needed in case cursor was set before show
8205#endif
8206 invalidateBackingStore(q->rect());
8207 window->setNativeWindowVisibility(true);
8208 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8209 if (window->isTopLevel()) {
8210 const QPoint crectTopLeft = q->data->crect.topLeft();
8211 const QPoint windowTopLeft = window->geometry().topLeft();
8212 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8213 q->data->crect.moveTopLeft(p: windowTopLeft);
8214 }
8215 }
8216}
8217
8218/*!
8219 Hides the widget. This function is equivalent to
8220 setVisible(false).
8221
8222
8223 \note If you are working with QDialog or its subclasses and you invoke
8224 the show() function after this function, the dialog will be displayed in
8225 its original position.
8226
8227 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8228*/
8229void QWidget::hide()
8230{
8231 setVisible(false);
8232}
8233
8234/*!\internal
8235 */
8236void QWidgetPrivate::hide_helper()
8237{
8238 Q_Q(QWidget);
8239
8240 bool isEmbedded = false;
8241#if QT_CONFIG(graphicsview)
8242 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(p: q) && nearestGraphicsProxyWidget(origin: q->parentWidget()) != nullptr;
8243#else
8244 Q_UNUSED(isEmbedded);
8245#endif
8246
8247 if (!isEmbedded && (q->windowType() == Qt::Popup))
8248 qApp->d_func()->closePopup(popup: q);
8249
8250 q->setAttribute(Qt::WA_Mapped, on: false);
8251 hide_sys();
8252
8253 bool wasVisible = q->testAttribute(attribute: Qt::WA_WState_Visible);
8254
8255 if (wasVisible) {
8256 q->setAttribute(Qt::WA_WState_Visible, on: false);
8257
8258 }
8259
8260 QHideEvent hideEvent;
8261 QCoreApplication::sendEvent(receiver: q, event: &hideEvent);
8262 hideChildren(spontaneous: false);
8263
8264 // next bit tries to move the focus if the focus widget is now
8265 // hidden.
8266 if (wasVisible) {
8267 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8268 QWidget *fw = QApplication::focusWidget();
8269 while (fw && !fw->isWindow()) {
8270 if (fw == q) {
8271 q->focusNextPrevChild(next: true);
8272 break;
8273 }
8274 fw = fw->parentWidget();
8275 }
8276 }
8277
8278 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8279 repaintManager->removeDirtyWidget(w: q);
8280
8281#if QT_CONFIG(accessibility)
8282 if (wasVisible) {
8283 QAccessibleEvent event(q, QAccessible::ObjectHide);
8284 QAccessible::updateAccessibility(event: &event);
8285 }
8286#endif
8287}
8288
8289void QWidgetPrivate::hide_sys()
8290{
8291 Q_Q(QWidget);
8292
8293 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8294
8295 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8296 q->setAttribute(Qt::WA_Mapped, on: false);
8297 // remove our window from the modal window list (native dialogs)
8298 if (window && q->isWindow()
8299#if QT_CONFIG(graphicsview)
8300 && (!extra || !extra->proxyWidget)
8301#endif
8302 && q->windowModality() != Qt::NonModal) {
8303 QGuiApplicationPrivate::hideModalWindow(window);
8304 }
8305 // do not return here, if window non-zero, we must hide it
8306 }
8307
8308 deactivateWidgetCleanup();
8309
8310 if (!q->isWindow()) {
8311 QWidget *p = q->parentWidget();
8312 if (p &&p->isVisible()) {
8313 if (renderToTexture)
8314 p->d_func()->invalidateBackingStore(q->geometry());
8315 else
8316 invalidateBackingStore(q->rect());
8317 }
8318 } else {
8319 invalidateBackingStore(q->rect());
8320 }
8321
8322 if (window)
8323 window->setNativeWindowVisibility(false);
8324}
8325
8326/*!
8327 \fn bool QWidget::isHidden() const
8328
8329 Returns \c true if the widget is hidden, otherwise returns \c false.
8330
8331 A hidden widget will only become visible when show() is called on
8332 it. It will not be automatically shown when the parent is shown.
8333
8334 To check visibility, use !isVisible() instead (notice the exclamation mark).
8335
8336 isHidden() implies !isVisible(), but a widget can be not visible
8337 and not hidden at the same time. This is the case for widgets that are children of
8338 widgets that are not visible.
8339
8340
8341 Widgets are hidden if:
8342 \list
8343 \li they were created as independent windows,
8344 \li they were created as children of visible widgets,
8345 \li hide() or setVisible(false) was called.
8346 \endlist
8347*/
8348
8349void QWidget::setVisible(bool visible)
8350{
8351 if (testAttribute(attribute: Qt::WA_WState_ExplicitShowHide) && testAttribute(attribute: Qt::WA_WState_Hidden) == !visible)
8352 return;
8353
8354 // Remember that setVisible was called explicitly
8355 setAttribute(Qt::WA_WState_ExplicitShowHide);
8356
8357 Q_D(QWidget);
8358 d->setVisible(visible);
8359}
8360
8361// This method is called from QWidgetWindow in response to QWindow::setVisible,
8362// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8363// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8364void QWidgetPrivate::setVisible(bool visible)
8365{
8366 Q_Q(QWidget);
8367 if (visible) { // show
8368 // Designer uses a trick to make grabWidget work without showing
8369 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8370 && !q->parentWidget()->testAttribute(attribute: Qt::WA_WState_Created))
8371 q->parentWidget()->window()->d_func()->createRecursively();
8372
8373 //create toplevels but not children of non-visible parents
8374 QWidget *pw = q->parentWidget();
8375 if (!q->testAttribute(attribute: Qt::WA_WState_Created)
8376 && (q->isWindow() || pw->testAttribute(attribute: Qt::WA_WState_Created))) {
8377 q->create();
8378 }
8379
8380 bool wasResized = q->testAttribute(attribute: Qt::WA_Resized);
8381 Qt::WindowStates initialWindowState = q->windowState();
8382
8383 // polish if necessary
8384 q->ensurePolished();
8385
8386 // whether we need to inform the parent widget immediately
8387 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(attribute: Qt::WA_WState_Hidden);
8388 // we are no longer hidden
8389 q->setAttribute(Qt::WA_WState_Hidden, on: false);
8390
8391 if (needUpdateGeometry)
8392 updateGeometry_helper(forceUpdate: true);
8393
8394 // activate our layout before we and our children become visible
8395 if (layout)
8396 layout->activate();
8397
8398 if (!q->isWindow()) {
8399 QWidget *parent = q->parentWidget();
8400 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8401 parent->d_func()->layout->activate();
8402 if (parent->isWindow())
8403 break;
8404 parent = parent->parentWidget();
8405 }
8406 if (parent)
8407 parent->d_func()->setDirtyOpaqueRegion();
8408 }
8409
8410 // adjust size if necessary
8411 if (!wasResized
8412 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8413 if (q->isWindow()) {
8414 q->adjustSize();
8415 if (q->windowState() != initialWindowState)
8416 q->setWindowState(initialWindowState);
8417 } else {
8418 q->adjustSize();
8419 }
8420 q->setAttribute(Qt::WA_Resized, on: false);
8421 }
8422
8423 q->setAttribute(Qt::WA_KeyboardFocusChange, on: false);
8424
8425 if (q->isWindow() || q->parentWidget()->isVisible()) {
8426 show_helper();
8427
8428 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8429 }
8430
8431 QEvent showToParentEvent(QEvent::ShowToParent);
8432 QCoreApplication::sendEvent(receiver: q, event: &showToParentEvent);
8433 } else { // hide
8434 if (QApplicationPrivate::hidden_focus_widget == q)
8435 QApplicationPrivate::hidden_focus_widget = nullptr;
8436
8437 // hw: The test on getOpaqueRegion() needs to be more intelligent
8438 // currently it doesn't work if the widget is hidden (the region will
8439 // be clipped). The real check should be testing the cached region
8440 // (and dirty flag) directly.
8441 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8442 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8443
8444 if (!q->testAttribute(attribute: Qt::WA_WState_Hidden)) {
8445 q->setAttribute(Qt::WA_WState_Hidden);
8446 if (q->testAttribute(attribute: Qt::WA_WState_Created))
8447 hide_helper();
8448 }
8449
8450 // invalidate layout similar to updateGeometry()
8451 if (!q->isWindow() && q->parentWidget()) {
8452 if (q->parentWidget()->d_func()->layout)
8453 q->parentWidget()->d_func()->layout->invalidate();
8454 else if (q->parentWidget()->isVisible())
8455 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QEvent(QEvent::LayoutRequest));
8456 }
8457
8458 QEvent hideToParentEvent(QEvent::HideToParent);
8459 QCoreApplication::sendEvent(receiver: q, event: &hideToParentEvent);
8460 }
8461}
8462
8463/*!
8464 Convenience function, equivalent to setVisible(!\a hidden).
8465*/
8466void QWidget::setHidden(bool hidden)
8467{
8468 setVisible(!hidden);
8469}
8470
8471void QWidgetPrivate::_q_showIfNotHidden()
8472{
8473 Q_Q(QWidget);
8474 if ( !(q->isHidden() && q->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide)) )
8475 q->setVisible(true);
8476}
8477
8478void QWidgetPrivate::showChildren(bool spontaneous)
8479{
8480 QList<QObject*> childList = children;
8481 for (int i = 0; i < childList.size(); ++i) {
8482 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8483 if (widget && widget->windowHandle() && !widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
8484 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
8485 if (!widget
8486 || widget->isWindow()
8487 || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8488 continue;
8489 if (spontaneous) {
8490 widget->setAttribute(Qt::WA_Mapped);
8491 widget->d_func()->showChildren(spontaneous: true);
8492 QShowEvent e;
8493 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8494 } else {
8495 if (widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
8496 widget->d_func()->show_recursive();
8497 else
8498 widget->show();
8499 }
8500 }
8501}
8502
8503void QWidgetPrivate::hideChildren(bool spontaneous)
8504{
8505 Q_Q(QWidget);
8506 QList<QObject*> childList = children;
8507 for (int i = 0; i < childList.size(); ++i) {
8508 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8509 if (!widget || widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8510 continue;
8511
8512 if (spontaneous)
8513 widget->setAttribute(Qt::WA_Mapped, on: false);
8514 else
8515 widget->setAttribute(Qt::WA_WState_Visible, on: false);
8516 widget->d_func()->hideChildren(spontaneous);
8517 QHideEvent e;
8518 if (spontaneous) {
8519 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8520 } else {
8521 QCoreApplication::sendEvent(receiver: widget, event: &e);
8522 if (widget->internalWinId()
8523 && widget->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
8524 // hide_sys() on an ancestor won't have any affect on this
8525 // widget, so it needs an explicit hide_sys() of its own
8526 widget->d_func()->hide_sys();
8527 }
8528 }
8529 qApp->d_func()->sendSyntheticEnterLeave(widget);
8530#if QT_CONFIG(accessibility)
8531 if (!spontaneous) {
8532 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8533 QAccessible::updateAccessibility(event: &event);
8534 }
8535#endif
8536 }
8537
8538 // If the window of this widget is not closed, then the leave event
8539 // will eventually handle the widget under mouse use case.
8540 // Otherwise, we need to explicitly handle it here.
8541 if (QWidget* widgetWindow = q->window();
8542 widgetWindow && widgetWindow->data->is_closing) {
8543 q->setAttribute(Qt::WA_UnderMouse, on: false);
8544 }
8545}
8546
8547/*!
8548 \internal
8549
8550 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8551 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8552 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8553 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8554 system (i.e. the user clicked the close button in the title bar).
8555
8556 QDialog calls this method directly in its hide() implementation, which might be
8557 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8558 to prevent recursion.
8559
8560 For non-windows, this is called directly by QWidget::close, and \a mode will be
8561 CloseWithEvent.
8562
8563 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8564*/
8565bool QWidgetPrivate::handleClose(CloseMode mode)
8566{
8567 if (data.is_closing)
8568 return true;
8569
8570 // We might not have initiated the close, so update the state now that we know
8571 data.is_closing = true;
8572
8573 Q_Q(QWidget);
8574 QPointer<QWidget> that = q;
8575
8576 if (data.in_destructor)
8577 mode = CloseNoEvent;
8578
8579 if (mode != CloseNoEvent) {
8580 QCloseEvent e;
8581 if (mode == CloseWithSpontaneousEvent)
8582 QApplication::sendSpontaneousEvent(receiver: q, event: &e);
8583 else
8584 QCoreApplication::sendEvent(receiver: q, event: &e);
8585 if (!that.isNull() && !e.isAccepted()) {
8586 data.is_closing = false;
8587 return false;
8588 }
8589 }
8590
8591 // even for windows, make sure we deliver a hide event and that all children get hidden
8592 if (!that.isNull() && !q->isHidden())
8593 q->hide();
8594
8595 if (!that.isNull()) {
8596 data.is_closing = false;
8597 if (q->testAttribute(attribute: Qt::WA_DeleteOnClose)) {
8598 q->setAttribute(Qt::WA_DeleteOnClose, on: false);
8599 q->deleteLater();
8600 }
8601 }
8602 return true;
8603}
8604
8605
8606/*!
8607 Closes this widget. Returns \c true if the widget was closed;
8608 otherwise returns \c false.
8609
8610 First it sends the widget a QCloseEvent. The widget is
8611 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8612 the close event. If it \l{QEvent::ignore()}{ignores}
8613 the event, nothing happens. The default
8614 implementation of QWidget::closeEvent() accepts the close event.
8615
8616 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8617 is also deleted. A close events is delivered to the widget no
8618 matter if the widget is visible or not.
8619
8620 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8621 last visible primary window (i.e. window with no parent) with the
8622 Qt::WA_QuitOnClose attribute set is closed. By default this
8623 attribute is set for all widgets except transient windows such as
8624 splash screens, tool windows, and popup menus.
8625
8626*/
8627
8628bool QWidget::close()
8629{
8630 return d_func()->close();
8631}
8632
8633bool QWidgetPrivate::close()
8634{
8635 // FIXME: We're not setting is_closing here, even though that would
8636 // make sense, as the code below will not end up in handleClose to
8637 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8638 // and we can't assume close is synchronous so we can't reset it here.
8639
8640 // Close native widgets via QWindow::close() in order to run QWindow
8641 // close code. The QWidget-specific close code in handleClose() will
8642 // in this case be called from the Close event handler in QWidgetWindow.
8643 if (QWindow *widgetWindow = windowHandle()) {
8644 if (widgetWindow->isTopLevel())
8645 return widgetWindow->close();
8646 }
8647
8648 return handleClose(mode: QWidgetPrivate::CloseWithEvent);
8649}
8650
8651/*!
8652 \property QWidget::visible
8653 \brief whether the widget is visible
8654
8655 Calling setVisible(true) or show() sets the widget to visible
8656 status if all its parent widgets up to the window are visible. If
8657 an ancestor is not visible, the widget won't become visible until
8658 all its ancestors are shown. If its size or position has changed,
8659 Qt guarantees that a widget gets move and resize events just
8660 before it is shown. If the widget has not been resized yet, Qt
8661 will adjust the widget's size to a useful default using
8662 adjustSize().
8663
8664 Calling setVisible(false) or hide() hides a widget explicitly. An
8665 explicitly hidden widget will never become visible, even if all
8666 its ancestors become visible, unless you show it.
8667
8668 A widget receives show and hide events when its visibility status
8669 changes. Between a hide and a show event, there is no need to
8670 waste CPU cycles preparing or displaying information to the user.
8671 A video application, for example, might simply stop generating new
8672 frames.
8673
8674 A widget that happens to be obscured by other windows on the
8675 screen is considered to be visible. The same applies to iconified
8676 windows and windows that exist on another virtual
8677 desktop (on platforms that support this concept). A widget
8678 receives spontaneous show and hide events when its mapping status
8679 is changed by the window system, e.g. a spontaneous hide event
8680 when the user minimizes the window, and a spontaneous show event
8681 when the window is restored again.
8682
8683 You almost never have to reimplement the setVisible() function. If
8684 you need to change some settings before a widget is shown, use
8685 showEvent() instead. If you need to do some delayed initialization
8686 use the Polish event delivered to the event() function.
8687
8688 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8689 showEvent(), hideEvent()
8690*/
8691
8692
8693/*!
8694 Returns \c true if this widget would become visible if \a ancestor is
8695 shown; otherwise returns \c false.
8696
8697 The true case occurs if neither the widget itself nor any parent
8698 up to but excluding \a ancestor has been explicitly hidden.
8699
8700 This function will still return true if the widget is obscured by
8701 other windows on the screen, but could be physically visible if it
8702 or they were to be moved.
8703
8704 isVisibleTo(0) is identical to isVisible().
8705
8706 \sa show(), hide(), isVisible()
8707*/
8708
8709bool QWidget::isVisibleTo(const QWidget *ancestor) const
8710{
8711 if (!ancestor)
8712 return isVisible();
8713 const QWidget * w = this;
8714 while (!w->isHidden()
8715 && !w->isWindow()
8716 && w->parentWidget()
8717 && w->parentWidget() != ancestor)
8718 w = w->parentWidget();
8719 return !w->isHidden();
8720}
8721
8722
8723/*!
8724 Returns the unobscured region where paint events can occur.
8725
8726 For visible widgets, this is an approximation of the area not
8727 covered by other widgets; otherwise, this is an empty region.
8728
8729 The repaint() function calls this function if necessary, so in
8730 general you do not need to call it.
8731
8732*/
8733QRegion QWidget::visibleRegion() const
8734{
8735 Q_D(const QWidget);
8736
8737 QRect clipRect = d->clipRect();
8738 if (clipRect.isEmpty())
8739 return QRegion();
8740 QRegion r(clipRect);
8741 d->subtractOpaqueChildren(source&: r, clipRect);
8742 d->subtractOpaqueSiblings(sourceRegion&: r);
8743 return r;
8744}
8745
8746
8747QSize QWidgetPrivate::adjustedSize() const
8748{
8749 Q_Q(const QWidget);
8750
8751 QSize s = q->sizeHint();
8752
8753 if (q->isWindow()) {
8754 Qt::Orientations exp;
8755 if (layout) {
8756 if (layout->hasHeightForWidth())
8757 s.setHeight(layout->totalHeightForWidth(w: s.width()));
8758 exp = layout->expandingDirections();
8759 } else
8760 {
8761 if (q->sizePolicy().hasHeightForWidth())
8762 s.setHeight(q->heightForWidth(s.width()));
8763 exp = q->sizePolicy().expandingDirections();
8764 }
8765 if (exp & Qt::Horizontal)
8766 s.setWidth(qMax(a: s.width(), b: 200));
8767 if (exp & Qt::Vertical)
8768 s.setHeight(qMax(a: s.height(), b: 100));
8769
8770 QRect screen;
8771 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(point: q->pos()))
8772 screen = screenAtPoint->geometry();
8773 else
8774 screen = QGuiApplication::primaryScreen()->geometry();
8775
8776 s.setWidth(qMin(a: s.width(), b: screen.width()*2/3));
8777 s.setHeight(qMin(a: s.height(), b: screen.height()*2/3));
8778
8779 if (QTLWExtra *extra = maybeTopData())
8780 extra->sizeAdjusted = true;
8781 }
8782
8783 if (!s.isValid()) {
8784 QRect r = q->childrenRect(); // get children rectangle
8785 if (r.isNull())
8786 return s;
8787 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8788 }
8789
8790 return s;
8791}
8792
8793/*!
8794 Adjusts the size of the widget to fit its contents.
8795
8796 This function uses sizeHint() if it is valid, i.e., the size hint's width
8797 and height are \>= 0. Otherwise, it sets the size to the children
8798 rectangle that covers all child widgets (the union of all child widget
8799 rectangles).
8800
8801 For windows, the screen size is also taken into account. If the sizeHint()
8802 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8803 {expanding}, the window will be at least (200, 100). The maximum size of
8804 a window is 2/3 of the screen's width and height.
8805
8806 \sa sizeHint(), childrenRect()
8807*/
8808
8809void QWidget::adjustSize()
8810{
8811 Q_D(QWidget);
8812 ensurePolished();
8813 QSize s = d->adjustedSize();
8814
8815 if (d->layout)
8816 d->layout->activate();
8817
8818 if (s.isValid())
8819 resize(s);
8820}
8821
8822
8823/*!
8824 \property QWidget::sizeHint
8825 \brief the recommended size for the widget
8826
8827 If the value of this property is an invalid size, no size is
8828 recommended.
8829
8830 The default implementation of sizeHint() returns an invalid size
8831 if there is no layout for this widget, and returns the layout's
8832 preferred size otherwise.
8833
8834 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8835 setMinimumSize(), updateGeometry()
8836*/
8837
8838QSize QWidget::sizeHint() const
8839{
8840 Q_D(const QWidget);
8841 if (d->layout)
8842 return d->layout->totalSizeHint();
8843 return QSize(-1, -1);
8844}
8845
8846/*!
8847 \property QWidget::minimumSizeHint
8848 \brief the recommended minimum size for the widget
8849
8850 If the value of this property is an invalid size, no minimum size
8851 is recommended.
8852
8853 The default implementation of minimumSizeHint() returns an invalid
8854 size if there is no layout for this widget, and returns the
8855 layout's minimum size otherwise. Most built-in widgets reimplement
8856 minimumSizeHint().
8857
8858 \l QLayout will never resize a widget to a size smaller than the
8859 minimum size hint unless minimumSize() is set or the size policy is
8860 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8861 size hint will be ignored.
8862
8863 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8864*/
8865QSize QWidget::minimumSizeHint() const
8866{
8867 Q_D(const QWidget);
8868 if (d->layout)
8869 return d->layout->totalMinimumSize();
8870 return QSize(-1, -1);
8871}
8872
8873
8874/*!
8875 \fn QWidget *QWidget::parentWidget() const
8876
8877 Returns the parent of this widget, or \nullptr if it does not have any
8878 parent widget.
8879*/
8880
8881
8882/*!
8883 Returns \c true if this widget is a parent, (or grandparent and so on
8884 to any level), of the given \a child, and both widgets are within
8885 the same window; otherwise returns \c false.
8886*/
8887
8888bool QWidget::isAncestorOf(const QWidget *child) const
8889{
8890 while (child) {
8891 if (child == this)
8892 return true;
8893 if (child->isWindow())
8894 return false;
8895 child = child->parentWidget();
8896 }
8897 return false;
8898}
8899
8900/*****************************************************************************
8901 QWidget event handling
8902 *****************************************************************************/
8903
8904/*!
8905 This is the main event handler; it handles event \a event. You can
8906 reimplement this function in a subclass, but we recommend using
8907 one of the specialized event handlers instead.
8908
8909 Key press and release events are treated differently from other
8910 events. event() checks for Tab and Shift+Tab and tries to move the
8911 focus appropriately. If there is no widget to move the focus to
8912 (or the key press is not Tab or Shift+Tab), event() calls
8913 keyPressEvent().
8914
8915 Mouse and tablet event handling is also slightly special: only
8916 when the widget is \l enabled, event() will call the specialized
8917 handlers such as mousePressEvent(); otherwise it will discard the
8918 event.
8919
8920 This function returns \c true if the event was recognized, otherwise
8921 it returns \c false. If the recognized event was accepted (see \l
8922 QEvent::accepted), any further processing such as event
8923 propagation to the parent widget stops.
8924
8925 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8926 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8927 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8928 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8929 QObject::event(), QObject::timerEvent()
8930*/
8931
8932bool QWidget::event(QEvent *event)
8933{
8934 Q_D(QWidget);
8935
8936 // ignore mouse and key events when disabled
8937 if (!isEnabled()) {
8938 switch(event->type()) {
8939 case QEvent::TabletPress:
8940 case QEvent::TabletRelease:
8941 case QEvent::TabletMove:
8942 case QEvent::MouseButtonPress:
8943 case QEvent::MouseButtonRelease:
8944 case QEvent::MouseButtonDblClick:
8945 case QEvent::MouseMove:
8946 case QEvent::TouchBegin:
8947 case QEvent::TouchUpdate:
8948 case QEvent::TouchEnd:
8949 case QEvent::TouchCancel:
8950 case QEvent::ContextMenu:
8951 case QEvent::KeyPress:
8952 case QEvent::KeyRelease:
8953#if QT_CONFIG(wheelevent)
8954 case QEvent::Wheel:
8955#endif
8956 return false;
8957 default:
8958 break;
8959 }
8960 }
8961 switch (event->type()) {
8962 case QEvent::PlatformSurface: {
8963 // Sync up QWidget's view of whether or not the widget has been created
8964 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8965 case QPlatformSurfaceEvent::SurfaceCreated:
8966 if (!testAttribute(attribute: Qt::WA_WState_Created))
8967 create();
8968 break;
8969 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8970 if (testAttribute(attribute: Qt::WA_WState_Created)) {
8971 // Child windows have already been destroyed by QWindow,
8972 // so we skip them here.
8973 destroy(destroyWindow: false, destroySubWindows: false);
8974 }
8975 break;
8976 }
8977 break;
8978 }
8979 case QEvent::MouseMove:
8980 mouseMoveEvent(event: (QMouseEvent*)event);
8981 break;
8982
8983 case QEvent::MouseButtonPress:
8984 mousePressEvent(event: (QMouseEvent*)event);
8985 break;
8986
8987 case QEvent::MouseButtonRelease:
8988 mouseReleaseEvent(event: (QMouseEvent*)event);
8989 break;
8990
8991 case QEvent::MouseButtonDblClick:
8992 mouseDoubleClickEvent(event: (QMouseEvent*)event);
8993 break;
8994#if QT_CONFIG(wheelevent)
8995 case QEvent::Wheel:
8996 wheelEvent(event: (QWheelEvent*)event);
8997 break;
8998#endif
8999#if QT_CONFIG(tabletevent)
9000 case QEvent::TabletMove:
9001 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(attribute: Qt::WA_TabletTracking))
9002 break;
9003 Q_FALLTHROUGH();
9004 case QEvent::TabletPress:
9005 case QEvent::TabletRelease:
9006 tabletEvent(event: (QTabletEvent*)event);
9007 break;
9008#endif
9009 case QEvent::KeyPress: {
9010 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9011 bool res = false;
9012 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9013 if (k->key() == Qt::Key_Backtab
9014 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9015 res = focusNextPrevChild(next: false);
9016 else if (k->key() == Qt::Key_Tab)
9017 res = focusNextPrevChild(next: true);
9018 if (res)
9019 break;
9020 }
9021 keyPressEvent(event: k);
9022#ifdef QT_KEYPAD_NAVIGATION
9023 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9024 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9025 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9026 if (k->key() == Qt::Key_Up)
9027 res = focusNextPrevChild(false);
9028 else if (k->key() == Qt::Key_Down)
9029 res = focusNextPrevChild(true);
9030 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9031 if (k->key() == Qt::Key_Up)
9032 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9033 else if (k->key() == Qt::Key_Right)
9034 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9035 else if (k->key() == Qt::Key_Down)
9036 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9037 else if (k->key() == Qt::Key_Left)
9038 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9039 }
9040 if (res) {
9041 k->accept();
9042 break;
9043 }
9044 }
9045#endif
9046#if QT_CONFIG(whatsthis)
9047 if (!k->isAccepted()
9048 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9049 && d->whatsThis.size()) {
9050 QWhatsThis::showText(pos: mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), text: d->whatsThis, w: this);
9051 k->accept();
9052 }
9053#endif
9054 }
9055 break;
9056
9057 case QEvent::KeyRelease:
9058 keyReleaseEvent(event: (QKeyEvent*)event);
9059 Q_FALLTHROUGH();
9060 case QEvent::ShortcutOverride:
9061 break;
9062
9063 case QEvent::InputMethod:
9064 inputMethodEvent((QInputMethodEvent *) event);
9065 break;
9066
9067 case QEvent::InputMethodQuery: {
9068 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9069 Qt::InputMethodQueries queries = query->queries();
9070 for (uint i = 0; i < 32; ++i) {
9071 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9072 if (q) {
9073 QVariant v = inputMethodQuery(q);
9074 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9075 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9076 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9077 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9078 // will only be set if the widget supports IM _and_ is not read-only. So for
9079 // read-only widgets, not all IM features will be supported when ImEnabled is
9080 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9081 v = QVariant(testAttribute(attribute: Qt::WA_InputMethodEnabled));
9082 }
9083 query->setValue(query: q, value: v);
9084 }
9085 }
9086 query->accept();
9087 }
9088 break;
9089
9090 case QEvent::PolishRequest:
9091 ensurePolished();
9092 break;
9093
9094 case QEvent::Polish: {
9095 style()->polish(widget: this);
9096 setAttribute(Qt::WA_WState_Polished);
9097 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9098 d->resolveFont();
9099 if (!QApplication::palette(this).isCopyOf(p: QGuiApplication::palette()))
9100 d->resolvePalette();
9101 }
9102 break;
9103
9104 case QEvent::ApplicationWindowIconChange:
9105 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon)) {
9106 d->setWindowIcon_sys();
9107 d->setWindowIcon_helper();
9108 }
9109 break;
9110 case QEvent::FocusIn:
9111 focusInEvent(event: (QFocusEvent*)event);
9112 d->updateWidgetTransform(event);
9113 break;
9114
9115 case QEvent::FocusOut:
9116 focusOutEvent(event: (QFocusEvent*)event);
9117 break;
9118
9119 case QEvent::Enter:
9120#if QT_CONFIG(statustip)
9121 if (d->statusTip.size()) {
9122 QStatusTipEvent tip(d->statusTip);
9123 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9124 }
9125#endif
9126 enterEvent(event: static_cast<QEnterEvent*>(event));
9127 break;
9128
9129 case QEvent::Leave:
9130#if QT_CONFIG(statustip)
9131 if (d->statusTip.size()) {
9132 QString empty;
9133 QStatusTipEvent tip(empty);
9134 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9135 }
9136#endif
9137 leaveEvent(event);
9138 break;
9139
9140 case QEvent::HoverEnter:
9141 case QEvent::HoverLeave:
9142 update();
9143 break;
9144
9145 case QEvent::Paint:
9146 // At this point the event has to be delivered, regardless
9147 // whether the widget isVisible() or not because it
9148 // already went through the filters
9149 paintEvent(event: (QPaintEvent*)event);
9150 break;
9151
9152 case QEvent::Move:
9153 moveEvent(event: (QMoveEvent*)event);
9154 d->updateWidgetTransform(event);
9155 break;
9156
9157 case QEvent::Resize:
9158 resizeEvent(event: (QResizeEvent*)event);
9159 d->updateWidgetTransform(event);
9160 break;
9161
9162 case QEvent::Close:
9163 closeEvent(event: (QCloseEvent *)event);
9164 break;
9165
9166#ifndef QT_NO_CONTEXTMENU
9167 case QEvent::ContextMenu:
9168 switch (data->context_menu_policy) {
9169 case Qt::PreventContextMenu:
9170 break;
9171 case Qt::DefaultContextMenu:
9172 contextMenuEvent(event: static_cast<QContextMenuEvent *>(event));
9173 break;
9174 case Qt::CustomContextMenu:
9175 emit customContextMenuRequested(pos: static_cast<QContextMenuEvent *>(event)->pos());
9176 break;
9177#if QT_CONFIG(menu)
9178 case Qt::ActionsContextMenu:
9179 if (d->actions.size()) {
9180 QMenu::exec(actions: d->actions, pos: static_cast<QContextMenuEvent *>(event)->globalPos(),
9181 at: nullptr, parent: this);
9182 break;
9183 }
9184 Q_FALLTHROUGH();
9185#endif
9186 default:
9187 event->ignore();
9188 break;
9189 }
9190 break;
9191#endif // QT_NO_CONTEXTMENU
9192
9193#if QT_CONFIG(draganddrop)
9194 case QEvent::Drop:
9195 dropEvent(event: (QDropEvent*) event);
9196 break;
9197
9198 case QEvent::DragEnter:
9199 dragEnterEvent(event: (QDragEnterEvent*) event);
9200 break;
9201
9202 case QEvent::DragMove:
9203 dragMoveEvent(event: (QDragMoveEvent*) event);
9204 break;
9205
9206 case QEvent::DragLeave:
9207 dragLeaveEvent(event: (QDragLeaveEvent*) event);
9208 break;
9209#endif
9210
9211 case QEvent::Show:
9212 showEvent(event: (QShowEvent*) event);
9213 break;
9214
9215 case QEvent::Hide:
9216 hideEvent(event: (QHideEvent*) event);
9217 break;
9218
9219 case QEvent::ShowWindowRequest:
9220 if (!isHidden())
9221 d->show_sys();
9222 break;
9223
9224 case QEvent::ApplicationFontChange:
9225 d->resolveFont();
9226 break;
9227 case QEvent::ApplicationPaletteChange:
9228 if (!(windowType() == Qt::Desktop))
9229 d->resolvePalette();
9230 break;
9231
9232 case QEvent::ToolBarChange:
9233 case QEvent::ActivationChange:
9234 case QEvent::EnabledChange:
9235 case QEvent::FontChange:
9236 case QEvent::StyleChange:
9237 case QEvent::PaletteChange:
9238 case QEvent::WindowTitleChange:
9239 case QEvent::IconTextChange:
9240 case QEvent::ModifiedChange:
9241 case QEvent::MouseTrackingChange:
9242 case QEvent::TabletTrackingChange:
9243 case QEvent::ParentChange:
9244 case QEvent::LocaleChange:
9245 case QEvent::MacSizeChange:
9246 case QEvent::ContentsRectChange:
9247 case QEvent::ThemeChange:
9248 case QEvent::ReadOnlyChange:
9249 changeEvent(event);
9250 break;
9251
9252 case QEvent::WindowStateChange: {
9253 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9254 if (wasMinimized != isMinimized()) {
9255 QWidget *widget = const_cast<QWidget *>(this);
9256 if (wasMinimized) {
9257 // Always send the spontaneous events here, otherwise it can break the application!
9258 if (!d->childrenShownByExpose) {
9259 // Show widgets only when they are not yet shown by the expose event
9260 d->showChildren(spontaneous: true);
9261 QShowEvent showEvent;
9262 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &showEvent);
9263 }
9264 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9265 } else {
9266 QHideEvent hideEvent;
9267 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &hideEvent);
9268 d->hideChildren(spontaneous: true);
9269 d->childrenHiddenByWState = true;
9270 }
9271 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9272 }
9273 changeEvent(event);
9274 }
9275 break;
9276
9277 case QEvent::WindowActivate:
9278 case QEvent::WindowDeactivate: {
9279 if (isVisible() && !palette().isEqual(cr1: QPalette::Active, cr2: QPalette::Inactive))
9280 update();
9281 QList<QObject*> childList = d->children;
9282 for (int i = 0; i < childList.size(); ++i) {
9283 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9284 if (w && w->isVisible() && !w->isWindow())
9285 QCoreApplication::sendEvent(receiver: w, event);
9286 }
9287 break; }
9288
9289 case QEvent::LanguageChange:
9290 changeEvent(event);
9291 {
9292 QList<QObject*> childList = d->children;
9293 for (int i = 0; i < childList.size(); ++i) {
9294 QObject *o = childList.at(i);
9295 if (o)
9296 QCoreApplication::sendEvent(receiver: o, event);
9297 }
9298 }
9299 update();
9300 break;
9301
9302 case QEvent::ApplicationLayoutDirectionChange:
9303 d->resolveLayoutDirection();
9304 break;
9305
9306 case QEvent::LayoutDirectionChange:
9307 if (d->layout)
9308 d->layout->invalidate();
9309 update();
9310 changeEvent(event);
9311 break;
9312 case QEvent::UpdateRequest:
9313 d->syncBackingStore();
9314 break;
9315 case QEvent::UpdateLater:
9316 update(static_cast<QUpdateLaterEvent*>(event)->region());
9317 break;
9318 case QEvent::StyleAnimationUpdate:
9319 if (isVisible() && !window()->isMinimized()) {
9320 event->accept();
9321 update();
9322 }
9323 break;
9324
9325 case QEvent::WindowBlocked:
9326 case QEvent::WindowUnblocked:
9327 if (!d->children.isEmpty()) {
9328 QWidget *modalWidget = QApplication::activeModalWidget();
9329 for (int i = 0; i < d->children.size(); ++i) {
9330 QObject *o = d->children.at(i);
9331 if (o && o != modalWidget && o->isWidgetType()) {
9332 QWidget *w = static_cast<QWidget *>(o);
9333 // do not forward the event to child windows; QApplication does this for us
9334 if (!w->isWindow())
9335 QCoreApplication::sendEvent(receiver: w, event);
9336 }
9337 }
9338 }
9339 break;
9340#if QT_CONFIG(tooltip)
9341 case QEvent::ToolTip:
9342 if (!d->toolTip.isEmpty())
9343 QToolTip::showText(pos: static_cast<QHelpEvent*>(event)->globalPos(), text: d->toolTip, w: this, rect: QRect(), msecShowTime: d->toolTipDuration);
9344 else
9345 event->ignore();
9346 break;
9347#endif
9348#if QT_CONFIG(whatsthis)
9349 case QEvent::WhatsThis:
9350 if (d->whatsThis.size())
9351 QWhatsThis::showText(pos: static_cast<QHelpEvent *>(event)->globalPos(), text: d->whatsThis, w: this);
9352 else
9353 event->ignore();
9354 break;
9355 case QEvent::QueryWhatsThis:
9356 if (d->whatsThis.isEmpty())
9357 event->ignore();
9358 break;
9359#endif
9360 case QEvent::EmbeddingControl:
9361 d->topData()->frameStrut.setCoords(xp1: 0 ,yp1: 0, xp2: 0, yp2: 0);
9362 data->fstrut_dirty = false;
9363 break;
9364#ifndef QT_NO_ACTION
9365 case QEvent::ActionAdded:
9366 case QEvent::ActionRemoved:
9367 case QEvent::ActionChanged:
9368 actionEvent(event: (QActionEvent*)event);
9369 break;
9370#endif
9371
9372 case QEvent::KeyboardLayoutChange:
9373 {
9374 changeEvent(event);
9375
9376 // inform children of the change
9377 QList<QObject*> childList = d->children;
9378 for (int i = 0; i < childList.size(); ++i) {
9379 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9380 if (w && w->isVisible() && !w->isWindow())
9381 QCoreApplication::sendEvent(receiver: w, event);
9382 }
9383 break;
9384 }
9385 case QEvent::TouchBegin:
9386 case QEvent::TouchUpdate:
9387 case QEvent::TouchEnd:
9388 case QEvent::TouchCancel:
9389 {
9390 event->ignore();
9391 break;
9392 }
9393#ifndef QT_NO_GESTURES
9394 case QEvent::Gesture:
9395 event->ignore();
9396 break;
9397#endif
9398 case QEvent::ScreenChangeInternal:
9399 if (const QTLWExtra *te = d->maybeTopData()) {
9400 const QWindow *win = te->window;
9401 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9402 }
9403 break;
9404 case QEvent::DevicePixelRatioChange:
9405 if (d->data.fnt.d->dpi != logicalDpiY())
9406 d->updateFont(font: d->data.fnt);
9407 d->renderToTextureReallyDirty = 1;
9408 break;
9409 case QEvent::DynamicPropertyChange: {
9410 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9411 if (propName.size() == 13 && !qstrncmp(str1: propName, str2: "_q_customDpi", len: 12)) {
9412 uint value = property(name: propName.constData()).toUInt();
9413 if (!d->extra)
9414 d->createExtra();
9415 const char axis = propName.at(i: 12);
9416 if (axis == 'X')
9417 d->extra->customDpiX = value;
9418 else if (axis == 'Y')
9419 d->extra->customDpiY = value;
9420 d->updateFont(font: d->data.fnt);
9421 }
9422 if (windowHandle() && !qstrncmp(str1: propName, str2: "_q_platform_", len: 12))
9423 windowHandle()->setProperty(name: propName, value: property(name: propName));
9424 Q_FALLTHROUGH();
9425 }
9426 default:
9427 return QObject::event(event);
9428 }
9429 return true;
9430}
9431
9432/*!
9433 This event handler can be reimplemented to handle state changes.
9434
9435 The state being changed in this event can be retrieved through the \a event
9436 supplied.
9437
9438 Change events include: QEvent::ToolBarChange,
9439 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9440 QEvent::StyleChange, QEvent::PaletteChange,
9441 QEvent::WindowTitleChange, QEvent::IconTextChange,
9442 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9443 QEvent::ParentChange, QEvent::WindowStateChange,
9444 QEvent::LanguageChange, QEvent::LocaleChange,
9445 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9446
9447*/
9448void QWidget::changeEvent(QEvent * event)
9449{
9450 switch(event->type()) {
9451 case QEvent::EnabledChange: {
9452 update();
9453#if QT_CONFIG(accessibility)
9454 QAccessible::State s;
9455 s.disabled = true;
9456 QAccessibleStateChangeEvent event(this, s);
9457 QAccessible::updateAccessibility(event: &event);
9458#endif
9459 break;
9460 }
9461
9462 case QEvent::FontChange:
9463 case QEvent::StyleChange: {
9464 Q_D(QWidget);
9465 update();
9466 updateGeometry();
9467 if (d->layout)
9468 d->layout->invalidate();
9469 break;
9470 }
9471
9472 case QEvent::PaletteChange:
9473 update();
9474 break;
9475
9476 case QEvent::ThemeChange:
9477 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9478 && qApp && !QCoreApplication::closingDown()) {
9479 if (testAttribute(attribute: Qt::WA_WState_Polished))
9480 QApplication::style()->unpolish(widget: this);
9481 if (testAttribute(attribute: Qt::WA_WState_Polished))
9482 QApplication::style()->polish(widget: this);
9483 QEvent styleChangedEvent(QEvent::StyleChange);
9484 QCoreApplication::sendEvent(receiver: this, event: &styleChangedEvent);
9485 if (isVisible())
9486 update();
9487 }
9488 break;
9489
9490#ifdef Q_OS_MAC
9491 case QEvent::MacSizeChange:
9492 updateGeometry();
9493 break;
9494#endif
9495
9496 default:
9497 break;
9498 }
9499}
9500
9501/*!
9502 This event handler, for event \a event, can be reimplemented in a
9503 subclass to receive mouse move events for the widget.
9504
9505 If mouse tracking is switched off, mouse move events only occur if
9506 a mouse button is pressed while the mouse is being moved. If mouse
9507 tracking is switched on, mouse move events occur even if no mouse
9508 button is pressed.
9509
9510 QMouseEvent::pos() reports the position of the mouse cursor,
9511 relative to this widget. For press and release events, the
9512 position is usually the same as the position of the last mouse
9513 move event, but it might be different if the user's hand shakes.
9514 This is a feature of the underlying window system, not Qt.
9515
9516 If you want to show a tooltip immediately, while the mouse is
9517 moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9518 and show them as a tooltip), you must first enable mouse tracking
9519 as described above. Then, to ensure that the tooltip is updated
9520 immediately, you must call QToolTip::showText() instead of
9521 setToolTip() in your implementation of mouseMoveEvent().
9522
9523 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9524 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9525*/
9526
9527void QWidget::mouseMoveEvent(QMouseEvent *event)
9528{
9529 event->ignore();
9530}
9531
9532/*!
9533 This event handler, for event \a event, can be reimplemented in a
9534 subclass to receive mouse press events for the widget.
9535
9536 If you create new widgets in the mousePressEvent() the
9537 mouseReleaseEvent() may not end up where you expect, depending on
9538 the underlying window system (or X11 window manager), the widgets'
9539 location and maybe more.
9540
9541 The default implementation implements the closing of popup widgets
9542 when you click outside the window. For other widget types it does
9543 nothing.
9544
9545 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9546 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9547*/
9548
9549void QWidget::mousePressEvent(QMouseEvent *event)
9550{
9551 event->ignore();
9552 if ((windowType() == Qt::Popup)) {
9553 event->accept();
9554 QWidget* w;
9555 while ((w = QApplication::activePopupWidget()) && w != this){
9556 w->close();
9557 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9558 w->hide(); // hide at least
9559 }
9560 if (!rect().contains(p: event->position().toPoint())){
9561 close();
9562 }
9563 }
9564}
9565
9566/*!
9567 This event handler, for event \a event, can be reimplemented in a
9568 subclass to receive mouse release events for the widget.
9569
9570 \sa mousePressEvent(), mouseDoubleClickEvent(),
9571 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9572*/
9573
9574void QWidget::mouseReleaseEvent(QMouseEvent *event)
9575{
9576 event->ignore();
9577}
9578
9579/*!
9580 This event handler, for event \a event, can be reimplemented in a
9581 subclass to receive mouse double click events for the widget.
9582
9583 The default implementation calls mousePressEvent().
9584
9585 \note The widget will also receive mouse press and mouse release
9586 events in addition to the double click event. And if another widget
9587 that overlaps this widget disappears in response to press or
9588 release events, then this widget will only receive the double click
9589 event. It is up to the developer to ensure that the application
9590 interprets these events correctly.
9591
9592 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9593 event(), QMouseEvent
9594*/
9595
9596void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9597{
9598 mousePressEvent(event);
9599}
9600
9601#if QT_CONFIG(wheelevent)
9602/*!
9603 This event handler, for event \a event, can be reimplemented in a
9604 subclass to receive wheel events for the widget.
9605
9606 If you reimplement this handler, it is very important that you
9607 \l{QEvent}{ignore()} the event if you do not handle
9608 it, so that the widget's parent can interpret it.
9609
9610 The default implementation ignores the event.
9611
9612 \sa QEvent::ignore(), QEvent::accept(), event(),
9613 QWheelEvent
9614*/
9615
9616void QWidget::wheelEvent(QWheelEvent *event)
9617{
9618 event->ignore();
9619}
9620#endif // QT_CONFIG(wheelevent)
9621
9622#if QT_CONFIG(tabletevent)
9623/*!
9624 This event handler, for event \a event, can be reimplemented in a
9625 subclass to receive tablet events for the widget.
9626
9627 If you reimplement this handler, it is very important that you
9628 \l{QEvent}{ignore()} the event if you do not handle
9629 it, so that the widget's parent can interpret it.
9630
9631 The default implementation ignores the event.
9632
9633 If tablet tracking is switched off, tablet move events only occur if the
9634 stylus is in contact with the tablet, or at least one stylus button is
9635 pressed, while the stylus is being moved. If tablet tracking is switched on,
9636 tablet move events occur even while the stylus is hovering in proximity of
9637 the tablet, with no buttons pressed.
9638
9639 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9640 QTabletEvent
9641*/
9642
9643void QWidget::tabletEvent(QTabletEvent *event)
9644{
9645 event->ignore();
9646}
9647#endif // QT_CONFIG(tabletevent)
9648
9649/*!
9650 This event handler, for event \a event, can be reimplemented in a
9651 subclass to receive key press events for the widget.
9652
9653 A widget must call setFocusPolicy() to accept focus initially and
9654 have focus in order to receive a key press event.
9655
9656 If you reimplement this handler, it is very important that you
9657 call the base class implementation if you do not act upon the key.
9658
9659 The default implementation closes popup widgets if the user
9660 presses the key sequence for QKeySequence::Cancel (typically the
9661 Escape key). Otherwise the event is ignored, so that the widget's
9662 parent can interpret it.
9663
9664 Note that QKeyEvent starts with isAccepted() == true, so you do not
9665 need to call QKeyEvent::accept() - just do not call the base class
9666 implementation if you act upon the key.
9667
9668 \sa keyReleaseEvent(), setFocusPolicy(),
9669 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9670*/
9671
9672void QWidget::keyPressEvent(QKeyEvent *event)
9673{
9674#ifndef QT_NO_SHORTCUT
9675 if ((windowType() == Qt::Popup) && event->matches(key: QKeySequence::Cancel)) {
9676 event->accept();
9677 close();
9678 } else
9679#endif
9680 {
9681 event->ignore();
9682 }
9683}
9684
9685/*!
9686 This event handler, for event \a event, can be reimplemented in a
9687 subclass to receive key release events for the widget.
9688
9689 A widget must \l{setFocusPolicy()}{accept focus}
9690 initially and \l{hasFocus()}{have focus} in order to
9691 receive a key release event.
9692
9693 If you reimplement this handler, it is very important that you
9694 call the base class implementation if you do not act upon the key.
9695
9696 The default implementation ignores the event, so that the widget's
9697 parent can interpret it.
9698
9699 Note that QKeyEvent starts with isAccepted() == true, so you do not
9700 need to call QKeyEvent::accept() - just do not call the base class
9701 implementation if you act upon the key.
9702
9703 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9704 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9705*/
9706
9707void QWidget::keyReleaseEvent(QKeyEvent *event)
9708{
9709 event->ignore();
9710}
9711
9712/*!
9713 \fn void QWidget::focusInEvent(QFocusEvent *event)
9714
9715 This event handler can be reimplemented in a subclass to receive
9716 keyboard focus events (focus received) for the widget. The event
9717 is passed in the \a event parameter
9718
9719 A widget normally must setFocusPolicy() to something other than
9720 Qt::NoFocus in order to receive focus events. (Note that the
9721 application programmer can call setFocus() on any widget, even
9722 those that do not normally accept focus.)
9723
9724 The default implementation updates the widget (except for windows
9725 that do not specify a focusPolicy()).
9726
9727 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9728 keyReleaseEvent(), event(), QFocusEvent
9729*/
9730
9731void QWidget::focusInEvent(QFocusEvent *)
9732{
9733 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9734 update();
9735 }
9736}
9737
9738/*!
9739 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9740
9741 This event handler can be reimplemented in a subclass to receive
9742 keyboard focus events (focus lost) for the widget. The events is
9743 passed in the \a event parameter.
9744
9745 A widget normally must setFocusPolicy() to something other than
9746 Qt::NoFocus in order to receive focus events. (Note that the
9747 application programmer can call setFocus() on any widget, even
9748 those that do not normally accept focus.)
9749
9750 The default implementation updates the widget (except for windows
9751 that do not specify a focusPolicy()).
9752
9753 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9754 keyReleaseEvent(), event(), QFocusEvent
9755*/
9756
9757void QWidget::focusOutEvent(QFocusEvent *)
9758{
9759 if (focusPolicy() != Qt::NoFocus || !isWindow())
9760 update();
9761
9762#if !defined(QT_PLATFORM_UIKIT)
9763 // FIXME: revisit autoSIP logic, QTBUG-42906
9764 if (qApp->autoSipEnabled() && testAttribute(attribute: Qt::WA_InputMethodEnabled))
9765 QGuiApplication::inputMethod()->hide();
9766#endif
9767}
9768
9769/*!
9770 \fn void QWidget::enterEvent(QEnterEvent *event)
9771
9772 This event handler can be reimplemented in a subclass to receive
9773 widget enter events which are passed in the \a event parameter.
9774
9775 An event is sent to the widget when the mouse cursor enters the
9776 widget.
9777
9778 \sa leaveEvent(), mouseMoveEvent(), event()
9779*/
9780
9781void QWidget::enterEvent(QEnterEvent *)
9782{
9783}
9784
9785/*!
9786 \fn void QWidget::leaveEvent(QEvent *event)
9787
9788 This event handler can be reimplemented in a subclass to receive
9789 widget leave events which are passed in the \a event parameter.
9790
9791 A leave event is sent to the widget when the mouse cursor leaves
9792 the widget.
9793
9794 \sa enterEvent(), mouseMoveEvent(), event()
9795*/
9796
9797void QWidget::leaveEvent(QEvent *)
9798{
9799}
9800
9801/*!
9802 \fn void QWidget::paintEvent(QPaintEvent *event)
9803
9804 This event handler can be reimplemented in a subclass to receive paint
9805 events passed in \a event.
9806
9807 A paint event is a request to repaint all or part of a widget. It can
9808 happen for one of the following reasons:
9809
9810 \list
9811 \li repaint() or update() was invoked,
9812 \li the widget was obscured and has now been uncovered, or
9813 \li many other reasons.
9814 \endlist
9815
9816 Many widgets can simply repaint their entire surface when asked to, but
9817 some slow widgets need to optimize by painting only the requested region:
9818 QPaintEvent::region(). This speed optimization does not change the result,
9819 as painting is clipped to that region during event processing. QListView
9820 and QTableView do this, for example.
9821
9822 Qt also tries to speed up painting by merging multiple paint events into
9823 one. When update() is called several times or the window system sends
9824 several paint events, Qt merges these events into one event with a larger
9825 region (see QRegion::united()). The repaint() function does not permit this
9826 optimization, so we suggest using update() whenever possible.
9827
9828 When the paint event occurs, the update region has normally been erased, so
9829 you are painting on the widget's background.
9830
9831 The background can be set using setBackgroundRole() and setPalette().
9832
9833 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9834 is no need to write double-buffering code in paintEvent() to avoid flicker.
9835
9836 \note Generally, you should refrain from calling update() or repaint()
9837 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9838 children inside a paintEvent() results in undefined behavior; the child may
9839 or may not get a paint event.
9840
9841 \warning If you are using a custom paint engine without Qt's backingstore,
9842 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9843 never be called; the backingstore will be used instead.
9844
9845 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9846 {Analog Clock}
9847*/
9848
9849void QWidget::paintEvent(QPaintEvent *)
9850{
9851}
9852
9853
9854/*!
9855 \fn void QWidget::moveEvent(QMoveEvent *event)
9856
9857 This event handler can be reimplemented in a subclass to receive
9858 widget move events which are passed in the \a event parameter.
9859 When the widget receives this event, it is already at the new
9860 position.
9861
9862 The old position is accessible through QMoveEvent::oldPos().
9863
9864 \sa resizeEvent(), event(), move(), QMoveEvent
9865*/
9866
9867void QWidget::moveEvent(QMoveEvent *)
9868{
9869}
9870
9871
9872/*!
9873 This event handler can be reimplemented in a subclass to receive
9874 widget resize events which are passed in the \a event parameter.
9875 When resizeEvent() is called, the widget already has its new
9876 geometry. The old size is accessible through
9877 QResizeEvent::oldSize().
9878
9879 The widget will be erased and receive a paint event immediately
9880 after processing the resize event. No drawing need be (or should
9881 be) done inside this handler.
9882
9883
9884 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9885 {Scribble Example}
9886*/
9887
9888void QWidget::resizeEvent(QResizeEvent * /* event */)
9889{
9890}
9891
9892#ifndef QT_NO_ACTION
9893/*!
9894 \fn void QWidget::actionEvent(QActionEvent *event)
9895
9896 This event handler is called with the given \a event whenever the
9897 widget's actions are changed.
9898
9899 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9900*/
9901void QWidget::actionEvent(QActionEvent *)
9902{
9903
9904}
9905#endif
9906
9907/*!
9908 This event handler is called with the given \a event when Qt receives a window
9909 close request for a top-level widget from the window system.
9910
9911 By default, the event is accepted and the widget is closed. You can reimplement
9912 this function to change the way the widget responds to window close requests.
9913 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9914 on all events.
9915
9916 Main window applications typically use reimplementations of this function to check
9917 whether the user's work has been saved and ask for permission before closing.
9918
9919 \sa event(), hide(), close(), QCloseEvent
9920*/
9921
9922void QWidget::closeEvent(QCloseEvent *event)
9923{
9924 event->accept();
9925}
9926
9927#ifndef QT_NO_CONTEXTMENU
9928/*!
9929 This event handler, for event \a event, can be reimplemented in a
9930 subclass to receive widget context menu events.
9931
9932 The handler is called when the widget's \l contextMenuPolicy is
9933 Qt::DefaultContextMenu.
9934
9935 The default implementation ignores the context event.
9936 See the \l QContextMenuEvent documentation for more details.
9937
9938 \sa event(), QContextMenuEvent, customContextMenuRequested()
9939*/
9940
9941void QWidget::contextMenuEvent(QContextMenuEvent *event)
9942{
9943 event->ignore();
9944}
9945#endif // QT_NO_CONTEXTMENU
9946
9947
9948/*!
9949 This event handler, for event \a event, can be reimplemented in a
9950 subclass to receive Input Method composition events. This handler
9951 is called when the state of the input method changes.
9952
9953 Note that when creating custom text editing widgets, the
9954 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9955 (using the setAttribute() function) in order to receive input
9956 method events.
9957
9958 The default implementation calls event->ignore(), which rejects the
9959 Input Method event. See the \l QInputMethodEvent documentation for more
9960 details.
9961
9962 \sa event(), QInputMethodEvent
9963*/
9964void QWidget::inputMethodEvent(QInputMethodEvent *event)
9965{
9966 event->ignore();
9967}
9968
9969/*!
9970 This method is only relevant for input widgets. It is used by the
9971 input method to query a set of properties of the widget to be
9972 able to support complex input method operations as support for
9973 surrounding text and reconversions.
9974
9975 \a query specifies which property is queried.
9976
9977 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9978*/
9979QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9980{
9981 switch(query) {
9982 case Qt::ImCursorRectangle:
9983 return QRect(width()/2, 0, 1, height());
9984 case Qt::ImFont:
9985 return font();
9986 case Qt::ImAnchorPosition:
9987 // Fallback.
9988 return inputMethodQuery(query: Qt::ImCursorPosition);
9989 case Qt::ImHints:
9990 return (int)inputMethodHints();
9991 case Qt::ImInputItemClipRectangle:
9992 return d_func()->clipRect();
9993 default:
9994 return QVariant();
9995 }
9996}
9997
9998/*!
9999 \property QWidget::inputMethodHints
10000 \brief What input method specific hints the widget has.
10001
10002 This is only relevant for input widgets. It is used by
10003 the input method to retrieve hints as to how the input method
10004 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
10005 is set, the input method may change its visual components to reflect
10006 that only numbers can be entered.
10007
10008 \warning Some widgets require certain flags in order to work as
10009 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
10010 instead of \c{w->setInputMethodHints(f)}.
10011
10012 \note The flags are only hints, so the particular input method
10013 implementation is free to ignore them. If you want to be
10014 sure that a certain type of characters are entered,
10015 you should also set a QValidator on the widget.
10016
10017 The default value is Qt::ImhNone.
10018
10019 \since 4.6
10020
10021 \sa inputMethodQuery()
10022*/
10023Qt::InputMethodHints QWidget::inputMethodHints() const
10024{
10025#if QT_CONFIG(im)
10026 const QWidgetPrivate *priv = d_func();
10027 while (priv->inheritsInputMethodHints) {
10028 priv = priv->q_func()->parentWidget()->d_func();
10029 Q_ASSERT(priv);
10030 }
10031 return priv->imHints;
10032#else
10033 return Qt::ImhNone;
10034#endif
10035}
10036
10037void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10038{
10039#ifndef QT_NO_IM
10040 Q_D(QWidget);
10041 if (d->imHints == hints)
10042 return;
10043 d->imHints = hints;
10044 if (this == QGuiApplication::focusObject())
10045 QGuiApplication::inputMethod()->update(queries: Qt::ImHints);
10046#else
10047 Q_UNUSED(hints);
10048#endif //QT_NO_IM
10049}
10050
10051
10052#if QT_CONFIG(draganddrop)
10053
10054/*!
10055 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10056
10057 This event handler is called when a drag is in progress and the
10058 mouse enters this widget. The event is passed in the \a event parameter.
10059
10060 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10061 move events}.
10062
10063 See the \l{dnd.html}{Drag-and-drop documentation} for an
10064 overview of how to provide drag-and-drop in your application.
10065
10066 \sa QDrag, QDragEnterEvent
10067*/
10068void QWidget::dragEnterEvent(QDragEnterEvent *)
10069{
10070}
10071
10072/*!
10073 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10074
10075 This event handler is called if a drag is in progress, and when
10076 any of the following conditions occur: the cursor enters this widget,
10077 the cursor moves within this widget, or a modifier key is pressed on
10078 the keyboard while this widget has the focus. The event is passed
10079 in the \a event parameter.
10080
10081 See the \l{dnd.html}{Drag-and-drop documentation} for an
10082 overview of how to provide drag-and-drop in your application.
10083
10084 \sa QDrag, QDragMoveEvent
10085*/
10086void QWidget::dragMoveEvent(QDragMoveEvent *)
10087{
10088}
10089
10090/*!
10091 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10092
10093 This event handler is called when a drag is in progress and the
10094 mouse leaves this widget. The event is passed in the \a event
10095 parameter.
10096
10097 See the \l{dnd.html}{Drag-and-drop documentation} for an
10098 overview of how to provide drag-and-drop in your application.
10099
10100 \sa QDrag, QDragLeaveEvent
10101*/
10102void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10103{
10104}
10105
10106/*!
10107 \fn void QWidget::dropEvent(QDropEvent *event)
10108
10109 This event handler is called when the drag is dropped on this
10110 widget. The event is passed in the \a event parameter.
10111
10112 See the \l{dnd.html}{Drag-and-drop documentation} for an
10113 overview of how to provide drag-and-drop in your application.
10114
10115 \sa QDrag, QDropEvent
10116*/
10117void QWidget::dropEvent(QDropEvent *)
10118{
10119}
10120
10121#endif // QT_CONFIG(draganddrop)
10122
10123/*!
10124 \fn void QWidget::showEvent(QShowEvent *event)
10125
10126 This event handler can be reimplemented in a subclass to receive
10127 widget show events which are passed in the \a event parameter.
10128
10129 Non-spontaneous show events are sent to widgets immediately
10130 before they are shown. The spontaneous show events of windows are
10131 delivered afterwards.
10132
10133 Note: A widget receives spontaneous show and hide events when its
10134 mapping status is changed by the window system, e.g. a spontaneous
10135 hide event when the user minimizes the window, and a spontaneous
10136 show event when the window is restored again. After receiving a
10137 spontaneous hide event, a widget is still considered visible in
10138 the sense of isVisible().
10139
10140 \sa visible, event(), QShowEvent
10141*/
10142void QWidget::showEvent(QShowEvent *)
10143{
10144}
10145
10146/*!
10147 \fn void QWidget::hideEvent(QHideEvent *event)
10148
10149 This event handler can be reimplemented in a subclass to receive
10150 widget hide events. The event is passed in the \a event parameter.
10151
10152 Hide events are sent to widgets immediately after they have been
10153 hidden.
10154
10155 Note: A widget receives spontaneous show and hide events when its
10156 mapping status is changed by the window system, e.g. a spontaneous
10157 hide event when the user minimizes the window, and a spontaneous
10158 show event when the window is restored again. After receiving a
10159 spontaneous hide event, a widget is still considered visible in
10160 the sense of isVisible().
10161
10162 \sa visible, event(), QHideEvent
10163*/
10164void QWidget::hideEvent(QHideEvent *)
10165{
10166}
10167
10168/*!
10169 This special event handler can be reimplemented in a subclass to
10170 receive native platform events identified by \a eventType
10171 which are passed in the \a message parameter.
10172
10173 In your reimplementation of this function, if you want to stop the
10174 event being handled by Qt, return true and set \a result. The \a result
10175 parameter has meaning only on Windows. If you return false, this native
10176 event is passed back to Qt, which translates the event into a Qt event
10177 and sends it to the widget.
10178
10179 \note Events are only delivered to this event handler if the widget
10180 has a native window handle.
10181
10182 \note This function superseedes the event filter functions
10183 x11Event(), winEvent() and macEvent() of Qt 4.
10184
10185 \sa QAbstractNativeEventFilter
10186
10187 \table
10188 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10189 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10190 \row \li macOS \li "NSEvent" \li NSEvent * \li
10191 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10192 \endtable
10193*/
10194
10195bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10196{
10197 Q_UNUSED(eventType);
10198 Q_UNUSED(message);
10199 Q_UNUSED(result);
10200 return false;
10201}
10202
10203/*!
10204 Ensures that the widget and its children have been polished by
10205 QStyle (i.e., have a proper font and palette).
10206
10207 QWidget calls this function after it has been fully constructed
10208 but before it is shown the very first time. You can call this
10209 function if you want to ensure that the widget is polished before
10210 doing an operation, e.g., the correct font size might be needed in
10211 the widget's sizeHint() reimplementation. Note that this function
10212 \e is called from the default implementation of sizeHint().
10213
10214 Polishing is useful for final initialization that must happen after
10215 all constructors (from base classes as well as from subclasses)
10216 have been called.
10217
10218 If you need to change some settings when a widget is polished,
10219 reimplement event() and handle the QEvent::Polish event type.
10220
10221 \b{Note:} The function is declared const so that it can be called from
10222 other const functions (e.g., sizeHint()).
10223
10224 \sa event()
10225*/
10226void QWidget::ensurePolished() const
10227{
10228 Q_D(const QWidget);
10229
10230 const QMetaObject *m = metaObject();
10231 if (m == d->polished)
10232 return;
10233 d->polished = m;
10234
10235 QEvent e(QEvent::Polish);
10236 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &e);
10237
10238 // polish children after 'this'
10239 QList<QObject*> children = d->children;
10240 for (int i = 0; i < children.size(); ++i) {
10241 QObject *o = children.at(i);
10242 if (!o->isWidgetType())
10243 continue;
10244 if (QWidget *w = qobject_cast<QWidget *>(o))
10245 w->ensurePolished();
10246 }
10247
10248 if (d->parent && d->sendChildEvents) {
10249 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10250 QCoreApplication::sendEvent(receiver: d->parent, event: &e);
10251 }
10252}
10253
10254/*!
10255 Returns the mask currently set on a widget. If no mask is set the
10256 return value will be an empty region.
10257
10258 \sa setMask(), clearMask(), QRegion::isEmpty()
10259*/
10260QRegion QWidget::mask() const
10261{
10262 Q_D(const QWidget);
10263 return d->extra ? d->extra->mask : QRegion();
10264}
10265
10266/*!
10267 Returns the layout manager that is installed on this widget, or \nullptr
10268 if no layout manager is installed.
10269
10270 The layout manager sets the geometry of the widget's children
10271 that have been added to the layout.
10272
10273 \sa setLayout(), sizePolicy(), {Layout Management}
10274*/
10275QLayout *QWidget::layout() const
10276{
10277 return d_func()->layout;
10278}
10279
10280
10281/*!
10282 \fn void QWidget::setLayout(QLayout *layout)
10283
10284 Sets the layout manager for this widget to \a layout.
10285
10286 If there already is a layout manager installed on this widget,
10287 QWidget won't let you install another. You must first delete the
10288 existing layout manager (returned by layout()) before you can
10289 call setLayout() with the new layout.
10290
10291 If \a layout is the layout manager on a different widget, setLayout()
10292 will reparent the layout and make it the layout manager for this widget.
10293
10294 Example:
10295
10296 \snippet layouts/layouts.cpp 24
10297
10298 An alternative to calling this function is to pass this widget to
10299 the layout's constructor.
10300
10301 The QWidget will take ownership of \a layout.
10302
10303 \sa layout(), {Layout Management}
10304*/
10305
10306void QWidget::setLayout(QLayout *l)
10307{
10308 if (Q_UNLIKELY(!l)) {
10309 qWarning(msg: "QWidget::setLayout: Cannot set layout to 0");
10310 return;
10311 }
10312 if (layout()) {
10313 if (Q_UNLIKELY(layout() != l))
10314 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10315 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10316 objectName().toLocal8Bit().data());
10317 return;
10318 }
10319
10320 QObject *oldParent = l->parent();
10321 if (oldParent && oldParent != this) {
10322 if (oldParent->isWidgetType()) {
10323 // Steal the layout off a widget parent. Takes effect when
10324 // morphing laid-out container widgets in Designer.
10325 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10326 oldParentWidget->takeLayout();
10327 } else {
10328 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10329 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10330 objectName().toLocal8Bit().data());
10331 return;
10332 }
10333 }
10334
10335 Q_D(QWidget);
10336 l->d_func()->topLevel = true;
10337 d->layout = l;
10338 if (oldParent != this) {
10339 l->setParent(this);
10340 l->d_func()->reparentChildWidgets(mw: this);
10341 l->invalidate();
10342 }
10343
10344 if (isWindow() && d->maybeTopData())
10345 d->topData()->sizeAdjusted = false;
10346}
10347
10348/*!
10349 \fn QLayout *QWidget::takeLayout()
10350
10351 Remove the layout from the widget.
10352 \since 4.5
10353*/
10354
10355QLayout *QWidget::takeLayout()
10356{
10357 Q_D(QWidget);
10358 QLayout *l = layout();
10359 if (!l)
10360 return nullptr;
10361 d->layout = nullptr;
10362 l->setParent(nullptr);
10363 return l;
10364}
10365
10366/*!
10367 \property QWidget::sizePolicy
10368 \brief the default layout behavior of the widget
10369
10370 If there is a QLayout that manages this widget's children, the
10371 size policy specified by that layout is used. If there is no such
10372 QLayout, the result of this function is used.
10373
10374 The default policy is Preferred/Preferred, which means that the
10375 widget can be freely resized, but prefers to be the size
10376 sizeHint() returns. Button-like widgets set the size policy to
10377 specify that they may stretch horizontally, but are fixed
10378 vertically. The same applies to lineedit controls (such as
10379 QLineEdit, QSpinBox or an editable QComboBox) and other
10380 horizontally orientated widgets (such as QProgressBar).
10381 QToolButton's are normally square, so they allow growth in both
10382 directions. Widgets that support different directions (such as
10383 QSlider, QScrollBar or QHeader) specify stretching in the
10384 respective direction only. Widgets that can provide scroll bars
10385 (usually subclasses of QScrollArea) tend to specify that they can
10386 use additional space, and that they can make do with less than
10387 sizeHint().
10388
10389 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10390*/
10391QSizePolicy QWidget::sizePolicy() const
10392{
10393 Q_D(const QWidget);
10394 return d->size_policy;
10395}
10396
10397void QWidget::setSizePolicy(QSizePolicy policy)
10398{
10399 Q_D(QWidget);
10400 setAttribute(Qt::WA_WState_OwnSizePolicy);
10401 if (policy == d->size_policy)
10402 return;
10403
10404 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10405 d->retainSizeWhenHiddenChanged = 1;
10406
10407 d->size_policy = policy;
10408
10409#if QT_CONFIG(graphicsview)
10410 if (const auto &extra = d->extra) {
10411 if (extra->proxyWidget)
10412 extra->proxyWidget->setSizePolicy(policy);
10413 }
10414#endif
10415
10416 updateGeometry();
10417 d->retainSizeWhenHiddenChanged = 0;
10418
10419 if (isWindow() && d->maybeTopData())
10420 d->topData()->sizeAdjusted = false;
10421}
10422
10423/*!
10424 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10425 \overload
10426
10427 Sets the size policy of the widget to \a horizontal and \a
10428 vertical, with standard stretch and no height-for-width.
10429
10430 \sa QSizePolicy::QSizePolicy()
10431*/
10432
10433/*!
10434 Returns the preferred height for this widget, given the width \a w.
10435
10436 If this widget has a layout, the default implementation returns
10437 the layout's preferred height. if there is no layout, the default
10438 implementation returns -1 indicating that the preferred height
10439 does not depend on the width.
10440*/
10441
10442int QWidget::heightForWidth(int w) const
10443{
10444 if (layout() && layout()->hasHeightForWidth())
10445 return layout()->totalHeightForWidth(w);
10446 return -1;
10447}
10448
10449
10450/*!
10451 \since 5.0
10452
10453 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10454*/
10455bool QWidget::hasHeightForWidth() const
10456{
10457 Q_D(const QWidget);
10458 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10459}
10460
10461/*!
10462 \fn QWidget *QWidget::childAt(int x, int y) const
10463
10464 Returns the visible child widget at the position (\a{x}, \a{y})
10465 in the widget's coordinate system. If there is no visible child
10466 widget at the specified position, the function returns \nullptr.
10467*/
10468
10469/*!
10470 \overload
10471
10472 Returns the visible child widget at point \a p in the widget's own
10473 coordinate system.
10474*/
10475
10476QWidget *QWidget::childAt(const QPoint &p) const
10477{
10478 return d_func()->childAt_helper(p, false);
10479}
10480
10481QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
10482{
10483 if (children.isEmpty())
10484 return nullptr;
10485
10486 if (!pointInsideRectAndMask(p))
10487 return nullptr;
10488 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10489}
10490
10491QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor) const
10492{
10493 for (int i = children.size() - 1; i >= 0; --i) {
10494 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
10495 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(attribute: Qt::WA_TransparentForMouseEvents)
10496 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10497 continue;
10498 }
10499
10500 // Map the point 'p' from parent coordinates to child coordinates.
10501 QPoint childPoint = p;
10502 childPoint -= child->data->crect.topLeft();
10503
10504 // Check if the point hits the child.
10505 if (!child->d_func()->pointInsideRectAndMask(p: childPoint))
10506 continue;
10507
10508 // Do the same for the child's descendants.
10509 if (QWidget *w = child->d_func()->childAtRecursiveHelper(p: childPoint, ignoreChildrenInDestructor))
10510 return w;
10511
10512 // We have found our target; namely the child at position 'p'.
10513 return child;
10514 }
10515 return nullptr;
10516}
10517
10518void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10519{
10520 Q_Q(QWidget);
10521 if (widgetItem)
10522 widgetItem->invalidateSizeCache();
10523 QWidget *parent;
10524 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10525 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10526
10527 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10528 if (parent->d_func()->layout)
10529 parent->d_func()->layout->invalidate();
10530 else if (parent->isVisible())
10531 QCoreApplication::postEvent(receiver: parent, event: new QEvent(QEvent::LayoutRequest));
10532 }
10533 }
10534}
10535
10536/*!
10537 Notifies the layout system that this widget has changed and may
10538 need to change geometry.
10539
10540 Call this function if the sizeHint() or sizePolicy() have changed.
10541
10542 For explicitly hidden widgets, updateGeometry() is a no-op. The
10543 layout system will be notified as soon as the widget is shown.
10544*/
10545
10546void QWidget::updateGeometry()
10547{
10548 Q_D(QWidget);
10549 d->updateGeometry_helper(forceUpdate: false);
10550}
10551
10552/*! \property QWidget::windowFlags
10553
10554 Window flags are a combination of a type (e.g. Qt::Dialog) and
10555 zero or more hints to the window system (e.g.
10556 Qt::FramelessWindowHint).
10557
10558 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10559 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10560 0) on the desktop. If the widget is a window and becomes a
10561 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10562 relative to its parent widget.
10563
10564 \note This function calls setParent() when changing the flags for
10565 a window, causing the widget to be hidden. You must call show() to make
10566 the widget visible again..
10567
10568 \sa windowType(), setWindowFlag(), {Window Flags Example}
10569*/
10570void QWidget::setWindowFlags(Qt::WindowFlags flags)
10571{
10572 Q_D(QWidget);
10573 d->setWindowFlags(flags);
10574}
10575
10576/*!
10577 \since 5.9
10578
10579 Sets the window flag \a flag on this widget if \a on is true;
10580 otherwise clears the flag.
10581
10582 \sa setWindowFlags(), windowFlags(), windowType()
10583*/
10584void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10585{
10586 Q_D(QWidget);
10587 if (on)
10588 d->setWindowFlags(data->window_flags | flag);
10589 else
10590 d->setWindowFlags(data->window_flags & ~flag);
10591}
10592
10593/*! \internal
10594
10595 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10596*/
10597void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10598{
10599 Q_Q(QWidget);
10600 if (q->data->window_flags == flags)
10601 return;
10602
10603 if ((q->data->window_flags | flags) & Qt::Window) {
10604 // the old type was a window and/or the new type is a window
10605 QPoint oldPos = q->pos();
10606 bool visible = q->isVisible();
10607 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10608 q->setParent(parent: q->parentWidget(), f: flags);
10609
10610 // if both types are windows or neither of them are, we restore
10611 // the old position
10612 if (!windowFlagChanged && (visible || q->testAttribute(attribute: Qt::WA_Moved)))
10613 q->move(p: oldPos);
10614 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10615 adjustQuitOnCloseAttribute();
10616 } else {
10617 q->data->window_flags = flags;
10618 }
10619}
10620
10621/*!
10622 Sets the window flags for the widget to \a flags,
10623 \e without telling the window system.
10624
10625 \warning Do not call this function unless you really know what
10626 you're doing.
10627
10628 \sa setWindowFlags()
10629*/
10630void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10631{
10632 data->window_flags = flags;
10633}
10634
10635/*!
10636 \fn Qt::WindowType QWidget::windowType() const
10637
10638 Returns the window type of this widget. This is identical to
10639 windowFlags() & Qt::WindowType_Mask.
10640
10641 \sa windowFlags
10642*/
10643
10644/*!
10645 Sets the parent of the widget to \a parent, and resets the window
10646 flags. The widget is moved to position (0, 0) in its new parent.
10647
10648 If the new parent widget is in a different window, the
10649 reparented widget and its children are appended to the end of the
10650 \l{setFocusPolicy()}{tab chain} of the new parent
10651 widget, in the same internal order as before. If one of the moved
10652 widgets had keyboard focus, setParent() calls clearFocus() for that
10653 widget.
10654
10655 If the new parent widget is in the same window as the
10656 old parent, setting the parent doesn't change the tab order or
10657 keyboard focus.
10658
10659 If the "new" parent widget is the old parent widget, this function
10660 does nothing.
10661
10662 \note The widget becomes invisible as part of changing its parent,
10663 even if it was previously visible. You must call show() to make the
10664 widget visible again.
10665
10666 \warning It is very unlikely that you will ever need this
10667 function. If you have a widget that changes its content
10668 dynamically, it is far easier to use \l QStackedWidget.
10669
10670 \sa setWindowFlags()
10671*/
10672void QWidget::setParent(QWidget *parent)
10673{
10674 if (parent == parentWidget())
10675 return;
10676 setParent(parent: (QWidget*)parent, f: windowFlags() & ~Qt::WindowType_Mask);
10677}
10678
10679void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10680{
10681 QWidgetPrivate *d = QWidgetPrivate::get(w: widget);
10682 if (d->renderToTexture) {
10683 QEvent e(eventType);
10684 QCoreApplication::sendEvent(receiver: widget, event: &e);
10685 }
10686
10687 for (int i = 0; i < d->children.size(); ++i) {
10688 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
10689 if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
10690 qSendWindowChangeToTextureChildrenRecursively(widget: w, eventType);
10691 }
10692}
10693
10694/*!
10695 \overload
10696
10697 This function also takes widget flags, \a f as an argument.
10698*/
10699
10700void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10701{
10702 Q_D(QWidget);
10703 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10704#ifdef QT_DEBUG
10705 const auto checkForParentChildLoops = qScopeGuard(f: [&](){
10706 int depth = 0;
10707 auto p = parentWidget();
10708 while (p) {
10709 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10710 qWarning(msg: "QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10711 "this is undefined behavior",
10712 this, metaObject()->className(), qPrintable(objectName()));
10713 }
10714 p = p->parentWidget();
10715 }
10716 });
10717#endif
10718
10719 const bool resized = testAttribute(attribute: Qt::WA_Resized);
10720 const bool wasCreated = testAttribute(attribute: Qt::WA_WState_Created);
10721 QWidget *oldtlw = window();
10722
10723 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10724 d->data.fstrut_dirty = true;
10725
10726 QWidget *desktopWidget = nullptr;
10727 if (parent && parent->windowType() == Qt::Desktop)
10728 desktopWidget = parent;
10729 bool newParent = (parent != parentWidget()) || desktopWidget;
10730
10731 if (newParent && parent && !desktopWidget) {
10732 if (testAttribute(attribute: Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings))
10733 parent->d_func()->enforceNativeChildren();
10734 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(attribute: Qt::WA_PaintOnScreen))
10735 setAttribute(Qt::WA_NativeWindow);
10736 }
10737
10738 if (wasCreated) {
10739 if (!testAttribute(attribute: Qt::WA_WState_Hidden)) {
10740 hide();
10741 setAttribute(Qt::WA_WState_ExplicitShowHide, on: false);
10742 }
10743 if (newParent) {
10744 QEvent e(QEvent::ParentAboutToChange);
10745 QCoreApplication::sendEvent(receiver: this, event: &e);
10746 }
10747 }
10748
10749 // texture-based widgets need a pre-notification when their associated top-level window changes
10750 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10751 if (d->textureChildSeen && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10752 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowAboutToChangeInternal);
10753
10754 // If we get parented into another window, children will be folded
10755 // into the new parent's focus chain, so clear focus now.
10756 if (newParent && isAncestorOf(child: focusWidget()) && !(f & Qt::Window))
10757 focusWidget()->clearFocus();
10758
10759 d->setParent_sys(parent, f);
10760
10761 if (desktopWidget)
10762 parent = nullptr;
10763
10764 if (d->textureChildSeen && parent) {
10765 // set the textureChildSeen flag up the whole parent chain
10766 QWidgetPrivate::get(w: parent)->setTextureChildSeen();
10767 }
10768
10769 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10770 if (newParent)
10771 oldPaintManager->removeDirtyWidget(w: this);
10772 // Move the widget and all its static children from
10773 // the old backing store to the new one.
10774 oldPaintManager->moveStaticWidgets(reparented: this);
10775 }
10776
10777 d->reparentFocusWidgets(oldtlw);
10778 setAttribute(Qt::WA_Resized, on: resized);
10779
10780 const bool useStyleSheetPropagationInWidgetStyles =
10781 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10782
10783 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(attribute: Qt::WA_StyleSheet)
10784 && (!parent || !parent->testAttribute(attribute: Qt::WA_StyleSheet))) {
10785 // if the parent has a font set or inherited, then propagate the mask to the new child
10786 if (parent) {
10787 const auto pd = parent->d_func();
10788 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10789 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10790 }
10791 d->resolveFont();
10792 d->resolvePalette();
10793 }
10794 d->resolveLayoutDirection();
10795 d->resolveLocale();
10796
10797 // Note: GL widgets under WGL or EGL will always need a ParentChange
10798 // event to handle recreation/rebinding of the GL context, hence the
10799 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10800 // platforms).
10801 if (newParent || !wasCreated
10802#if QT_CONFIG(opengles2)
10803 || (f & Qt::MSWindowsOwnDC)
10804#endif
10805 ) {
10806 // propagate enabled updates enabled state to non-windows
10807 if (!isWindow()) {
10808 if (!testAttribute(attribute: Qt::WA_ForceDisabled))
10809 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10810 if (!testAttribute(attribute: Qt::WA_ForceUpdatesDisabled))
10811 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10812 }
10813 d->inheritStyle();
10814
10815 // send and post remaining QObject events
10816 if (parent && d->sendChildEvents) {
10817 QChildEvent e(QEvent::ChildAdded, this);
10818 QCoreApplication::sendEvent(receiver: parent, event: &e);
10819 }
10820
10821 if (parent && d->sendChildEvents && d->polished) {
10822 QChildEvent e(QEvent::ChildPolished, this);
10823 QCoreApplication::sendEvent(receiver: parent, event: &e);
10824 }
10825
10826 QEvent e(QEvent::ParentChange);
10827 QCoreApplication::sendEvent(receiver: this, event: &e);
10828 }
10829
10830 // texture-based widgets need another event when their top-level window
10831 // changes (more precisely, has already changed at this point)
10832 if (d->textureChildSeen && oldtlw != window())
10833 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowChangeInternal);
10834
10835 if (!wasCreated) {
10836 if (isWindow() || parentWidget()->isVisible())
10837 setAttribute(Qt::WA_WState_Hidden, on: true);
10838 else if (!testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
10839 setAttribute(Qt::WA_WState_Hidden, on: false);
10840 }
10841
10842 d->updateIsOpaque();
10843
10844#if QT_CONFIG(graphicsview)
10845 // Embed the widget into a proxy if the parent is embedded.
10846 // ### Doesn't handle reparenting out of an embedded widget.
10847 if (oldtlw->graphicsProxyWidget()) {
10848 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: oldtlw))
10849 ancestorProxy->d_func()->unembedSubWindow(this);
10850 }
10851 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(p: this)) {
10852 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: parent))
10853 ancestorProxy->d_func()->embedSubWindow(this);
10854 }
10855#endif
10856
10857 if (d->extra && d->extra->hasWindowContainer)
10858 QWindowContainer::parentWasChanged(parent: this);
10859
10860 QWidget *newtlw = window();
10861 if (oldtlw != newtlw) {
10862 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10863 // Only evaluate the reparented subtree. While it might be tempting to
10864 // do it on newtlw instead, the performance implications of that are
10865 // problematic when it comes to large widget trees.
10866 if (q_evaluateRhiConfig(w: this, outConfig: nullptr, outType: &surfaceType)) {
10867 newtlw->d_func()->usesRhiFlush = true;
10868 bool recreate = false;
10869 if (QWindow *w = newtlw->windowHandle()) {
10870 if (w->surfaceType() != surfaceType)
10871 recreate = true;
10872 }
10873 // QTBUG-115652: Besides the toplevel the nativeParentWidget()'s QWindow must be checked as well.
10874 if (QWindow *w = d->windowHandle(mode: QWidgetPrivate::WindowHandleMode::Closest)) {
10875 if (w->surfaceType() != surfaceType)
10876 recreate = true;
10877 }
10878 if (recreate) {
10879 newtlw->destroy();
10880 newtlw->create();
10881 }
10882 }
10883 }
10884}
10885
10886void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10887{
10888 Q_Q(QWidget);
10889
10890 Qt::WindowFlags oldFlags = data.window_flags;
10891 bool wasCreated = q->testAttribute(attribute: Qt::WA_WState_Created);
10892
10893 QScreen *targetScreen = nullptr;
10894 // Handle a request to move the widget to a particular screen
10895 if (newparent && newparent->windowType() == Qt::Desktop) {
10896 // make sure the widget is created on the same screen as the
10897 // programmer specified desktop widget
10898 targetScreen = newparent->screen();
10899 newparent = nullptr;
10900 }
10901
10902 setWinId(0);
10903
10904 if (parent != newparent) {
10905 QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
10906 if (q->windowHandle()) {
10907 q->windowHandle()->setFlags(f);
10908 QWidget *parentWithWindow =
10909 newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
10910 if (parentWithWindow) {
10911 QWidget *topLevel = parentWithWindow->window();
10912 if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
10913 q->windowHandle()->setTransientParent(topLevel->windowHandle());
10914 q->windowHandle()->setParent(nullptr);
10915 } else {
10916 q->windowHandle()->setTransientParent(nullptr);
10917 q->windowHandle()->setParent(parentWithWindow->windowHandle());
10918 }
10919 } else {
10920 q->windowHandle()->setTransientParent(nullptr);
10921 q->windowHandle()->setParent(nullptr);
10922 }
10923 }
10924 }
10925
10926 if (!newparent) {
10927 f |= Qt::Window;
10928 if (parent)
10929 targetScreen = q->parentWidget()->window()->screen();
10930 }
10931
10932 bool explicitlyHidden = q->testAttribute(attribute: Qt::WA_WState_Hidden) && q->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide);
10933
10934 // Reparenting toplevel to child
10935 if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(attribute: Qt::WA_NativeWindow)) {
10936 if (extra && extra->hasWindowContainer)
10937 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
10938
10939 QWindow *newParentWindow = newparent->windowHandle();
10940 if (!newParentWindow)
10941 if (QWidget *npw = newparent->nativeParentWidget())
10942 newParentWindow = npw->windowHandle();
10943
10944 for (QObject *child : q->windowHandle()->children()) {
10945 QWindow *childWindow = qobject_cast<QWindow *>(o: child);
10946 if (!childWindow)
10947 continue;
10948
10949 QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(object: childWindow);
10950 QWidget *childWidget = childWW ? childWW->widget() : nullptr;
10951 if (!childWW || (childWidget && childWidget->testAttribute(attribute: Qt::WA_NativeWindow)))
10952 childWindow->setParent(newParentWindow);
10953 }
10954 q->destroy();
10955 }
10956
10957 adjustFlags(flags&: f, w: q);
10958 data.window_flags = f;
10959 q->setAttribute(Qt::WA_WState_Created, on: false);
10960 q->setAttribute(Qt::WA_WState_Visible, on: false);
10961 q->setAttribute(Qt::WA_WState_Hidden, on: false);
10962
10963 if (newparent && wasCreated && (q->testAttribute(attribute: Qt::WA_NativeWindow) || (f & Qt::Window)))
10964 q->createWinId();
10965
10966 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
10967 q->setAttribute(Qt::WA_WState_Hidden);
10968 q->setAttribute(Qt::WA_WState_ExplicitShowHide, on: explicitlyHidden);
10969
10970 // move the window to the selected screen
10971 if (!newparent && targetScreen) {
10972 // only if it is already created
10973 if (q->testAttribute(attribute: Qt::WA_WState_Created))
10974 q->windowHandle()->setScreen(targetScreen);
10975 else
10976 topData()->initialScreen = targetScreen;
10977 }
10978}
10979
10980/*!
10981 Scrolls the widget including its children \a dx pixels to the
10982 right and \a dy downward. Both \a dx and \a dy may be negative.
10983
10984 After scrolling, the widgets will receive paint events for
10985 the areas that need to be repainted. For widgets that Qt knows to
10986 be opaque, this is only the newly exposed parts.
10987 For example, if an opaque widget is scrolled 8 pixels to the left,
10988 only an 8-pixel wide stripe at the right edge needs updating.
10989
10990 Since widgets propagate the contents of their parents by default,
10991 you need to set the \l autoFillBackground property, or use
10992 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
10993 a widget opaque.
10994
10995 For widgets that use contents propagation, a scroll will cause an
10996 update of the entire scroll area.
10997
10998 \sa {Transparency and Double Buffering}
10999*/
11000
11001void QWidget::scroll(int dx, int dy)
11002{
11003 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11004 return;
11005 if (dx == 0 && dy == 0)
11006 return;
11007 Q_D(QWidget);
11008#if QT_CONFIG(graphicsview)
11009 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11010 // Graphics View maintains its own dirty region as a list of rects;
11011 // until we can connect item updates directly to the view, we must
11012 // separately add a translated dirty region.
11013 for (const QRect &rect : d->dirty)
11014 proxy->update(rect: rect.translated(dx, dy));
11015 proxy->scroll(dx, dy, rect: proxy->subWidgetRect(widget: this));
11016 return;
11017 }
11018#endif
11019 d->setDirtyOpaqueRegion();
11020 d->scroll_sys(dx, dy);
11021}
11022
11023void QWidgetPrivate::scroll_sys(int dx, int dy)
11024{
11025 Q_Q(QWidget);
11026 scrollChildren(dx, dy);
11027 scrollRect(q->rect(), dx, dy);
11028}
11029
11030/*!
11031 \overload
11032
11033 This version only scrolls \a r and does not move the children of
11034 the widget.
11035
11036 If \a r is empty or invalid, the result is undefined.
11037
11038 \sa QScrollArea
11039*/
11040void QWidget::scroll(int dx, int dy, const QRect &r)
11041{
11042
11043 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11044 return;
11045 if (dx == 0 && dy == 0)
11046 return;
11047 Q_D(QWidget);
11048#if QT_CONFIG(graphicsview)
11049 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11050 // Graphics View maintains its own dirty region as a list of rects;
11051 // until we can connect item updates directly to the view, we must
11052 // separately add a translated dirty region.
11053 if (!d->dirty.isEmpty()) {
11054 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11055 proxy->update(rect);
11056 }
11057 proxy->scroll(dx, dy, rect: r.translated(p: proxy->subWidgetRect(widget: this).topLeft().toPoint()));
11058 return;
11059 }
11060#endif
11061 d->scroll_sys(dx, dy, r);
11062}
11063
11064void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11065{
11066 scrollRect(r, dx, dy);
11067}
11068
11069/*!
11070 Repaints the widget directly by calling paintEvent() immediately,
11071 unless updates are disabled or the widget is hidden.
11072
11073 We suggest only using repaint() if you need an immediate repaint,
11074 for example during animation. In almost all circumstances update()
11075 is better, as it permits Qt to optimize for speed and minimize
11076 flicker.
11077
11078 \warning If you call repaint() in a function which may itself be
11079 called from paintEvent(), you may get infinite recursion. The
11080 update() function never causes recursion.
11081
11082 \sa update(), paintEvent(), setUpdatesEnabled()
11083*/
11084
11085void QWidget::repaint()
11086{
11087 repaint(rect());
11088}
11089
11090/*! \overload
11091
11092 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11093 the widget.
11094
11095 If \a w is negative, it is replaced with \c{width() - x}, and if
11096 \a h is negative, it is replaced width \c{height() - y}.
11097*/
11098void QWidget::repaint(int x, int y, int w, int h)
11099{
11100 if (x > data->crect.width() || y > data->crect.height())
11101 return;
11102
11103 if (w < 0)
11104 w = data->crect.width() - x;
11105 if (h < 0)
11106 h = data->crect.height() - y;
11107
11108 repaint(QRect(x, y, w, h));
11109}
11110
11111/*! \overload
11112
11113 This version repaints a rectangle \a rect inside the widget.
11114*/
11115void QWidget::repaint(const QRect &rect)
11116{
11117 Q_D(QWidget);
11118 d->repaint(r: rect);
11119}
11120
11121/*!
11122 \overload
11123
11124 This version repaints a region \a rgn inside the widget.
11125*/
11126void QWidget::repaint(const QRegion &rgn)
11127{
11128 Q_D(QWidget);
11129 d->repaint(r: rgn);
11130}
11131
11132template <typename T>
11133void QWidgetPrivate::repaint(T r)
11134{
11135 Q_Q(QWidget);
11136
11137 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11138 return;
11139
11140 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11141 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11142 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11143}
11144
11145/*!
11146 Updates the widget unless updates are disabled or the widget is
11147 hidden.
11148
11149 This function does not cause an immediate repaint; instead it
11150 schedules a paint event for processing when Qt returns to the main
11151 event loop. This permits Qt to optimize for more speed and less
11152 flicker than a call to repaint() does.
11153
11154 Calling update() several times normally results in just one
11155 paintEvent() call.
11156
11157 Qt normally erases the widget's area before the paintEvent() call.
11158 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11159 responsible for painting all its pixels with an opaque color.
11160
11161 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11162*/
11163void QWidget::update()
11164{
11165 update(rect());
11166}
11167
11168/*! \fn void QWidget::update(int x, int y, int w, int h)
11169 \overload
11170
11171 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11172 the widget.
11173*/
11174
11175/*!
11176 \overload
11177
11178 This version updates a rectangle \a rect inside the widget.
11179*/
11180void QWidget::update(const QRect &rect)
11181{
11182 Q_D(QWidget);
11183 d->update(r: rect);
11184}
11185
11186/*!
11187 \overload
11188
11189 This version repaints a region \a rgn inside the widget.
11190*/
11191void QWidget::update(const QRegion &rgn)
11192{
11193 Q_D(QWidget);
11194 d->update(r: rgn);
11195}
11196
11197template <typename T>
11198void QWidgetPrivate::update(T r)
11199{
11200 Q_Q(QWidget);
11201
11202 if (renderToTexture && !q->isVisible()) {
11203 renderToTextureReallyDirty = 1;
11204 return;
11205 }
11206
11207 if (!q->isVisible() || !q->updatesEnabled())
11208 return;
11209
11210 T clipped = r & q->rect();
11211
11212 if (clipped.isEmpty())
11213 return;
11214
11215 if (q->testAttribute(attribute: Qt::WA_WState_InPaintEvent)) {
11216 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(clipped));
11217 return;
11218 }
11219
11220 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11221 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11222 tlwExtra->repaintManager->markDirty(clipped, q);
11223}
11224
11225 /*!
11226 \internal
11227
11228 This just sets the corresponding attribute bit to 1 or 0
11229 */
11230static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11231 QWidgetPrivate *d)
11232{
11233 if (attribute < int(8*sizeof(uint))) {
11234 if (on)
11235 data->widget_attributes |= (1<<attribute);
11236 else
11237 data->widget_attributes &= ~(1<<attribute);
11238 } else {
11239 const int x = attribute - 8*sizeof(uint);
11240 const int int_off = x / (8*sizeof(uint));
11241 if (on)
11242 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11243 else
11244 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11245 }
11246}
11247
11248#ifdef Q_OS_MAC
11249void QWidgetPrivate::macUpdateSizeAttribute()
11250{
11251 Q_Q(QWidget);
11252 QEvent event(QEvent::MacSizeChange);
11253 QCoreApplication::sendEvent(q, &event);
11254 for (int i = 0; i < children.size(); ++i) {
11255 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11256 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11257 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11258 && !w->testAttribute(Qt::WA_MacSmallSize)
11259 && !w->testAttribute(Qt::WA_MacNormalSize))
11260 w->d_func()->macUpdateSizeAttribute();
11261 }
11262 resolveFont();
11263}
11264#endif
11265
11266/*!
11267 Sets the attribute \a attribute on this widget if \a on is true;
11268 otherwise clears the attribute.
11269
11270 \sa testAttribute()
11271*/
11272void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11273{
11274 if (testAttribute(attribute) == on)
11275 return;
11276
11277 Q_D(QWidget);
11278 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11279 "QWidget::setAttribute(WidgetAttribute, bool): "
11280 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11281#ifdef Q_OS_WIN
11282 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11283 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
11284 // see ::paintEngine for details
11285 paintEngine();
11286 if (d->noPaintOnScreen)
11287 return;
11288 }
11289#endif
11290
11291 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11292 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11293 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11294 if (!platformIntegration->hasCapability(cap: QPlatformIntegration::NativeWidgets))
11295 return;
11296 }
11297
11298 setAttribute_internal(attribute, on, data, d);
11299
11300 switch (attribute) {
11301
11302#if QT_CONFIG(draganddrop)
11303 case Qt::WA_AcceptDrops: {
11304 if (on && !testAttribute(attribute: Qt::WA_DropSiteRegistered))
11305 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: true);
11306 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered)))
11307 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: false);
11308 QEvent e(QEvent::AcceptDropsChange);
11309 QCoreApplication::sendEvent(receiver: this, event: &e);
11310 break;
11311 }
11312 case Qt::WA_DropSiteRegistered: {
11313 for (int i = 0; i < d->children.size(); ++i) {
11314 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
11315 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_AcceptDrops) && w->testAttribute(attribute: Qt::WA_DropSiteRegistered) != on)
11316 w->setAttribute(attribute: Qt::WA_DropSiteRegistered, on);
11317 }
11318 break;
11319 }
11320#endif
11321
11322 case Qt::WA_NoChildEventsForParent:
11323 d->sendChildEvents = !on;
11324 break;
11325 case Qt::WA_NoChildEventsFromChildren:
11326 d->receiveChildEvents = !on;
11327 break;
11328 case Qt::WA_MacNormalSize:
11329 case Qt::WA_MacSmallSize:
11330 case Qt::WA_MacMiniSize:
11331#ifdef Q_OS_MAC
11332 {
11333 // We can only have one of these set at a time
11334 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11335 Qt::WA_MacMiniSize };
11336 for (int i = 0; i < 3; ++i) {
11337 if (MacSizes[i] != attribute)
11338 setAttribute_internal(MacSizes[i], false, data, d);
11339 }
11340 d->macUpdateSizeAttribute();
11341 }
11342#endif
11343 break;
11344 case Qt::WA_ShowModal:
11345 if (!on) {
11346 // reset modality type to NonModal when clearing WA_ShowModal
11347 data->window_modality = Qt::NonModal;
11348 } else if (data->window_modality == Qt::NonModal) {
11349 // If modality hasn't been set prior to setting WA_ShowModal, use
11350 // ApplicationModal.
11351 data->window_modality = Qt::ApplicationModal;
11352 // Some window managers do not allow us to enter modality after the
11353 // window is visible.The window must be hidden before changing the
11354 // windowModality property and then reshown.
11355 }
11356 if (testAttribute(attribute: Qt::WA_WState_Created)) {
11357 // don't call setModal_sys() before create()
11358 d->setModal_sys();
11359 }
11360 break;
11361 case Qt::WA_MouseTracking: {
11362 QEvent e(QEvent::MouseTrackingChange);
11363 QCoreApplication::sendEvent(receiver: this, event: &e);
11364 break; }
11365 case Qt::WA_TabletTracking: {
11366 QEvent e(QEvent::TabletTrackingChange);
11367 QCoreApplication::sendEvent(receiver: this, event: &e);
11368 break; }
11369 case Qt::WA_NativeWindow: {
11370 d->createTLExtra();
11371 if (on)
11372 d->createTLSysExtra();
11373#ifndef QT_NO_IM
11374 QWidget *focusWidget = d->effectiveFocusWidget();
11375 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11376 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11377 QGuiApplication::inputMethod()->commit();
11378 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11379 }
11380 if (!QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11381 parentWidget()->d_func()->enforceNativeChildren();
11382 if (on && !internalWinId() && testAttribute(attribute: Qt::WA_WState_Created))
11383 d->createWinId();
11384 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11385 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11386 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11387 }
11388#endif //QT_NO_IM
11389 break;
11390 }
11391 case Qt::WA_PaintOnScreen:
11392 d->updateIsOpaque();
11393 Q_FALLTHROUGH();
11394 case Qt::WA_OpaquePaintEvent:
11395 d->updateIsOpaque();
11396 break;
11397 case Qt::WA_NoSystemBackground:
11398 d->updateIsOpaque();
11399 Q_FALLTHROUGH();
11400 case Qt::WA_UpdatesDisabled:
11401 d->updateSystemBackground();
11402 break;
11403 case Qt::WA_TransparentForMouseEvents:
11404 break;
11405 case Qt::WA_InputMethodEnabled: {
11406#ifndef QT_NO_IM
11407 if (QGuiApplication::focusObject() == this) {
11408 if (!on)
11409 QGuiApplication::inputMethod()->commit();
11410 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11411 }
11412#endif //QT_NO_IM
11413 break;
11414 }
11415 case Qt::WA_WindowPropagation:
11416 d->resolvePalette();
11417 d->resolveFont();
11418 d->resolveLocale();
11419 break;
11420 case Qt::WA_DontShowOnScreen: {
11421 if (on && isVisible()) {
11422 // Make sure we keep the current state and only hide the widget
11423 // from the desktop. show_sys will only update platform specific
11424 // attributes at this point.
11425 d->hide_sys();
11426 d->show_sys();
11427 }
11428 break;
11429 }
11430
11431 case Qt::WA_X11NetWmWindowTypeDesktop:
11432 case Qt::WA_X11NetWmWindowTypeDock:
11433 case Qt::WA_X11NetWmWindowTypeToolBar:
11434 case Qt::WA_X11NetWmWindowTypeMenu:
11435 case Qt::WA_X11NetWmWindowTypeUtility:
11436 case Qt::WA_X11NetWmWindowTypeSplash:
11437 case Qt::WA_X11NetWmWindowTypeDialog:
11438 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11439 case Qt::WA_X11NetWmWindowTypePopupMenu:
11440 case Qt::WA_X11NetWmWindowTypeToolTip:
11441 case Qt::WA_X11NetWmWindowTypeNotification:
11442 case Qt::WA_X11NetWmWindowTypeCombo:
11443 case Qt::WA_X11NetWmWindowTypeDND:
11444 d->setNetWmWindowTypes();
11445 break;
11446
11447 case Qt::WA_StaticContents:
11448 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11449 if (on)
11450 repaintManager->addStaticWidget(widget: this);
11451 else
11452 repaintManager->removeStaticWidget(widget: this);
11453 }
11454 break;
11455 case Qt::WA_TranslucentBackground:
11456 if (on)
11457 setAttribute(attribute: Qt::WA_NoSystemBackground);
11458 d->updateIsTranslucent();
11459
11460 break;
11461 case Qt::WA_AcceptTouchEvents:
11462 break;
11463 default:
11464 break;
11465 }
11466}
11467
11468/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11469
11470 Returns \c true if attribute \a attribute is set on this widget;
11471 otherwise returns \c false.
11472
11473 \sa setAttribute()
11474 */
11475bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11476{
11477 Q_D(const QWidget);
11478 const int x = attribute - 8*sizeof(uint);
11479 const int int_off = x / (8*sizeof(uint));
11480 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11481}
11482
11483/*!
11484 \property QWidget::windowOpacity
11485
11486 \brief The level of opacity for the window.
11487
11488 The valid range of opacity is from 1.0 (completely opaque) to
11489 0.0 (completely transparent).
11490
11491 By default the value of this property is 1.0.
11492
11493 This feature is available on Embedded Linux, \macos, Windows,
11494 and X11 platforms that support the Composite extension.
11495
11496 \note On X11 you need to have a composite manager running,
11497 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11498 supported by the window manager you are using.
11499
11500 \warning Changing this property from opaque to transparent might issue a
11501 paint event that needs to be processed before the window is displayed
11502 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11503 that semi-transparent windows update and resize significantly slower than
11504 opaque windows.
11505
11506 \sa setMask()
11507*/
11508qreal QWidget::windowOpacity() const
11509{
11510 Q_D(const QWidget);
11511 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11512}
11513
11514void QWidget::setWindowOpacity(qreal opacity)
11515{
11516 Q_D(QWidget);
11517 if (!isWindow())
11518 return;
11519
11520 opacity = qBound(min: qreal(0.0), val: opacity, max: qreal(1.0));
11521 QTLWExtra *extra = d->topData();
11522 extra->opacity = uint(opacity * 255);
11523 setAttribute(attribute: Qt::WA_WState_WindowOpacitySet);
11524 d->setWindowOpacity_sys(opacity);
11525
11526 if (!testAttribute(attribute: Qt::WA_WState_Created))
11527 return;
11528
11529#if QT_CONFIG(graphicsview)
11530 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11531 // Avoid invalidating the cache if set.
11532 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11533 proxy->update();
11534 else if (QGraphicsScene *scene = proxy->scene())
11535 scene->update(rect: proxy->sceneBoundingRect());
11536 return;
11537 }
11538#endif
11539}
11540
11541void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11542{
11543 Q_Q(QWidget);
11544 if (q->windowHandle())
11545 q->windowHandle()->setOpacity(level);
11546}
11547
11548/*!
11549 \property QWidget::windowModified
11550 \brief whether the document shown in the window has unsaved changes
11551
11552 A modified window is a window whose content has changed but has
11553 not been saved to disk. This flag will have different effects
11554 varied by the platform. On \macos the close button will have a
11555 modified look; on other platforms, the window title will have an
11556 '*' (asterisk).
11557
11558 The window title must contain a "[*]" placeholder, which
11559 indicates where the '*' should appear. Normally, it should appear
11560 right after the file name (e.g., "document1.txt[*] - Text
11561 Editor"). If the window isn't modified, the placeholder is simply
11562 removed.
11563
11564 Note that if a widget is set as modified, all its ancestors will
11565 also be set as modified. However, if you call \c
11566 {setWindowModified(false)} on a widget, this will not propagate to
11567 its parent because other children of the parent might have been
11568 modified.
11569
11570 \sa windowTitle
11571*/
11572bool QWidget::isWindowModified() const
11573{
11574 return testAttribute(attribute: Qt::WA_WindowModified);
11575}
11576
11577void QWidget::setWindowModified(bool mod)
11578{
11579 Q_D(QWidget);
11580 setAttribute(attribute: Qt::WA_WindowModified, on: mod);
11581
11582 d->setWindowModified_helper();
11583
11584 QEvent e(QEvent::ModifiedChange);
11585 QCoreApplication::sendEvent(receiver: this, event: &e);
11586}
11587
11588void QWidgetPrivate::setWindowModified_helper()
11589{
11590 Q_Q(QWidget);
11591 QWindow *window = q->windowHandle();
11592 if (!window)
11593 return;
11594 QPlatformWindow *platformWindow = window->handle();
11595 if (!platformWindow)
11596 return;
11597 bool on = q->testAttribute(attribute: Qt::WA_WindowModified);
11598 if (!platformWindow->setWindowModified(on)) {
11599 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11600 qWarning(msg: "QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11601 setWindowTitle_helper(q->windowTitle());
11602 setWindowIconText_helper(q->windowIconText());
11603 }
11604}
11605
11606#if QT_CONFIG(tooltip)
11607/*!
11608 \property QWidget::toolTip
11609
11610 \brief the widget's tooltip
11611
11612 Note that by default tooltips are only shown for widgets that are
11613 children of the active window. You can change this behavior by
11614 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11615 not on the widget with the tooltip.
11616
11617 If you want to control a tooltip's behavior, you can intercept the
11618 event() function and catch the QEvent::ToolTip event (e.g., if you
11619 want to customize the area for which the tooltip should be shown).
11620
11621 By default, this property contains an empty string.
11622
11623 \sa QToolTip, statusTip, whatsThis
11624*/
11625void QWidget::setToolTip(const QString &s)
11626{
11627 Q_D(QWidget);
11628 d->toolTip = s;
11629
11630 QEvent event(QEvent::ToolTipChange);
11631 QCoreApplication::sendEvent(receiver: this, event: &event);
11632}
11633
11634QString QWidget::toolTip() const
11635{
11636 Q_D(const QWidget);
11637 return d->toolTip;
11638}
11639
11640/*!
11641 \property QWidget::toolTipDuration
11642 \brief the widget's tooltip duration
11643 \since 5.2
11644
11645 Specifies how long time the tooltip will be displayed, in milliseconds.
11646 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11647
11648 \sa toolTip
11649*/
11650
11651void QWidget::setToolTipDuration(int msec)
11652{
11653 Q_D(QWidget);
11654 d->toolTipDuration = msec;
11655}
11656
11657int QWidget::toolTipDuration() const
11658{
11659 Q_D(const QWidget);
11660 return d->toolTipDuration;
11661}
11662
11663#endif // QT_CONFIG(tooltip)
11664
11665
11666#if QT_CONFIG(statustip)
11667/*!
11668 \property QWidget::statusTip
11669 \brief the widget's status tip
11670
11671 By default, this property contains an empty string.
11672
11673 \sa toolTip, whatsThis
11674*/
11675void QWidget::setStatusTip(const QString &s)
11676{
11677 Q_D(QWidget);
11678 d->statusTip = s;
11679}
11680
11681QString QWidget::statusTip() const
11682{
11683 Q_D(const QWidget);
11684 return d->statusTip;
11685}
11686#endif // QT_CONFIG(statustip)
11687
11688#if QT_CONFIG(whatsthis)
11689/*!
11690 \property QWidget::whatsThis
11691
11692 \brief the widget's What's This help text.
11693
11694 By default, this property contains an empty string.
11695
11696 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11697*/
11698void QWidget::setWhatsThis(const QString &s)
11699{
11700 Q_D(QWidget);
11701 d->whatsThis = s;
11702}
11703
11704QString QWidget::whatsThis() const
11705{
11706 Q_D(const QWidget);
11707 return d->whatsThis;
11708}
11709#endif // QT_CONFIG(whatsthis)
11710
11711#if QT_CONFIG(accessibility)
11712/*!
11713 \property QWidget::accessibleName
11714
11715 \brief the widget's name as seen by assistive technologies
11716
11717 This is the primary name by which assistive technology such as screen readers
11718 announce this widget. For most widgets setting this property is not required.
11719 For example for QPushButton the button's text will be used.
11720
11721 It is important to set this property when the widget does not provide any
11722 text. For example a button that only contains an icon needs to set this
11723 property to work with screen readers.
11724 The name should be short and equivalent to the visual information conveyed
11725 by the widget.
11726
11727 This property has to be \l{Internationalization with Qt}{localized}.
11728
11729 By default, this property contains an empty string.
11730
11731 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11732*/
11733void QWidget::setAccessibleName(const QString &name)
11734{
11735 Q_D(QWidget);
11736 d->accessibleName = name;
11737 QAccessibleEvent event(this, QAccessible::NameChanged);
11738 QAccessible::updateAccessibility(event: &event);
11739}
11740
11741QString QWidget::accessibleName() const
11742{
11743 Q_D(const QWidget);
11744 return d->accessibleName;
11745}
11746
11747/*!
11748 \property QWidget::accessibleDescription
11749
11750 \brief the widget's description as seen by assistive technologies
11751
11752 The accessible description of a widget should convey what a widget does.
11753 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11754 the description should give more context, such as \gui{Saves the current document}.
11755
11756 This property has to be \l{Internationalization with Qt}{localized}.
11757
11758 By default, this property contains an empty string and Qt falls back
11759 to using the tool tip to provide this information.
11760
11761 \sa QWidget::accessibleName, QAccessibleInterface::text()
11762*/
11763void QWidget::setAccessibleDescription(const QString &description)
11764{
11765 Q_D(QWidget);
11766 d->accessibleDescription = description;
11767 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11768 QAccessible::updateAccessibility(event: &event);
11769}
11770
11771QString QWidget::accessibleDescription() const
11772{
11773 Q_D(const QWidget);
11774 return d->accessibleDescription;
11775}
11776#endif // QT_CONFIG(accessibility)
11777
11778#ifndef QT_NO_SHORTCUT
11779/*!
11780 Adds a shortcut to Qt's shortcut system that watches for the given
11781 \a key sequence in the given \a context. If the \a context is
11782 Qt::ApplicationShortcut, the shortcut applies to the application as a
11783 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11784 or to the window itself, Qt::WindowShortcut.
11785
11786 If the same \a key sequence has been grabbed by several widgets,
11787 when the \a key sequence occurs a QEvent::Shortcut event is sent
11788 to all the widgets to which it applies in a non-deterministic
11789 order, but with the ``ambiguous'' flag set to true.
11790
11791 \warning You should not normally need to use this function;
11792 instead create \l{QAction}s with the shortcut key sequences you
11793 require (if you also want equivalent menu options and toolbar
11794 buttons), or create \l{QShortcut}s if you just need key sequences.
11795 Both QAction and QShortcut handle all the event filtering for you,
11796 and provide signals which are triggered when the user triggers the
11797 key sequence, so are much easier to use than this low-level
11798 function.
11799
11800 \sa releaseShortcut(), setShortcutEnabled()
11801*/
11802int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11803{
11804 Q_ASSERT(qApp);
11805 if (key.isEmpty())
11806 return 0;
11807 setAttribute(attribute: Qt::WA_GrabbedShortcut);
11808 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(owner: this, key, context, matcher: qWidgetShortcutContextMatcher);
11809}
11810
11811/*!
11812 Removes the shortcut with the given \a id from Qt's shortcut
11813 system. The widget will no longer receive QEvent::Shortcut events
11814 for the shortcut's key sequence (unless it has other shortcuts
11815 with the same key sequence).
11816
11817 \warning You should not normally need to use this function since
11818 Qt's shortcut system removes shortcuts automatically when their
11819 parent widget is destroyed. It is best to use QAction or
11820 QShortcut to handle shortcuts, since they are easier to use than
11821 this low-level function. Note also that this is an expensive
11822 operation.
11823
11824 \sa grabShortcut(), setShortcutEnabled()
11825*/
11826void QWidget::releaseShortcut(int id)
11827{
11828 Q_ASSERT(qApp);
11829 if (id)
11830 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, owner: this, key: 0);
11831}
11832
11833/*!
11834 If \a enable is true, the shortcut with the given \a id is
11835 enabled; otherwise the shortcut is disabled.
11836
11837 \warning You should not normally need to use this function since
11838 Qt's shortcut system enables/disables shortcuts automatically as
11839 widgets become hidden/visible and gain or lose focus. It is best
11840 to use QAction or QShortcut to handle shortcuts, since they are
11841 easier to use than this low-level function.
11842
11843 \sa grabShortcut(), releaseShortcut()
11844*/
11845void QWidget::setShortcutEnabled(int id, bool enable)
11846{
11847 Q_ASSERT(qApp);
11848 if (id)
11849 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, owner: this, key: 0);
11850}
11851
11852/*!
11853 \since 4.2
11854
11855 If \a enable is true, auto repeat of the shortcut with the
11856 given \a id is enabled; otherwise it is disabled.
11857
11858 \sa grabShortcut(), releaseShortcut()
11859*/
11860void QWidget::setShortcutAutoRepeat(int id, bool enable)
11861{
11862 Q_ASSERT(qApp);
11863 if (id)
11864 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on: enable, id, owner: this, key: 0);
11865}
11866#endif // QT_NO_SHORTCUT
11867
11868/*!
11869 Updates the widget's micro focus and informs input methods
11870 that the state specified by \a query has changed.
11871*/
11872void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
11873{
11874 if (this == QGuiApplication::focusObject())
11875 QGuiApplication::inputMethod()->update(queries: query);
11876}
11877
11878/*!
11879 Raises this widget to the top of the parent widget's stack.
11880
11881 After this call the widget will be visually in front of any
11882 overlapping sibling widgets.
11883
11884 \note When using activateWindow(), you can call this function to
11885 ensure that the window is stacked on top.
11886
11887 \sa lower(), stackUnder()
11888*/
11889
11890void QWidget::raise()
11891{
11892 Q_D(QWidget);
11893 if (!isWindow()) {
11894 QWidget *p = parentWidget();
11895 const int parentChildCount = p->d_func()->children.size();
11896 if (parentChildCount < 2)
11897 return;
11898 const int from = p->d_func()->children.indexOf(t: this);
11899 Q_ASSERT(from >= 0);
11900 // Do nothing if the widget is already in correct stacking order _and_ created.
11901 if (from != parentChildCount -1)
11902 p->d_func()->children.move(from, to: parentChildCount - 1);
11903 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
11904 create();
11905 else if (from == parentChildCount - 1)
11906 return;
11907
11908 QRegion region(rect());
11909 d->subtractOpaqueSiblings(sourceRegion&: region);
11910 d->invalidateBackingStore(region);
11911 }
11912 if (testAttribute(attribute: Qt::WA_WState_Created))
11913 d->raise_sys();
11914
11915 if (d->extra && d->extra->hasWindowContainer)
11916 QWindowContainer::parentWasRaised(parent: this);
11917
11918 QEvent e(QEvent::ZOrderChange);
11919 QCoreApplication::sendEvent(receiver: this, event: &e);
11920}
11921
11922void QWidgetPrivate::raise_sys()
11923{
11924 Q_Q(QWidget);
11925 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
11926 q->windowHandle()->raise();
11927 } else if (renderToTexture) {
11928 if (QWidget *p = q->parentWidget()) {
11929 setDirtyOpaqueRegion();
11930 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
11931 }
11932 }
11933}
11934
11935/*!
11936 Lowers the widget to the bottom of the parent widget's stack.
11937
11938 After this call the widget will be visually behind (and therefore
11939 obscured by) any overlapping sibling widgets.
11940
11941 \sa raise(), stackUnder()
11942*/
11943
11944void QWidget::lower()
11945{
11946 Q_D(QWidget);
11947 if (!isWindow()) {
11948 QWidget *p = parentWidget();
11949 const int parentChildCount = p->d_func()->children.size();
11950 if (parentChildCount < 2)
11951 return;
11952 const int from = p->d_func()->children.indexOf(t: this);
11953 Q_ASSERT(from >= 0);
11954 // Do nothing if the widget is already in correct stacking order _and_ created.
11955 if (from != 0)
11956 p->d_func()->children.move(from, to: 0);
11957 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
11958 create();
11959 else if (from == 0)
11960 return;
11961 }
11962 if (testAttribute(attribute: Qt::WA_WState_Created))
11963 d->lower_sys();
11964
11965 if (d->extra && d->extra->hasWindowContainer)
11966 QWindowContainer::parentWasLowered(parent: this);
11967
11968 QEvent e(QEvent::ZOrderChange);
11969 QCoreApplication::sendEvent(receiver: this, event: &e);
11970}
11971
11972void QWidgetPrivate::lower_sys()
11973{
11974 Q_Q(QWidget);
11975 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
11976 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
11977 q->windowHandle()->lower();
11978 } else if (QWidget *p = q->parentWidget()) {
11979 setDirtyOpaqueRegion();
11980 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
11981 }
11982}
11983
11984/*!
11985 Places the widget under \a w in the parent widget's stack.
11986
11987 To make this work, the widget itself and \a w must be siblings.
11988
11989 \sa raise(), lower()
11990*/
11991void QWidget::stackUnder(QWidget* w)
11992{
11993 Q_D(QWidget);
11994 QWidget *p = parentWidget();
11995 if (!w || isWindow() || p != w->parentWidget() || this == w)
11996 return;
11997 if (p) {
11998 int from = p->d_func()->children.indexOf(t: this);
11999 int to = p->d_func()->children.indexOf(t: w);
12000 Q_ASSERT(from >= 0);
12001 Q_ASSERT(to >= 0);
12002 if (from < to)
12003 --to;
12004 // Do nothing if the widget is already in correct stacking order _and_ created.
12005 if (from != to)
12006 p->d_func()->children.move(from, to);
12007 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12008 create();
12009 else if (from == to)
12010 return;
12011 }
12012 if (testAttribute(attribute: Qt::WA_WState_Created))
12013 d->stackUnder_sys(w);
12014
12015 QEvent e(QEvent::ZOrderChange);
12016 QCoreApplication::sendEvent(receiver: this, event: &e);
12017}
12018
12019void QWidgetPrivate::stackUnder_sys(QWidget*)
12020{
12021 Q_Q(QWidget);
12022 if (QWidget *p = q->parentWidget()) {
12023 setDirtyOpaqueRegion();
12024 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12025 }
12026}
12027
12028/*!
12029 \fn bool QWidget::isTopLevel() const
12030 \deprecated
12031
12032 Use isWindow() instead.
12033*/
12034
12035/*!
12036 \fn bool QWidget::isRightToLeft() const
12037 \internal
12038*/
12039
12040/*!
12041 \fn bool QWidget::isLeftToRight() const
12042 \internal
12043*/
12044
12045/*!
12046 \macro QWIDGETSIZE_MAX
12047 \relates QWidget
12048
12049 Defines the maximum size for a QWidget object.
12050
12051 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12052 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12053
12054 \sa QWidget::setMaximumSize()
12055*/
12056
12057/*!
12058 \fn QWidget::setupUi(QWidget *widget)
12059
12060 Sets up the user interface for the specified \a widget.
12061
12062 \note This function is available with widgets that derive from user
12063 interface descriptions created using \l{uic}.
12064
12065 \sa {Using a Designer UI File in Your Application}
12066*/
12067
12068QRect QWidgetPrivate::frameStrut() const
12069{
12070 Q_Q(const QWidget);
12071 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
12072 // x2 = x1 + w - 1, so w/h = 1
12073 return QRect(0, 0, 1, 1);
12074 }
12075
12076 if (data.fstrut_dirty
12077 // ### Fix properly for 4.3
12078 && q->isVisible()
12079 && q->testAttribute(attribute: Qt::WA_WState_Created))
12080 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12081
12082 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12083}
12084
12085void QWidgetPrivate::updateFrameStrut()
12086{
12087 Q_Q(QWidget);
12088 if (q->data->fstrut_dirty) {
12089 if (QTLWExtra *te = maybeTopData()) {
12090 if (te->window && te->window->handle()) {
12091 const QMargins margins = te->window->frameMargins();
12092 if (!margins.isNull()) {
12093 te->frameStrut.setCoords(xp1: margins.left(), yp1: margins.top(), xp2: margins.right(), yp2: margins.bottom());
12094 q->data->fstrut_dirty = false;
12095 }
12096 }
12097 }
12098 }
12099}
12100
12101#ifdef QT_KEYPAD_NAVIGATION
12102/*!
12103 \internal
12104
12105 Changes the focus from the current focusWidget to a widget in
12106 the \a direction.
12107
12108 Returns \c true, if there was a widget in that direction
12109*/
12110bool QWidgetPrivate::navigateToDirection(Direction direction)
12111{
12112 QWidget *targetWidget = widgetInNavigationDirection(direction);
12113 if (targetWidget)
12114 targetWidget->setFocus();
12115 return (targetWidget != 0);
12116}
12117
12118/*!
12119 \internal
12120
12121 Searches for a widget that is positioned in the \a direction, starting
12122 from the current focusWidget.
12123
12124 Returns the pointer to a found widget or \nullptr, if there was no widget
12125 in that direction.
12126*/
12127QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12128{
12129 const QWidget *sourceWidget = QApplication::focusWidget();
12130 if (!sourceWidget)
12131 return nullptr;
12132 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12133 const int sourceX =
12134 (direction == DirectionNorth || direction == DirectionSouth) ?
12135 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12136 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12137 const int sourceY =
12138 (direction == DirectionEast || direction == DirectionWest) ?
12139 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12140 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12141 const QPoint sourcePoint(sourceX, sourceY);
12142 const QPoint sourceCenter = sourceRect.center();
12143 const QWidget *sourceWindow = sourceWidget->window();
12144
12145 QWidget *targetWidget = nullptr;
12146 int shortestDistance = INT_MAX;
12147
12148 const auto targetCandidates = QApplication::allWidgets();
12149 for (QWidget *targetCandidate : targetCandidates) {
12150
12151 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12152
12153 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12154 // but the owner of the proxy cannot.
12155 // Additionally, empty widgets should be ignored.
12156 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12157 continue;
12158
12159 // Only navigate to a target widget that...
12160 if ( targetCandidate != sourceWidget
12161 // ...takes the focus,
12162 && targetCandidate->focusPolicy() & Qt::TabFocus
12163 // ...is above if DirectionNorth,
12164 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12165 // ...is on the right if DirectionEast,
12166 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12167 // ...is below if DirectionSouth,
12168 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12169 // ...is on the left if DirectionWest,
12170 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12171 // ...is enabled,
12172 && targetCandidate->isEnabled()
12173 // ...is visible,
12174 && targetCandidate->isVisible()
12175 // ...is in the same window,
12176 && targetCandidate->window() == sourceWindow) {
12177 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12178 const QRect &targetCandidateRect) {
12179 int dx = 0;
12180 int dy = 0;
12181 if (p.x() < r.left())
12182 dx = r.left() - p.x();
12183 else if (p.x() > r.right())
12184 dx = p.x() - r.right();
12185 if (p.y() < r.top())
12186 dy = r.top() - p.y();
12187 else if (p.y() > r.bottom())
12188 dy = p.y() - r.bottom();
12189 return dx + dy;
12190 }();
12191 if (targetCandidateDistance < shortestDistance) {
12192 shortestDistance = targetCandidateDistance;
12193 targetWidget = targetCandidate;
12194 }
12195 }
12196 }
12197 return targetWidget;
12198}
12199
12200/*!
12201 \internal
12202
12203 Tells us if it there is currently a reachable widget by keypad navigation in
12204 a certain \a orientation.
12205 If no navigation is possible, occurring key events in that \a orientation may
12206 be used to interact with the value in the focused widget, even though it
12207 currently has not the editFocus.
12208
12209 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12210*/
12211bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12212{
12213 return orientation == Qt::Horizontal?
12214 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12215 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12216 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12217 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12218}
12219/*!
12220 \internal
12221
12222 Checks, if the \a widget is inside a QTabWidget. If is is inside
12223 one, left/right key events will be used to switch between tabs in keypad
12224 navigation. If there is no QTabWidget, the horizontal key events can be used
12225to
12226 interact with the value in the focused widget, even though it currently has
12227 not the editFocus.
12228
12229 \sa QWidget::hasEditFocus()
12230*/
12231bool QWidgetPrivate::inTabWidget(QWidget *widget)
12232{
12233 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12234 if (qobject_cast<const QTabWidget*>(tabWidget))
12235 return true;
12236 return false;
12237}
12238#endif
12239
12240/*!
12241 \since 5.0
12242 \internal
12243
12244 Sets the backing store to be the \a store specified.
12245 The QWidget will take ownership of the \a store.
12246*/
12247void QWidget::setBackingStore(QBackingStore *store)
12248{
12249 // ### createWinId() ??
12250
12251 if (!isWindow())
12252 return;
12253
12254 Q_D(QWidget);
12255
12256 QTLWExtra *topData = d->topData();
12257 if (topData->backingStore == store)
12258 return;
12259
12260 QBackingStore *oldStore = topData->backingStore;
12261 deleteBackingStore(d);
12262 topData->backingStore = store;
12263
12264 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12265 if (!repaintManager)
12266 return;
12267
12268 if (isWindow()) {
12269 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12270 delete repaintManager->backingStore();
12271 repaintManager->setBackingStore(store);
12272 }
12273}
12274
12275/*!
12276 \since 5.0
12277
12278 Returns the QBackingStore this widget will be drawn into.
12279*/
12280QBackingStore *QWidget::backingStore() const
12281{
12282 Q_D(const QWidget);
12283 QTLWExtra *extra = d->maybeTopData();
12284 if (extra && extra->backingStore)
12285 return extra->backingStore;
12286
12287 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12288 return repaintManager ? repaintManager->backingStore() : nullptr;
12289}
12290
12291void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12292{
12293 if (left)
12294 *left = (int)leftLayoutItemMargin;
12295 if (top)
12296 *top = (int)topLayoutItemMargin;
12297 if (right)
12298 *right = (int)rightLayoutItemMargin;
12299 if (bottom)
12300 *bottom = (int)bottomLayoutItemMargin;
12301}
12302
12303void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12304{
12305 if (leftLayoutItemMargin == left
12306 && topLayoutItemMargin == top
12307 && rightLayoutItemMargin == right
12308 && bottomLayoutItemMargin == bottom)
12309 return;
12310
12311 Q_Q(QWidget);
12312 leftLayoutItemMargin = (signed char)left;
12313 topLayoutItemMargin = (signed char)top;
12314 rightLayoutItemMargin = (signed char)right;
12315 bottomLayoutItemMargin = (signed char)bottom;
12316 q->updateGeometry();
12317}
12318
12319void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12320{
12321 Q_Q(QWidget);
12322 QStyleOption myOpt;
12323 if (!opt) {
12324 myOpt.initFrom(w: q);
12325 myOpt.rect.setRect(ax: 0, ay: 0, aw: 32768, ah: 32768); // arbitrary
12326 opt = &myOpt;
12327 }
12328
12329 QRect liRect = q->style()->subElementRect(subElement: element, option: opt, widget: q);
12330 if (liRect.isValid()) {
12331 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12332 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12333 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12334 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12335 } else {
12336 leftLayoutItemMargin = 0;
12337 topLayoutItemMargin = 0;
12338 rightLayoutItemMargin = 0;
12339 bottomLayoutItemMargin = 0;
12340 }
12341}
12342// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12343void QWidgetPrivate::adjustQuitOnCloseAttribute()
12344{
12345 Q_Q(QWidget);
12346
12347 if (!q->parentWidget()) {
12348 Qt::WindowType type = q->windowType();
12349 if (type == Qt::Widget || type == Qt::SubWindow)
12350 type = Qt::Window;
12351 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12352 q->setAttribute(attribute: Qt::WA_QuitOnClose, on: false);
12353 }
12354}
12355
12356void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12357{
12358 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12359 if (!wd->textureChildSeen)
12360 return;
12361 if (end)
12362 wd->endCompose();
12363 else
12364 wd->beginCompose();
12365 for (int i = 0; i < wd->children.size(); ++i) {
12366 w = qobject_cast<QWidget *>(o: wd->children.at(i));
12367 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12368 sendComposeStatus(w, end);
12369 }
12370}
12371
12372Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12373{
12374 return widget->data;
12375}
12376
12377Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12378{
12379 return widget->d_func();
12380}
12381
12382
12383#if QT_CONFIG(graphicsview)
12384/*!
12385 \since 4.5
12386
12387 Returns the proxy widget for the corresponding embedded widget in a graphics
12388 view; otherwise returns \nullptr.
12389
12390 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12391 QGraphicsScene::addWidget()
12392 */
12393QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12394{
12395 Q_D(const QWidget);
12396 if (d->extra) {
12397 return d->extra->proxyWidget;
12398 }
12399 return nullptr;
12400}
12401#endif
12402
12403#ifndef QT_NO_GESTURES
12404/*!
12405 Subscribes the widget to a given \a gesture with specific \a flags.
12406
12407 \sa ungrabGesture(), QGestureEvent
12408 \since 4.6
12409*/
12410void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12411{
12412 Q_D(QWidget);
12413 d->gestureContext.insert(key: gesture, value: flags);
12414 (void)QGestureManager::instance(); // create a gesture manager
12415}
12416
12417/*!
12418 Unsubscribes the widget from a given \a gesture type
12419
12420 \sa grabGesture(), QGestureEvent
12421 \since 4.6
12422*/
12423void QWidget::ungrabGesture(Qt::GestureType gesture)
12424{
12425 // if you modify this function, check the inlined version in ~QWidget, too
12426 Q_D(QWidget);
12427 if (d->gestureContext.remove(key: gesture)) {
12428 if (QGestureManager *manager = QGestureManager::instance())
12429 manager->cleanupCachedGestures(target: this, type: gesture);
12430 }
12431}
12432#endif // QT_NO_GESTURES
12433
12434/*!
12435 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12436
12437 Frees up window system resources. Destroys the widget window if \a
12438 destroyWindow is true.
12439
12440 destroy() calls itself recursively for all the child widgets,
12441 passing \a destroySubWindows for the \a destroyWindow parameter.
12442 To have more control over destruction of subwidgets, destroy
12443 subwidgets selectively first.
12444
12445 This function is usually called from the QWidget destructor.
12446*/
12447void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12448{
12449 Q_D(QWidget);
12450
12451 d->aboutToDestroy();
12452 if (!isWindow() && parentWidget())
12453 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(rect: geometry()));
12454 d->deactivateWidgetCleanup();
12455
12456 if ((windowType() == Qt::Popup) && qApp)
12457 qApp->d_func()->closePopup(popup: this);
12458
12459 if (this == QApplicationPrivate::active_window)
12460 QApplicationPrivate::setActiveWindow(nullptr);
12461 if (QWidget::mouseGrabber() == this)
12462 releaseMouse();
12463 if (QWidget::keyboardGrabber() == this)
12464 releaseKeyboard();
12465
12466 setAttribute(attribute: Qt::WA_WState_Created, on: false);
12467
12468 if (windowType() != Qt::Desktop) {
12469 if (destroySubWindows) {
12470 QObjectList childList(children());
12471 for (int i = 0; i < childList.size(); i++) {
12472 QWidget *widget = qobject_cast<QWidget *>(o: childList.at(i));
12473 if (widget && widget->testAttribute(attribute: Qt::WA_NativeWindow)) {
12474 if (widget->windowHandle()) {
12475 widget->destroy();
12476 }
12477 }
12478 }
12479 }
12480 if (destroyWindow) {
12481 d->deleteTLSysExtra();
12482 } else {
12483 if (parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_WState_Created)) {
12484 d->hide_sys();
12485 }
12486 }
12487
12488 d->setWinId(0);
12489 }
12490}
12491
12492/*!
12493 \fn QPaintEngine *QWidget::paintEngine() const
12494
12495 Returns the widget's paint engine.
12496
12497 Note that this function should not be called explicitly by the
12498 user, since it's meant for reimplementation purposes only. The
12499 function is called by Qt internally, and the default
12500 implementation may not always return a valid pointer.
12501*/
12502QPaintEngine *QWidget::paintEngine() const
12503{
12504 qWarning(msg: "QWidget::paintEngine: Should no longer be called");
12505
12506#ifdef Q_OS_WIN
12507 // We set this bit which is checked in setAttribute for
12508 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12509 //
12510 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12511 // Windows which would mean suddenly their widgets stop working.
12512 //
12513 // 2. Users set paint on screen and subclass paintEngine() to
12514 // return 0, in which case we have a "hole" in the backingstore
12515 // allowing use of GDI or DirectX directly.
12516 //
12517 // 1 is WRONG, but to minimize silent failures, we have set this
12518 // bit to ignore the setAttribute call. 2. needs to be
12519 // supported because its our only means of embedding native
12520 // graphics stuff.
12521 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12522#endif
12523
12524 return nullptr; //##### @@@
12525}
12526
12527// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12528static inline bool canMapPosition(QWindow *window)
12529{
12530 return window->handle() && !qt_window_private(window)->resizeEventPending;
12531}
12532
12533#if QT_CONFIG(graphicsview)
12534static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12535{
12536 QGraphicsProxyWidget *result = nullptr;
12537 const QWidgetPrivate *d = qt_widget_private(widget: const_cast<QWidget *>(w));
12538 if (d->extra)
12539 result = d->extra->proxyWidget;
12540 return result;
12541}
12542#endif // QT_CONFIG(graphicsview)
12543
12544struct MapToGlobalTransformResult {
12545 QTransform transform;
12546 QWindow *window;
12547};
12548
12549static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12550{
12551 MapToGlobalTransformResult result;
12552 result.window = nullptr;
12553 for ( ; w ; w = w->parentWidget()) {
12554#if QT_CONFIG(graphicsview)
12555 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12556 if (const QGraphicsScene *scene = qgpw->scene()) {
12557 const QList <QGraphicsView *> views = scene->views();
12558 if (!views.isEmpty()) {
12559 result.transform *= qgpw->sceneTransform();
12560 result.transform *= views.first()->viewportTransform();
12561 w = views.first()->viewport();
12562 }
12563 }
12564 }
12565#endif // QT_CONFIG(graphicsview)
12566 QWindow *window = w->windowHandle();
12567 if (window && canMapPosition(window)) {
12568 result.window = window;
12569 break;
12570 }
12571
12572 const QPoint topLeft = w->geometry().topLeft();
12573 result.transform.translate(dx: topLeft.x(), dy: topLeft.y());
12574 if (w->isWindow())
12575 break;
12576 }
12577 return result;
12578}
12579
12580/*!
12581 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12582
12583 Translates the widget coordinate \a pos to global screen
12584 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12585 the global coordinates of the top-left pixel of the widget.
12586
12587 \sa mapFromGlobal(), mapTo(), mapToParent()
12588 \since 6.0
12589*/
12590QPointF QWidget::mapToGlobal(const QPointF &pos) const
12591{
12592 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12593 const QPointF g = t.transform.map(p: pos);
12594 return t.window ? t.window->mapToGlobal(pos: g) : g;
12595}
12596
12597/*!
12598 \overload
12599*/
12600QPoint QWidget::mapToGlobal(const QPoint &pos) const
12601{
12602 return mapToGlobal(pos: QPointF(pos)).toPoint();
12603}
12604
12605/*!
12606 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12607
12608 Translates the global screen coordinate \a pos to widget
12609 coordinates.
12610
12611 \sa mapToGlobal(), mapFrom(), mapFromParent()
12612 \since 6.0
12613*/
12614QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12615{
12616 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12617 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12618 return t.transform.inverted().map(p: windowLocal);
12619}
12620
12621/*!
12622 \overload
12623*/
12624QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12625{
12626 return mapFromGlobal(pos: QPointF(pos)).toPoint();
12627}
12628
12629QWidget *qt_pressGrab = nullptr;
12630QWidget *qt_mouseGrb = nullptr;
12631static bool mouseGrabWithCursor = false;
12632static QWidget *keyboardGrb = nullptr;
12633
12634static inline QWindow *grabberWindow(const QWidget *w)
12635{
12636 QWindow *window = w->windowHandle();
12637 if (!window)
12638 if (const QWidget *nativeParent = w->nativeParentWidget())
12639 window = nativeParent->windowHandle();
12640 return window;
12641}
12642
12643#ifndef QT_NO_CURSOR
12644static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12645#else
12646static void grabMouseForWidget(QWidget *widget)
12647#endif
12648{
12649 if (qt_mouseGrb)
12650 qt_mouseGrb->releaseMouse();
12651
12652 mouseGrabWithCursor = false;
12653 if (QWindow *window = grabberWindow(w: widget)) {
12654#ifndef QT_NO_CURSOR
12655 if (cursor) {
12656 mouseGrabWithCursor = true;
12657 QGuiApplication::setOverrideCursor(*cursor);
12658 }
12659#endif // !QT_NO_CURSOR
12660 window->setMouseGrabEnabled(true);
12661 }
12662
12663 qt_mouseGrb = widget;
12664 qt_pressGrab = nullptr;
12665}
12666
12667static void releaseMouseGrabOfWidget(QWidget *widget)
12668{
12669 if (qt_mouseGrb == widget) {
12670 if (QWindow *window = grabberWindow(w: widget)) {
12671#ifndef QT_NO_CURSOR
12672 if (mouseGrabWithCursor) {
12673 QGuiApplication::restoreOverrideCursor();
12674 mouseGrabWithCursor = false;
12675 }
12676#endif // !QT_NO_CURSOR
12677 window->setMouseGrabEnabled(false);
12678 }
12679 }
12680 qt_mouseGrb = nullptr;
12681}
12682
12683/*!
12684 \fn void QWidget::grabMouse()
12685
12686 Grabs the mouse input.
12687
12688 This widget receives all mouse events until releaseMouse() is
12689 called; other widgets get no mouse events at all. Keyboard
12690 events are not affected. Use grabKeyboard() if you want to grab
12691 that.
12692
12693 \warning Bugs in mouse-grabbing applications very often lock the
12694 terminal. Use this function with extreme caution, and consider
12695 using the \c -nograb command line option while debugging.
12696
12697 It is almost never necessary to grab the mouse when using Qt, as
12698 Qt grabs and releases it sensibly. In particular, Qt grabs the
12699 mouse when a mouse button is pressed and keeps it until the last
12700 button is released.
12701
12702 \note Only visible widgets can grab mouse input. If isVisible()
12703 returns \c false for a widget, that widget cannot call grabMouse().
12704
12705 \note On Windows, grabMouse() only works when the mouse is inside a window
12706 owned by the process.
12707 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12708
12709 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12710*/
12711void QWidget::grabMouse()
12712{
12713 grabMouseForWidget(widget: this);
12714}
12715
12716/*!
12717 \fn void QWidget::grabMouse(const QCursor &cursor)
12718 \overload grabMouse()
12719
12720 Grabs the mouse input and changes the cursor shape.
12721
12722 The cursor will assume shape \a cursor (for as long as the mouse
12723 focus is grabbed) and this widget will be the only one to receive
12724 mouse events until releaseMouse() is called().
12725
12726 \warning Grabbing the mouse might lock the terminal.
12727
12728 \note See the note in QWidget::grabMouse().
12729
12730 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12731*/
12732#ifndef QT_NO_CURSOR
12733void QWidget::grabMouse(const QCursor &cursor)
12734{
12735 grabMouseForWidget(widget: this, cursor: &cursor);
12736}
12737#endif
12738
12739bool QWidgetPrivate::stealMouseGrab(bool grab)
12740{
12741 // This is like a combination of grab/releaseMouse() but with error checking
12742 // and it has no effect on the result of mouseGrabber().
12743 Q_Q(QWidget);
12744 QWindow *window = grabberWindow(w: q);
12745 return window ? window->setMouseGrabEnabled(grab) : false;
12746}
12747
12748/*!
12749 \fn void QWidget::releaseMouse()
12750
12751 Releases the mouse grab.
12752
12753 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12754*/
12755void QWidget::releaseMouse()
12756{
12757 releaseMouseGrabOfWidget(widget: this);
12758}
12759
12760/*!
12761 \fn void QWidget::grabKeyboard()
12762
12763 Grabs the keyboard input.
12764
12765 This widget receives all keyboard events until releaseKeyboard()
12766 is called; other widgets get no keyboard events at all. Mouse
12767 events are not affected. Use grabMouse() if you want to grab that.
12768
12769 The focus widget is not affected, except that it doesn't receive
12770 any keyboard events. setFocus() moves the focus as usual, but the
12771 new focus widget receives keyboard events only after
12772 releaseKeyboard() is called.
12773
12774 If a different widget is currently grabbing keyboard input, that
12775 widget's grab is released first.
12776
12777 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12778*/
12779void QWidget::grabKeyboard()
12780{
12781 if (keyboardGrb)
12782 keyboardGrb->releaseKeyboard();
12783 if (QWindow *window = grabberWindow(w: this))
12784 window->setKeyboardGrabEnabled(true);
12785 keyboardGrb = this;
12786}
12787
12788bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12789{
12790 // This is like a combination of grab/releaseKeyboard() but with error
12791 // checking and it has no effect on the result of keyboardGrabber().
12792 Q_Q(QWidget);
12793 QWindow *window = grabberWindow(w: q);
12794 return window ? window->setKeyboardGrabEnabled(grab) : false;
12795}
12796
12797/*!
12798 \fn void QWidget::releaseKeyboard()
12799
12800 Releases the keyboard grab.
12801
12802 \sa grabKeyboard(), grabMouse(), releaseMouse()
12803*/
12804void QWidget::releaseKeyboard()
12805{
12806 if (keyboardGrb == this) {
12807 if (QWindow *window = grabberWindow(w: this))
12808 window->setKeyboardGrabEnabled(false);
12809 keyboardGrb = nullptr;
12810 }
12811}
12812
12813/*!
12814 \fn QWidget *QWidget::mouseGrabber()
12815
12816 Returns the widget that is currently grabbing the mouse input.
12817
12818 If no widget in this application is currently grabbing the mouse,
12819 \nullptr is returned.
12820
12821 \sa grabMouse(), keyboardGrabber()
12822*/
12823QWidget *QWidget::mouseGrabber()
12824{
12825 if (qt_mouseGrb)
12826 return qt_mouseGrb;
12827 return qt_pressGrab;
12828}
12829
12830/*!
12831 \fn QWidget *QWidget::keyboardGrabber()
12832
12833 Returns the widget that is currently grabbing the keyboard input.
12834
12835 If no widget in this application is currently grabbing the
12836 keyboard, \nullptr is returned.
12837
12838 \sa grabMouse(), mouseGrabber()
12839*/
12840QWidget *QWidget::keyboardGrabber()
12841{
12842 return keyboardGrb;
12843}
12844
12845/*!
12846 \fn void QWidget::activateWindow()
12847
12848 Sets the top-level widget containing this widget to be the active
12849 window.
12850
12851 An active window is a visible top-level window that has the
12852 keyboard input focus.
12853
12854 This function performs the same operation as clicking the mouse on
12855 the title bar of a top-level window. On X11, the result depends on
12856 the Window Manager. If you want to ensure that the window is
12857 stacked on top as well you should also call raise(). Note that the
12858 window must be visible, otherwise activateWindow() has no effect.
12859
12860 On Windows, if you are calling this when the application is not
12861 currently the active one then it will not make it the active
12862 window. It will change the color of the taskbar entry to indicate
12863 that the window has changed in some way. This is because Microsoft
12864 does not allow an application to interrupt what the user is currently
12865 doing in another application.
12866
12867 \sa isActiveWindow(), window(), show()
12868*/
12869void QWidget::activateWindow()
12870{
12871 QWindow *const wnd = window()->windowHandle();
12872
12873 if (wnd)
12874 wnd->requestActivate();
12875}
12876
12877/*!
12878
12879 Internal implementation of the virtual QPaintDevice::metric()
12880 function.
12881
12882 \a m is the metric to get.
12883*/
12884int QWidget::metric(PaintDeviceMetric m) const
12885{
12886 QScreen *screen = this->screen();
12887
12888 if (!screen) {
12889 if (m == PdmDpiX || m == PdmDpiY)
12890 return 72;
12891 return QPaintDevice::metric(metric: m);
12892 }
12893
12894 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12895
12896 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12897 static bool downscale = qEnvironmentVariableIntValue(varName: "QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12898 QWindow *window = this->window()->windowHandle();
12899 if (window)
12900 return downscale ? std::ceil(x: window->devicePixelRatio()) : window->devicePixelRatio();
12901 return screen->devicePixelRatio();
12902 };
12903
12904 switch (m) {
12905 case PdmWidth:
12906 return data->crect.width();
12907 case PdmWidthMM:
12908 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12909 case PdmHeight:
12910 return data->crect.height();
12911 case PdmHeightMM:
12912 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12913 case PdmDepth:
12914 return screen->depth();
12915 case PdmDpiX:
12916 for (const QWidget *p = this; p; p = p->parentWidget()) {
12917 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12918 return p->d_func()->extra->customDpiX;
12919 }
12920 return qRound(d: screen->logicalDotsPerInchX());
12921 case PdmDpiY:
12922 for (const QWidget *p = this; p; p = p->parentWidget()) {
12923 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12924 return p->d_func()->extra->customDpiY;
12925 }
12926 return qRound(d: screen->logicalDotsPerInchY());
12927 case PdmPhysicalDpiX:
12928 return qRound(d: screen->physicalDotsPerInchX());
12929 case PdmPhysicalDpiY:
12930 return qRound(d: screen->physicalDotsPerInchY());
12931 case PdmDevicePixelRatio:
12932 return resolveDevicePixelRatio();
12933 case PdmDevicePixelRatioScaled:
12934 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
12935 default:
12936 break;
12937 }
12938 return QPaintDevice::metric(metric: m);
12939}
12940
12941/*!
12942 Initializes the \a painter pen, background and font to the same as
12943 the given widget's. This function is called automatically when the
12944 painter is opened on a QWidget.
12945*/
12946void QWidget::initPainter(QPainter *painter) const
12947{
12948 const QPalette &pal = palette();
12949 painter->d_func()->state->pen = QPen(pal.brush(cr: foregroundRole()), 1);
12950 painter->d_func()->state->bgBrush = pal.brush(cr: backgroundRole());
12951 QFont f(font(), const_cast<QWidget *>(this));
12952 painter->d_func()->state->deviceFont = f;
12953 painter->d_func()->state->font = f;
12954}
12955
12956/*!
12957 \internal
12958
12959 Do PaintDevice rendering with the specified \a offset.
12960*/
12961QPaintDevice *QWidget::redirected(QPoint *offset) const
12962{
12963 return d_func()->redirected(offset);
12964}
12965
12966/*!
12967 \internal
12968
12969 A painter that is shared among other instances of QPainter.
12970*/
12971QPainter *QWidget::sharedPainter() const
12972{
12973 // Someone sent a paint event directly to the widget
12974 if (!d_func()->redirectDev)
12975 return nullptr;
12976
12977 QPainter *sp = d_func()->sharedPainter();
12978 if (!sp || !sp->isActive())
12979 return nullptr;
12980
12981 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12982 return nullptr;
12983
12984 return sp;
12985}
12986
12987/*!
12988 \fn void QWidget::setMask(const QRegion &region)
12989 \overload
12990
12991 Causes only the parts of the widget which overlap \a region to be
12992 visible. If the region includes pixels outside the rect() of the
12993 widget, window system controls in that area may or may not be
12994 visible, depending on the platform.
12995
12996 Since QRegion allows arbitrarily complex regions to be created, widget
12997 masks can be made to suit the most unconventionally-shaped windows, and
12998 even allow widgets to be displayed with holes in them. Note that this
12999 effect can be slow if the region is particularly complex.
13000
13001 Widget masks are used to hint to the window system that the application
13002 does not want mouse events for areas outside the mask. On most systems,
13003 they also result in coarse visual clipping. To get smooth window edges, use
13004 translucent background and anti-aliased painting instead, as shown in the
13005 \l{Translucent Background} example.
13006
13007 \sa windowOpacity
13008*/
13009void QWidget::setMask(const QRegion &newMask)
13010{
13011 Q_D(QWidget);
13012
13013 d->createExtra();
13014 if (newMask == d->extra->mask)
13015 return;
13016
13017#ifndef QT_NO_BACKINGSTORE
13018 const QRegion oldMask(d->extra->mask);
13019#endif
13020
13021 d->extra->mask = newMask;
13022 d->extra->hasMask = !newMask.isEmpty();
13023
13024 if (!testAttribute(attribute: Qt::WA_WState_Created))
13025 return;
13026
13027 d->setMask_sys(newMask);
13028
13029#ifndef QT_NO_BACKINGSTORE
13030 if (!isVisible())
13031 return;
13032
13033 if (!d->extra->hasMask) {
13034 // Mask was cleared; update newly exposed area.
13035 QRegion expose(rect());
13036 expose -= oldMask;
13037 if (!expose.isEmpty()) {
13038 d->setDirtyOpaqueRegion();
13039 update(rgn: expose);
13040 }
13041 return;
13042 }
13043
13044 if (!isWindow()) {
13045 // Update newly exposed area on the parent widget.
13046 QRegion parentExpose(rect());
13047 parentExpose -= newMask;
13048 if (!parentExpose.isEmpty()) {
13049 d->setDirtyOpaqueRegion();
13050 parentExpose.translate(p: data->crect.topLeft());
13051 parentWidget()->update(rgn: parentExpose);
13052 }
13053
13054 // Update newly exposed area on this widget
13055 if (!oldMask.isEmpty())
13056 update(rgn: newMask - oldMask);
13057 }
13058#endif
13059}
13060
13061void QWidgetPrivate::setMask_sys(const QRegion &region)
13062{
13063 Q_Q(QWidget);
13064 if (QWindow *window = q->windowHandle())
13065 window->setMask(region);
13066}
13067
13068/*!
13069 \fn void QWidget::setMask(const QBitmap &bitmap)
13070
13071 Causes only the pixels of the widget for which \a bitmap has a
13072 corresponding 1 bit to be visible. If the region includes pixels
13073 outside the rect() of the widget, window system controls in that
13074 area may or may not be visible, depending on the platform.
13075
13076 Note that this effect can be slow if the region is particularly
13077 complex.
13078
13079 The following code shows how an image with an alpha channel can be
13080 used to generate a mask for a widget:
13081
13082 \snippet widget-mask/main.cpp 0
13083
13084 The label shown by this code is masked using the image it contains,
13085 giving the appearance that an irregularly-shaped image is being drawn
13086 directly onto the screen.
13087
13088 Masked widgets receive mouse events only on their visible
13089 portions.
13090
13091 \sa clearMask(), windowOpacity()
13092*/
13093void QWidget::setMask(const QBitmap &bitmap)
13094{
13095 setMask(QRegion(bitmap));
13096}
13097
13098/*!
13099 \fn void QWidget::clearMask()
13100
13101 Removes any mask set by setMask().
13102
13103 \sa setMask()
13104*/
13105void QWidget::clearMask()
13106{
13107 Q_D(QWidget);
13108 if (!d->extra || !d->extra->hasMask)
13109 return;
13110 setMask(QRegion());
13111}
13112
13113void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13114{
13115 Q_ASSERT(widgetAsObject->isWidgetType());
13116 Q_ASSERT(!newParent || newParent->isWidgetType());
13117 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13118 widget->setParent(static_cast<QWidget*>(newParent));
13119}
13120
13121std::string QWidgetPrivate::flagsForDumping() const
13122{
13123 Q_Q(const QWidget);
13124 std::string flags = QObjectPrivate::flagsForDumping();
13125 if (QApplication::focusWidget() == q)
13126 flags += 'F';
13127 if (q->isVisible()) {
13128 std::stringstream s;
13129 s << '<'
13130 << q->width() << 'x' << q->height()
13131 << std::showpos << q->x() << q->y()
13132 << '>';
13133 flags += s.str();
13134 } else {
13135 flags += 'I';
13136 }
13137 return flags;
13138}
13139
13140void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13141{
13142#if QT_CONFIG(xcb)
13143 Q_Q(QWidget);
13144
13145 if (!q->windowHandle())
13146 return;
13147
13148 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13149 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDesktop))
13150 wmWindowType |= QXcbWindow::Desktop;
13151 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDock))
13152 wmWindowType |= QXcbWindow::Dock;
13153 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolBar))
13154 wmWindowType |= QXcbWindow::Toolbar;
13155 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeMenu))
13156 wmWindowType |= QXcbWindow::Menu;
13157 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeUtility))
13158 wmWindowType |= QXcbWindow::Utility;
13159 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeSplash))
13160 wmWindowType |= QXcbWindow::Splash;
13161 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDialog))
13162 wmWindowType |= QXcbWindow::Dialog;
13163 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDropDownMenu))
13164 wmWindowType |= QXcbWindow::DropDownMenu;
13165 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypePopupMenu))
13166 wmWindowType |= QXcbWindow::PopupMenu;
13167 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolTip))
13168 wmWindowType |= QXcbWindow::Tooltip;
13169 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeNotification))
13170 wmWindowType |= QXcbWindow::Notification;
13171 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeCombo))
13172 wmWindowType |= QXcbWindow::Combo;
13173 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDND))
13174 wmWindowType |= QXcbWindow::Dnd;
13175
13176 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13177 return;
13178
13179 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13180 xcbWindow->setWindowType(wmWindowType);
13181#else
13182 Q_UNUSED(skipIfMissing);
13183#endif
13184}
13185
13186#ifndef QT_NO_DEBUG_STREAM
13187
13188static inline void formatWidgetAttributes(QDebug debug, const QWidget *widget)
13189{
13190 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13191 const QMetaEnum me = qtMo->enumerator(index: qtMo->indexOfEnumerator(name: "WidgetAttribute"));
13192 debug << ", attributes=[";
13193 int count = 0;
13194 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13195 if (widget->testAttribute(attribute: static_cast<Qt::WidgetAttribute>(a))) {
13196 if (count++)
13197 debug << ',';
13198 debug << me.valueToKey(value: a);
13199 }
13200 }
13201 debug << ']';
13202}
13203
13204QDebug operator<<(QDebug debug, const QWidget *widget)
13205{
13206 const QDebugStateSaver saver(debug);
13207 debug.nospace();
13208 if (widget) {
13209 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13210 if (!widget->objectName().isEmpty())
13211 debug << ", name=" << widget->objectName();
13212 if (debug.verbosity() > 2) {
13213 const QRect geometry = widget->geometry();
13214 const QRect frameGeometry = widget->frameGeometry();
13215 if (widget->isVisible())
13216 debug << ", visible";
13217 if (!widget->isEnabled())
13218 debug << ", disabled";
13219 debug << ", states=" << widget->windowState()
13220 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13221 formatWidgetAttributes(debug, widget);
13222 if (widget->isWindow())
13223 debug << ", window";
13224 debug << ", " << geometry.width() << 'x' << geometry.height()
13225 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13226 if (frameGeometry != geometry) {
13227 const QMargins margins(geometry.x() - frameGeometry.x(),
13228 geometry.y() - frameGeometry.y(),
13229 frameGeometry.right() - geometry.right(),
13230 frameGeometry.bottom() - geometry.bottom());
13231 debug << ", margins=" << margins;
13232 }
13233 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13234 if (const WId wid = widget->internalWinId())
13235 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13236 }
13237 debug << ')';
13238 } else {
13239 debug << "QWidget(0x0)";
13240 }
13241 return debug;
13242}
13243#endif // !QT_NO_DEBUG_STREAM
13244
13245QT_END_NAMESPACE
13246
13247#include "moc_qwidget.cpp"
13248#include "moc_qwidget_p.cpp"
13249

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