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());