1// Copyright (C) 2017 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qapplication.h"
6#include "qapplication_p.h"
7#include "qbrush.h"
8#include "qcursor.h"
9#include "private/qduplicatetracker_p.h"
10#include "qevent.h"
11#include "qlayout.h"
12#if QT_CONFIG(menu)
13#include "qmenu.h"
14#endif
15#include "qmetaobject.h"
16#include "qpixmap.h"
17#include "qpointer.h"
18#include "qstack.h"
19#include "qstyle.h"
20#include "qstylefactory.h"
21#include "qvariant.h"
22#include "qwidget.h"
23#include "qstyleoption.h"
24#include "qstylehints.h"
25#if QT_CONFIG(accessibility)
26# include "qaccessible.h"
27#endif
28#include <qpa/qplatformwindow.h>
29#include <qpa/qplatformwindow_p.h>
30#include "private/qwidgetwindow_p.h"
31#include "qpainter.h"
32#if QT_CONFIG(tooltip)
33#include "qtooltip.h"
34#endif
35#if QT_CONFIG(whatsthis)
36#include "qwhatsthis.h"
37#endif
38#include "qdebug.h"
39#if QT_CONFIG(style_stylesheet)
40#include "private/qstylesheetstyle_p.h"
41#endif
42#include "private/qstyle_p.h"
43#include "qfileinfo.h"
44#include "qscopeguard.h"
45#include <QtGui/private/qhighdpiscaling_p.h>
46#include <QtGui/qinputmethod.h>
47
48#if QT_CONFIG(graphicseffect)
49#include <private/qgraphicseffect_p.h>
50#endif
51#include <qbackingstore.h>
52#include <private/qwidgetrepaintmanager_p.h>
53#include <private/qpaintengine_raster_p.h>
54
55#include "qwidget_p.h"
56#include <QtGui/private/qwindow_p.h>
57#if QT_CONFIG(action)
58# include "QtGui/private/qaction_p.h"
59#endif
60#include "qlayout_p.h"
61#if QT_CONFIG(graphicsview)
62#include "QtWidgets/qgraphicsproxywidget.h"
63#include "QtWidgets/qgraphicsscene.h"
64#include "private/qgraphicsproxywidget_p.h"
65#include "private/qgraphicsview_p.h"
66#endif
67#include "QtWidgets/qabstractscrollarea.h"
68#include "private/qabstractscrollarea_p.h"
69#include "private/qevent_p.h"
70
71#include "private/qgesturemanager_p.h"
72
73#ifdef QT_KEYPAD_NAVIGATION
74#if QT_CONFIG(tabwidget)
75#include "qtabwidget.h" // Needed in inTabWidget()
76#endif
77#endif // QT_KEYPAD_NAVIGATION
78
79#include "qwindowcontainer_p.h"
80
81#include <sstream>
82
83QT_BEGIN_NAMESPACE
84
85using namespace QNativeInterface::Private;
86using namespace Qt::StringLiterals;
87
88Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
89Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
90Q_STATIC_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
91Q_STATIC_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
92
93#ifndef QT_NO_DEBUG_STREAM
94namespace {
95 struct WidgetAttributes { const QWidget *widget; };
96 QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
97}
98#endif
99
100static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
101{
102 return (qMax(a: r1.left(), b: r2.left()) <= qMin(a: r1.right(), b: r2.right()) &&
103 qMax(a: r1.top(), b: r2.top()) <= qMin(a: r1.bottom(), b: r2.bottom()));
104}
105
106extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
107
108static void setAttribute_internal(Qt::WidgetAttribute attribute,
109 bool on, QWidgetData *data, QWidgetPrivate *d);
110
111QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
112 : QObjectPrivate(version)
113 , focus_next(nullptr)
114 , focus_prev(nullptr)
115 , focus_child(nullptr)
116 , layout(nullptr)
117 , needsFlush(nullptr)
118 , redirectDev(nullptr)
119 , widgetItem(nullptr)
120 , extraPaintEngine(nullptr)
121 , polished(nullptr)
122 , graphicsEffect(nullptr)
123#if !defined(QT_NO_IM)
124 , imHints(Qt::ImhNone)
125#endif
126#if QT_CONFIG(tooltip)
127 , toolTipDuration(-1)
128#endif
129 , directFontResolveMask(0)
130 , inheritedFontResolveMask(0)
131 , directPaletteResolveMask(0)
132 , inheritedPaletteResolveMask(0)
133 , leftmargin(0)
134 , topmargin(0)
135 , rightmargin(0)
136 , bottommargin(0)
137 , leftLayoutItemMargin(0)
138 , topLayoutItemMargin(0)
139 , rightLayoutItemMargin(0)
140 , bottomLayoutItemMargin(0)
141 , hd(nullptr)
142 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
143 , fg_role(QPalette::NoRole)
144 , bg_role(QPalette::NoRole)
145 , dirtyOpaqueChildren(1)
146 , isOpaque(0)
147 , retainSizeWhenHiddenChanged(0)
148 , inDirtyList(0)
149 , isScrolled(0)
150 , isMoved(0)
151 , usesDoubleBufferedGLContext(0)
152 , mustHaveWindowHandle(0)
153 , renderToTexture(0)
154 , textureChildSeen(0)
155#ifndef QT_NO_IM
156 , inheritsInputMethodHints(0)
157#endif
158 , renderToTextureReallyDirty(1)
159 , usesRhiFlush(0)
160 , childrenHiddenByWState(0)
161 , childrenShownByExpose(0)
162 , dontSetExplicitShowHide(0)
163#if defined(Q_OS_WIN)
164 , noPaintOnScreen(0)
165#endif
166{
167 if (Q_UNLIKELY(!qApp)) {
168 qFatal(msg: "QWidget: Must construct a QApplication before a QWidget");
169 return;
170 }
171
172 willBeWidget = true; // used in QObject's ctor
173 memset(s: high_attributes, c: 0, n: sizeof(high_attributes));
174
175#ifdef QWIDGET_EXTRA_DEBUG
176 static int count = 0;
177 qDebug() << "widgets" << ++count;
178#endif
179}
180
181
182QWidgetPrivate::~QWidgetPrivate()
183{
184 if (widgetItem)
185 widgetItem->wid = nullptr;
186
187 if (extra)
188 deleteExtra();
189}
190
191/*!
192 \internal
193*/
194void QWidgetPrivate::scrollChildren(int dx, int dy)
195{
196 Q_Q(QWidget);
197 if (q->children().size() > 0) { // scroll children
198 QPoint pd(dx, dy);
199 QObjectList childObjects = q->children();
200 for (int i = 0; i < childObjects.size(); ++i) { // move all children
201 QWidget *w = qobject_cast<QWidget*>(o: childObjects.at(i));
202 if (w && !w->isWindow()) {
203 QPoint oldp = w->pos();
204 QRect r(w->pos() + pd, w->size());
205 w->data->crect = r;
206 if (w->testAttribute(attribute: Qt::WA_WState_Created))
207 w->d_func()->setWSGeometry();
208 w->d_func()->setDirtyOpaqueRegion();
209 QMoveEvent e(r.topLeft(), oldp);
210 QCoreApplication::sendEvent(receiver: w, event: &e);
211 }
212 }
213 }
214}
215
216void QWidgetPrivate::setWSGeometry()
217{
218 Q_Q(QWidget);
219 if (QWindow *window = q->windowHandle())
220 window->setGeometry(data.crect);
221}
222
223void QWidgetPrivate::updateWidgetTransform(QEvent *event)
224{
225 Q_Q(QWidget);
226 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
227 QTransform t;
228 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
229 t.translate(dx: p.x(), dy: p.y());
230 QGuiApplication::inputMethod()->setInputItemTransform(t);
231 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
232 QGuiApplication::inputMethod()->update(queries: Qt::ImInputItemClipRectangle);
233 }
234}
235
236#ifdef QT_KEYPAD_NAVIGATION
237QPointer<QWidget> QWidgetPrivate::editingWidget;
238
239/*!
240 Returns \c true if this widget currently has edit focus; otherwise false.
241
242 This feature is only available in Qt for Embedded Linux.
243
244 \sa setEditFocus(), QApplication::navigationMode()
245*/
246bool QWidget::hasEditFocus() const
247{
248 const QWidget* w = this;
249 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
250 w = w->d_func()->extra->focus_proxy;
251 return QWidgetPrivate::editingWidget == w;
252}
253
254/*!
255 \fn void QWidget::setEditFocus(bool enable)
256
257 If \a enable is true, make this widget have edit focus, in which
258 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
259 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
260 change focus.
261
262 This feature is only available in Qt for Embedded Linux.
263
264 \sa hasEditFocus(), QApplication::navigationMode()
265*/
266void QWidget::setEditFocus(bool on)
267{
268 QWidget *f = this;
269 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
270 f = f->d_func()->extra->focus_proxy;
271
272 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
273 QWidgetPrivate::editingWidget->setEditFocus(false);
274
275 if (on && !f->hasFocus())
276 f->setFocus();
277
278 if ((!on && !QWidgetPrivate::editingWidget)
279 || (on && QWidgetPrivate::editingWidget == f)) {
280 return;
281 }
282
283 if (!on && QWidgetPrivate::editingWidget == f) {
284 QWidgetPrivate::editingWidget = 0;
285 QEvent event(QEvent::LeaveEditFocus);
286 QCoreApplication::sendEvent(f, &event);
287 QCoreApplication::sendEvent(f->style(), &event);
288 } else if (on) {
289 QWidgetPrivate::editingWidget = f;
290 QEvent event(QEvent::EnterEditFocus);
291 QCoreApplication::sendEvent(f, &event);
292 QCoreApplication::sendEvent(f->style(), &event);
293 }
294}
295#endif
296
297/*!
298 \property QWidget::autoFillBackground
299 \brief whether the widget background is filled automatically
300 \since 4.1
301
302 If enabled, this property will cause Qt to fill the background of the
303 widget before invoking the paint event. The color used is defined by the
304 QPalette::Window color role from the widget's \l{QPalette}{palette}.
305
306 In addition, Windows are always filled with QPalette::Window, unless the
307 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
308
309 This property cannot be turned off (i.e., set to false) if a widget's
310 parent has a static gradient for its background.
311
312 \warning Use this property with caution in conjunction with
313 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
314 background or a border-image, this property is automatically disabled.
315
316 By default, this property is \c false.
317
318 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
319 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
320*/
321bool QWidget::autoFillBackground() const
322{
323 Q_D(const QWidget);
324 return d->extra && d->extra->autoFillBackground;
325}
326
327void QWidget::setAutoFillBackground(bool enabled)
328{
329 Q_D(QWidget);
330 if (!d->extra)
331 d->createExtra();
332 if (d->extra->autoFillBackground == enabled)
333 return;
334
335 d->extra->autoFillBackground = enabled;
336 d->updateIsOpaque();
337 update();
338 d->updateIsOpaque();
339}
340
341/*!
342 \class QWidget
343 \brief The QWidget class is the base class of all user interface objects.
344
345 \ingroup basicwidgets
346 \inmodule QtWidgets
347
348 The widget is the atom of the user interface: it receives mouse, keyboard
349 and other events from the window system, and paints a representation of
350 itself on the screen. Every widget is rectangular, and they are sorted in a
351 Z-order. A widget is clipped by its parent and by the widgets in front of
352 it.
353
354 A widget that is not embedded in a parent widget is called a window.
355 Usually, windows have a frame and a title bar, although it is also possible
356 to create windows without such decoration using suitable
357 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
358 subclasses of QDialog are the most common window types.
359
360 Every widget's constructor accepts one or two standard arguments:
361
362 \list 1
363 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
364 If it is \nullptr (the default), the new widget will be a window.
365 If not, it will be a child of \e parent, and be constrained by
366 \e parent's geometry (unless you specify Qt::Window as window flag).
367 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
368 the default is suitable for most widgets, but to get, for
369 example, a window without a window system frame, you must use
370 special flags.
371 \endlist
372
373 QWidget has many member functions, but some of them have little direct
374 functionality; for example, QWidget has a font property, but never uses
375 this itself. There are many subclasses that provide real functionality,
376 such as QLabel, QPushButton, QListWidget, and QTabWidget.
377
378
379 \section1 Top-Level and Child Widgets
380
381 A widget without a parent widget is always an independent window (top-level
382 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
383 title bar and icon, respectively.
384
385 Non-window widgets are child widgets, displayed within their parent
386 widgets. Most widgets in Qt are mainly useful as child widgets. For
387 example, it is possible to display a button as a top-level window, but most
388 people prefer to put their buttons inside other widgets, such as QDialog.
389
390 \image parent-child-widgets.png A parent widget containing various child widgets.
391
392 The diagram above shows a QGroupBox widget being used to hold various child
393 widgets in a layout provided by QGridLayout. The QLabel child widgets have
394 been outlined to indicate their full sizes.
395
396 If you want to use a QWidget to hold child widgets, you will usually want to
397 add a layout to the parent QWidget. See \l{Layout Management} for more
398 information.
399
400
401 \section1 Composite Widgets
402
403 When a widget is used as a container to group a number of child widgets, it
404 is known as a composite widget. These can be created by constructing a
405 widget with the required visual properties - a QFrame, for example - and
406 adding child widgets to it, usually managed by a layout.
407
408 Composite widgets can also be created by subclassing a standard widget,
409 such as QWidget or QFrame, and adding the necessary layout and child
410 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
411 {examples provided with Qt} use this approach, and it is also covered in
412 the Qt \l{Widgets Tutorial}.
413
414
415 \section1 Custom Widgets and Painting
416
417 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
418 display custom content that is composed using a series of painting
419 operations with an instance of the QPainter class. This approach contrasts
420 with the canvas-style approach used by the \l{Graphics View}
421 {Graphics View Framework} where items are added to a scene by the
422 application and are rendered by the framework itself.
423
424 Each widget performs all painting operations from within its paintEvent()
425 function. This is called whenever the widget needs to be redrawn, either
426 because of some external change or when requested by the application.
427
428 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
429 can handle paint events.
430
431
432 \section1 Size Hints and Size Policies
433
434 When implementing a new widget, it is almost always useful to reimplement
435 sizeHint() to provide a reasonable default size for the widget and to set
436 the correct size policy with setSizePolicy().
437
438 By default, composite widgets that do not provide a size hint will be
439 sized according to the space requirements of their child widgets.
440
441 The size policy lets you supply good default behavior for the layout
442 management system, so that other widgets can contain and manage yours
443 easily. The default size policy indicates that the size hint represents
444 the preferred size of the widget, and this is often good enough for many
445 widgets.
446
447 \note The size of top-level widgets are constrained to 2/3 of the desktop's
448 height and width. You can resize() the widget manually if these bounds are
449 inadequate.
450
451
452 \section1 Events
453
454 Widgets respond to events that are typically caused by user actions. Qt
455 delivers events to widgets by calling specific event handler functions with
456 instances of QEvent subclasses containing information about each event.
457
458 If your widget only contains child widgets, you probably don't need to
459 implement any event handlers. If you want to detect a mouse click in a
460 child widget, call the child's underMouse() function inside the widget's
461 mousePressEvent().
462
463 The \l{widgets/scribble}{Scribble example} implements a wider set of
464 events to handle mouse movement, button presses, and window resizing.
465
466 You will need to supply the behavior and content for your own widgets, but
467 here is a brief overview of the events that are relevant to QWidget,
468 starting with the most common ones:
469
470 \list
471 \li paintEvent() is called whenever the widget needs to be repainted.
472 Every widget displaying custom content must implement it. Painting
473 using a QPainter can only take place in a paintEvent() or a
474 function called by a paintEvent().
475 \li resizeEvent() is called when the widget has been resized.
476 \li mousePressEvent() is called when a mouse button is pressed while
477 the mouse cursor is inside the widget, or when the widget has
478 grabbed the mouse using grabMouse(). Pressing the mouse without
479 releasing it is effectively the same as calling grabMouse().
480 \li mouseReleaseEvent() is called when a mouse button is released. A
481 widget receives mouse release events when it has received the
482 corresponding mouse press event. This means that if the user
483 presses the mouse inside \e your widget, then drags the mouse
484 somewhere else before releasing the mouse button, \e your widget
485 receives the release event. There is one exception: if a popup menu
486 appears while the mouse button is held down, this popup immediately
487 steals the mouse events.
488 \li mouseDoubleClickEvent() is called when the user double-clicks in
489 the widget. If the user double-clicks, the widget receives a mouse
490 press event, a mouse release event, (a mouse click event,) a second
491 mouse press, this event and finally a second mouse release event.
492 (Some mouse move events may also be
493 received if the mouse is not held steady during this operation.) It
494 is \e{not possible} to distinguish a click from a double-click
495 until the second click arrives. (This is one reason why most GUI
496 books recommend that double-clicks be an extension of
497 single-clicks, rather than trigger a different action.)
498 \endlist
499
500 Widgets that accept keyboard input need to reimplement a few more event
501 handlers:
502
503 \list
504 \li keyPressEvent() is called whenever a key is pressed, and again when
505 a key has been held down long enough for it to auto-repeat. The
506 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
507 they are not used by the focus-change mechanisms. To force those
508 keys to be processed by your widget, you must reimplement
509 QWidget::event().
510 \li focusInEvent() is called when the widget gains keyboard focus
511 (assuming you have called setFocusPolicy()). Well-behaved widgets
512 indicate that they own the keyboard focus in a clear but discreet
513 way.
514 \li focusOutEvent() is called when the widget loses keyboard focus.
515 \endlist
516
517 You may be required to also reimplement some of the less common event
518 handlers:
519
520 \list
521 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
522 button is held down. This can be useful during drag and drop
523 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
524 you get mouse move events even when no buttons are held down.
525 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
526 \li keyReleaseEvent() is called whenever a key is released and while it
527 is held down (if the key is auto-repeating). In that case, the
528 widget will receive a pair of key release and key press event for
529 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
530 to the widget if they are not used by the focus-change mechanisms.
531 To force those keys to be processed by your widget, you must
532 reimplement QWidget::event().
533 \li wheelEvent() is called whenever the user turns the mouse wheel
534 while the widget has the focus.
535 \li enterEvent() is called when the mouse enters the widget's screen
536 space. (This excludes screen space owned by any of the widget's
537 children.)
538 \li leaveEvent() is called when the mouse leaves the widget's screen
539 space. If the mouse enters a child widget, it will not cause a
540 leaveEvent().
541 \li moveEvent() is called when the widget has been moved relative to
542 its parent.
543 \li closeEvent() is called when the user closes the widget (or when
544 close() is called).
545 \endlist
546
547 There are also some rather obscure events described in the documentation
548 for QEvent::Type. To handle these events, you need to reimplement event()
549 directly.
550
551 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
552 (to move the keyboard focus), and passes on most of the other events to
553 one of the more specialized handlers above.
554
555 Events and the mechanism used to deliver them are covered in
556 \l{The Event System}.
557
558 \section1 Groups of Functions and Properties
559
560 \table
561 \header \li Context \li Functions and Properties
562
563 \row \li Window functions \li
564 show(),
565 hide(),
566 raise(),
567 lower(),
568 close().
569
570 \row \li Top-level windows \li
571 \l windowModified, \l windowTitle, \l windowIcon,
572 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
573 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
574 showNormal().
575
576 \row \li Window contents \li
577 update(),
578 repaint(),
579 scroll().
580
581 \row \li Geometry \li
582 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
583 \l sizePolicy, sizeHint(), minimumSizeHint(),
584 updateGeometry(), layout(),
585 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
586 adjustSize(),
587 mapFromGlobal(), mapToGlobal(),
588 mapFromParent(), mapToParent(),
589 \l maximumSize, \l minimumSize, \l sizeIncrement,
590 \l baseSize, setFixedSize()
591
592 \row \li Mode \li
593 \l visible, isVisibleTo(),
594 \l enabled, isEnabledTo(),
595 \l modal,
596 isWindow(),
597 \l mouseTracking,
598 \l updatesEnabled,
599 visibleRegion().
600
601 \row \li Look and feel \li
602 style(),
603 setStyle(),
604 \l styleSheet,
605 \l cursor,
606 \l font,
607 \l palette,
608 backgroundRole(), setBackgroundRole(),
609 fontInfo(), fontMetrics().
610
611 \row \li Keyboard focus functions \li
612 \l focus, \l focusPolicy,
613 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
614 focusNextChild(), focusPreviousChild().
615
616 \row \li Mouse and keyboard grabbing \li
617 grabMouse(), releaseMouse(),
618 grabKeyboard(), releaseKeyboard(),
619 mouseGrabber(), keyboardGrabber().
620
621 \row \li Event handlers \li
622 event(),
623 mousePressEvent(),
624 mouseReleaseEvent(),
625 mouseDoubleClickEvent(),
626 mouseMoveEvent(),
627 keyPressEvent(),
628 keyReleaseEvent(),
629 focusInEvent(),
630 focusOutEvent(),
631 wheelEvent(),
632 enterEvent(),
633 leaveEvent(),
634 paintEvent(),
635 moveEvent(),
636 resizeEvent(),
637 closeEvent(),
638 dragEnterEvent(),
639 dragMoveEvent(),
640 dragLeaveEvent(),
641 dropEvent(),
642 childEvent(),
643 showEvent(),
644 hideEvent(),
645 customEvent().
646 changeEvent(),
647
648 \row \li System functions \li
649 parentWidget(), window(), setParent(), winId(),
650 find(), metric().
651
652 \row \li Context menu \li
653 contextMenuPolicy, contextMenuEvent(),
654 customContextMenuRequested(), actions()
655
656 \row \li Interactive help \li
657 setToolTip(), setWhatsThis()
658
659 \endtable
660
661
662 \section1 Widget Style Sheets
663
664 In addition to the standard widget styles for each platform, widgets can
665 also be styled according to rules specified in a \l{styleSheet}
666 {style sheet}. This feature enables you to customize the appearance of
667 specific widgets to provide visual cues to users about their purpose. For
668 example, a button could be styled in a particular way to indicate that it
669 performs a destructive action.
670
671 The use of widget style sheets is described in more detail in the
672 \l{Qt Style Sheets} document.
673
674
675 \section1 Transparency and Double Buffering
676
677 QWidget automatically double-buffers its painting, so there
678 is no need to write double-buffering code in paintEvent() to avoid
679 flicker.
680
681 The contents of parent widgets are propagated by
682 default to each of their children as long as Qt::WA_PaintOnScreen is not
683 set. Custom widgets can be written to take advantage of this feature by
684 updating irregular regions (to create non-rectangular child widgets), or
685 painting with colors that have less than full alpha component. The
686 following diagram shows how attributes and properties of a custom widget
687 can be fine-tuned to achieve different effects.
688
689 \image propagation-custom.png
690
691 In the above diagram, a semi-transparent rectangular child widget with an
692 area removed is constructed and added to a parent widget (a QLabel showing
693 a pixmap). Then, different properties and widget attributes are set to
694 achieve different effects:
695
696 \list
697 \li The left widget has no additional properties or widget attributes
698 set. This default state suits most custom widgets that have
699 transparency, are irregularly-shaped, or do not paint over their
700 entire area with an opaque brush.
701 \li The center widget has the \l autoFillBackground property set. This
702 property is used with custom widgets that rely on the widget to
703 supply a default background, and do not paint over their entire
704 area with an opaque brush.
705 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
706 set. This indicates that the widget will paint over its entire area
707 with opaque colors. The widget's area will initially be
708 \e{uninitialized}, represented in the diagram with a red diagonal
709 grid pattern that shines through the overpainted area.
710 \endlist
711
712 To rapidly update custom widgets with simple background colors, such as
713 real-time plotting or graphing widgets, it is better to define a suitable
714 background color (using setBackgroundRole() with the
715 QPalette::Window role), set the \l autoFillBackground property, and only
716 implement the necessary drawing functionality in the widget's paintEvent().
717
718 To rapidly update custom widgets that constantly paint over their entire
719 areas with opaque content, for example, video streaming widgets, it is
720 better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
721 overhead associated with repainting the widget's background.
722
723 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
724 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
725 attribute takes precedence. Depending on your requirements, you should
726 choose either one of them.
727
728 The contents of parent widgets are also propagated to standard Qt widgets.
729 This can lead to some unexpected results if the parent widget is decorated
730 in a non-standard way, as shown in the diagram below.
731
732 \image propagation-standard.png
733
734 The scope for customizing the painting behavior of standard Qt widgets,
735 without resorting to subclassing, is slightly less than that possible for
736 custom widgets. Usually, the desired appearance of a standard widget can be
737 achieved by setting its \l autoFillBackground property.
738
739
740 \section1 Creating Translucent Windows
741
742 You can create windows with translucent regions on window systems that
743 support compositing.
744
745 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
746 attribute with setAttribute() and ensure that its background is painted with
747 non-opaque colors in the regions you want to be partially transparent.
748
749 Platform notes:
750
751 \list
752 \li X11: This feature relies on the use of an X server that supports ARGB visuals
753 and a compositing window manager.
754 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
755 for the translucency to work.
756 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
757 for the translucency to work.
758 \endlist
759
760
761 \section1 Native Widgets vs Alien Widgets
762
763 Alien widgets are widgets unknown to the windowing system. They do not have
764 a native window handle associated with them. This feature significantly
765 speeds up widget painting, resizing, and removes flicker.
766
767 Should you require the old behavior with native windows, choose one of the
768 following options:
769
770 \list 1
771 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
772 \li Set the Qt::AA_NativeWindows attribute on your application. All
773 widgets will be native widgets.
774 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
775 and all its ancestors will become native (unless
776 Qt::WA_DontCreateNativeAncestors is set).
777 \li Call QWidget::winId to enforce a native window (this implies 3).
778 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
779 (this implies 3).
780 \endlist
781
782 \sa QEvent, QPainter, QGridLayout, QBoxLayout
783
784*/
785
786QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
787QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
788
789
790/*****************************************************************************
791 QWidget member functions
792 *****************************************************************************/
793
794/*
795 Widget state flags:
796 \list
797 \li Qt::WA_WState_Created The widget has a valid winId().
798 \li Qt::WA_WState_Visible The widget is currently visible.
799 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
800 become visible unless you call show() on it. Qt::WA_WState_Hidden
801 implies !Qt::WA_WState_Visible.
802 \li Qt::WA_WState_CompressKeys Compress keyboard events.
803 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
804 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
805 \li Qt::WA_WState_Reparented The widget has been reparented.
806 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
807 \endlist
808*/
809
810struct QWidgetExceptionCleaner
811{
812 /* this cleans up when the constructor throws an exception */
813 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
814 {
815#ifdef QT_NO_EXCEPTIONS
816 Q_UNUSED(that);
817 Q_UNUSED(d);
818#else
819 QWidgetPrivate::allWidgets->remove(that);
820 d->removeFromFocusChain();
821#endif
822 }
823};
824
825/*!
826 Constructs a widget which is a child of \a parent, with widget
827 flags set to \a f.
828
829 If \a parent is \nullptr, the new widget becomes a window. If
830 \a parent is another widget, this widget becomes a child window
831 inside \a parent. The new widget is deleted when its \a parent is
832 deleted.
833
834 The widget flags argument, \a f, is normally 0, but it can be set
835 to customize the frame of a window (i.e. \a parent must be
836 \nullptr). To customize the frame, use a value composed
837 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
838
839 If you add a child widget to an already visible widget you must
840 explicitly show the child to make it visible.
841
842 Note that the X11 version of Qt may not be able to deliver all
843 combinations of style flags on all systems. This is because on
844 X11, Qt can only ask the window manager, and the window manager
845 can override the application's settings. On Windows, Qt can set
846 whatever flags you want.
847
848 \sa windowFlags
849*/
850QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
851 : QWidget(*new QWidgetPrivate, parent, f)
852{
853}
854
855
856/*! \internal
857*/
858QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
859 : QObject(dd, nullptr), QPaintDevice()
860 , data(&dd.data)
861{
862 Q_D(QWidget);
863 QT_TRY {
864 d->init(desktopWidget: parent, f);
865 } QT_CATCH(...) {
866 QWidgetExceptionCleaner::cleanup(that: this, d: d_func());
867 QT_RETHROW;
868 }
869}
870
871/*!
872 \internal
873*/
874int QWidget::devType() const
875{
876 return QInternal::Widget;
877}
878
879
880//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
881void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
882{
883 bool customize = (flags & (Qt::CustomizeWindowHint
884 | Qt::FramelessWindowHint
885 | Qt::WindowTitleHint
886 | Qt::WindowSystemMenuHint
887 | Qt::WindowMinimizeButtonHint
888 | Qt::WindowMaximizeButtonHint
889 | Qt::WindowCloseButtonHint
890 | Qt::WindowContextHelpButtonHint));
891
892 uint type = (flags & Qt::WindowType_Mask);
893
894 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
895 type = Qt::Window;
896 flags |= Qt::Window;
897 }
898
899 if (flags & Qt::CustomizeWindowHint) {
900 // modify window flags to make them consistent.
901 // Only enable this on non-Mac platforms. Since the old way of doing this would
902 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
903 // we can't just add this in.
904 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
905# ifdef Q_OS_WIN
906 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
907# endif
908 ) {
909 flags |= Qt::WindowSystemMenuHint;
910 flags |= Qt::WindowTitleHint;
911 flags &= ~Qt::FramelessWindowHint;
912 }
913 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
914 // if any of the window hints that affect the titlebar are set
915 // and the window is supposed to have frame, we add a titlebar
916 // and system menu by default.
917 flags |= Qt::WindowSystemMenuHint;
918 flags |= Qt::WindowTitleHint;
919 }
920 if (!customize) { // don't modify window flags if the user explicitly set them.
921 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
922 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
923 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
924 }
925 if (w->testAttribute(attribute: Qt::WA_TransparentForMouseEvents))
926 flags |= Qt::WindowTransparentForInput;
927}
928
929void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
930{
931 Q_Q(QWidget);
932 isWidget = true;
933 wasWidget = true;
934
935 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
936
937 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
938 qFatal(msg: "QWidget: Cannot create a QWidget without QApplication");
939
940 Q_ASSERT(allWidgets);
941 if (allWidgets)
942 allWidgets->insert(value: q);
943
944#if QT_CONFIG(thread)
945 if (!parent) {
946 Q_ASSERT_X(QThread::isMainThread(), "QWidget",
947 "Widgets must be created in the GUI thread.");
948 }
949#endif
950
951 data.fstrut_dirty = true;
952
953 data.winid = 0;
954 data.widget_attributes = 0;
955 data.window_flags = f;
956 data.window_state = 0;
957 data.focus_policy = 0;
958 data.context_menu_policy = Qt::DefaultContextMenu;
959 data.window_modality = Qt::NonModal;
960
961 data.sizehint_forced = 0;
962 data.is_closing = false;
963 data.in_show = 0;
964 data.in_set_window_state = 0;
965 data.in_destructor = false;
966
967 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
968 if (f & Qt::MSWindowsOwnDC) {
969 mustHaveWindowHandle = 1;
970 q->setAttribute(Qt::WA_NativeWindow);
971 }
972
973 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
974 adjustQuitOnCloseAttribute();
975
976 q->setAttribute(Qt::WA_WState_Hidden);
977
978 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
979 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
980 initFocusChain();
981
982 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
983 q->create();
984 else if (parentWidget)
985 q->setParent(parent: parentWidget, f: data.window_flags);
986 else {
987 adjustFlags(flags&: data.window_flags, w: q);
988 resolveLayoutDirection();
989 // opaque system background?
990 const QBrush &background = q->palette().brush(cr: QPalette::Window);
991 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
992 }
993 data.fnt = QFont(data.fnt, q);
994
995 q->setAttribute(Qt::WA_PendingMoveEvent);
996 q->setAttribute(Qt::WA_PendingResizeEvent);
997
998 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
999 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1000
1001 QEvent e(QEvent::Create);
1002 QCoreApplication::sendEvent(receiver: q, event: &e);
1003 QCoreApplication::postEvent(receiver: q, event: new QEvent(QEvent::PolishRequest));
1004
1005 extraPaintEngine = nullptr;
1006}
1007
1008void QWidgetPrivate::createRecursively()
1009{
1010 Q_Q(QWidget);
1011 q->create(0, initializeWindow: true, destroyOldWindow: true);
1012 for (int i = 0; i < children.size(); ++i) {
1013 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
1014 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(attribute: Qt::WA_WState_Created))
1015 child->d_func()->createRecursively();
1016 }
1017}
1018
1019QRhi *QWidgetPrivate::rhi() const
1020{
1021 Q_Q(const QWidget);
1022 if (auto *backingStore = q->backingStore()) {
1023 auto *window = windowHandle(mode: WindowHandleMode::Closest);
1024 return backingStore->handle()->rhi(window);
1025 } else {
1026 return nullptr;
1027 }
1028}
1029
1030/*!
1031 \internal
1032 Returns the closest parent widget that has a QWindow window handle
1033
1034 \note This behavior is different from nativeParentWidget(), which
1035 returns the closest parent that has a QWindow window handle with
1036 a created QPlatformWindow, and hence native window (winId).
1037*/
1038QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
1039{
1040 Q_Q(const QWidget);
1041 QWidget *parent = q->parentWidget();
1042 while (parent && !parent->windowHandle())
1043 parent = parent->parentWidget();
1044 return parent;
1045}
1046
1047QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1048{
1049 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1050 if (QTLWExtra *x = maybeTopData()) {
1051 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1052 return x->window;
1053 }
1054 }
1055 if (mode == WindowHandleMode::Closest) {
1056 // FIXME: Use closestParentWidgetWithWindowHandle instead
1057 if (auto nativeParent = q_func()->nativeParentWidget()) {
1058 if (auto window = nativeParent->windowHandle())
1059 return window;
1060 }
1061 }
1062 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1063 if (auto topLevel = q_func()->topLevelWidget()) {
1064 if (auto window = topLevel ->windowHandle())
1065 return window;
1066 }
1067 }
1068 return nullptr;
1069}
1070
1071/*!
1072 \internal
1073
1074 Used by clients outside of widgets to get a handle to the
1075 closest QWindow without having to link to widgets.
1076*/
1077QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1078{
1079 return windowHandle(mode: QWidgetPrivate::WindowHandleMode::Closest);
1080}
1081
1082QScreen *QWidgetPrivate::associatedScreen() const
1083{
1084#if QT_CONFIG(graphicsview)
1085 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1086 if (nearestGraphicsProxyWidget(origin: q_func()))
1087 return nullptr;
1088#endif
1089 if (auto window = windowHandle(mode: WindowHandleMode::Closest))
1090 return window->screen();
1091 return nullptr;
1092}
1093
1094// finds the first rhiconfig in the hierarchy that has enable==true
1095static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1096{
1097 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1098 if (config.isEnabled()) {
1099 if (outConfig)
1100 *outConfig = config;
1101 if (outType)
1102 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1103 return true;
1104 }
1105 for (const QObject *child : w->children()) {
1106 if (const QWidget *childWidget = qobject_cast<const QWidget *>(o: child)) {
1107 if (q_evaluateRhiConfigRecursive(w: childWidget, outConfig, outType)) {
1108 static bool optOut = qEnvironmentVariableIsSet(varName: "QT_WIDGETS_NO_CHILD_RHI");
1109 // Native child widgets should not trigger RHI for its parent
1110 // hierarchy, but will still flush the native child using RHI.
1111 if (!optOut && childWidget->testAttribute(attribute: Qt::WA_NativeWindow))
1112 continue;
1113
1114 return true;
1115 }
1116 }
1117 }
1118 return false;
1119}
1120
1121bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1122{
1123 // First, check env.vars. or other means that force the usage of rhi-based
1124 // flushing with a specific graphics API. This takes precedence over what
1125 // the widgets themselves declare. This is global, applying to all
1126 // top-levels.
1127 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1128 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1129 return true;
1130 }
1131
1132 // Otherwise, check the widget hierarchy to see if there is a child (or
1133 // ourselves) that declare the need for rhi-based composition.
1134 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1135 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1136 return true;
1137 }
1138
1139 return false;
1140}
1141
1142// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1143
1144/*!
1145 Creates a new widget window.
1146
1147 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1148 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1149 QWindow wrapping a foreign window and pass it to
1150 QWidget::createWindowContainer() instead.
1151
1152 \sa createWindowContainer(), QWindow::fromWinId()
1153*/
1154
1155void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1156{
1157 Q_UNUSED(initializeWindow);
1158 Q_UNUSED(destroyOldWindow);
1159
1160 Q_D(QWidget);
1161 if (Q_UNLIKELY(window))
1162 qWarning(msg: "QWidget::create(): Parameter 'window' does not have any effect.");
1163 if (testAttribute(attribute: Qt::WA_WState_Created) && window == 0 && internalWinId())
1164 return;
1165
1166 if (d->data.in_destructor)
1167 return;
1168
1169 Qt::WindowType type = windowType();
1170 Qt::WindowFlags &flags = data->window_flags;
1171
1172 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1173 type = Qt::Window;
1174 flags |= Qt::Window;
1175 }
1176
1177 if (QWidget *parent = parentWidget()) {
1178 if (type & Qt::Window) {
1179 if (!parent->testAttribute(attribute: Qt::WA_WState_Created))
1180 parent->createWinId();
1181 } else if (testAttribute(attribute: Qt::WA_NativeWindow) && !parent->internalWinId()
1182 && !testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
1183 // We're about to create a native child widget that doesn't have a native parent;
1184 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1185 // attribute is set.
1186 d->createWinId();
1187 // Nothing more to do.
1188 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1189 Q_ASSERT(internalWinId());
1190 return;
1191 }
1192 }
1193
1194
1195 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue(varName: "QT_ONSCREEN_PAINT") > 0;
1196 if (paintOnScreenEnv)
1197 setAttribute(Qt::WA_PaintOnScreen);
1198
1199 if (QApplicationPrivate::testAttribute(flag: Qt::AA_NativeWindows))
1200 setAttribute(Qt::WA_NativeWindow);
1201
1202 if (isWindow()) {
1203 // Make top levels automatically respect safe areas by default
1204 auto *topExtra = d->maybeTopData();
1205 if (!topExtra || !topExtra->explicitContentsMarginsRespectsSafeArea) {
1206 setAttribute_internal(attribute: Qt::WA_ContentsMarginsRespectsSafeArea,
1207 on: true, data, d);
1208 }
1209 }
1210
1211 d->updateIsOpaque();
1212
1213 setAttribute(Qt::WA_WState_Created); // set created flag
1214 d->create();
1215
1216 // A real toplevel window needs a paint manager
1217 if (isWindow() && windowType() != Qt::Desktop)
1218 d->topData()->repaintManager.reset(p: new QWidgetRepaintManager(this));
1219
1220 d->setModal_sys();
1221
1222 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered))
1223 setAttribute(Qt::WA_DropSiteRegistered, on: true);
1224
1225 // need to force the resting of the icon after changing parents
1226 if (testAttribute(attribute: Qt::WA_SetWindowIcon))
1227 d->setWindowIcon_sys();
1228
1229 if (isWindow() && !d->topData()->iconText.isEmpty())
1230 d->setWindowIconText_helper(d->topData()->iconText);
1231 if (isWindow() && !d->topData()->caption.isEmpty())
1232 d->setWindowTitle_helper(d->topData()->caption);
1233 if (isWindow() && !d->topData()->filePath.isEmpty())
1234 d->setWindowFilePath_helper(d->topData()->filePath);
1235 if (windowType() != Qt::Desktop) {
1236 d->updateSystemBackground();
1237
1238 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon))
1239 d->setWindowIcon_sys();
1240 }
1241
1242 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1243 // as those force native window creation on their ancestors before they are shown.
1244 // If the strut is not updated, any subsequent move of the top level window before show
1245 // will cause window frame to be ignored when positioning the window.
1246 // Note that this only helps on platforms that handle window creation synchronously.
1247 d->updateFrameStrut();
1248}
1249
1250void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1251{
1252 QObjectList children = parentWidget->children();
1253 for (int i = 0; i < children.size(); i++) {
1254 if (children.at(i)->isWidgetType()) {
1255 const QWidget *childWidget = qobject_cast<const QWidget *>(object: children.at(i));
1256 if (childWidget) { // should not be necessary
1257 if (childWidget->testAttribute(attribute: Qt::WA_NativeWindow)) {
1258 if (!childWidget->internalWinId())
1259 childWidget->winId();
1260 if (childWidget->windowHandle()) {
1261 if (childWidget->isWindow()) {
1262 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1263 } else {
1264 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1265 }
1266 }
1267 } else {
1268 q_createNativeChildrenAndSetParent(parentWidget: childWidget);
1269 }
1270 }
1271 }
1272 }
1273
1274}
1275
1276void QWidgetPrivate::create()
1277{
1278 Q_Q(QWidget);
1279
1280 if (!q->testAttribute(attribute: Qt::WA_NativeWindow) && !q->isWindow())
1281 return; // we only care about real toplevels
1282
1283 QWidgetWindow *win = topData()->window;
1284 // topData() ensures the extra is created but does not ensure 'window' is non-null
1285 // in case the extra was already valid.
1286 if (!win) {
1287 createTLSysExtra();
1288 Q_ASSERT(topData()->window);
1289 win = topData()->window;
1290 }
1291
1292 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1293 for (const QByteArray &propertyName : dynamicPropertyNames) {
1294 if (!qstrncmp(str1: propertyName, str2: "_q_platform_", len: 12))
1295 win->setProperty(name: propertyName, value: q->property(name: propertyName));
1296 }
1297
1298 Qt::WindowFlags &flags = data.window_flags;
1299
1300#if defined(QT_PLATFORM_UIKIT)
1301 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1302 flags |= Qt::ExpandedClientAreaHint;
1303#endif
1304
1305 if (q->testAttribute(attribute: Qt::WA_ShowWithoutActivating))
1306 win->setProperty(name: "_q_showWithoutActivating", value: QVariant(true));
1307 if (q->testAttribute(attribute: Qt::WA_MacAlwaysShowToolWindow))
1308 win->setProperty(name: "_q_macAlwaysShowToolWindow", value: QVariant(true));
1309 win->setFlags(flags);
1310 fixPosIncludesFrame();
1311 if (q->testAttribute(attribute: Qt::WA_Moved)
1312 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
1313 win->setGeometry(q->geometry());
1314 else
1315 win->resize(newSize: q->size());
1316 if (win->isTopLevel()) {
1317 QScreen *targetScreen = topData()->initialScreen;
1318 topData()->initialScreen = nullptr;
1319 if (!targetScreen) {
1320 targetScreen = q->windowType() != Qt::Desktop
1321 ? q->screen() : nullptr;
1322 }
1323 win->setScreen(targetScreen);
1324 }
1325
1326 QSurfaceFormat format = win->requestedFormat();
1327 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1328 && q->testAttribute(attribute: Qt::WA_TranslucentBackground)) {
1329 format.setAlphaBufferSize(8);
1330 }
1331 win->setFormat(format);
1332
1333 if (QWidget *nativeParent = q->nativeParentWidget()) {
1334 if (nativeParent->windowHandle()) {
1335 if (flags & Qt::Window) {
1336 win->setTransientParent(nativeParent->window()->windowHandle());
1337 win->setParent(nullptr);
1338 } else {
1339 win->setTransientParent(nullptr);
1340 win->setParent(nativeParent->windowHandle());
1341 }
1342 }
1343 }
1344
1345 qt_window_private(window: win)->positionPolicy = topData()->posIncludesFrame ?
1346 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1347
1348 if (q->windowType() != Qt::Desktop || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
1349 win->create();
1350 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1351 if (QPlatformWindow *platformWindow = win->handle())
1352 platformWindow->setFrameStrutEventsEnabled(true);
1353 }
1354
1355 data.window_flags = win->flags();
1356
1357#if QT_CONFIG(xcb)
1358 if (!topData()->role.isNull()) {
1359 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1360 xcbWindow->setWindowRole(topData()->role);
1361 }
1362#endif
1363
1364 QBackingStore *store = q->backingStore();
1365 usesRhiFlush = false;
1366
1367 if (q->windowType() == Qt::Desktop) {
1368 q->setAttribute(Qt::WA_PaintOnScreen, on: true);
1369 } else {
1370 if (!store && q->isWindow())
1371 q->setBackingStore(new QBackingStore(win));
1372
1373 QPlatformBackingStoreRhiConfig rhiConfig;
1374 usesRhiFlush = q_evaluateRhiConfig(w: q, outConfig: &rhiConfig, outType: nullptr);
1375 if (usesRhiFlush && q->backingStore()) {
1376 // Trigger creation of support infrastructure up front,
1377 // now that we have a specific RHI configuration.
1378 q->backingStore()->handle()->createRhi(window: win, config: rhiConfig);
1379 }
1380 }
1381
1382 setWindowModified_helper();
1383
1384 if (win->handle()) {
1385 WId id = win->winId();
1386 // See the QPlatformWindow::winId() documentation
1387 Q_ASSERT(id != WId(0));
1388 setWinId(id);
1389 }
1390 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1391
1392 // Check children and create windows for them if necessary
1393 q_createNativeChildrenAndSetParent(parentWidget: q);
1394
1395 if (extra && !extra->mask.isEmpty())
1396 setMask_sys(extra->mask);
1397
1398 if (data.crect.width() == 0 || data.crect.height() == 0) {
1399 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
1400 } else {
1401 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
1402 if (q->isVisible()) {
1403 // If widget is already shown, set window visible, too
1404 win->setNativeWindowVisibility(true);
1405 }
1406 }
1407}
1408
1409#ifdef Q_OS_WIN
1410static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1411#endif
1412
1413void QWidgetPrivate::createTLSysExtra()
1414{
1415 Q_Q(QWidget);
1416 if (!extra->topextra->window && (q->testAttribute(attribute: Qt::WA_NativeWindow) || q->isWindow())) {
1417 extra->topextra->window = new QWidgetWindow(q);
1418 if (extra->minw || extra->minh)
1419 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1420 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1421 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1422 if (extra->topextra->opacity != 255 && q->isWindow())
1423 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1424
1425 const bool isTipLabel = q->inherits(classname: "QTipLabel");
1426 const bool isAlphaWidget = !isTipLabel && q->inherits(classname: "QAlphaWidget");
1427#ifdef Q_OS_WIN
1428 // Pass on native parent handle for Widget embedded into Active X.
1429 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1430 if (activeXNativeParentHandle.isValid())
1431 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1432 if (isTipLabel || isAlphaWidget)
1433 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1434#endif
1435 if (isTipLabel || isAlphaWidget || q->inherits(classname: "QRollEffect"))
1436 qt_window_private(window: extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1437
1438 updateIsTranslucent();
1439 }
1440
1441}
1442
1443/*!
1444 Destroys the widget.
1445
1446 All this widget's children are deleted first. The application
1447 exits if this widget is the main widget.
1448*/
1449
1450QWidget::~QWidget()
1451{
1452 Q_D(QWidget);
1453 d->data.in_destructor = true;
1454
1455#if defined (QT_CHECK_STATE)
1456 if (Q_UNLIKELY(paintingActive()))
1457 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1458#endif
1459
1460#ifndef QT_NO_GESTURES
1461 if (QGestureManager *manager = QGestureManager::instance(ic: QGestureManager::DontForceCreation)) {
1462 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1463 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1464 manager->cleanupCachedGestures(target: this, type: *it);
1465 }
1466 d->gestureContext.clear();
1467#endif
1468
1469#ifndef QT_NO_ACTION
1470 // remove all actions from this widget
1471 for (auto action : std::as_const(t&: d->actions)) {
1472 QActionPrivate *apriv = action->d_func();
1473 apriv->associatedObjects.removeAll(t: this);
1474 }
1475 d->actions.clear();
1476#endif
1477
1478#ifndef QT_NO_SHORTCUT
1479 // Remove all shortcuts grabbed by this
1480 // widget, unless application is closing
1481 if (!QApplicationPrivate::is_app_closing && testAttribute(attribute: Qt::WA_GrabbedShortcut))
1482 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id: 0, owner: this, key: QKeySequence());
1483#endif
1484
1485 // delete layout while we still are a valid widget
1486 delete d->layout;
1487 d->layout = nullptr;
1488
1489 // Remove this from focus list
1490 d->removeFromFocusChain(rules: QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1491
1492 QT_TRY {
1493#if QT_CONFIG(graphicsview)
1494 const QWidget* w = this;
1495 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1496 w = w->d_func()->extra->focus_proxy;
1497 QWidget *window = w->window();
1498 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1499 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1500#endif
1501 clearFocus();
1502 } QT_CATCH(...) {
1503 // swallow this problem because we are in a destructor
1504 }
1505
1506 d->setDirtyOpaqueRegion();
1507
1508 if (isWindow() && isVisible() && internalWinId()) {
1509 QT_TRY {
1510 d->close();
1511 } QT_CATCH(...) {
1512 // if we're out of memory, at least hide the window.
1513 QT_TRY {
1514 hide();
1515 } QT_CATCH(...) {
1516 // and if that also doesn't work, then give up
1517 }
1518 }
1519 } else if (isVisible()) {
1520 qApp->d_func()->sendSyntheticEnterLeave(widget: this);
1521 }
1522
1523 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1524 repaintManager->removeDirtyWidget(w: this);
1525 if (testAttribute(attribute: Qt::WA_StaticContents))
1526 repaintManager->removeStaticWidget(widget: this);
1527 }
1528
1529 delete d->needsFlush;
1530 d->needsFlush = nullptr;
1531
1532 // The next 20 lines are duplicated from QObject, but required here
1533 // since QWidget deletes is children itself
1534 bool blocked = d->blockSig;
1535 d->blockSig = 0; // unblock signals so we always emit destroyed()
1536
1537 if (d->isSignalConnected(signalIdx: 0)) {
1538 QT_TRY {
1539 emit destroyed(this);
1540 } QT_CATCH(...) {
1541 // all the signal/slots connections are still in place - if we don't
1542 // quit now, we will crash pretty soon.
1543 qWarning(msg: "Detected an unexpected exception in ~QWidget while emitting destroyed().");
1544 QT_RETHROW;
1545 }
1546 }
1547
1548 if (d->declarativeData) {
1549 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1550 if (QAbstractDeclarativeData::destroyed)
1551 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1552 d->declarativeData = nullptr; // don't activate again in ~QObject
1553 d->wasDeleted = false;
1554 }
1555
1556 d->blockSig = blocked;
1557
1558 if (!d->children.isEmpty())
1559 d->deleteChildren();
1560
1561 QCoreApplication::removePostedEvents(receiver: this);
1562
1563 QT_TRY {
1564 destroy(); // platform-dependent cleanup
1565 } QT_CATCH(...) {
1566 // if this fails we can't do anything about it but at least we are not allowed to throw.
1567 }
1568 --QWidgetPrivate::instanceCounter;
1569
1570 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1571 QWidgetPrivate::allWidgets->remove(value: this);
1572
1573 QT_TRY {
1574 QEvent e(QEvent::Destroy);
1575 QCoreApplication::sendEvent(receiver: this, event: &e);
1576 } QT_CATCH(const std::exception&) {
1577 // if this fails we can't do anything about it but at least we are not allowed to throw.
1578 }
1579
1580#if QT_CONFIG(graphicseffect)
1581 delete d->graphicsEffect;
1582#endif
1583 d->deleteExtra();
1584
1585 d->isWidget = false;
1586}
1587
1588int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1589int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1590
1591void QWidgetPrivate::setWinId(WId id) // set widget identifier
1592{
1593 Q_Q(QWidget);
1594 if (mapper && data.winid) {
1595 mapper->remove(key: data.winid);
1596 }
1597
1598 const WId oldWinId = data.winid;
1599
1600 data.winid = id;
1601 if (mapper && id) {
1602 mapper->insert(key: data.winid, value: q);
1603 }
1604
1605 if (oldWinId != id) {
1606 QEvent e(QEvent::WinIdChange);
1607 QCoreApplication::sendEvent(receiver: q, event: &e);
1608 }
1609}
1610
1611void QWidgetPrivate::createTLExtra()
1612{
1613 if (!extra)
1614 createExtra();
1615 if (!extra->topextra) {
1616 extra->topextra = std::make_unique<QTLWExtra>();
1617 QTLWExtra* x = extra->topextra.get();
1618 x->backingStore = nullptr;
1619 x->sharedPainter = nullptr;
1620 x->incw = x->inch = 0;
1621 x->basew = x->baseh = 0;
1622 x->frameStrut.setCoords(xp1: 0, yp1: 0, xp2: 0, yp2: 0);
1623 x->normalGeometry = QRect(0,0,-1,-1);
1624 x->savedFlags = { };
1625 x->opacity = 255;
1626 x->posIncludesFrame = 0;
1627 x->sizeAdjusted = false;
1628 x->embedded = 0;
1629 x->explicitContentsMarginsRespectsSafeArea = 0;
1630 x->window = nullptr;
1631 x->initialScreen = nullptr;
1632
1633#ifdef QWIDGET_EXTRA_DEBUG
1634 static int count = 0;
1635 qDebug() << "tlextra" << ++count;
1636#endif
1637 }
1638}
1639
1640/*!
1641 \internal
1642 Creates the widget extra data.
1643*/
1644
1645void QWidgetPrivate::createExtra()
1646{
1647 if (!extra) { // if not exists
1648 extra = std::make_unique<QWExtra>();
1649 extra->glContext = nullptr;
1650#if QT_CONFIG(graphicsview)
1651 extra->proxyWidget = nullptr;
1652#endif
1653 extra->minw = 0;
1654 extra->minh = 0;
1655 extra->maxw = QWIDGETSIZE_MAX;
1656 extra->maxh = QWIDGETSIZE_MAX;
1657 extra->customDpiX = 0;
1658 extra->customDpiY = 0;
1659 extra->explicitMinSize = 0;
1660 extra->explicitMaxSize = 0;
1661 extra->autoFillBackground = 0;
1662 extra->nativeChildrenForced = 0;
1663 extra->inRenderWithPainter = 0;
1664 extra->hasWindowContainer = false;
1665 extra->hasMask = 0;
1666 createSysExtra();
1667#ifdef QWIDGET_EXTRA_DEBUG
1668 static int count = 0;
1669 qDebug() << "extra" << ++count;
1670#endif
1671 }
1672}
1673
1674void QWidgetPrivate::createSysExtra()
1675{
1676}
1677
1678/*!
1679 \internal
1680 Deletes the widget extra data.
1681*/
1682
1683void QWidgetPrivate::deleteExtra()
1684{
1685 if (extra) { // if exists
1686 deleteSysExtra();
1687#if QT_CONFIG(style_stylesheet)
1688 // dereference the stylesheet style
1689 if (QStyleSheetStyle *proxy = qt_styleSheet(style: extra->style))
1690 proxy->deref();
1691#endif
1692 if (extra->topextra)
1693 deleteTLSysExtra();
1694
1695 // extra->xic destroyed in QWidget::destroy()
1696 extra.reset();
1697 }
1698}
1699
1700void QWidgetPrivate::deleteSysExtra()
1701{
1702}
1703
1704void QWidgetPrivate::deleteTLSysExtra()
1705{
1706 Q_Q(QWidget);
1707 if (extra && extra->topextra) {
1708 if (extra->hasWindowContainer)
1709 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
1710
1711 delete extra->topextra->window;
1712 extra->topextra->window = nullptr;
1713 }
1714}
1715
1716/*
1717 Returns \c region of widgets above this which overlap with
1718 \a rect, which is in parent's coordinate system (same as crect).
1719*/
1720
1721QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1722{
1723 Q_Q(const QWidget);
1724
1725 const QWidget *w = q;
1726 QRect r = rect;
1727 QPoint p;
1728 QRegion region;
1729 while (w) {
1730 if (w->isWindow())
1731 break;
1732 QWidgetPrivate *pd = w->parentWidget()->d_func();
1733 bool above = false;
1734 for (int i = 0; i < pd->children.size(); ++i) {
1735 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
1736 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1737 continue;
1738 if (!above) {
1739 above = (sibling == w);
1740 continue;
1741 }
1742
1743 const QRect siblingRect = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
1744 if (qRectIntersects(r1: siblingRect, r2: r)) {
1745 const auto &siblingExtra = sibling->d_func()->extra;
1746 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1747 && !siblingExtra->mask.translated(p: sibling->data->crect.topLeft()).intersects(r)) {
1748 continue;
1749 }
1750 region += siblingRect.translated(p: -p);
1751 if (breakAfterFirst)
1752 break;
1753 }
1754 }
1755 w = w->parentWidget();
1756 r.translate(p: pd->data.crect.topLeft());
1757 p += pd->data.crect.topLeft();
1758 }
1759 return region;
1760}
1761
1762void QWidgetPrivate::syncBackingStore()
1763{
1764 if (shouldPaintOnScreen()) {
1765 paintOnScreen(rgn: dirty);
1766 dirty = QRegion();
1767 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1768 repaintManager->sync();
1769 }
1770}
1771
1772void QWidgetPrivate::syncBackingStore(const QRegion &region)
1773{
1774 if (shouldPaintOnScreen())
1775 paintOnScreen(rgn: region);
1776 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1777 repaintManager->sync(exposedWidget: q_func(), exposedRegion: region);
1778 }
1779}
1780
1781void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1782{
1783 if (data.in_destructor)
1784 return;
1785
1786 if (shouldDiscardSyncRequest())
1787 return;
1788
1789 Q_Q(QWidget);
1790 if (q->testAttribute(attribute: Qt::WA_StaticContents)) {
1791 if (!extra)
1792 createExtra();
1793 extra->staticContentsSize = data.crect.size();
1794 }
1795
1796 QPaintEngine *engine = q->paintEngine();
1797
1798 // QGLWidget does not support partial updates if:
1799 // 1) The context is double buffered
1800 // 2) The context is single buffered and auto-fill background is enabled.
1801 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1802 || engine->type() == QPaintEngine::OpenGL2))
1803 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1804 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1805
1806 toBePainted &= clipRect();
1807 clipToEffectiveMask(region&: toBePainted);
1808 if (toBePainted.isEmpty())
1809 return; // Nothing to repaint.
1810
1811 drawWidget(pdev: q, rgn: toBePainted, offset: QPoint(), flags: QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, sharedPainter: nullptr);
1812
1813 if (Q_UNLIKELY(q->paintingActive()))
1814 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1815}
1816
1817void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1818{
1819 Q_Q(QWidget);
1820
1821 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1822 return; // nothing we can do
1823
1824 if (enable != q->testAttribute(attribute: Qt::WA_UpdatesDisabled))
1825 return; // nothing to do
1826
1827 q->setAttribute(Qt::WA_UpdatesDisabled, on: !enable);
1828 if (enable)
1829 q->update();
1830
1831 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1832 for (int i = 0; i < children.size(); ++i) {
1833 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
1834 if (w && !w->isWindow() && !w->testAttribute(attribute))
1835 w->d_func()->setUpdatesEnabled_helper(enable);
1836 }
1837}
1838
1839/*!
1840 \internal
1841
1842 Propagate this widget's palette to all children, except style sheet
1843 widgets, and windows that don't enable window propagation (palettes don't
1844 normally propagate to windows).
1845*/
1846void QWidgetPrivate::propagatePaletteChange()
1847{
1848 Q_Q(QWidget);
1849 // Propagate a new inherited mask to all children.
1850#if QT_CONFIG(graphicsview)
1851 if (!q->parentWidget() && extra && extra->proxyWidget) {
1852 QGraphicsProxyWidget *p = extra->proxyWidget;
1853 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1854 } else
1855#endif // QT_CONFIG(graphicsview)
1856 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
1857 inheritedPaletteResolveMask = 0;
1858 }
1859
1860 directPaletteResolveMask = data.pal.resolveMask();
1861 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1862
1863 const bool useStyleSheetPropagationInWidgetStyles =
1864 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1865
1866 QEvent pc(QEvent::PaletteChange);
1867 QCoreApplication::sendEvent(receiver: q, event: &pc);
1868 for (int i = 0; i < children.size(); ++i) {
1869 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
1870 if (w && (!w->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1871 && (!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
1872 QWidgetPrivate *wd = w->d_func();
1873 wd->inheritedPaletteResolveMask = mask;
1874 wd->resolvePalette();
1875 }
1876 }
1877}
1878
1879/*
1880 Returns the widget's clipping rectangle.
1881*/
1882QRect QWidgetPrivate::clipRect() const
1883{
1884 Q_Q(const QWidget);
1885 const QWidget * w = q;
1886 if (!w->isVisible())
1887 return QRect();
1888 QRect r = effectiveRectFor(rect: q->rect());
1889 int ox = 0;
1890 int oy = 0;
1891 while (w
1892 && w->isVisible()
1893 && !w->isWindow()
1894 && w->parentWidget()) {
1895 ox -= w->x();
1896 oy -= w->y();
1897 w = w->parentWidget();
1898 r &= QRect(ox, oy, w->width(), w->height());
1899 }
1900 return r;
1901}
1902
1903/*
1904 Returns the widget's clipping region (without siblings).
1905*/
1906QRegion QWidgetPrivate::clipRegion() const
1907{
1908 Q_Q(const QWidget);
1909 if (!q->isVisible())
1910 return QRegion();
1911 QRegion r(q->rect());
1912 const QWidget * w = q;
1913 const QWidget *ignoreUpTo;
1914 int ox = 0;
1915 int oy = 0;
1916 while (w
1917 && w->isVisible()
1918 && !w->isWindow()
1919 && w->parentWidget()) {
1920 ox -= w->x();
1921 oy -= w->y();
1922 ignoreUpTo = w;
1923 w = w->parentWidget();
1924 r &= QRegion(ox, oy, w->width(), w->height());
1925
1926 int i = 0;
1927 while(w->d_func()->children.at(i: i++) != static_cast<const QObject *>(ignoreUpTo))
1928 ;
1929 for ( ; i < w->d_func()->children.size(); ++i) {
1930 if (QWidget *sibling = qobject_cast<QWidget *>(o: w->d_func()->children.at(i))) {
1931 if (sibling->isVisible() && !sibling->isWindow()) {
1932 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1933 sibling->width(), sibling->height());
1934 if (qRectIntersects(r1: siblingRect, r2: q->rect()))
1935 r -= QRegion(siblingRect);
1936 }
1937 }
1938 }
1939 }
1940 return r;
1941}
1942
1943void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1944{
1945// Transform the system clip region from device-independent pixels to device pixels
1946 QTransform scaleTransform;
1947 scaleTransform.scale(sx: devicePixelRatio, sy: devicePixelRatio);
1948
1949 paintEngine->d_func()->baseSystemClip = region;
1950 paintEngine->d_func()->setSystemTransform(scaleTransform);
1951
1952}
1953
1954#if QT_CONFIG(graphicseffect)
1955void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1956{
1957 Q_Q(QWidget);
1958 QWidget *w = q;
1959 do {
1960 if (w->graphicsEffect()) {
1961 QWidgetEffectSourcePrivate *sourced =
1962 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1963 if (!sourced->updateDueToGraphicsEffect)
1964 w->graphicsEffect()->source()->d_func()->invalidateCache();
1965 }
1966 w = w->parentWidget();
1967 } while (w);
1968}
1969#endif // QT_CONFIG(graphicseffect)
1970
1971void QWidgetPrivate::setDirtyOpaqueRegion()
1972{
1973 Q_Q(QWidget);
1974
1975 dirtyOpaqueChildren = true;
1976
1977#if QT_CONFIG(graphicseffect)
1978 invalidateGraphicsEffectsRecursively();
1979#endif // QT_CONFIG(graphicseffect)
1980
1981 if (q->isWindow())
1982 return;
1983
1984 QWidget *parent = q->parentWidget();
1985 if (!parent)
1986 return;
1987
1988 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1989 QWidgetPrivate *pd = parent->d_func();
1990 if (!pd->dirtyOpaqueChildren)
1991 pd->setDirtyOpaqueRegion();
1992}
1993
1994const QRegion &QWidgetPrivate::getOpaqueChildren() const
1995{
1996 if (!dirtyOpaqueChildren)
1997 return opaqueChildren;
1998
1999 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2000 that->opaqueChildren = QRegion();
2001
2002 for (int i = 0; i < children.size(); ++i) {
2003 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
2004 if (!child || !child->isVisible() || child->isWindow())
2005 continue;
2006
2007 const QPoint offset = child->geometry().topLeft();
2008 QWidgetPrivate *childd = child->d_func();
2009 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2010 if (childd->extra && childd->extra->hasMask)
2011 r &= childd->extra->mask;
2012 if (r.isEmpty())
2013 continue;
2014 r.translate(p: offset);
2015 that->opaqueChildren += r;
2016 }
2017
2018 that->opaqueChildren &= q_func()->rect();
2019 that->dirtyOpaqueChildren = false;
2020
2021 return that->opaqueChildren;
2022}
2023
2024void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2025{
2026 if (children.isEmpty() || clipRect.isEmpty())
2027 return;
2028
2029 const QRegion &r = getOpaqueChildren();
2030 if (!r.isEmpty())
2031 source -= (r & clipRect);
2032}
2033
2034//subtract any relatives that are higher up than me --- this is too expensive !!!
2035void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2036 bool alsoNonOpaque) const
2037{
2038 Q_Q(const QWidget);
2039 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue(varName: "QT_NO_SUBTRACTOPAQUESIBLINGS");
2040 if (disableSubtractOpaqueSiblings || q->isWindow())
2041 return;
2042
2043 QRect clipBoundingRect;
2044 bool dirtyClipBoundingRect = true;
2045
2046 QRegion parentClip;
2047 bool dirtyParentClip = true;
2048
2049 QPoint parentOffset = data.crect.topLeft();
2050
2051 const QWidget *w = q;
2052
2053 while (w) {
2054 if (w->isWindow())
2055 break;
2056 QWidgetPrivate *pd = w->parentWidget()->d_func();
2057 const int myIndex = pd->children.indexOf(t: const_cast<QWidget *>(w));
2058 const QRect widgetGeometry = w->d_func()->effectiveRectFor(rect: w->data->crect);
2059 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2060 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
2061 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2062 continue;
2063
2064 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
2065 if (!qRectIntersects(r1: siblingGeometry, r2: widgetGeometry))
2066 continue;
2067
2068 if (dirtyClipBoundingRect) {
2069 clipBoundingRect = sourceRegion.boundingRect();
2070 dirtyClipBoundingRect = false;
2071 }
2072
2073 if (!qRectIntersects(r1: siblingGeometry, r2: clipBoundingRect.translated(p: parentOffset)))
2074 continue;
2075
2076 if (dirtyParentClip) {
2077 parentClip = sourceRegion.translated(p: parentOffset);
2078 dirtyParentClip = false;
2079 }
2080
2081 const QPoint siblingPos(sibling->data->crect.topLeft());
2082 const QRect siblingClipRect(sibling->d_func()->clipRect());
2083 QRegion siblingDirty(parentClip);
2084 siblingDirty &= (siblingClipRect.translated(p: siblingPos));
2085 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2086 && !sibling->d_func()->graphicsEffect;
2087 if (hasMask)
2088 siblingDirty &= sibling->d_func()->extra->mask.translated(p: siblingPos);
2089 if (siblingDirty.isEmpty())
2090 continue;
2091
2092 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2093 if (hasMask) {
2094 siblingDirty.translate(p: -parentOffset);
2095 sourceRegion -= siblingDirty;
2096 } else {
2097 sourceRegion -= siblingGeometry.translated(p: -parentOffset);
2098 }
2099 } else {
2100 if (hasDirtySiblingsAbove)
2101 *hasDirtySiblingsAbove = true;
2102 if (sibling->d_func()->children.isEmpty())
2103 continue;
2104 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2105 opaqueSiblingChildren.translate(p: -parentOffset + siblingPos);
2106 sourceRegion -= opaqueSiblingChildren;
2107 }
2108 if (sourceRegion.isEmpty())
2109 return;
2110
2111 dirtyClipBoundingRect = true;
2112 dirtyParentClip = true;
2113 }
2114
2115 w = w->parentWidget();
2116 parentOffset += pd->data.crect.topLeft();
2117 dirtyParentClip = true;
2118 }
2119}
2120
2121void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2122{
2123 Q_Q(const QWidget);
2124
2125 const QWidget *w = q;
2126 QPoint offset;
2127
2128#if QT_CONFIG(graphicseffect)
2129 if (graphicsEffect && !w->isWindow()) {
2130 w = q->parentWidget();
2131 offset -= data.crect.topLeft();
2132 }
2133#endif // QT_CONFIG(graphicseffect)
2134
2135 while (w) {
2136 const QWidgetPrivate *wd = w->d_func();
2137 if (wd->extra && wd->extra->hasMask)
2138 region &= (w != q) ? wd->extra->mask.translated(p: offset) : wd->extra->mask;
2139 if (w->isWindow())
2140 return;
2141 offset -= wd->data.crect.topLeft();
2142 w = w->parentWidget();
2143 }
2144}
2145
2146bool QWidgetPrivate::shouldPaintOnScreen() const
2147{
2148#if defined(QT_NO_BACKINGSTORE)
2149 return true;
2150#else
2151 Q_Q(const QWidget);
2152 if (q->testAttribute(attribute: Qt::WA_PaintOnScreen)
2153 || (!q->isWindow() && q->window()->testAttribute(attribute: Qt::WA_PaintOnScreen))) {
2154 return true;
2155 }
2156
2157 return false;
2158#endif
2159}
2160
2161void QWidgetPrivate::updateIsOpaque()
2162{
2163 // hw: todo: only needed if opacity actually changed
2164 setDirtyOpaqueRegion();
2165
2166#if QT_CONFIG(graphicseffect)
2167 if (graphicsEffect) {
2168 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2169 setOpaque(false);
2170 return;
2171 }
2172#endif // QT_CONFIG(graphicseffect)
2173
2174 Q_Q(QWidget);
2175 if (q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) || q->testAttribute(attribute: Qt::WA_PaintOnScreen)) {
2176 setOpaque(true);
2177 return;
2178 }
2179
2180 const QPalette &pal = q->palette();
2181
2182 if (q->autoFillBackground()) {
2183 const QBrush &autoFillBrush = pal.brush(cr: q->backgroundRole());
2184 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2185 setOpaque(true);
2186 return;
2187 }
2188 }
2189
2190 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
2191 const QBrush &windowBrush = q->palette().brush(cr: QPalette::Window);
2192 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2193 setOpaque(true);
2194 return;
2195 }
2196 }
2197 setOpaque(false);
2198}
2199
2200void QWidgetPrivate::setOpaque(bool opaque)
2201{
2202 if (isOpaque != opaque) {
2203 isOpaque = opaque;
2204 updateIsTranslucent();
2205 }
2206}
2207
2208void QWidgetPrivate::updateIsTranslucent()
2209{
2210 Q_Q(QWidget);
2211 if (QWindow *window = q->windowHandle()) {
2212 QSurfaceFormat format = window->format();
2213 const int oldAlpha = format.alphaBufferSize();
2214 const int newAlpha = q->testAttribute(attribute: Qt::WA_TranslucentBackground) ? 8 : -1;
2215 if (oldAlpha != newAlpha) {
2216 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2217 //
2218 // If that is not the case, then the setFormat() is not just futile
2219 // but downright dangerous. Futile because the format matters only
2220 // when creating the native window, no point in changing it
2221 // afterwards. Dangerous because a QOpenGLContext or something else
2222 // may eventually query the QWindow's format(), in order to ensure
2223 // compatibility (in terms of native concepts such as pixel format,
2224 // EGLConfig, etc.), and if we change it here, then the returned
2225 // format does not describe reality anymore. (reality being the
2226 // settings with which the native resource was created).
2227 //
2228 // Whereas if one does a destroy()-create() then this all here
2229 // won't matter because the format is updated in
2230 // QWidgetPrivate::create() again.
2231 //
2232 if (!window->handle()) {
2233 format.setAlphaBufferSize(newAlpha);
2234 window->setFormat(format);
2235 }
2236 }
2237 }
2238}
2239
2240static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2241{
2242 Q_ASSERT(painter);
2243
2244 if (brush.style() == Qt::TexturePattern) {
2245 const QRect rect(rgn.boundingRect());
2246 painter->setClipRegion(rgn);
2247 painter->drawTiledPixmap(rect, pm: brush.texture(), offset: rect.topLeft());
2248 } else if (brush.gradient()
2249 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2250 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2251 painter->save();
2252 painter->setClipRegion(rgn);
2253 painter->fillRect(x: 0, y: 0, w: painter->device()->width(), h: painter->device()->height(), b: brush);
2254 painter->restore();
2255 } else {
2256 for (const QRect &rect : rgn)
2257 painter->fillRect(rect, brush);
2258 }
2259}
2260
2261bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2262{
2263#if QT_CONFIG(scrollarea)
2264 Q_Q(const QWidget);
2265 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2266 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2267 return false;
2268 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(object: parent);
2269 if (scrollArea && scrollArea->viewport() == q) {
2270 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2271 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2272 painter->setBrushOrigin(-priv->contentsOffset());
2273 }
2274#endif // QT_CONFIG(scrollarea)
2275 return true;
2276}
2277
2278void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2279{
2280 Q_Q(const QWidget);
2281
2282 bool brushOriginSet = false;
2283 const QBrush autoFillBrush = q->palette().brush(cr: q->backgroundRole());
2284
2285 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2286 const QBrush bg = q->palette().brush(cr: QPalette::Window);
2287 if (!brushOriginSet)
2288 brushOriginSet = updateBrushOrigin(painter, brush: bg);
2289 if (!(flags & DontSetCompositionMode)) {
2290 //copy alpha straight in
2291 QPainter::CompositionMode oldMode = painter->compositionMode();
2292 painter->setCompositionMode(QPainter::CompositionMode_Source);
2293 fillRegion(painter, rgn, brush: bg);
2294 painter->setCompositionMode(oldMode);
2295 } else {
2296 fillRegion(painter, rgn, brush: bg);
2297 }
2298 }
2299
2300 if (q->autoFillBackground()) {
2301 if (!brushOriginSet)
2302 brushOriginSet = updateBrushOrigin(painter, brush: autoFillBrush);
2303 fillRegion(painter, rgn, brush: autoFillBrush);
2304 }
2305
2306 if (q->testAttribute(attribute: Qt::WA_StyledBackground)) {
2307 painter->setClipRegion(rgn);
2308 QStyleOption opt;
2309 opt.initFrom(w: q);
2310 q->style()->drawPrimitive(pe: QStyle::PE_Widget, opt: &opt, p: painter, w: q);
2311 }
2312}
2313
2314/*
2315 \internal
2316 This function is called when a widget is hidden or destroyed.
2317 It resets some application global pointers that should only refer active,
2318 visible widgets.
2319*/
2320
2321extern QWidget *qt_button_down;
2322
2323void QWidgetPrivate::deactivateWidgetCleanup()
2324{
2325 Q_Q(QWidget);
2326 // If this was the active application window, reset it
2327 if (QApplication::activeWindow() == q)
2328 QApplicationPrivate::setActiveWindow(nullptr);
2329 // If the is the active mouse press widget, reset it
2330 if (q == qt_button_down)
2331 qt_button_down = nullptr;
2332}
2333
2334
2335/*!
2336 Returns a pointer to the widget with window identifier/handle \a
2337 id.
2338
2339 The window identifier type depends on the underlying window
2340 system, see \c qwindowdefs.h for the actual definition. If there
2341 is no widget with this identifier, \nullptr is returned.
2342*/
2343
2344QWidget *QWidget::find(WId id)
2345{
2346 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(key: id, defaultValue: 0) : nullptr;
2347}
2348
2349
2350
2351/*!
2352 \fn WId QWidget::internalWinId() const
2353 \internal
2354 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2355
2356*/
2357
2358/*!
2359 \fn WId QWidget::winId() const
2360
2361 Returns the window system identifier of the widget.
2362
2363 Portable in principle, but if you use it you are probably about to
2364 do something non-portable. Be careful.
2365
2366 If a widget is non-native (alien) and winId() is invoked on it, that widget
2367 will be provided a native handle.
2368
2369 This value may change at run-time. An event with type QEvent::WinIdChange
2370 will be sent to the widget following a change in window system identifier.
2371
2372 \sa find()
2373*/
2374WId QWidget::winId() const
2375{
2376 if (!data->in_destructor
2377 && (!testAttribute(attribute: Qt::WA_WState_Created) || !internalWinId()))
2378 {
2379 QWidget *that = const_cast<QWidget*>(this);
2380 that->setAttribute(Qt::WA_NativeWindow);
2381 that->d_func()->createWinId();
2382 return that->data->winid;
2383 }
2384 return data->winid;
2385}
2386
2387void QWidgetPrivate::createWinId()
2388{
2389 Q_Q(QWidget);
2390
2391 const bool forceNativeWindow = q->testAttribute(attribute: Qt::WA_NativeWindow);
2392 if (!q->testAttribute(attribute: Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2393 if (!q->isWindow()) {
2394 QWidget *parent = q->parentWidget();
2395 QWidgetPrivate *pd = parent->d_func();
2396 if (forceNativeWindow && !q->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors))
2397 parent->setAttribute(Qt::WA_NativeWindow);
2398 if (!parent->internalWinId()) {
2399 pd->createWinId();
2400 }
2401
2402 for (int i = 0; i < pd->children.size(); ++i) {
2403 QWidget *w = qobject_cast<QWidget *>(o: pd->children.at(i));
2404 if (w && !w->isWindow() && (!w->testAttribute(attribute: Qt::WA_WState_Created)
2405 || (!w->internalWinId() && w->testAttribute(attribute: Qt::WA_NativeWindow)))) {
2406 w->create();
2407 }
2408 }
2409 } else {
2410 q->create();
2411 }
2412 }
2413}
2414
2415/*!
2416\internal
2417Ensures that the widget is set on the screen point is on. This is handy getting a correct
2418size hint before a resize in e.g QMenu and QToolTip.
2419Returns if the screen was changed.
2420*/
2421
2422bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2423{
2424 Q_Q(QWidget);
2425 if (!q->isWindow())
2426 return false;
2427 // Find the screen for pos and make the widget understand it is on that screen.
2428 return setScreen(QGuiApplication::screenAt(point: pos));
2429}
2430
2431/*!
2432\internal
2433Ensures that the widget's QWindow is set to be on the given \a screen.
2434Returns true if the screen was changed.
2435*/
2436
2437bool QWidgetPrivate::setScreen(QScreen *screen)
2438{
2439 Q_Q(QWidget);
2440 if (!screen || !q->isWindow())
2441 return false;
2442 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2443 if (currentScreen != screen) {
2444 topData()->initialScreen = screen;
2445 if (windowHandle())
2446 windowHandle()->setScreen(screen);
2447 return true;
2448 }
2449 return false;
2450}
2451
2452/*!
2453\internal
2454Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2455
2456*/
2457
2458void QWidget::createWinId()
2459{
2460 Q_D(QWidget);
2461 d->createWinId();
2462}
2463
2464/*!
2465 \since 4.4
2466
2467 Returns the effective window system identifier of the widget, i.e. the
2468 native parent's window system identifier.
2469
2470 If the widget is native, this function returns the native widget ID.
2471 Otherwise, the window ID of the first native parent widget, i.e., the
2472 top-level widget that contains this widget, is returned.
2473
2474 \note We recommend that you do not store this value as it is likely to
2475 change at run-time.
2476
2477 \sa nativeParentWidget()
2478*/
2479WId QWidget::effectiveWinId() const
2480{
2481 const WId id = internalWinId();
2482 if (id || !testAttribute(attribute: Qt::WA_WState_Created))
2483 return id;
2484 if (const QWidget *realParent = nativeParentWidget())
2485 return realParent->internalWinId();
2486 return 0;
2487}
2488
2489/*!
2490 If this is a native widget, return the associated QWindow.
2491 Otherwise return null.
2492
2493 Native widgets include toplevel widgets, QGLWidget, and child widgets
2494 on which winId() was called.
2495
2496 \since 5.0
2497
2498 \sa winId(), screen()
2499*/
2500QWindow *QWidget::windowHandle() const
2501{
2502 Q_D(const QWidget);
2503 return d->windowHandle();
2504}
2505
2506/*!
2507 Returns the screen the widget is on.
2508
2509 \since 5.14
2510
2511 \sa windowHandle()
2512*/
2513QScreen *QWidget::screen() const
2514{
2515 Q_D(const QWidget);
2516 if (auto associatedScreen = d->associatedScreen())
2517 return associatedScreen;
2518 if (auto topLevel = window()) {
2519 if (auto topData = qt_widget_private(widget: topLevel)->topData()) {
2520 if (topData->initialScreen)
2521 return topData->initialScreen;
2522 }
2523 if (auto screenByPos = QGuiApplication::screenAt(point: topLevel->geometry().center()))
2524 return screenByPos;
2525 }
2526 return QGuiApplication::primaryScreen();
2527}
2528
2529/*!
2530 Sets the screen on which the widget should be shown to \a screen.
2531
2532 Setting the screen only makes sense for windows. If necessary, the widget's
2533 window will get recreated on \a screen.
2534
2535 \note If the screen is part of a virtual desktop of multiple screens,
2536 the window will not move automatically to \a screen. To place the
2537 window relative to the screen, use the screen's topLeft() position.
2538
2539 \sa QWindow::setScreen()
2540*/
2541void QWidget::setScreen(QScreen *screen)
2542{
2543 Q_D(QWidget);
2544 d->setScreen(screen);
2545}
2546
2547#if QT_CONFIG(style_stylesheet)
2548
2549/*!
2550 \property QWidget::styleSheet
2551 \brief the widget's style sheet
2552 \since 4.2
2553
2554 The style sheet contains a textual description of customizations to the
2555 widget's style, as described in the \l{Qt Style Sheets} document.
2556
2557 Since Qt 4.5, Qt style sheets fully supports \macos.
2558
2559 \warning Qt style sheets are currently not supported for custom QStyle
2560 subclasses. We plan to address this in some future release.
2561
2562 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2563*/
2564QString QWidget::styleSheet() const
2565{
2566 Q_D(const QWidget);
2567 if (!d->extra)
2568 return QString();
2569 return d->extra->styleSheet;
2570}
2571
2572void QWidget::setStyleSheet(const QString& styleSheet)
2573{
2574 Q_D(QWidget);
2575 if (data->in_destructor)
2576 return;
2577 d->createExtra();
2578
2579 QStyleSheetStyle *proxy = qt_styleSheet(style: d->extra->style);
2580 d->extra->styleSheet = styleSheet;
2581 if (styleSheet.isEmpty()) { // stylesheet removed
2582 if (!proxy)
2583 return;
2584
2585 d->inheritStyle();
2586 return;
2587 }
2588
2589 if (proxy) { // style sheet update
2590 bool repolish = d->polished;
2591 if (!repolish) {
2592 const auto childWidgets = findChildren<QWidget*>();
2593 for (auto child : childWidgets) {
2594 repolish = child->d_func()->polished;
2595 if (repolish)
2596 break;
2597 }
2598 }
2599 if (repolish)
2600 proxy->repolish(widget: this);
2601 return;
2602 }
2603
2604 if (testAttribute(attribute: Qt::WA_SetStyle)) {
2605 d->setStyle_helper(newStyle: new QStyleSheetStyle(d->extra->style), propagate: true);
2606 } else {
2607 d->setStyle_helper(newStyle: new QStyleSheetStyle(nullptr), propagate: true);
2608 }
2609}
2610
2611#endif // QT_NO_STYLE_STYLESHEET
2612
2613/*!
2614 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2615*/
2616
2617QStyle *QWidget::style() const
2618{
2619 Q_D(const QWidget);
2620
2621 if (d->extra && d->extra->style)
2622 return d->extra->style;
2623 return QApplication::style();
2624}
2625
2626/*!
2627 Sets the widget's GUI style to \a style. The ownership of the style
2628 object is not transferred.
2629
2630 If no style is set, the widget uses the application's style,
2631 QApplication::style() instead.
2632
2633 Setting a widget's style has no effect on existing or future child
2634 widgets.
2635
2636 \warning This function is particularly useful for demonstration
2637 purposes, where you want to show Qt's styling capabilities. Real
2638 applications should avoid it and use one consistent GUI style
2639 instead.
2640
2641 \warning Qt style sheets are currently not supported for custom QStyle
2642 subclasses. We plan to address this in some future release.
2643
2644 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2645*/
2646
2647void QWidget::setStyle(QStyle *style)
2648{
2649 Q_D(QWidget);
2650 setAttribute(Qt::WA_SetStyle, on: style != nullptr);
2651 d->createExtra();
2652#if QT_CONFIG(style_stylesheet)
2653 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2654 //if for some reason someone try to set a QStyleSheetStyle, ref it
2655 //(this may happen for example in QButtonDialogBox which propagates its style)
2656 styleSheetStyle->ref();
2657 d->setStyle_helper(newStyle: style, propagate: false);
2658 } else if (qt_styleSheet(style: d->extra->style) || !qApp->styleSheet().isEmpty()) {
2659 // if we have an application stylesheet or have a proxy already, propagate
2660 d->setStyle_helper(newStyle: new QStyleSheetStyle(style), propagate: true);
2661 } else
2662#endif
2663 d->setStyle_helper(newStyle: style, propagate: false);
2664}
2665
2666void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2667{
2668 Q_Q(QWidget);
2669 QStyle *oldStyle = q->style();
2670
2671 createExtra();
2672
2673#if QT_CONFIG(style_stylesheet)
2674 QPointer<QStyle> origStyle = extra->style;
2675#endif
2676 extra->style = newStyle;
2677
2678 // repolish
2679 if (polished && q->windowType() != Qt::Desktop && oldStyle != q->style()) {
2680 oldStyle->unpolish(widget: q);
2681 q->style()->polish(widget: q);
2682 }
2683
2684 if (propagate) {
2685 // We copy the list because the order may be modified
2686 const QObjectList childrenList = children;
2687 for (int i = 0; i < childrenList.size(); ++i) {
2688 QWidget *c = qobject_cast<QWidget*>(o: childrenList.at(i));
2689 if (c)
2690 c->d_func()->inheritStyle();
2691 }
2692 }
2693
2694#if QT_CONFIG(style_stylesheet)
2695 if (!qt_styleSheet(style: newStyle)) {
2696 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(style: origStyle)) {
2697 cssStyle->clearWidgetFont(w: q);
2698 }
2699 }
2700#endif
2701
2702 QEvent e(QEvent::StyleChange);
2703 QCoreApplication::sendEvent(receiver: q, event: &e);
2704
2705#if QT_CONFIG(style_stylesheet)
2706 // dereference the old stylesheet style
2707 if (QStyleSheetStyle *proxy = qt_styleSheet(style: origStyle))
2708 proxy->deref();
2709#endif
2710}
2711
2712// Inherits style from the current parent and propagates it as necessary
2713void QWidgetPrivate::inheritStyle()
2714{
2715#if QT_CONFIG(style_stylesheet)
2716 Q_Q(QWidget);
2717
2718 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2719
2720 QStyleSheetStyle *proxy = qt_styleSheet(style: extraStyle);
2721
2722 if (!q->styleSheet().isEmpty()) {
2723 Q_ASSERT(proxy);
2724 proxy->repolish(widget: q);
2725 return;
2726 }
2727
2728 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2729 QWidget *parent = q->parentWidget();
2730 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2731 // If we have stylesheet on app or parent has stylesheet style, we need
2732 // to be running a proxy
2733 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(style: parentStyle)) {
2734 QStyle *newStyle = parentStyle;
2735 if (q->testAttribute(attribute: Qt::WA_SetStyle) && qt_styleSheet(style: origStyle) == nullptr)
2736 newStyle = new QStyleSheetStyle(origStyle);
2737 else if (auto *styleSheetStyle = qt_styleSheet(style: origStyle))
2738 newStyle = styleSheetStyle;
2739 else if (QStyleSheetStyle *newProxy = qt_styleSheet(style: parentStyle))
2740 newProxy->ref();
2741
2742 setStyle_helper(newStyle, propagate: true);
2743 return;
2744 }
2745
2746 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2747 // we just need our original style back
2748 if (origStyle == extraStyle) // is it any different?
2749 return;
2750
2751 // We could have inherited the proxy from our parent (which has a custom style)
2752 // In such a case we need to start following the application style (i.e revert
2753 // the propagation behavior of QStyleSheetStyle)
2754 if (!q->testAttribute(attribute: Qt::WA_SetStyle))
2755 origStyle = nullptr;
2756
2757 setStyle_helper(newStyle: origStyle, propagate: true);
2758#endif // QT_NO_STYLE_STYLESHEET
2759}
2760
2761
2762/*!
2763 \fn bool QWidget::isWindow() const
2764
2765 Returns \c true if the widget is an independent window, otherwise
2766 returns \c false.
2767
2768 A window is a widget that isn't visually the child of any other
2769 widget and that usually has a frame and a
2770 \l{QWidget::setWindowTitle()}{window title}.
2771
2772 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2773 It will then be grouped with its parent and deleted when the
2774 parent is deleted, minimized when the parent is minimized etc. If
2775 supported by the window manager, it will also have a common
2776 taskbar entry with its parent.
2777
2778 QDialog and QMainWindow widgets are by default windows, even if a
2779 parent widget is specified in the constructor. This behavior is
2780 specified by the Qt::Window flag.
2781
2782 \sa window(), isModal(), parentWidget()
2783*/
2784
2785/*!
2786 \property QWidget::modal
2787 \brief whether the widget is a modal widget
2788
2789 This property only makes sense for windows. A modal widget
2790 prevents widgets in all other windows from getting any input.
2791
2792 By default, this property is \c false.
2793
2794 \sa isWindow(), windowModality, QDialog
2795*/
2796
2797/*!
2798 \property QWidget::windowModality
2799 \brief which windows are blocked by the modal widget
2800 \since 4.1
2801
2802 This property only makes sense for windows. A modal widget
2803 prevents widgets in other windows from getting input. The value of
2804 this property controls which windows are blocked when the widget
2805 is visible. Changing this property while the window is visible has
2806 no effect; you must hide() the widget first, then show() it again.
2807
2808 By default, this property is Qt::NonModal.
2809
2810 \sa isWindow(), QWidget::modal, QDialog
2811*/
2812
2813Qt::WindowModality QWidget::windowModality() const
2814{
2815 return static_cast<Qt::WindowModality>(data->window_modality);
2816}
2817
2818void QWidget::setWindowModality(Qt::WindowModality windowModality)
2819{
2820 data->window_modality = windowModality;
2821 // setModal_sys() will be called by setAttribute()
2822 setAttribute(Qt::WA_ShowModal, on: (data->window_modality != Qt::NonModal));
2823 setAttribute(Qt::WA_SetWindowModality, on: true);
2824}
2825
2826void QWidgetPrivate::setModal_sys()
2827{
2828 Q_Q(QWidget);
2829 if (q->windowHandle())
2830 q->windowHandle()->setModality(q->windowModality());
2831}
2832
2833/*!
2834 \fn bool QWidget::underMouse() const
2835
2836 Returns \c true if the widget is under the mouse cursor; otherwise
2837 returns \c false.
2838
2839 This value is not updated properly during drag and drop
2840 operations.
2841
2842 \sa enterEvent(), leaveEvent()
2843*/
2844
2845/*!
2846 \property QWidget::minimized
2847 \brief whether this widget is minimized (iconified)
2848
2849 This property is only relevant for windows.
2850
2851 By default, this property is \c false.
2852
2853 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2854*/
2855bool QWidget::isMinimized() const
2856{ return data->window_state & Qt::WindowMinimized; }
2857
2858/*!
2859 Shows the widget minimized, as an icon.
2860
2861 Calling this function only affects \l{isWindow()}{windows}.
2862
2863 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2864 isMinimized()
2865*/
2866void QWidget::showMinimized()
2867{
2868 bool isMin = isMinimized();
2869 if (isMin && isVisible())
2870 return;
2871
2872 ensurePolished();
2873
2874 if (!isMin)
2875 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2876 setVisible(true);
2877}
2878
2879/*!
2880 \property QWidget::maximized
2881 \brief whether this widget is maximized
2882
2883 This property is only relevant for windows.
2884
2885 \note Due to limitations on some window systems, this does not always
2886 report the expected results (e.g., if the user on X11 maximizes the
2887 window via the window manager, Qt has no way of distinguishing this
2888 from any other resize). This is expected to improve as window manager
2889 protocols evolve.
2890
2891 By default, this property is \c false.
2892
2893 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2894*/
2895bool QWidget::isMaximized() const
2896{ return data->window_state & Qt::WindowMaximized; }
2897
2898
2899
2900/*!
2901 Returns the current window state. The window state is a OR'ed
2902 combination of Qt::WindowState: Qt::WindowMinimized,
2903 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2904
2905 \sa Qt::WindowState, setWindowState()
2906 */
2907Qt::WindowStates QWidget::windowState() const
2908{
2909 return Qt::WindowStates(data->window_state);
2910}
2911
2912/*!\internal
2913
2914 The function sets the window state on child widgets similar to
2915 setWindowState(). The difference is that the window state changed
2916 event has the isOverride() flag set. It exists mainly to keep
2917 QWorkspace working.
2918 */
2919void QWidget::overrideWindowState(Qt::WindowStates newstate)
2920{
2921 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2922 data->window_state = newstate;
2923 QCoreApplication::sendEvent(receiver: this, event: &e);
2924}
2925
2926/*!
2927 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2928
2929 Sets the window state to \a windowState. The window state is a OR'ed
2930 combination of Qt::WindowState: Qt::WindowMinimized,
2931 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2932
2933 If the window is not visible (i.e. isVisible() returns \c false), the
2934 window state will take effect when show() is called. For visible
2935 windows, the change is immediate. For example, to toggle between
2936 full-screen and normal mode, use the following code:
2937
2938 \snippet code/src_gui_kernel_qwidget.cpp 0
2939
2940 To restore and activate a minimized window (while
2941 preserving its maximized and/or full-screen state), use the following:
2942
2943 \snippet code/src_gui_kernel_qwidget.cpp 1
2944
2945 Calling this function will hide the widget. You must call show() to make
2946 the widget visible again.
2947
2948 \note On some window systems Qt::WindowActive is not immediate, and may be
2949 ignored in certain cases.
2950
2951 When the window state changes, the widget receives a changeEvent()
2952 of type QEvent::WindowStateChange.
2953
2954 \sa Qt::WindowState, windowState()
2955*/
2956void QWidget::setWindowState(Qt::WindowStates newstate)
2957{
2958 Q_D(QWidget);
2959 Qt::WindowStates oldstate = windowState();
2960 if (newstate.testFlag(flag: Qt::WindowMinimized)) // QTBUG-46763
2961 newstate.setFlag(flag: Qt::WindowActive, on: false);
2962 if (oldstate == newstate)
2963 return;
2964 if (isWindow() && !testAttribute(attribute: Qt::WA_WState_Created))
2965 create();
2966
2967 data->window_state = newstate;
2968 data->in_set_window_state = 1;
2969 if (isWindow()) {
2970 // Ensure the initial size is valid, since we store it as normalGeometry below.
2971 if (!testAttribute(attribute: Qt::WA_Resized) && !isVisible())
2972 adjustSize();
2973
2974 d->createTLExtra();
2975 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2976 d->topData()->normalGeometry = geometry();
2977
2978 Q_ASSERT(windowHandle());
2979 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2980 }
2981 data->in_set_window_state = 0;
2982
2983 if (newstate & Qt::WindowActive)
2984 activateWindow();
2985
2986 QWindowStateChangeEvent e(oldstate);
2987 QCoreApplication::sendEvent(receiver: this, event: &e);
2988}
2989
2990/*!
2991 \property QWidget::fullScreen
2992 \brief whether the widget is shown in full screen mode
2993
2994 A widget in full screen mode occupies the whole screen area and does not
2995 display window decorations, such as a title bar.
2996
2997 By default, this property is \c false.
2998
2999 \sa windowState(), minimized, maximized
3000*/
3001bool QWidget::isFullScreen() const
3002{ return data->window_state & Qt::WindowFullScreen; }
3003
3004/*!
3005 Shows the widget in full-screen mode.
3006
3007 Calling this function only affects \l{isWindow()}{windows}.
3008
3009 To return from full-screen mode, call showNormal() or close().
3010
3011 \note Full-screen mode works fine under Windows, but has certain
3012 problems under X. These problems are due to limitations of the
3013 ICCCM protocol that specifies the communication between X11
3014 clients and the window manager. ICCCM simply does not understand
3015 the concept of non-decorated full-screen windows. Therefore, the
3016 best you can do is to request a borderless window and place and
3017 resize it to fill the entire screen. Depending on the window
3018 manager, this may or may not work. The borderless window is
3019 requested using MOTIF hints, which are at least partially
3020 supported by virtually all modern window managers.
3021
3022 An alternative would be to bypass the window manager entirely and
3023 create a window with the Qt::X11BypassWindowManagerHint flag. This
3024 has other severe problems though, like broken keyboard focus
3025 and very strange effects on desktop changes or when the user raises
3026 other windows.
3027
3028 X11 window managers that follow modern post-ICCCM specifications
3029 support full-screen mode properly.
3030
3031 On macOS, showing a window full screen puts the entire application in
3032 full-screen mode, providing it with a dedicated desktop. Showing another
3033 window while the application runs in full-screen mode might automatically
3034 make that window full screen as well. To prevent that, exit full-screen
3035 mode by calling showNormal() or by close() on the full screen window
3036 before showing another window.
3037
3038 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3039*/
3040void QWidget::showFullScreen()
3041{
3042 ensurePolished();
3043
3044 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3045 | Qt::WindowFullScreen);
3046 setVisible(true);
3047#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3048 // activating it here before libscreen activates it causes problems
3049 activateWindow();
3050#endif
3051}
3052
3053/*!
3054 Shows the widget maximized.
3055
3056 Calling this function only affects \l{isWindow()}{windows}.
3057
3058 On X11, this function may not work properly with certain window
3059 managers. See the \l{Window Geometry} documentation for an explanation.
3060
3061 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3062*/
3063void QWidget::showMaximized()
3064{
3065 ensurePolished();
3066
3067 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3068 | Qt::WindowMaximized);
3069 setVisible(true);
3070}
3071
3072/*!
3073 Restores the widget after it has been maximized or minimized.
3074
3075 Calling this function only affects \l{isWindow()}{windows}.
3076
3077 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3078*/
3079void QWidget::showNormal()
3080{
3081 ensurePolished();
3082
3083 setWindowState(windowState() & ~(Qt::WindowMinimized
3084 | Qt::WindowMaximized
3085 | Qt::WindowFullScreen));
3086 setVisible(true);
3087}
3088
3089/*!
3090 Returns \c true if this widget would become enabled if \a ancestor is
3091 enabled; otherwise returns \c false.
3092
3093
3094
3095 This is the case if neither the widget itself nor every parent up
3096 to but excluding \a ancestor has been explicitly disabled.
3097
3098 isEnabledTo(0) returns false if this widget or any if its ancestors
3099 was explicitly disabled.
3100
3101 The word ancestor here means a parent widget within the same window.
3102
3103 Therefore isEnabledTo(0) stops at this widget's window, unlike
3104 isEnabled() which also takes parent windows into considerations.
3105
3106 \sa setEnabled(), enabled
3107*/
3108
3109bool QWidget::isEnabledTo(const QWidget *ancestor) const
3110{
3111 const QWidget * w = this;
3112 while (!w->testAttribute(attribute: Qt::WA_ForceDisabled)
3113 && !w->isWindow()
3114 && w->parentWidget()
3115 && w->parentWidget() != ancestor)
3116 w = w->parentWidget();
3117 return !w->testAttribute(attribute: Qt::WA_ForceDisabled);
3118}
3119
3120#ifndef QT_NO_ACTION
3121/*!
3122 Appends the action \a action to this widget's list of actions.
3123
3124 All QWidgets have a list of \l{QAction}s. However, they can be
3125 represented graphically in many different ways. The default use of
3126 the QAction list (as returned by actions()) is to create a context
3127 QMenu.
3128
3129 A QWidget should only have one of each action and adding an action
3130 it already has will not cause the same action to be in the widget twice.
3131
3132 The ownership of \a action is not transferred to this QWidget.
3133
3134 \sa removeAction(), insertAction(), actions(), QMenu
3135*/
3136void QWidget::addAction(QAction *action)
3137{
3138 insertAction(before: nullptr, action);
3139}
3140
3141/*!
3142 Appends the actions \a actions to this widget's list of actions.
3143
3144 \sa removeAction(), QMenu, addAction()
3145*/
3146void QWidget::addActions(const QList<QAction *> &actions)
3147{
3148 for(int i = 0; i < actions.size(); i++)
3149 insertAction(before: nullptr, action: actions.at(i));
3150}
3151
3152/*!
3153 Inserts the action \a action to this widget's list of actions,
3154 before the action \a before. It appends the action if \a before is \nullptr or
3155 \a before is not a valid action for this widget.
3156
3157 A QWidget should only have one of each action.
3158
3159 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3160*/
3161void QWidget::insertAction(QAction *before, QAction *action)
3162{
3163 if (Q_UNLIKELY(!action)) {
3164 qWarning(msg: "QWidget::insertAction: Attempt to insert null action");
3165 return;
3166 }
3167
3168 Q_D(QWidget);
3169 if (d->actions.contains(t: action))
3170 removeAction(action);
3171
3172 int pos = d->actions.indexOf(t: before);
3173 if (pos < 0) {
3174 before = nullptr;
3175 pos = d->actions.size();
3176 }
3177 d->actions.insert(i: pos, t: action);
3178
3179 QActionPrivate *apriv = action->d_func();
3180 apriv->associatedObjects.append(t: this);
3181
3182 QActionEvent e(QEvent::ActionAdded, action, before);
3183 QCoreApplication::sendEvent(receiver: this, event: &e);
3184}
3185
3186/*!
3187 Inserts the actions \a actions to this widget's list of actions,
3188 before the action \a before. It appends the action if \a before is \nullptr or
3189 \a before is not a valid action for this widget.
3190
3191 A QWidget can have at most one of each action.
3192
3193 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3194*/
3195void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3196{
3197 for(int i = 0; i < actions.size(); ++i)
3198 insertAction(before, action: actions.at(i));
3199}
3200
3201/*!
3202 Removes the action \a action from this widget's list of actions.
3203 \sa insertAction(), actions(), insertAction()
3204*/
3205void QWidget::removeAction(QAction *action)
3206{
3207 if (!action)
3208 return;
3209
3210 Q_D(QWidget);
3211
3212 QActionPrivate *apriv = action->d_func();
3213 apriv->associatedObjects.removeAll(t: this);
3214
3215 if (d->actions.removeAll(t: action)) {
3216 QActionEvent e(QEvent::ActionRemoved, action);
3217 QCoreApplication::sendEvent(receiver: this, event: &e);
3218 }
3219}
3220
3221/*!
3222 Returns the (possibly empty) list of this widget's actions.
3223
3224 \sa contextMenuPolicy, insertAction(), removeAction()
3225*/
3226QList<QAction*> QWidget::actions() const
3227{
3228 Q_D(const QWidget);
3229 return d->actions;
3230}
3231
3232/*!
3233 \fn QAction *QWidget::addAction(const QString &text);
3234 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3235 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3236 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3237
3238 \since 6.3
3239
3240 These convenience functions create a new action with text \a text,
3241 icon \a icon and shortcut \a shortcut, if any.
3242
3243 The functions add the newly created action to the widget's
3244 list of actions, and return it.
3245
3246 QWidget takes ownership of the returned QAction.
3247*/
3248QAction *QWidget::addAction(const QString &text)
3249{
3250 QAction *ret = new QAction(text, this);
3251 addAction(action: ret);
3252 return ret;
3253}
3254
3255QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3256{
3257 QAction *ret = new QAction(icon, text, this);
3258 addAction(action: ret);
3259 return ret;
3260}
3261
3262#if QT_CONFIG(shortcut)
3263QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3264{
3265 QAction *ret = addAction(text);
3266 ret->setShortcut(shortcut);
3267 return ret;
3268}
3269
3270QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3271{
3272 QAction *ret = addAction(icon, text);
3273 ret->setShortcut(shortcut);
3274 return ret;
3275}
3276#endif
3277
3278/*!
3279 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3280 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3281 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3282 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3283
3284 \overload
3285 \since 6.3
3286
3287 This convenience function creates a new action with the text \a
3288 text, icon \a icon, and shortcut \a shortcut, if any.
3289
3290 The action's \l{QAction::triggered()}{triggered()} signal is connected
3291 to the \a receiver's \a member slot. The function adds the newly created
3292 action to the widget's list of actions and returns it.
3293
3294 QWidget takes ownership of the returned QAction.
3295*/
3296QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3297 Qt::ConnectionType type)
3298{
3299 QAction *action = addAction(text);
3300 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3301 return action;
3302}
3303
3304QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3305 const QObject *receiver, const char* member,
3306 Qt::ConnectionType type)
3307{
3308 QAction *action = addAction(icon, text);
3309 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3310 return action;
3311}
3312
3313#if QT_CONFIG(shortcut)
3314QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3315 const QObject *receiver, const char* member,
3316 Qt::ConnectionType type)
3317{
3318 QAction *action = addAction(text, receiver, member, type);
3319 action->setShortcut(shortcut);
3320 return action;
3321}
3322
3323QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3324 const QObject *receiver, const char* member,
3325 Qt::ConnectionType type)
3326{
3327 QAction *action = addAction(icon, text, receiver, member, type);
3328 action->setShortcut(shortcut);
3329 return action;
3330}
3331#endif // QT_CONFIG(shortcut)
3332
3333/*!
3334 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3335 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3336 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3337 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3338
3339 \since 6.3
3340 \overload
3341
3342 These convenience functions create a new action with the text \a text,
3343 icon \a icon, and shortcut \a shortcut, if any.
3344
3345 The action's \l{QAction::triggered()}{triggered()} signal is connected
3346 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3347 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3348
3349 The function adds the newly created action to the widget's list of
3350 actions and returns it.
3351
3352 QWidget takes ownership of the returned QAction.
3353*/
3354#endif // QT_NO_ACTION
3355
3356/*!
3357 \property QWidget::enabled
3358 \brief whether the widget is enabled
3359
3360 In general an enabled widget handles keyboard and mouse events; a disabled
3361 widget does not. An exception is made with \l{QAbstractButton}.
3362
3363 Some widgets display themselves differently when they are
3364 disabled. For example a button might draw its label grayed out. If
3365 your widget needs to know when it becomes enabled or disabled, you
3366 can use the changeEvent() with type QEvent::EnabledChange.
3367
3368 Disabling a widget implicitly disables all its children. Enabling
3369 respectively enables all child widgets unless they have been
3370 explicitly disabled. It it not possible to explicitly enable a child
3371 widget which is not a window while its parent widget remains disabled.
3372
3373 By default, this property is \c true.
3374
3375 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3376*/
3377void QWidget::setEnabled(bool enable)
3378{
3379 Q_D(QWidget);
3380 setAttribute(Qt::WA_ForceDisabled, on: !enable);
3381 d->setEnabled_helper(enable);
3382}
3383
3384void QWidgetPrivate::setEnabled_helper(bool enable)
3385{
3386 Q_Q(QWidget);
3387
3388 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3389 return; // nothing we can do
3390
3391 if (enable != q->testAttribute(attribute: Qt::WA_Disabled))
3392 return; // nothing to do
3393
3394 q->setAttribute(Qt::WA_Disabled, on: !enable);
3395 updateSystemBackground();
3396
3397 if (!enable && q->window()->focusWidget() == q) {
3398 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3399 if (!parentIsEnabled || !q->focusNextChild())
3400 q->clearFocus();
3401 }
3402
3403 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3404 for (int i = 0; i < children.size(); ++i) {
3405 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
3406 if (w && !w->testAttribute(attribute))
3407 w->d_func()->setEnabled_helper(enable);
3408 }
3409#ifndef QT_NO_CURSOR
3410 if (q->testAttribute(attribute: Qt::WA_SetCursor) || q->isWindow()) {
3411 // enforce the windows behavior of clearing the cursor on
3412 // disabled widgets
3413 qt_qpa_set_cursor(w: q, force: false);
3414 }
3415#endif
3416#ifndef QT_NO_IM
3417 if (q->testAttribute(attribute: Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3418 QWidget *focusWidget = effectiveFocusWidget();
3419
3420 if (enable) {
3421 if (focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled))
3422 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3423 } else {
3424 QGuiApplication::inputMethod()->commit();
3425 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3426 }
3427 }
3428#endif //QT_NO_IM
3429 QEvent e(QEvent::EnabledChange);
3430 QCoreApplication::sendEvent(receiver: q, event: &e);
3431}
3432
3433/*!
3434 \property QWidget::acceptDrops
3435 \brief whether drop events are enabled for this widget
3436
3437 Setting this property to true announces to the system that this
3438 widget \e may be able to accept drop events.
3439
3440 If the widget is the desktop (windowType() == Qt::Desktop), this may
3441 fail if another application is using the desktop; you can call
3442 acceptDrops() to test if this occurs.
3443
3444 \warning Do not modify this property in a drag and drop event handler.
3445
3446 By default, this property is \c false.
3447
3448 \sa {Drag and Drop in Qt}{Drag and Drop}
3449*/
3450bool QWidget::acceptDrops() const
3451{
3452 return testAttribute(attribute: Qt::WA_AcceptDrops);
3453}
3454
3455void QWidget::setAcceptDrops(bool on)
3456{
3457 setAttribute(Qt::WA_AcceptDrops, on);
3458
3459}
3460
3461/*!
3462 Disables widget input events if \a disable is true; otherwise
3463 enables input events.
3464
3465 See the \l enabled documentation for more information.
3466
3467 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3468*/
3469void QWidget::setDisabled(bool disable)
3470{
3471 setEnabled(!disable);
3472}
3473
3474/*!
3475 \property QWidget::frameGeometry
3476 \brief geometry of the widget relative to its parent including any
3477 window frame
3478
3479 See the \l{Window Geometry} documentation for an overview of geometry
3480 issues with windows.
3481
3482 By default, this property contains a value that depends on the user's
3483 platform and screen geometry.
3484
3485 \sa geometry(), x(), y(), pos()
3486*/
3487QRect QWidget::frameGeometry() const
3488{
3489 Q_D(const QWidget);
3490 if (isWindow() && ! (windowType() == Qt::Popup)) {
3491 QRect fs = d->frameStrut();
3492 return QRect(data->crect.x() - fs.left(),
3493 data->crect.y() - fs.top(),
3494 data->crect.width() + fs.left() + fs.right(),
3495 data->crect.height() + fs.top() + fs.bottom());
3496 }
3497 return data->crect;
3498}
3499
3500/*!
3501 \property QWidget::x
3502
3503 \brief the x coordinate of the widget relative to its parent including
3504 any window frame
3505
3506 See the \l{Window Geometry} documentation for an overview of geometry
3507 issues with windows.
3508
3509 By default, this property has a value of 0.
3510
3511 \sa frameGeometry, y, pos
3512*/
3513int QWidget::x() const
3514{
3515 Q_D(const QWidget);
3516 if (isWindow() && ! (windowType() == Qt::Popup))
3517 return data->crect.x() - d->frameStrut().left();
3518 return data->crect.x();
3519}
3520
3521/*!
3522 \property QWidget::y
3523 \brief the y coordinate of the widget relative to its parent and
3524 including any window frame
3525
3526 See the \l{Window Geometry} documentation for an overview of geometry
3527 issues with windows.
3528
3529 By default, this property has a value of 0.
3530
3531 \sa frameGeometry, x, pos
3532*/
3533int QWidget::y() const
3534{
3535 Q_D(const QWidget);
3536 if (isWindow() && ! (windowType() == Qt::Popup))
3537 return data->crect.y() - d->frameStrut().top();
3538 return data->crect.y();
3539}
3540
3541/*!
3542 \property QWidget::pos
3543 \brief the position of the widget within its parent widget
3544
3545 If the widget is a window, the position is that of the widget on
3546 the desktop, including its frame.
3547
3548 When changing the position, the widget, if visible, receives a
3549 move event (moveEvent()) immediately. If the widget is not
3550 currently visible, it is guaranteed to receive an event before it
3551 is shown.
3552
3553 By default, this property contains a position that refers to the
3554 origin.
3555
3556 \warning Calling move() or setGeometry() inside moveEvent() can
3557 lead to infinite recursion.
3558
3559 See the \l{Window Geometry} documentation for an overview of geometry
3560 issues with windows.
3561
3562 \note Not all windowing systems support setting or querying top level window positions.
3563 On such a system, programmatically moving windows may not have any effect, and artificial
3564 values may be returned for the current positions, such as \c QPoint(0, 0).
3565
3566 \sa frameGeometry, size, x(), y()
3567*/
3568QPoint QWidget::pos() const
3569{
3570 Q_D(const QWidget);
3571 QPoint result = data->crect.topLeft();
3572 if (isWindow() && ! (windowType() == Qt::Popup))
3573 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3574 result -= d->frameStrut().topLeft();
3575 return result;
3576}
3577
3578/*!
3579 \property QWidget::geometry
3580 \brief the geometry of the widget relative to its parent and
3581 excluding the window frame
3582
3583 When changing the geometry, the widget, if visible, receives a
3584 move event (moveEvent()) and/or a resize event (resizeEvent())
3585 immediately. If the widget is not currently visible, it is
3586 guaranteed to receive appropriate events before it is shown.
3587
3588 The size component is adjusted if it lies outside the range
3589 defined by minimumSize() and maximumSize().
3590
3591 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3592 can lead to infinite recursion.
3593
3594 See the \l{Window Geometry} documentation for an overview of geometry
3595 issues with windows.
3596
3597 By default, this property contains a value that depends on the user's
3598 platform and screen geometry.
3599
3600 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3601 resizeEvent(), minimumSize(), maximumSize()
3602*/
3603
3604/*!
3605 \property QWidget::size
3606 \brief the size of the widget excluding any window frame
3607
3608 If the widget is visible when it is being resized, it receives a resize event
3609 (resizeEvent()) immediately. If the widget is not currently
3610 visible, it is guaranteed to receive an event before it is shown.
3611
3612 The size is adjusted if it lies outside the range defined by
3613 minimumSize() and maximumSize().
3614
3615 By default, this property contains a value that depends on the user's
3616 platform and screen geometry.
3617
3618 \warning Calling resize() or setGeometry() inside resizeEvent() can
3619 lead to infinite recursion.
3620
3621 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3622 appear on screen. This also applies to windows.
3623
3624 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3625*/
3626
3627/*!
3628 \property QWidget::width
3629 \brief the width of the widget excluding any window frame
3630
3631 See the \l{Window Geometry} documentation for an overview of geometry
3632 issues with windows.
3633
3634 \note Do not use this function to find the width of a screen on
3635 a multi-screen desktop. See QScreen for details.
3636
3637 By default, this property contains a value that depends on the user's
3638 platform and screen geometry.
3639
3640 \sa geometry, height, size
3641*/
3642
3643/*!
3644 \property QWidget::height
3645 \brief the height of the widget excluding any window frame
3646
3647 See the \l{Window Geometry} documentation for an overview of geometry
3648 issues with windows.
3649
3650 By default, this property contains a value that depends on the user's
3651 platform and \l{QScreen::geometry}{screen geometry}.
3652
3653 \sa geometry, width, size
3654*/
3655
3656/*!
3657 \property QWidget::rect
3658 \brief the internal geometry of the widget excluding any window
3659 frame
3660
3661 The rect property equals QRect(0, 0, width(), height()).
3662
3663 See the \l{Window Geometry} documentation for an overview of geometry
3664 issues with windows.
3665
3666 By default, this property contains a value that depends on the user's
3667 platform and screen geometry.
3668
3669 \sa size
3670*/
3671
3672/*!
3673 \property QWidget::normalGeometry
3674
3675 \brief the geometry of the widget as it will appear when shown as
3676 a normal (not maximized or full screen) top-level widget
3677
3678 If the widget is already in this state the normal geometry will
3679 reflect the widget's current geometry().
3680
3681 For child widgets this property always holds an empty rectangle.
3682
3683 By default, this property contains an empty rectangle.
3684
3685 \sa QWidget::windowState(), QWidget::geometry
3686*/
3687QRect QWidget::normalGeometry() const
3688{
3689 Q_D(const QWidget);
3690 if (!isWindow())
3691 return QRect();
3692
3693 if (!isMaximized() && !isFullScreen())
3694 return geometry();
3695
3696 return d->topData()->normalGeometry;
3697}
3698
3699
3700/*!
3701 \property QWidget::childrenRect
3702 \brief the bounding rectangle of the widget's children
3703
3704 Hidden children are excluded.
3705
3706 By default, for a widget with no children, this property contains a
3707 rectangle with zero width and height located at the origin.
3708
3709 \sa childrenRegion(), geometry()
3710*/
3711
3712QRect QWidget::childrenRect() const
3713{
3714 Q_D(const QWidget);
3715 QRect r(0, 0, 0, 0);
3716 for (int i = 0; i < d->children.size(); ++i) {
3717 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3718 if (w && !w->isWindow() && !w->isHidden())
3719 r |= w->geometry();
3720 }
3721 return r;
3722}
3723
3724/*!
3725 \property QWidget::childrenRegion
3726 \brief the combined region occupied by the widget's children
3727
3728 Hidden children are excluded.
3729
3730 By default, for a widget with no children, this property contains an
3731 empty region.
3732
3733 \sa childrenRect(), geometry(), mask()
3734*/
3735
3736QRegion QWidget::childrenRegion() const
3737{
3738 Q_D(const QWidget);
3739 QRegion r;
3740 for (int i = 0; i < d->children.size(); ++i) {
3741 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3742 if (w && !w->isWindow() && !w->isHidden()) {
3743 QRegion mask = w->mask();
3744 if (mask.isEmpty())
3745 r |= w->geometry();
3746 else
3747 r |= mask.translated(p: w->pos());
3748 }
3749 }
3750 return r;
3751}
3752
3753
3754/*!
3755 \property QWidget::minimumSize
3756 \brief the widget's minimum size
3757
3758 The widget cannot be resized to a smaller size than the minimum
3759 widget size. The widget's size is forced to the minimum size if
3760 the current size is smaller.
3761
3762 The minimum size set by this function will override the minimum size
3763 defined by QLayout. To unset the minimum size, use a
3764 value of \c{QSize(0, 0)}.
3765
3766 By default, this property contains a size with zero width and height.
3767
3768 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3769*/
3770
3771QSize QWidget::minimumSize() const
3772{
3773 Q_D(const QWidget);
3774 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3775}
3776
3777/*!
3778 \property QWidget::maximumSize
3779 \brief the widget's maximum size in pixels
3780
3781 The widget cannot be resized to a larger size than the maximum
3782 widget size.
3783
3784 By default, this property contains a size in which both width and height
3785 have values of 16777215.
3786
3787 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3788 of widgets.
3789
3790 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3791*/
3792
3793QSize QWidget::maximumSize() const
3794{
3795 Q_D(const QWidget);
3796 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3797 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3798}
3799
3800
3801/*!
3802 \property QWidget::minimumWidth
3803 \brief the widget's minimum width in pixels
3804
3805 This property corresponds to the width held by the \l minimumSize property.
3806
3807 By default, this property has a value of 0.
3808
3809 \sa minimumSize, minimumHeight
3810*/
3811
3812/*!
3813 \property QWidget::minimumHeight
3814 \brief the widget's minimum height in pixels
3815
3816 This property corresponds to the height held by the \l minimumSize property.
3817
3818 By default, this property has a value of 0.
3819
3820 \sa minimumSize, minimumWidth
3821*/
3822
3823/*!
3824 \property QWidget::maximumWidth
3825 \brief the widget's maximum width in pixels
3826
3827 This property corresponds to the width held by the \l maximumSize property.
3828
3829 By default, this property contains a value of 16777215.
3830
3831 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3832 of widgets.
3833
3834 \sa maximumSize, maximumHeight
3835*/
3836
3837/*!
3838 \property QWidget::maximumHeight
3839 \brief the widget's maximum height in pixels
3840
3841 This property corresponds to the height held by the \l maximumSize property.
3842
3843 By default, this property contains a value of 16777215.
3844
3845 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3846 of widgets.
3847
3848 \sa maximumSize, maximumWidth
3849*/
3850
3851/*!
3852 \property QWidget::sizeIncrement
3853 \brief the size increment of the widget
3854
3855 When the user resizes the window, the size will move in steps of
3856 sizeIncrement().width() pixels horizontally and
3857 sizeIncrement.height() pixels vertically, with baseSize() as the
3858 basis. Preferred widget sizes are for non-negative integers \e i
3859 and \e j:
3860 \snippet code/src_gui_kernel_qwidget.cpp 2
3861
3862 Note that while you can set the size increment for all widgets, it
3863 only affects windows.
3864
3865 By default, this property contains a size with zero width and height.
3866
3867 \warning The size increment has no effect under Windows, and may
3868 be disregarded by the window manager on X11.
3869
3870 \sa size, minimumSize, maximumSize
3871*/
3872QSize QWidget::sizeIncrement() const
3873{
3874 Q_D(const QWidget);
3875 return (d->extra && d->extra->topextra)
3876 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3877 : QSize(0, 0);
3878}
3879
3880/*!
3881 \property QWidget::baseSize
3882 \brief the base size of the widget
3883
3884 The base size is used to calculate a proper widget size if the
3885 widget defines sizeIncrement().
3886
3887 By default, for a newly-created widget, this property contains a size with
3888 zero width and height.
3889
3890 \sa setSizeIncrement()
3891*/
3892
3893QSize QWidget::baseSize() const
3894{
3895 Q_D(const QWidget);
3896 return (d->extra && d->extra->topextra)
3897 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3898 : QSize(0, 0);
3899}
3900
3901bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3902{
3903 Q_Q(QWidget);
3904
3905 int mw = minw, mh = minh;
3906 if (mw == QWIDGETSIZE_MAX)
3907 mw = 0;
3908 if (mh == QWIDGETSIZE_MAX)
3909 mh = 0;
3910 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3911 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) "
3912 "The largest allowed size is (%d,%d)",
3913 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3914 QWIDGETSIZE_MAX);
3915 minw = mw = qMin<int>(a: minw, QWIDGETSIZE_MAX);
3916 minh = mh = qMin<int>(a: minh, QWIDGETSIZE_MAX);
3917 }
3918 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3919 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3920 "are not possible",
3921 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3922 minw = mw = qMax(a: minw, b: 0);
3923 minh = mh = qMax(a: minh, b: 0);
3924 }
3925 createExtra();
3926 if (extra->minw == mw && extra->minh == mh)
3927 return false;
3928 extra->minw = mw;
3929 extra->minh = mh;
3930 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3931 return true;
3932}
3933
3934void QWidgetPrivate::setConstraints_sys()
3935{
3936 Q_Q(QWidget);
3937 if (extra && q->windowHandle()) {
3938 QWindow *win = q->windowHandle();
3939 QWindowPrivate *winp = qt_window_private(window: win);
3940
3941 winp->minimumSize = QSize(extra->minw, extra->minh);
3942 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3943
3944 if (extra->topextra) {
3945 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3946 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3947 }
3948
3949 if (winp->platformWindow) {
3950 fixPosIncludesFrame();
3951 winp->platformWindow->propagateSizeHints();
3952 }
3953 }
3954}
3955
3956/*!
3957 \overload
3958
3959 This function corresponds to setMinimumSize(QSize(minw, minh)).
3960 Sets the minimum width to \a minw and the minimum height to \a
3961 minh.
3962*/
3963
3964void QWidget::setMinimumSize(int minw, int minh)
3965{
3966 Q_D(QWidget);
3967 if (!d->setMinimumSize_helper(minw, minh))
3968 return;
3969
3970 if (isWindow())
3971 d->setConstraints_sys();
3972 if (minw > width() || minh > height()) {
3973 bool resized = testAttribute(attribute: Qt::WA_Resized);
3974 bool maximized = isMaximized();
3975 resize(w: qMax(a: minw,b: width()), h: qMax(a: minh,b: height()));
3976 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
3977 if (maximized)
3978 data->window_state = data->window_state | Qt::WindowMaximized;
3979 }
3980#if QT_CONFIG(graphicsview)
3981 if (d->extra) {
3982 if (d->extra->proxyWidget)
3983 d->extra->proxyWidget->setMinimumSize(aw: minw, ah: minh);
3984 }
3985#endif
3986 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3987}
3988
3989bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3990{
3991 Q_Q(QWidget);
3992 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3993 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) "
3994 "The largest allowed size is (%d,%d)",
3995 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3996 QWIDGETSIZE_MAX);
3997 maxw = qMin<int>(a: maxw, QWIDGETSIZE_MAX);
3998 maxh = qMin<int>(a: maxh, QWIDGETSIZE_MAX);
3999 }
4000 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4001 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4002 "are not possible",
4003 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4004 maxw = qMax(a: maxw, b: 0);
4005 maxh = qMax(a: maxh, b: 0);
4006 }
4007 createExtra();
4008 if (extra->maxw == maxw && extra->maxh == maxh)
4009 return false;
4010 extra->maxw = maxw;
4011 extra->maxh = maxh;
4012 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4013 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4014 return true;
4015}
4016
4017/*!
4018 \overload
4019
4020 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4021 maxh)). Sets the maximum width to \a maxw and the maximum height
4022 to \a maxh.
4023*/
4024void QWidget::setMaximumSize(int maxw, int maxh)
4025{
4026 Q_D(QWidget);
4027 if (!d->setMaximumSize_helper(maxw, maxh))
4028 return;
4029
4030 if (isWindow())
4031 d->setConstraints_sys();
4032 if (maxw < width() || maxh < height()) {
4033 bool resized = testAttribute(attribute: Qt::WA_Resized);
4034 resize(w: qMin(a: maxw,b: width()), h: qMin(a: maxh,b: height()));
4035 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
4036 }
4037
4038#if QT_CONFIG(graphicsview)
4039 if (d->extra) {
4040 if (d->extra->proxyWidget)
4041 d->extra->proxyWidget->setMaximumSize(aw: maxw, ah: maxh);
4042 }
4043#endif
4044
4045 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4046}
4047
4048/*!
4049 \overload
4050
4051 Sets the x (width) size increment to \a w and the y (height) size
4052 increment to \a h.
4053*/
4054void QWidget::setSizeIncrement(int w, int h)
4055{
4056 Q_D(QWidget);
4057 d->createTLExtra();
4058 QTLWExtra* x = d->topData();
4059 if (x->incw == w && x->inch == h)
4060 return;
4061 x->incw = w;
4062 x->inch = h;
4063 if (isWindow())
4064 d->setConstraints_sys();
4065}
4066
4067/*!
4068 \overload
4069
4070 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4071 the widgets base size to width \a basew and height \a baseh.
4072*/
4073void QWidget::setBaseSize(int basew, int baseh)
4074{
4075 Q_D(QWidget);
4076 d->createTLExtra();
4077 QTLWExtra* x = d->topData();
4078 if (x->basew == basew && x->baseh == baseh)
4079 return;
4080 x->basew = basew;
4081 x->baseh = baseh;
4082 if (isWindow())
4083 d->setConstraints_sys();
4084}
4085
4086/*!
4087 Sets both the minimum and maximum sizes of the widget to \a s,
4088 thereby preventing it from ever growing or shrinking.
4089
4090 This will override the default size constraints set by QLayout.
4091
4092 To remove constraints, set the size to QWIDGETSIZE_MAX.
4093
4094 Alternatively, if you want the widget to have a
4095 fixed size based on its contents, you can call
4096 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4097
4098 \sa maximumSize, minimumSize
4099*/
4100
4101void QWidget::setFixedSize(const QSize & s)
4102{
4103 setFixedSize(w: s.width(), h: s.height());
4104}
4105
4106
4107/*!
4108 \fn void QWidget::setFixedSize(int w, int h)
4109 \overload
4110
4111 Sets the width of the widget to \a w and the height to \a h.
4112*/
4113
4114void QWidget::setFixedSize(int w, int h)
4115{
4116 Q_D(QWidget);
4117 bool minSizeSet = d->setMinimumSize_helper(minw&: w, minh&: h);
4118 bool maxSizeSet = d->setMaximumSize_helper(maxw&: w, maxh&: h);
4119 if (!minSizeSet && !maxSizeSet)
4120 return;
4121
4122 if (isWindow())
4123 d->setConstraints_sys();
4124 else
4125 d->updateGeometry_helper(forceUpdate: true);
4126
4127 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4128 resize(w, h);
4129}
4130
4131void QWidget::setMinimumWidth(int w)
4132{
4133 Q_D(QWidget);
4134 d->createExtra();
4135 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4136 setMinimumSize(minw: w, minh: minimumSize().height());
4137 d->extra->explicitMinSize = expl;
4138}
4139
4140void QWidget::setMinimumHeight(int h)
4141{
4142 Q_D(QWidget);
4143 d->createExtra();
4144 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4145 setMinimumSize(minw: minimumSize().width(), minh: h);
4146 d->extra->explicitMinSize = expl;
4147}
4148
4149void QWidget::setMaximumWidth(int w)
4150{
4151 Q_D(QWidget);
4152 d->createExtra();
4153 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4154 setMaximumSize(maxw: w, maxh: maximumSize().height());
4155 d->extra->explicitMaxSize = expl;
4156}
4157
4158void QWidget::setMaximumHeight(int h)
4159{
4160 Q_D(QWidget);
4161 d->createExtra();
4162 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4163 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4164 d->extra->explicitMaxSize = expl;
4165}
4166
4167/*!
4168 Sets both the minimum and maximum width of the widget to \a w
4169 without changing the heights. Provided for convenience.
4170
4171 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4172*/
4173
4174void QWidget::setFixedWidth(int w)
4175{
4176 Q_D(QWidget);
4177 d->createExtra();
4178 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4179 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4180 setMinimumSize(minw: w, minh: minimumSize().height());
4181 setMaximumSize(maxw: w, maxh: maximumSize().height());
4182 d->extra->explicitMinSize = explMin;
4183 d->extra->explicitMaxSize = explMax;
4184}
4185
4186
4187/*!
4188 Sets both the minimum and maximum heights of the widget to \a h
4189 without changing the widths. Provided for convenience.
4190
4191 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4192*/
4193
4194void QWidget::setFixedHeight(int h)
4195{
4196 Q_D(QWidget);
4197 d->createExtra();
4198 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4199 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4200 setMinimumSize(minw: minimumSize().width(), minh: h);
4201 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4202 d->extra->explicitMinSize = explMin;
4203 d->extra->explicitMaxSize = explMax;
4204}
4205
4206
4207/*!
4208 Translates the widget coordinate \a pos to the coordinate system
4209 of \a parent. The \a parent must not be \nullptr and must be a parent
4210 of the calling widget.
4211
4212 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4213 \since 6.0
4214*/
4215
4216QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4217{
4218 QPointF p = pos;
4219 if (parent) {
4220 const QWidget * w = this;
4221 while (w != parent) {
4222 p = w->mapToParent(p);
4223 w = w->parentWidget();
4224 if (!w) {
4225 qWarning(msg: "QWidget::mapTo(): parent must be in parent hierarchy");
4226 break;
4227 }
4228 }
4229 }
4230 return p;
4231}
4232
4233/*!
4234 \overload
4235*/
4236QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4237{
4238 return mapTo(parent, pos: QPointF(pos)).toPoint();
4239}
4240
4241/*!
4242 Translates the widget coordinate \a pos from the coordinate system
4243 of \a parent to this widget's coordinate system. The \a parent
4244 must not be \nullptr and must be a parent of the calling widget.
4245
4246 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4247 \since 6.0
4248*/
4249
4250QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4251{
4252 QPointF p(pos);
4253 if (parent) {
4254 const QWidget * w = this;
4255 while (w != parent) {
4256 p = w->mapFromParent(p);
4257 w = w->parentWidget();
4258 if (!w) {
4259 qWarning(msg: "QWidget::mapFrom(): parent must be in parent hierarchy");
4260 break;
4261 }
4262 }
4263 }
4264 return p;
4265}
4266
4267/*!
4268 \overload
4269*/
4270QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4271{
4272 return mapFrom(parent, pos: QPointF(pos)).toPoint();
4273}
4274
4275/*!
4276 Translates the widget coordinate \a pos to a coordinate in the
4277 parent widget.
4278
4279 Same as mapToGlobal() if the widget has no parent.
4280
4281 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4282 \since 6.0
4283*/
4284
4285QPointF QWidget::mapToParent(const QPointF &pos) const
4286{
4287 return pos + QPointF(data->crect.topLeft());
4288}
4289
4290/*!
4291 \overload
4292*/
4293QPoint QWidget::mapToParent(const QPoint &pos) const
4294{
4295 return pos + data->crect.topLeft();
4296}
4297
4298/*!
4299 Translates the parent widget coordinate \a pos to widget
4300 coordinates.
4301
4302 Same as mapFromGlobal() if the widget has no parent.
4303
4304 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4305 \since 6.0
4306*/
4307
4308QPointF QWidget::mapFromParent(const QPointF &pos) const
4309{
4310 return pos - QPointF(data->crect.topLeft());
4311}
4312
4313/*!
4314 \overload
4315*/
4316QPoint QWidget::mapFromParent(const QPoint &pos) const
4317{
4318 return pos - data->crect.topLeft();
4319}
4320
4321
4322/*!
4323 Returns the window for this widget, i.e. the next ancestor widget
4324 that has (or could have) a window-system frame.
4325
4326 If the widget is a window, the widget itself is returned.
4327
4328 Typical usage is changing the window title:
4329
4330 \snippet code/src_gui_kernel_qwidget.cpp 3
4331
4332 \sa isWindow()
4333*/
4334
4335QWidget *QWidget::window() const
4336{
4337 QWidget *w = const_cast<QWidget *>(this);
4338 QWidget *p = w->parentWidget();
4339 while (!w->isWindow() && p) {
4340 w = p;
4341 p = p->parentWidget();
4342 }
4343 return w;
4344}
4345
4346/*!
4347 \since 4.4
4348
4349 Returns the native parent for this widget, i.e. the next ancestor widget
4350 that has a system identifier, or \nullptr if it does not have any native
4351 parent.
4352
4353 \sa effectiveWinId()
4354*/
4355QWidget *QWidget::nativeParentWidget() const
4356{
4357 QWidget *parent = parentWidget();
4358 while (parent && !parent->internalWinId())
4359 parent = parent->parentWidget();
4360 return parent;
4361}
4362
4363/*! \fn QWidget *QWidget::topLevelWidget() const
4364 \deprecated
4365
4366 Use window() instead.
4367*/
4368
4369
4370
4371/*!
4372 Returns the background role of the widget.
4373
4374 The background role defines the brush from the widget's \l palette that
4375 is used to render the background.
4376
4377 If no explicit background role is set, the widget inherits its parent
4378 widget's background role.
4379
4380 \sa setBackgroundRole(), foregroundRole()
4381 */
4382QPalette::ColorRole QWidget::backgroundRole() const
4383{
4384
4385 const QWidget *w = this;
4386 do {
4387 QPalette::ColorRole role = w->d_func()->bg_role;
4388 if (role != QPalette::NoRole)
4389 return role;
4390 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4391 break;
4392 w = w->parentWidget();
4393 } while (w);
4394 return QPalette::Window;
4395}
4396
4397/*!
4398 Sets the background role of the widget to \a role.
4399
4400 The background role defines the brush from the widget's \l palette that
4401 is used to render the background.
4402
4403 If \a role is QPalette::NoRole, then the widget inherits its
4404 parent's background role.
4405
4406 Note that styles are free to choose any color from the palette.
4407 You can modify the palette or set a style sheet if you don't
4408 achieve the result you want with setBackgroundRole().
4409
4410 \sa backgroundRole(), foregroundRole()
4411 */
4412
4413void QWidget::setBackgroundRole(QPalette::ColorRole role)
4414{
4415 Q_D(QWidget);
4416 d->bg_role = role;
4417 d->updateSystemBackground();
4418 d->propagatePaletteChange();
4419 d->updateIsOpaque();
4420}
4421
4422/*!
4423 Returns the foreground role.
4424
4425 The foreground role defines the color from the widget's \l palette that
4426 is used to draw the foreground.
4427
4428 If no explicit foreground role is set, the function returns a role
4429 that contrasts with the background role.
4430
4431 \sa setForegroundRole(), backgroundRole()
4432 */
4433QPalette::ColorRole QWidget::foregroundRole() const
4434{
4435 Q_D(const QWidget);
4436 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4437 if (rl != QPalette::NoRole)
4438 return rl;
4439 QPalette::ColorRole role = QPalette::WindowText;
4440 switch (backgroundRole()) {
4441 case QPalette::Button:
4442 role = QPalette::ButtonText;
4443 break;
4444 case QPalette::Base:
4445 role = QPalette::Text;
4446 break;
4447 case QPalette::Dark:
4448 case QPalette::Shadow:
4449 role = QPalette::Light;
4450 break;
4451 case QPalette::Highlight:
4452 role = QPalette::HighlightedText;
4453 break;
4454 case QPalette::ToolTipBase:
4455 role = QPalette::ToolTipText;
4456 break;
4457 default:
4458 ;
4459 }
4460 return role;
4461}
4462
4463/*!
4464 Sets the foreground role of the widget to \a role.
4465
4466 The foreground role defines the color from the widget's \l palette that
4467 is used to draw the foreground.
4468
4469 If \a role is QPalette::NoRole, the widget uses a foreground role
4470 that contrasts with the background role.
4471
4472 Note that styles are free to choose any color from the palette.
4473 You can modify the palette or set a style sheet if you don't
4474 achieve the result you want with setForegroundRole().
4475
4476 \sa foregroundRole(), backgroundRole()
4477 */
4478void QWidget::setForegroundRole(QPalette::ColorRole role)
4479{
4480 Q_D(QWidget);
4481 d->fg_role = role;
4482 d->updateSystemBackground();
4483 d->propagatePaletteChange();
4484}
4485
4486/*!
4487 \property QWidget::palette
4488 \brief the widget's palette
4489
4490 This property describes the widget's palette. The palette is used by the
4491 widget's style when rendering standard components, and is available as a
4492 means to ensure that custom widgets can maintain consistency with the
4493 native platform's look and feel. It's common that different platforms, or
4494 different styles, have different palettes.
4495
4496 When you assign a new palette to a widget, the color roles from this
4497 palette are combined with the widget's default palette to form the
4498 widget's final palette. The palette entry for the widget's background role
4499 is used to fill the widget's background (see QWidget::autoFillBackground),
4500 and the foreground role initializes QPainter's pen.
4501
4502 The default depends on the system environment. QApplication maintains a
4503 system/theme palette which serves as a default for all widgets. There may
4504 also be special palette defaults for certain types of widgets (e.g., on
4505 Windows Vista, all classes that derive from QMenuBar have a special
4506 default palette). You can also define default palettes for widgets
4507 yourself by passing a custom palette and the name of a widget to
4508 QApplication::setPalette(). Finally, the style always has the option of
4509 polishing the palette as it's assigned (see QStyle::polish()).
4510
4511 QWidget propagates explicit palette roles from parent to child. If you
4512 assign a brush or color to a specific role on a palette and assign that
4513 palette to a widget, that role will propagate to all the widget's
4514 children, overriding any system defaults for that role. Note that palettes
4515 by default don't propagate to windows (see isWindow()) unless the
4516 Qt::WA_WindowPropagation attribute is enabled.
4517
4518 QWidget's palette propagation is similar to its font propagation.
4519
4520 The current style, which is used to render the content of all standard Qt
4521 widgets, is free to choose colors and brushes from the widget palette, or,
4522 in some cases, to ignore the palette (partially, or completely). In
4523 particular, certain styles like GTK style, Mac style, and Windows Vista
4524 style, depend on third party APIs to render the content of widgets,
4525 and these styles typically do not follow the palette. Because of this,
4526 assigning roles to a widget's palette is not guaranteed to change the
4527 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4528
4529 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4530 When using style sheets, the palette of a widget can be customized using
4531 the "color", "background-color", "selection-color",
4532 "selection-background-color" and "alternate-background-color".
4533
4534 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4535*/
4536const QPalette &QWidget::palette() const
4537{
4538 if (!isEnabled()) {
4539 data->pal.setCurrentColorGroup(QPalette::Disabled);
4540 } else if ((!isVisible() || isActiveWindow())
4541#if defined(Q_OS_WIN)
4542 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4543#endif
4544 ) {
4545 data->pal.setCurrentColorGroup(QPalette::Active);
4546 } else {
4547 data->pal.setCurrentColorGroup(QPalette::Inactive);
4548 }
4549 return data->pal;
4550}
4551
4552void QWidget::setPalette(const QPalette &palette)
4553{
4554 Q_D(QWidget);
4555 setAttribute(Qt::WA_SetPalette, on: palette.resolveMask() != 0);
4556
4557 // Determine which palette is inherited from this widget's ancestors and
4558 // QApplication::palette, resolve this against \a palette (attributes from
4559 // the inherited palette are copied over this widget's palette). Then
4560 // propagate this palette to this widget's children.
4561 QPalette naturalPalette = d->naturalWidgetPalette(inheritedMask: d->inheritedPaletteResolveMask);
4562 QPalette resolvedPalette = palette.resolve(other: naturalPalette);
4563 d->setPalette_helper(resolvedPalette);
4564}
4565
4566/*!
4567 \internal
4568
4569 Returns the palette that the widget \a w inherits from its ancestors and
4570 QApplication::palette. \a inheritedMask is the combination of the widget's
4571 ancestors palette request masks (i.e., which attributes from the parent
4572 widget's palette are implicitly imposed on this widget by the user). Note
4573 that this font does not take into account the palette set on \a w itself.
4574*/
4575QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4576{
4577 Q_Q(const QWidget);
4578
4579 const bool useStyleSheetPropagationInWidgetStyles =
4580 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4581
4582 QPalette naturalPalette = QApplication::palette(q);
4583 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4584 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4585#if QT_CONFIG(graphicsview)
4586 || (extra && extra->proxyWidget)
4587#endif // QT_CONFIG(graphicsview)
4588 )) {
4589 if (QWidget *p = q->parentWidget()) {
4590 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4591 if (!naturalPalette.isCopyOf(p: QGuiApplication::palette())) {
4592 QPalette inheritedPalette = p->palette();
4593 inheritedPalette.setResolveMask(inheritedMask);
4594 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4595 } else {
4596 naturalPalette = p->palette();
4597 }
4598 }
4599 }
4600#if QT_CONFIG(graphicsview)
4601 else if (extra && extra->proxyWidget) {
4602 QPalette inheritedPalette = extra->proxyWidget->palette();
4603 inheritedPalette.setResolveMask(inheritedMask);
4604 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4605 }
4606#endif // QT_CONFIG(graphicsview)
4607 }
4608 naturalPalette.setResolveMask(0);
4609 return naturalPalette;
4610}
4611/*!
4612 \internal
4613
4614 Determine which palette is inherited from this widget's ancestors and
4615 QApplication::palette, resolve this against this widget's palette
4616 (attributes from the inherited palette are copied over this widget's
4617 palette). Then propagate this palette to this widget's children.
4618*/
4619void QWidgetPrivate::resolvePalette()
4620{
4621 QPalette naturalPalette = naturalWidgetPalette(inheritedMask: inheritedPaletteResolveMask);
4622 QPalette resolvedPalette = data.pal.resolve(other: naturalPalette);
4623 setPalette_helper(resolvedPalette);
4624}
4625
4626void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4627{
4628 Q_Q(QWidget);
4629 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4630 return;
4631 data.pal = palette;
4632 updateSystemBackground();
4633 propagatePaletteChange();
4634 updateIsOpaque();
4635 q->update();
4636 updateIsOpaque();
4637}
4638
4639void QWidgetPrivate::updateSystemBackground()
4640{
4641}
4642
4643/*!
4644 \property QWidget::font
4645 \brief the font currently set for the widget
4646
4647 This property describes the widget's requested font. The font is used by
4648 the widget's style when rendering standard components, and is available as
4649 a means to ensure that custom widgets can maintain consistency with the
4650 native platform's look and feel. It's common that different platforms, or
4651 different styles, define different fonts for an application.
4652
4653 When you assign a new font to a widget, the properties from this font are
4654 combined with the widget's default font to form the widget's final
4655 font. You can call fontInfo() to get a copy of the widget's final
4656 font. The final font is also used to initialize QPainter's font.
4657
4658 The default depends on the system environment. QApplication maintains a
4659 system/theme font which serves as a default for all widgets. There may
4660 also be special font defaults for certain types of widgets. You can also
4661 define default fonts for widgets yourself by passing a custom font and the
4662 name of a widget to QApplication::setFont(). Finally, the font is matched
4663 against Qt's font database to find the best match.
4664
4665 QWidget propagates explicit font properties from parent to child. If you
4666 change a specific property on a font and assign that font to a widget,
4667 that property will propagate to all the widget's children, overriding any
4668 system defaults for that property. Note that fonts by default don't
4669 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4670 attribute is enabled.
4671
4672 QWidget's font propagation is similar to its palette propagation.
4673
4674 The current style, which is used to render the content of all standard Qt
4675 widgets, is free to choose to use the widget font, or in some cases, to
4676 ignore it (partially, or completely). In particular, certain styles like
4677 GTK style, Mac style, and Windows Vista style, apply special
4678 modifications to the widget font to match the platform's native look and
4679 feel. Because of this, assigning properties to a widget's font is not
4680 guaranteed to change the appearance of the widget. Instead, you may choose
4681 to apply a \l styleSheet.
4682
4683 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4684 style sheets will take precedence if the settings conflict.
4685
4686 \sa fontInfo(), fontMetrics()
4687*/
4688
4689void QWidget::setFont(const QFont &font)
4690{
4691 Q_D(QWidget);
4692
4693#if QT_CONFIG(style_stylesheet)
4694 const QStyleSheetStyle* style;
4695 if (d->extra && (style = qt_styleSheet(style: d->extra->style)))
4696 style->saveWidgetFont(w: this, font);
4697#endif
4698
4699 setAttribute(Qt::WA_SetFont, on: font.resolveMask() != 0);
4700
4701 // Determine which font is inherited from this widget's ancestors and
4702 // QApplication::font, resolve this against \a font (attributes from the
4703 // inherited font are copied over). Then propagate this font to this
4704 // widget's children.
4705 QFont naturalFont = d->naturalWidgetFont(inheritedMask: d->inheritedFontResolveMask);
4706 QFont resolvedFont = font.resolve(naturalFont);
4707 d->setFont_helper(resolvedFont);
4708}
4709
4710/*
4711 \internal
4712
4713 Returns the font that the widget \a w inherits from its ancestors and
4714 QApplication::font. \a inheritedMask is the combination of the widget's
4715 ancestors font request masks (i.e., which attributes from the parent
4716 widget's font are implicitly imposed on this widget by the user). Note
4717 that this font does not take into account the font set on \a w itself.
4718
4719 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4720 is applied, fonts are not propagated anymore
4721*/
4722QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4723{
4724 Q_Q(const QWidget);
4725
4726 const bool useStyleSheetPropagationInWidgetStyles =
4727 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4728
4729 QFont naturalFont = QApplication::font(q);
4730 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4731 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4732#if QT_CONFIG(graphicsview)
4733 || (extra && extra->proxyWidget)
4734#endif // QT_CONFIG(graphicsview)
4735 )) {
4736 if (QWidget *p = q->parentWidget()) {
4737 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4738 if (!naturalFont.isCopyOf(QApplication::font())) {
4739 if (inheritedMask != 0) {
4740 QFont inheritedFont = p->font();
4741 inheritedFont.setResolveMask(inheritedMask);
4742 naturalFont = inheritedFont.resolve(naturalFont);
4743 } // else nothing to do (naturalFont = naturalFont)
4744 } else {
4745 naturalFont = p->font();
4746 }
4747 }
4748 }
4749#if QT_CONFIG(graphicsview)
4750 else if (extra && extra->proxyWidget) {
4751 if (inheritedMask != 0) {
4752 QFont inheritedFont = extra->proxyWidget->font();
4753 inheritedFont.setResolveMask(inheritedMask);
4754 naturalFont = inheritedFont.resolve(naturalFont);
4755 } // else nothing to do (naturalFont = naturalFont)
4756 }
4757#endif // QT_CONFIG(graphicsview)
4758 }
4759 naturalFont.setResolveMask(0);
4760 return naturalFont;
4761}
4762
4763/*!
4764 \internal
4765
4766 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4767*/
4768QFont QWidgetPrivate::localFont() const
4769{
4770 QFont localfont = data.fnt;
4771 localfont.setResolveMask(directFontResolveMask);
4772 return localfont;
4773}
4774
4775/*!
4776 \internal
4777
4778 Determine which font is implicitly imposed on this widget by its ancestors
4779 and QApplication::font, resolve this against its own font (attributes from
4780 the implicit font are copied over). Then propagate this font to this
4781 widget's children.
4782*/
4783void QWidgetPrivate::resolveFont()
4784{
4785 QFont naturalFont = naturalWidgetFont(inheritedMask: inheritedFontResolveMask);
4786 QFont resolvedFont = localFont().resolve(naturalFont);
4787 setFont_helper(resolvedFont);
4788}
4789
4790/*!
4791 \internal
4792
4793 Assign \a font to this widget, and propagate it to all children, except
4794 style sheet widgets (handled differently) and windows that don't enable
4795 window propagation. \a implicitMask is the union of all ancestor widgets'
4796 font request masks, and determines which attributes from this widget's
4797 font should propagate.
4798*/
4799void QWidgetPrivate::updateFont(const QFont &font)
4800{
4801 Q_Q(QWidget);
4802#if QT_CONFIG(style_stylesheet)
4803 const QStyleSheetStyle* cssStyle;
4804 cssStyle = extra ? qt_styleSheet(style: extra->style) : nullptr;
4805 const bool useStyleSheetPropagationInWidgetStyles =
4806 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4807#endif
4808
4809 data.fnt = QFont(font, q);
4810
4811 // Combine new mask with natural mask and propagate to children.
4812#if QT_CONFIG(graphicsview)
4813 if (!q->parentWidget() && extra && extra->proxyWidget) {
4814 QGraphicsProxyWidget *p = extra->proxyWidget;
4815 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4816 } else
4817#endif // QT_CONFIG(graphicsview)
4818 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
4819 inheritedFontResolveMask = 0;
4820 }
4821 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4822 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4823 // isn't all weak information, but save the original mask to be able to let new changes on the
4824 // parent widget font propagate correctly.
4825 directFontResolveMask = data.fnt.resolveMask();
4826 data.fnt.setResolveMask(newMask);
4827
4828 for (int i = 0; i < children.size(); ++i) {
4829 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4830 if (w) {
4831 if (0) {
4832#if QT_CONFIG(style_stylesheet)
4833 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(attribute: Qt::WA_StyleSheet)) {
4834 // Style sheets follow a different font propagation scheme.
4835 if (cssStyle)
4836 cssStyle->updateStyleSheetFont(w);
4837#endif
4838 } else if ((!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
4839 // Propagate font changes.
4840 QWidgetPrivate *wd = w->d_func();
4841 wd->inheritedFontResolveMask = newMask;
4842 wd->resolveFont();
4843 }
4844 }
4845 }
4846
4847#if QT_CONFIG(style_stylesheet)
4848 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4849 cssStyle->updateStyleSheetFont(w: q);
4850 }
4851#endif
4852
4853 QEvent e(QEvent::FontChange);
4854 QCoreApplication::sendEvent(receiver: q, event: &e);
4855}
4856
4857void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4858{
4859 Q_Q(QWidget);
4860
4861 if ( (direction == Qt::RightToLeft) == q->testAttribute(attribute: Qt::WA_RightToLeft))
4862 return;
4863 q->setAttribute(Qt::WA_RightToLeft, on: (direction == Qt::RightToLeft));
4864 if (!children.isEmpty()) {
4865 for (int i = 0; i < children.size(); ++i) {
4866 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4867 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4868 w->d_func()->setLayoutDirection_helper(direction);
4869 }
4870 }
4871 QEvent e(QEvent::LayoutDirectionChange);
4872 QCoreApplication::sendEvent(receiver: q, event: &e);
4873}
4874
4875void QWidgetPrivate::resolveLayoutDirection()
4876{
4877 Q_Q(const QWidget);
4878 if (!q->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4879 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4880}
4881
4882/*!
4883 \property QWidget::layoutDirection
4884
4885 \brief the layout direction for this widget.
4886
4887 \note This method no longer affects text layout direction since Qt 4.7.
4888
4889 By default, this property is set to Qt::LeftToRight.
4890
4891 When the layout direction is set on a widget, it will propagate to
4892 the widget's children, but not to a child that is a window and not
4893 to a child for which setLayoutDirection() has been explicitly
4894 called. Also, child widgets added \e after setLayoutDirection()
4895 has been called for the parent do not inherit the parent's layout
4896 direction.
4897
4898
4899 \sa QApplication::layoutDirection
4900*/
4901void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4902{
4903 Q_D(QWidget);
4904
4905 if (direction == Qt::LayoutDirectionAuto) {
4906 unsetLayoutDirection();
4907 return;
4908 }
4909
4910 setAttribute(Qt::WA_SetLayoutDirection);
4911 d->setLayoutDirection_helper(direction);
4912}
4913
4914Qt::LayoutDirection QWidget::layoutDirection() const
4915{
4916 return testAttribute(attribute: Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4917}
4918
4919void QWidget::unsetLayoutDirection()
4920{
4921 Q_D(QWidget);
4922 setAttribute(Qt::WA_SetLayoutDirection, on: false);
4923 d->resolveLayoutDirection();
4924}
4925
4926/*!
4927 \fn QFontMetrics QWidget::fontMetrics() const
4928
4929 Returns the font metrics for the widget's current font.
4930 Equivalent to \c QFontMetrics(widget->font()).
4931
4932 \sa font(), fontInfo(), setFont()
4933*/
4934
4935/*!
4936 \fn QFontInfo QWidget::fontInfo() const
4937
4938 Returns the font info for the widget's current font.
4939 Equivalent to \c QFontInfo(widget->font()).
4940
4941 \sa font(), fontMetrics(), setFont()
4942*/
4943
4944
4945/*!
4946 \property QWidget::cursor
4947 \brief the cursor shape for this widget
4948
4949 The mouse cursor will assume this shape when it's over this
4950 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4951
4952 An editor widget might use an I-beam cursor:
4953 \snippet code/src_gui_kernel_qwidget.cpp 6
4954
4955 If no cursor has been set, or after a call to unsetCursor(), the
4956 parent's cursor is used.
4957
4958 By default, this property contains a cursor with the Qt::ArrowCursor
4959 shape.
4960
4961 Some underlying window implementations will reset the cursor if it
4962 leaves a widget even if the mouse is grabbed. If you want to have
4963 a cursor set for all widgets, even when outside the window, consider
4964 QGuiApplication::setOverrideCursor().
4965
4966 \sa QGuiApplication::setOverrideCursor()
4967*/
4968
4969#ifndef QT_NO_CURSOR
4970QCursor QWidget::cursor() const
4971{
4972 Q_D(const QWidget);
4973 if (testAttribute(attribute: Qt::WA_SetCursor))
4974 return (d->extra && d->extra->curs)
4975 ? *d->extra->curs
4976 : QCursor(Qt::ArrowCursor);
4977 if (isWindow() || !parentWidget())
4978 return QCursor(Qt::ArrowCursor);
4979 return parentWidget()->cursor();
4980}
4981
4982void QWidget::setCursor(const QCursor &cursor)
4983{
4984 Q_D(QWidget);
4985 if (cursor.shape() != Qt::ArrowCursor
4986 || (d->extra && d->extra->curs))
4987 {
4988 d->createExtra();
4989 d->extra->curs = std::make_unique<QCursor>(args: cursor);
4990 }
4991 setAttribute(Qt::WA_SetCursor);
4992 d->setCursor_sys(cursor);
4993
4994 QEvent event(QEvent::CursorChange);
4995 QCoreApplication::sendEvent(receiver: this, event: &event);
4996}
4997
4998void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4999{
5000 Q_UNUSED(cursor);
5001 Q_Q(QWidget);
5002 qt_qpa_set_cursor(w: q, force: false);
5003}
5004
5005void QWidget::unsetCursor()
5006{
5007 Q_D(QWidget);
5008 if (d->extra)
5009 d->extra->curs.reset();
5010 if (!isWindow())
5011 setAttribute(Qt::WA_SetCursor, on: false);
5012 d->unsetCursor_sys();
5013
5014 QEvent event(QEvent::CursorChange);
5015 QCoreApplication::sendEvent(receiver: this, event: &event);
5016}
5017
5018void QWidgetPrivate::unsetCursor_sys()
5019{
5020 Q_Q(QWidget);
5021 qt_qpa_set_cursor(w: q, force: false);
5022}
5023
5024static inline void applyCursor(QWidget *w, const QCursor &c)
5025{
5026 if (QWindow *window = w->windowHandle())
5027 window->setCursor(c);
5028}
5029
5030static inline void unsetCursor(QWidget *w)
5031{
5032 if (QWindow *window = w->windowHandle())
5033 window->unsetCursor();
5034}
5035
5036void qt_qpa_set_cursor(QWidget *w, bool force)
5037{
5038 if (!w->testAttribute(attribute: Qt::WA_WState_Created))
5039 return;
5040
5041 static QPointer<QWidget> lastUnderMouse = nullptr;
5042 if (force) {
5043 lastUnderMouse = w;
5044 } else if (lastUnderMouse) {
5045 const WId lastWinId = lastUnderMouse->effectiveWinId();
5046 const WId winId = w->effectiveWinId();
5047 if (lastWinId && lastWinId == winId)
5048 w = lastUnderMouse;
5049 } else if (!w->internalWinId()) {
5050 return; // The mouse is not under this widget, and it's not native, so don't change it.
5051 }
5052
5053 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5054 && !w->testAttribute(attribute: Qt::WA_SetCursor))
5055 w = w->parentWidget();
5056
5057 QWidget *nativeParent = w;
5058 if (!w->internalWinId())
5059 nativeParent = w->nativeParentWidget();
5060 if (!nativeParent || !nativeParent->internalWinId())
5061 return;
5062
5063 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_SetCursor)) {
5064 if (w->isEnabled())
5065 applyCursor(w: nativeParent, c: w->cursor());
5066 else
5067 // Enforce the windows behavior of clearing the cursor on
5068 // disabled widgets.
5069 unsetCursor(w: nativeParent);
5070 } else {
5071 unsetCursor(w: nativeParent);
5072 }
5073}
5074#endif
5075
5076/*!
5077 \enum QWidget::RenderFlag
5078
5079 This enum describes how to render the widget when calling QWidget::render().
5080
5081 \value DrawWindowBackground If you enable this option, the widget's background
5082 is rendered into the target even if autoFillBackground is not set. By default,
5083 this option is enabled.
5084
5085 \value DrawChildren If you enable this option, the widget's children
5086 are rendered recursively into the target. By default, this option is enabled.
5087
5088 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5089 is ignored when rendering into the target. By default, this option is disabled.
5090
5091 \since 4.3
5092*/
5093
5094/*!
5095 \since 4.3
5096
5097 Renders the \a sourceRegion of this widget into the \a target
5098 using \a renderFlags to determine how to render. Rendering
5099 starts at \a targetOffset in the \a target. For example:
5100
5101 \snippet code/src_gui_kernel_qwidget.cpp 7
5102
5103 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5104 the region, i.e. the entire widget.
5105
5106 Ensure that you call QPainter::end() for the \a target device's
5107 active painter (if any) before rendering. For example:
5108
5109 \snippet code/src_gui_kernel_qwidget.cpp 8
5110
5111 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5112 instead.
5113*/
5114void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5115 const QRegion &sourceRegion, RenderFlags renderFlags)
5116{
5117 QPainter p(target);
5118 render(painter: &p, targetOffset, sourceRegion, renderFlags);
5119}
5120
5121/*!
5122 \overload
5123
5124 Renders the widget into the \a painter's QPainter::device().
5125
5126 Transformations and settings applied to the \a painter will be used
5127 when rendering.
5128
5129 \note The \a painter must be active. On \macos the widget will be
5130 rendered into a QPixmap and then drawn by the \a painter.
5131
5132 \sa QPainter::device()
5133*/
5134void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5135 const QRegion &sourceRegion, RenderFlags renderFlags)
5136{
5137 if (Q_UNLIKELY(!painter)) {
5138 qWarning(msg: "QWidget::render: Null pointer to painter");
5139 return;
5140 }
5141
5142 if (Q_UNLIKELY(!painter->isActive())) {
5143 qWarning(msg: "QWidget::render: Cannot render with an inactive painter");
5144 return;
5145 }
5146
5147 const qreal opacity = painter->opacity();
5148 if (qFuzzyIsNull(d: opacity))
5149 return; // Fully transparent.
5150
5151 Q_D(QWidget);
5152 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5153 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(region: sourceRegion, renderFlags)
5154 : sourceRegion;
5155 if (toBePainted.isEmpty())
5156 return;
5157
5158 if (!d->extra)
5159 d->createExtra();
5160 d->extra->inRenderWithPainter = true;
5161
5162 QPaintEngine *engine = painter->paintEngine();
5163 Q_ASSERT(engine);
5164 QPaintEnginePrivate *enginePriv = engine->d_func();
5165 Q_ASSERT(enginePriv);
5166 QPaintDevice *target = engine->paintDevice();
5167 Q_ASSERT(target);
5168
5169 // Render via a pixmap when dealing with non-opaque painters or printers.
5170 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5171 d->render_helper(painter, targetOffset, sourceRegion: toBePainted, renderFlags);
5172 d->extra->inRenderWithPainter = inRenderWithPainter;
5173 return;
5174 }
5175
5176 // Set new shared painter.
5177 QPainter *oldPainter = d->sharedPainter();
5178 d->setSharedPainter(painter);
5179
5180 // Save current system clip, viewport and transform,
5181 const QTransform oldTransform = enginePriv->systemTransform;
5182 const QRegion oldSystemClip = enginePriv->systemClip;
5183 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5184 const QRegion oldSystemViewport = enginePriv->systemViewport;
5185 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5186
5187 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5188 if (painter->hasClipping()) {
5189 const QRegion painterClip = painter->deviceTransform().map(r: painter->clipRegion());
5190 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5191 } else {
5192 enginePriv->setSystemViewport(oldSystemClip);
5193 }
5194 painter->setLayoutDirection(layoutDirection());
5195
5196 d->render(target, targetOffset, sourceRegion: toBePainted, renderFlags);
5197
5198 // Restore system clip, viewport and transform.
5199 enginePriv->baseSystemClip = oldBaseClip;
5200 enginePriv->setSystemTransformAndViewport(xform: oldTransform, region: oldSystemViewport);
5201 enginePriv->systemStateChanged();
5202 painter->setLayoutDirection(oldLayoutDirection);
5203
5204 // Restore shared painter.
5205 d->setSharedPainter(oldPainter);
5206
5207 d->extra->inRenderWithPainter = inRenderWithPainter;
5208}
5209
5210static void sendResizeEvents(QWidget *target)
5211{
5212 QResizeEvent e(target->size(), QSize());
5213 QCoreApplication::sendEvent(receiver: target, event: &e);
5214
5215 const QObjectList children = target->children();
5216 for (int i = 0; i < children.size(); ++i) {
5217 if (!children.at(i)->isWidgetType())
5218 continue;
5219 QWidget *child = static_cast<QWidget*>(children.at(i));
5220 if (!child->isWindow() && child->testAttribute(attribute: Qt::WA_PendingResizeEvent))
5221 sendResizeEvents(target: child);
5222 }
5223}
5224
5225/*!
5226 \since 5.0
5227
5228 Renders the widget into a pixmap restricted by the
5229 given \a rectangle. If the widget has any children, then
5230 they are also painted in the appropriate positions.
5231
5232 If a rectangle with an invalid size is specified (the default),
5233 the entire widget is painted.
5234
5235 \sa render(), QPixmap
5236*/
5237QPixmap QWidget::grab(const QRect &rectangle)
5238{
5239 Q_D(QWidget);
5240 if (testAttribute(attribute: Qt::WA_PendingResizeEvent) || !testAttribute(attribute: Qt::WA_WState_Created))
5241 sendResizeEvents(target: this);
5242
5243 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5244
5245 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5246 QRect r(rectangle);
5247 if (r.width() < 0 || r.height() < 0) {
5248 // For grabbing widgets that haven't been shown yet,
5249 // we trigger the layouting mechanism to determine the widget's size.
5250 r = d->prepareToRender(region: QRegion(), renderFlags).boundingRect();
5251 r.setTopLeft(rectangle.topLeft());
5252 }
5253
5254 if (!r.intersects(r: rect()))
5255 return QPixmap();
5256
5257 const qreal dpr = devicePixelRatio();
5258 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5259 res.setDevicePixelRatio(dpr);
5260 if (!d->isOpaque)
5261 res.fill(fillColor: Qt::transparent);
5262 d->render(target: &res, targetOffset: QPoint(), sourceRegion: QRegion(r), renderFlags);
5263
5264 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5265 return res;
5266}
5267
5268/*!
5269 \brief The graphicsEffect function returns a pointer to the
5270 widget's graphics effect.
5271
5272 If the widget has no graphics effect, \nullptr is returned.
5273
5274 \since 4.6
5275
5276 \sa setGraphicsEffect()
5277*/
5278#if QT_CONFIG(graphicseffect)
5279QGraphicsEffect *QWidget::graphicsEffect() const
5280{
5281 Q_D(const QWidget);
5282 return d->graphicsEffect;
5283}
5284#endif // QT_CONFIG(graphicseffect)
5285
5286/*!
5287
5288 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5289
5290 Sets \a effect as the widget's effect. If there already is an effect installed
5291 on this widget, QWidget will delete the existing effect before installing
5292 the new \a effect.
5293
5294 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5295 the effect from the widget and install it on this widget.
5296
5297 QWidget takes ownership of \a effect.
5298
5299 \note This function will apply the effect on itself and all its children.
5300
5301 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5302 QOpenGLWidget and QQuickWidget.
5303
5304 \since 4.6
5305
5306 \sa graphicsEffect()
5307*/
5308#if QT_CONFIG(graphicseffect)
5309void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5310{
5311 Q_D(QWidget);
5312 if (d->graphicsEffect == effect)
5313 return;
5314
5315 if (d->graphicsEffect) {
5316 d->invalidateBackingStore(rect());
5317 delete d->graphicsEffect;
5318 d->graphicsEffect = nullptr;
5319 }
5320
5321 if (effect) {
5322 // Set new effect.
5323 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5324 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5325 d->graphicsEffect = effect;
5326 effect->d_func()->setGraphicsEffectSource(source);
5327 update();
5328 }
5329
5330 d->updateIsOpaque();
5331}
5332#endif // QT_CONFIG(graphicseffect)
5333
5334bool QWidgetPrivate::isAboutToShow() const
5335{
5336 if (data.in_show)
5337 return true;
5338
5339 Q_Q(const QWidget);
5340 if (q->isHidden())
5341 return false;
5342
5343 // The widget will be shown if any of its ancestors are about to show.
5344 QWidget *parent = q->parentWidget();
5345 return parent ? parent->d_func()->isAboutToShow() : false;
5346}
5347
5348QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5349{
5350 Q_Q(QWidget);
5351 const bool isVisible = q->isVisible();
5352
5353 // Make sure the widget is laid out correctly.
5354 if (!isVisible && !isAboutToShow()) {
5355 QWidget *topLevel = q->window();
5356 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5357 topLevel->ensurePolished();
5358
5359 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5360 // they're not explicitly hidden.
5361 QWidget *widget = q;
5362 QWidgetList hiddenWidgets;
5363 while (widget) {
5364 if (widget->isHidden()) {
5365 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
5366 hiddenWidgets.append(t: widget);
5367 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5368 widget->d_func()->updateGeometry_helper(forceUpdate: true);
5369 }
5370 widget = widget->parentWidget();
5371 }
5372
5373 // Activate top-level layout.
5374 if (topLevel->d_func()->layout)
5375 topLevel->d_func()->layout->activate();
5376
5377 // Adjust size if necessary.
5378 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5379 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5380 && !topLevel->testAttribute(attribute: Qt::WA_Resized)) {
5381 topLevel->adjustSize();
5382 topLevel->setAttribute(Qt::WA_Resized, on: false);
5383 }
5384
5385 // Activate child layouts.
5386 topLevel->d_func()->activateChildLayoutsRecursively();
5387
5388 // We're not cheating with WA_WState_Hidden anymore.
5389 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5390 QWidget *widget = hiddenWidgets.at(i);
5391 widget->setAttribute(Qt::WA_WState_Hidden);
5392 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5393 widget->parentWidget()->d_func()->layout->invalidate();
5394 }
5395 } else if (isVisible) {
5396 q->window()->d_func()->sendPendingMoveAndResizeEvents(recursive: true, disableUpdates: true);
5397 }
5398
5399 // Calculate the region to be painted.
5400 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5401 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5402 toBePainted &= extra->mask;
5403 return toBePainted;
5404}
5405
5406void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5407 QWidget::RenderFlags renderFlags)
5408{
5409 Q_ASSERT(painter);
5410 Q_ASSERT(!toBePainted.isEmpty());
5411
5412 Q_Q(QWidget);
5413 const QTransform originalTransform = painter->worldTransform();
5414 const bool useDeviceCoordinates = originalTransform.isScaling();
5415 if (!useDeviceCoordinates) {
5416 // Render via a pixmap.
5417 const QRect rect = toBePainted.boundingRect();
5418 const QSize size = rect.size();
5419 if (size.isNull())
5420 return;
5421
5422 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5423 QPixmap pixmap(size * pixmapDevicePixelRatio);
5424 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5425
5426 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5427 pixmap.fill(fillColor: Qt::transparent);
5428 q->render(target: &pixmap, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5429
5430 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5431 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: true);
5432
5433 painter->drawPixmap(p: targetOffset, pm: pixmap);
5434
5435 if (restore)
5436 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: false);
5437
5438 } else {
5439 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5440 QTransform transform = originalTransform;
5441 transform.translate(dx: targetOffset.x(), dy: targetOffset.y());
5442
5443 QPaintDevice *device = painter->device();
5444 Q_ASSERT(device);
5445
5446 // Calculate device rect.
5447 const QRectF rect(toBePainted.boundingRect());
5448 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5449 deviceRect &= QRect(0, 0, device->width(), device->height());
5450
5451 QPixmap pixmap(deviceRect.size());
5452 pixmap.fill(fillColor: Qt::transparent);
5453
5454 // Create a pixmap device coordinate painter.
5455 QPainter pixmapPainter(&pixmap);
5456 pixmapPainter.setRenderHints(hints: painter->renderHints());
5457 transform *= QTransform::fromTranslate(dx: -deviceRect.x(), dy: -deviceRect.y());
5458 pixmapPainter.setTransform(transform);
5459
5460 q->render(painter: &pixmapPainter, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5461 pixmapPainter.end();
5462
5463 // And then draw the pixmap.
5464 painter->setTransform(transform: QTransform());
5465 painter->drawPixmap(p: deviceRect.topLeft(), pm: pixmap);
5466 painter->setTransform(transform: originalTransform);
5467 }
5468}
5469
5470void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5471 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5472{
5473 if (rgn.isEmpty())
5474 return;
5475
5476 Q_Q(QWidget);
5477
5478 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5479 << "into paint device" << pdev << "with" << flags;
5480
5481 const bool asRoot = flags & DrawAsRoot;
5482 bool onScreen = shouldPaintOnScreen();
5483
5484#if QT_CONFIG(graphicseffect)
5485 if (graphicsEffect && graphicsEffect->isEnabled()) {
5486 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5487 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5488 (source->d_func());
5489 if (!sourced->context) {
5490 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5491 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5492 sourced->context = &context;
5493 if (!sharedPainter) {
5494 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: effectRgn.translated(p: offset));
5495 QPainter p(pdev);
5496 p.translate(offset);
5497 context.painter = &p;
5498 graphicsEffect->draw(painter: &p);
5499 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5500 } else {
5501 context.painter = sharedPainter;
5502 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5503 sourced->invalidateCache();
5504 sourced->lastEffectTransform = sharedPainter->worldTransform();
5505 }
5506 sharedPainter->save();
5507 sharedPainter->translate(offset);
5508 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: sharedPainter->device()->devicePixelRatio(), region: effectRgn.translated(p: offset));
5509 graphicsEffect->draw(painter: sharedPainter);
5510 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: 1, region: QRegion());
5511 sharedPainter->restore();
5512 }
5513 sourced->context = nullptr;
5514
5515 if (repaintManager)
5516 repaintManager->markNeedsFlush(widget: q, region: effectRgn, topLevelOffset: offset);
5517
5518 return;
5519 }
5520 }
5521#endif // QT_CONFIG(graphicseffect)
5522 flags = flags & ~UseEffectRegionBounds;
5523
5524 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5525 const bool recursive = flags & DrawRecursive;
5526 const bool alsoInvisible = flags & DrawInvisible;
5527
5528 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5529
5530 QRegion toBePainted(rgn);
5531 if (asRoot && !alsoInvisible)
5532 toBePainted &= clipRect(); //(rgn & visibleRegion());
5533 if (!(flags & DontSubtractOpaqueChildren))
5534 subtractOpaqueChildren(source&: toBePainted, clipRect: q->rect());
5535
5536 if (!toBePainted.isEmpty()) {
5537 if (!onScreen || alsoOnScreen) {
5538 //update the "in paint event" flag
5539 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5540 qWarning(msg: "QWidget::repaint: Recursive repaint detected");
5541 q->setAttribute(Qt::WA_WState_InPaintEvent);
5542
5543 //clip away the new area
5544 QPaintEngine *paintEngine = pdev->paintEngine();
5545 if (paintEngine) {
5546 setRedirected(replacement: pdev, offset: -offset);
5547
5548 if (sharedPainter)
5549 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted);
5550 else
5551 paintEngine->d_func()->systemRect = q->data->crect;
5552
5553 //paint the background
5554 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(attribute: Qt::WA_StyledBackground))
5555 && !q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
5556 beginBackingStorePainting();
5557 QPainter p(q);
5558 p.setRenderHint(hint: QPainter::SmoothPixmapTransform);
5559 paintBackground(painter: &p, rgn: toBePainted, flags: (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5560 endBackingStorePainting();
5561 }
5562
5563 if (!sharedPainter)
5564 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted.translated(p: offset));
5565
5566 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(attribute: Qt::WA_TintedBackground)) {
5567 beginBackingStorePainting();
5568 QPainter p(q);
5569 QColor tint = q->palette().window().color();
5570 tint.setAlphaF(.6f);
5571 p.fillRect(toBePainted.boundingRect(), color: tint);
5572 endBackingStorePainting();
5573 }
5574 }
5575
5576#if 0
5577 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5578 qDebug() << "clipping to" << toBePainted << "location == " << offset
5579 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5580#endif
5581
5582 bool skipPaintEvent = false;
5583 if (renderToTexture) {
5584 // This widget renders into a texture which is composed later. We just need to
5585 // punch a hole in the backingstore, so the texture will be visible.
5586 beginBackingStorePainting();
5587 if (!q->testAttribute(attribute: Qt::WA_AlwaysStackOnTop) && repaintManager) {
5588 QPainter p(q);
5589 p.setCompositionMode(QPainter::CompositionMode_Source);
5590 p.fillRect(r: q->rect(), c: Qt::transparent);
5591 } else if (!repaintManager) {
5592 // We are not drawing to a backingstore: fall back to QImage
5593 QImage img = grabFramebuffer();
5594 // grabFramebuffer() always sets the format to RGB32
5595 // regardless of whether it is transparent or not.
5596 if (img.format() == QImage::Format_RGB32)
5597 img.reinterpretAsFormat(f: QImage::Format_ARGB32_Premultiplied);
5598 QPainter p(q);
5599 p.drawImage(r: q->rect(), image: img);
5600 skipPaintEvent = true;
5601 }
5602 endBackingStorePainting();
5603 if (renderToTextureReallyDirty)
5604 renderToTextureReallyDirty = 0;
5605 else
5606 skipPaintEvent = true;
5607 }
5608
5609 if (!skipPaintEvent) {
5610 //actually send the paint event
5611 sendPaintEvent(toBePainted);
5612 }
5613
5614 if (repaintManager)
5615 repaintManager->markNeedsFlush(widget: q, region: toBePainted, topLevelOffset: offset);
5616
5617 //restore
5618 if (paintEngine) {
5619 restoreRedirected();
5620 if (!sharedPainter)
5621 paintEngine->d_func()->systemRect = QRect();
5622 else
5623 paintEngine->d_func()->currentClipDevice = nullptr;
5624
5625 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5626 }
5627 q->setAttribute(Qt::WA_WState_InPaintEvent, on: false);
5628 if (Q_UNLIKELY(q->paintingActive()))
5629 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5630
5631 if (paintEngine && paintEngine->autoDestruct()) {
5632 delete paintEngine;
5633 }
5634 } else if (q->isWindow()) {
5635 QPaintEngine *engine = pdev->paintEngine();
5636 if (engine) {
5637 QPainter p(pdev);
5638 p.setClipRegion(toBePainted);
5639 const QBrush bg = q->palette().brush(cr: QPalette::Window);
5640 if (bg.style() == Qt::TexturePattern)
5641 p.drawTiledPixmap(rect: q->rect(), pm: bg.texture());
5642 else
5643 p.fillRect(q->rect(), bg);
5644
5645 if (engine->autoDestruct())
5646 delete engine;
5647 }
5648 }
5649 }
5650
5651 if (recursive && !children.isEmpty()) {
5652 paintSiblingsRecursive(pdev, children, index: children.size() - 1, rgn, offset, flags: flags & ~DrawAsRoot,
5653 sharedPainter, repaintManager);
5654 }
5655}
5656
5657void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5658{
5659 Q_Q(QWidget);
5660 QPaintEvent e(toBePainted);
5661 QCoreApplication::sendSpontaneousEvent(receiver: q, event: &e);
5662
5663 if (renderToTexture)
5664 resolveSamples();
5665}
5666
5667void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5668 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5669{
5670 if (Q_UNLIKELY(!target)) {
5671 qWarning(msg: "QWidget::render: null pointer to paint device");
5672 return;
5673 }
5674
5675 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5676 QRegion paintRegion = !inRenderWithPainter
5677 ? prepareToRender(region: sourceRegion, renderFlags)
5678 : sourceRegion;
5679 if (paintRegion.isEmpty())
5680 return;
5681
5682 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5683
5684 // Use the target's shared painter if set (typically set when doing
5685 // "other->render(widget);" in the widget's paintEvent.
5686 if (target->devType() == QInternal::Widget) {
5687 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5688 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5689 QPainter *targetPainter = targetPrivate->sharedPainter();
5690 if (targetPainter && targetPainter->isActive())
5691 setSharedPainter(targetPainter);
5692 }
5693 }
5694
5695 // Use the target's redirected device if set and adjust offset and paint
5696 // region accordingly. This is typically the case when people call render
5697 // from the paintEvent.
5698 QPoint offset = targetOffset;
5699 offset -= paintRegion.boundingRect().topLeft();
5700 QPoint redirectionOffset;
5701 QPaintDevice *redirected = nullptr;
5702
5703 if (target->devType() == QInternal::Widget)
5704 redirected = static_cast<QWidget *>(target)->d_func()->redirected(offset: &redirectionOffset);
5705
5706 if (redirected) {
5707 target = redirected;
5708 offset -= redirectionOffset;
5709 }
5710
5711 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5712 if (QPaintEngine *targetEngine = target->paintEngine()) {
5713 const QRegion targetSystemClip = targetEngine->systemClip();
5714 if (!targetSystemClip.isEmpty())
5715 paintRegion &= targetSystemClip.translated(p: -offset);
5716 }
5717 }
5718
5719 // Set backingstore flags.
5720 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5721 if (renderFlags & QWidget::DrawWindowBackground)
5722 flags |= DrawAsRoot;
5723
5724 if (renderFlags & QWidget::DrawChildren)
5725 flags |= DrawRecursive;
5726 else
5727 flags |= DontSubtractOpaqueChildren;
5728
5729 flags |= DontSetCompositionMode;
5730
5731 // Render via backingstore.
5732 drawWidget(pdev: target, rgn: paintRegion, offset, flags, sharedPainter: sharedPainter());
5733
5734 // Restore shared painter.
5735 if (oldSharedPainter)
5736 setSharedPainter(oldSharedPainter);
5737}
5738
5739void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5740 const QPoint &offset, DrawWidgetFlags flags
5741 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5742{
5743 QWidget *w = nullptr;
5744 QRect boundingRect;
5745 bool dirtyBoundingRect = true;
5746 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5747 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5748
5749 do {
5750 QWidget *x = qobject_cast<QWidget*>(o: siblings.at(i: index));
5751 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5752 && !(excludeNativeChildren && x->internalWinId())) {
5753 if (dirtyBoundingRect) {
5754 boundingRect = rgn.boundingRect();
5755 dirtyBoundingRect = false;
5756 }
5757
5758 if (qRectIntersects(r1: boundingRect, r2: x->d_func()->effectiveRectFor(rect: x->data->crect))) {
5759 w = x;
5760 break;
5761 }
5762 }
5763 --index;
5764 } while (index >= 0);
5765
5766 if (!w)
5767 return;
5768
5769 QWidgetPrivate *wd = w->d_func();
5770 const QPoint widgetPos(w->data->crect.topLeft());
5771 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5772 if (index > 0) {
5773 QRegion wr(rgn);
5774 if (wd->isOpaque)
5775 wr -= hasMask ? wd->extra->mask.translated(p: widgetPos) : w->data->crect;
5776 paintSiblingsRecursive(pdev, siblings, index: --index, rgn: wr, offset, flags,
5777 sharedPainter, repaintManager);
5778 }
5779
5780 if (w->updatesEnabled()
5781#if QT_CONFIG(graphicsview)
5782 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5783#endif // QT_CONFIG(graphicsview)
5784 ) {
5785 QRegion wRegion(rgn);
5786 wRegion &= wd->effectiveRectFor(rect: w->data->crect);
5787 wRegion.translate(p: -widgetPos);
5788 if (hasMask)
5789 wRegion &= wd->extra->mask;
5790 wd->drawWidget(pdev, rgn: wRegion, offset: offset + widgetPos, flags, sharedPainter, repaintManager);
5791 }
5792}
5793
5794#if QT_CONFIG(graphicseffect)
5795QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5796{
5797 if (system != Qt::DeviceCoordinates)
5798 return m_widget->rect();
5799
5800 if (Q_UNLIKELY(!context)) {
5801 // Device coordinates without context not yet supported.
5802 qWarning(msg: "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5803 return QRectF();
5804 }
5805
5806 return context->painter->worldTransform().mapRect(m_widget->rect());
5807}
5808
5809void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5810{
5811 if (!context || context->painter != painter) {
5812 m_widget->render(painter);
5813 return;
5814 }
5815
5816 // The region saved in the context is neither clipped to the rect
5817 // nor the mask, so we have to clip it here before calling drawWidget.
5818 QRegion toBePainted = context->rgn;
5819 toBePainted &= m_widget->rect();
5820 QWidgetPrivate *wd = qt_widget_private(widget: m_widget);
5821 if (wd->extra && wd->extra->hasMask)
5822 toBePainted &= wd->extra->mask;
5823
5824 wd->drawWidget(pdev: context->pdev, rgn: toBePainted, offset: context->offset, flags: context->flags,
5825 sharedPainter: context->sharedPainter, repaintManager: context->repaintManager);
5826}
5827
5828QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5829 QGraphicsEffect::PixmapPadMode mode) const
5830{
5831 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5832 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5833 // Device coordinates without context not yet supported.
5834 qWarning(msg: "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5835 return QPixmap();
5836 }
5837
5838 QPoint pixmapOffset;
5839 QRectF sourceRect = m_widget->rect();
5840
5841 if (deviceCoordinates) {
5842 const QTransform &painterTransform = context->painter->worldTransform();
5843 sourceRect = painterTransform.mapRect(sourceRect);
5844 pixmapOffset = painterTransform.map(p: pixmapOffset);
5845 }
5846
5847 QRect effectRect;
5848
5849 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5850 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5851 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5852 effectRect = sourceRect.adjusted(xp1: -1, yp1: -1, xp2: 1, yp2: 1).toAlignedRect();
5853 else
5854 effectRect = sourceRect.toAlignedRect();
5855
5856 if (offset)
5857 *offset = effectRect.topLeft();
5858
5859 pixmapOffset -= effectRect.topLeft();
5860
5861 qreal dpr(1.0);
5862 if (const auto *paintDevice = context->painter->device())
5863 dpr = paintDevice->devicePixelRatio();
5864 else
5865 qWarning(msg: "QWidgetEffectSourcePrivate::pixmap: Painter not active");
5866 QPixmap pixmap(effectRect.size() * dpr);
5867 pixmap.setDevicePixelRatio(dpr);
5868
5869 pixmap.fill(fillColor: Qt::transparent);
5870 m_widget->render(target: &pixmap, targetOffset: pixmapOffset, sourceRegion: QRegion(), renderFlags: QWidget::DrawChildren);
5871 return pixmap;
5872}
5873#endif // QT_CONFIG(graphicseffect)
5874
5875#if QT_CONFIG(graphicsview)
5876/*!
5877 \internal
5878
5879 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5880 widget and its ancestors. The search starts at \a origin (inclusive).
5881 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5882 embedded widget was found.
5883*/
5884QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5885{
5886 if (origin) {
5887 const auto &extra = origin->d_func()->extra;
5888 if (extra && extra->proxyWidget)
5889 return extra->proxyWidget;
5890 return nearestGraphicsProxyWidget(origin: origin->parentWidget());
5891 }
5892 return nullptr;
5893}
5894#endif
5895
5896/*!
5897 \property QWidget::locale
5898 \brief the widget's locale
5899 \since 4.3
5900
5901 As long as no special locale has been set, this is either
5902 the parent's locale or (if this widget is a top level widget),
5903 the default locale.
5904
5905 If the widget displays dates or numbers, these should be formatted
5906 using the widget's locale.
5907
5908 \sa QLocale, QLocale::setDefault()
5909*/
5910
5911void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5912{
5913 Q_Q(QWidget);
5914 if (locale == loc && !forceUpdate)
5915 return;
5916
5917 locale = loc;
5918
5919 if (!children.isEmpty()) {
5920 for (int i = 0; i < children.size(); ++i) {
5921 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
5922 if (!w)
5923 continue;
5924 if (w->testAttribute(attribute: Qt::WA_SetLocale))
5925 continue;
5926 if (w->isWindow() && !w->testAttribute(attribute: Qt::WA_WindowPropagation))
5927 continue;
5928 w->d_func()->setLocale_helper(loc, forceUpdate);
5929 }
5930 }
5931 QEvent e(QEvent::LocaleChange);
5932 QCoreApplication::sendEvent(receiver: q, event: &e);
5933}
5934
5935void QWidget::setLocale(const QLocale &locale)
5936{
5937 Q_D(QWidget);
5938
5939 setAttribute(Qt::WA_SetLocale);
5940 d->setLocale_helper(loc: locale);
5941}
5942
5943QLocale QWidget::locale() const
5944{
5945 Q_D(const QWidget);
5946
5947 return d->locale;
5948}
5949
5950void QWidgetPrivate::resolveLocale()
5951{
5952 Q_Q(const QWidget);
5953
5954 if (!q->testAttribute(attribute: Qt::WA_SetLocale)) {
5955 QWidget *parent = q->parentWidget();
5956 setLocale_helper(loc: !parent || (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation))
5957 ? QLocale() : parent->locale());
5958 }
5959}
5960
5961void QWidget::unsetLocale()
5962{
5963 Q_D(QWidget);
5964 setAttribute(Qt::WA_SetLocale, on: false);
5965 d->resolveLocale();
5966}
5967
5968/*!
5969 \property QWidget::windowTitle
5970 \brief the window title (caption)
5971
5972 This property only makes sense for top-level widgets, such as
5973 windows and dialogs. If no caption has been set, the title is based of the
5974 \l windowFilePath. If neither of these is set, then the title is
5975 an empty string.
5976
5977 If you use the \l windowModified mechanism, the window title must
5978 contain a "[*]" placeholder, which indicates where the '*' should
5979 appear. Normally, it should appear right after the file name
5980 (e.g., "document1.txt[*] - Text Editor"). If the \l
5981 windowModified property is \c false (the default), the placeholder
5982 is simply removed.
5983
5984 On some desktop platforms (including Windows and Unix), the application name
5985 (from QGuiApplication::applicationDisplayName) is added at the end of the
5986 window title, if set. This is done by the QPA plugin, so it is shown to the
5987 user, but isn't part of the windowTitle string.
5988
5989 \sa windowIcon, windowModified, windowFilePath
5990*/
5991QString QWidget::windowTitle() const
5992{
5993 Q_D(const QWidget);
5994 if (d->extra && d->extra->topextra) {
5995 if (!d->extra->topextra->caption.isEmpty())
5996 return d->extra->topextra->caption;
5997 if (!d->extra->topextra->filePath.isEmpty())
5998 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
5999 }
6000 return QString();
6001}
6002
6003/*!
6004 Returns a modified window title with the [*] place holder
6005 replaced according to the rules described in QWidget::setWindowTitle
6006
6007 This function assumes that "[*]" can be quoted by another
6008 "[*]", so it will replace two place holders by one and
6009 a single last one by either "*" or nothing depending on
6010 the modified flag.
6011
6012 \internal
6013*/
6014QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6015{
6016 Q_ASSERT(widget);
6017
6018 QString cap = title;
6019 if (cap.isEmpty())
6020 return cap;
6021
6022 const auto placeHolder = "[*]"_L1;
6023 int index = cap.indexOf(s: placeHolder);
6024
6025 // here the magic begins
6026 while (index != -1) {
6027 index += placeHolder.size();
6028 int count = 1;
6029 while (cap.indexOf(s: placeHolder, from: index) == index) {
6030 ++count;
6031 index += placeHolder.size();
6032 }
6033
6034 if (count%2) { // odd number of [*] -> replace last one
6035 int lastIndex = cap.lastIndexOf(s: placeHolder, from: index - 1);
6036 if (widget->isWindowModified()
6037 && widget->style()->styleHint(stylehint: QStyle::SH_TitleBar_ModifyNotification, opt: nullptr, widget))
6038 cap.replace(i: lastIndex, len: 3, after: QWidget::tr(s: "*"));
6039 else
6040 cap.remove(i: lastIndex, len: 3);
6041 }
6042
6043 index = cap.indexOf(s: placeHolder, from: index);
6044 }
6045
6046 cap.replace(before: "[*][*]"_L1, after: placeHolder);
6047
6048 return cap;
6049}
6050
6051void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6052{
6053 Q_Q(QWidget);
6054 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6055 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6056}
6057
6058void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6059{
6060 Q_Q(QWidget);
6061 if (!q->isWindow())
6062 return;
6063
6064 if (QWindow *window = q->windowHandle())
6065 {
6066#if QT_CONFIG(accessibility)
6067 QString oldAccessibleName;
6068 const QAccessibleInterface *accessible = QAccessible::isActive()
6069 ? QAccessible::queryAccessibleInterface(q)
6070 : nullptr;
6071 if (accessible)
6072 oldAccessibleName = accessible->text(t: QAccessible::Name);
6073#endif
6074
6075 window->setTitle(caption);
6076
6077#if QT_CONFIG(accessibility)
6078 if (accessible && accessible->text(t: QAccessible::Name) != oldAccessibleName) {
6079 QAccessibleEvent event(q, QAccessible::NameChanged);
6080 QAccessible::updateAccessibility(event: &event);
6081 }
6082#endif
6083 }
6084}
6085
6086void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6087{
6088 Q_Q(QWidget);
6089 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6090 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6091}
6092
6093void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6094{
6095#if QT_CONFIG(xcb)
6096 Q_Q(QWidget);
6097 // ### The QWidget property is deprecated, but the XCB window function is not.
6098 // It should remain available for the rare application that needs it.
6099 if (QWindow *window = q->windowHandle()) {
6100 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6101 xcbWindow->setWindowIconText(iconText);
6102 }
6103#else
6104 Q_UNUSED(iconText);
6105#endif
6106}
6107
6108/*!
6109 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6110
6111 This signal is emitted when the window's icon text has changed, with the
6112 new \a iconText as an argument.
6113
6114 \since 5.2
6115 \deprecated
6116
6117 This signal is deprecated.
6118*/
6119
6120void QWidget::setWindowIconText(const QString &iconText)
6121{
6122 if (QWidget::windowIconText() == iconText)
6123 return;
6124
6125 Q_D(QWidget);
6126 d->topData()->iconText = iconText;
6127 d->setWindowIconText_helper(iconText);
6128
6129 QEvent e(QEvent::IconTextChange);
6130 QCoreApplication::sendEvent(receiver: this, event: &e);
6131
6132 emit windowIconTextChanged(iconText);
6133}
6134
6135/*!
6136 \fn void QWidget::windowTitleChanged(const QString &title)
6137
6138 This signal is emitted when the window's title has changed, with the
6139 new \a title as an argument.
6140
6141 \since 5.2
6142*/
6143
6144void QWidget::setWindowTitle(const QString &title)
6145{
6146 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6147 return;
6148
6149 Q_D(QWidget);
6150 d->topData()->caption = title;
6151 d->setWindowTitle_helper(title);
6152
6153 QEvent e(QEvent::WindowTitleChange);
6154 QCoreApplication::sendEvent(receiver: this, event: &e);
6155
6156 emit windowTitleChanged(title);
6157}
6158
6159
6160/*!
6161 \property QWidget::windowIcon
6162 \brief the widget's icon
6163
6164 This property only makes sense for windows. If no icon
6165 has been set, windowIcon() returns the application icon
6166 (QApplication::windowIcon()).
6167
6168 \note On \macos, window icons represent the active document,
6169 and will not be displayed unless a file path has also been
6170 set using setWindowFilePath.
6171
6172 \sa windowTitle, setWindowFilePath
6173*/
6174QIcon QWidget::windowIcon() const
6175{
6176 const QWidget *w = this;
6177 while (w) {
6178 const QWidgetPrivate *d = w->d_func();
6179 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6180 return *d->extra->topextra->icon;
6181 w = w->parentWidget();
6182 }
6183 return QApplication::windowIcon();
6184}
6185
6186void QWidgetPrivate::setWindowIcon_helper()
6187{
6188 Q_Q(QWidget);
6189 QEvent e(QEvent::WindowIconChange);
6190
6191 // Do not send the event if the widget is a top level.
6192 // In that case, setWindowIcon_sys does it, and event propagation from
6193 // QWidgetWindow to the top level QWidget ensures that the event reaches
6194 // the top level anyhow
6195 if (!q->windowHandle())
6196 QCoreApplication::sendEvent(receiver: q, event: &e);
6197 for (int i = 0; i < children.size(); ++i) {
6198 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
6199 if (w && !w->isWindow())
6200 QCoreApplication::sendEvent(receiver: w, event: &e);
6201 }
6202}
6203
6204/*!
6205 \fn void QWidget::windowIconChanged(const QIcon &icon)
6206
6207 This signal is emitted when the window's icon has changed, with the
6208 new \a icon as an argument.
6209
6210 \since 5.2
6211*/
6212
6213void QWidget::setWindowIcon(const QIcon &icon)
6214{
6215 Q_D(QWidget);
6216
6217 setAttribute(Qt::WA_SetWindowIcon, on: !icon.isNull());
6218 d->createTLExtra();
6219
6220 if (!d->extra->topextra->icon)
6221 d->extra->topextra->icon = std::make_unique<QIcon>(args: icon);
6222 else
6223 *d->extra->topextra->icon = icon;
6224
6225 d->setWindowIcon_sys();
6226 d->setWindowIcon_helper();
6227
6228 emit windowIconChanged(icon);
6229}
6230
6231void QWidgetPrivate::setWindowIcon_sys()
6232{
6233 Q_Q(QWidget);
6234 if (QWindow *window = q->windowHandle())
6235 window->setIcon(q->windowIcon());
6236}
6237
6238/*!
6239 \property QWidget::windowIconText
6240 \brief the text to be displayed on the icon of a minimized window
6241
6242 This property only makes sense for windows. If no icon
6243 text has been set, this accessor returns an empty string.
6244 It is only implemented on the X11 platform, and only certain
6245 window managers use this window property.
6246
6247 \deprecated
6248 This property is deprecated.
6249
6250 \sa windowIcon, windowTitle
6251*/
6252
6253QString QWidget::windowIconText() const
6254{
6255 Q_D(const QWidget);
6256 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6257}
6258
6259/*!
6260 \property QWidget::windowFilePath
6261 \since 4.4
6262 \brief the file path associated with a widget
6263
6264 This property only makes sense for windows. It associates a file path with
6265 a window. If you set the file path, but have not set the window title, Qt
6266 sets the window title to the file name of the specified path, obtained using
6267 QFileInfo::fileName().
6268
6269 If the window title is set at any point, then the window title takes precedence and
6270 will be shown instead of the file path string.
6271
6272 Additionally, on \macos, this has an added benefit that it sets the
6273 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6274 for the window, assuming that the file path exists.
6275
6276 If no file path is set, this property contains an empty string.
6277
6278 By default, this property contains an empty string.
6279
6280 \sa windowTitle, windowIcon
6281*/
6282
6283QString QWidget::windowFilePath() const
6284{
6285 Q_D(const QWidget);
6286 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6287}
6288
6289void QWidget::setWindowFilePath(const QString &filePath)
6290{
6291 if (filePath == windowFilePath())
6292 return;
6293
6294 Q_D(QWidget);
6295
6296 d->createTLExtra();
6297 d->extra->topextra->filePath = filePath;
6298 d->setWindowFilePath_helper(filePath);
6299}
6300
6301void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6302{
6303 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6304#ifdef Q_OS_MAC
6305 setWindowTitle_helper(QFileInfo(filePath).fileName());
6306#else
6307 Q_Q(QWidget);
6308 Q_UNUSED(filePath);
6309 setWindowTitle_helper(q->windowTitle());
6310#endif
6311 }
6312#ifdef Q_OS_MAC
6313 setWindowFilePath_sys(filePath);
6314#endif
6315}
6316
6317void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6318{
6319 Q_Q(QWidget);
6320 if (!q->isWindow())
6321 return;
6322
6323 if (QWindow *window = q->windowHandle())
6324 window->setFilePath(filePath);
6325}
6326
6327/*!
6328 Returns the window's role, or an empty string.
6329
6330 \sa windowIcon, windowTitle
6331*/
6332
6333QString QWidget::windowRole() const
6334{
6335 Q_D(const QWidget);
6336 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6337}
6338
6339/*!
6340 Sets the window's role to \a role. This only makes sense for
6341 windows on X11.
6342*/
6343void QWidget::setWindowRole(const QString &role)
6344{
6345#if QT_CONFIG(xcb)
6346 Q_D(QWidget);
6347 d->createTLExtra();
6348 d->topData()->role = role;
6349 if (windowHandle()) {
6350 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6351 xcbWindow->setWindowRole(role);
6352 }
6353#else
6354 Q_UNUSED(role);
6355#endif
6356}
6357
6358/*!
6359 \property QWidget::mouseTracking
6360 \brief whether mouse tracking is enabled for the widget
6361
6362 If mouse tracking is disabled (the default), the widget only
6363 receives mouse move events when at least one mouse button is
6364 pressed while the mouse is being moved.
6365
6366 If mouse tracking is enabled, the widget receives mouse move
6367 events even if no buttons are pressed.
6368
6369 \sa mouseMoveEvent()
6370*/
6371
6372/*!
6373 \property QWidget::tabletTracking
6374 \brief whether tablet tracking is enabled for the widget
6375 \since 5.9
6376
6377 If tablet tracking is disabled (the default), the widget only
6378 receives tablet move events when the stylus is in contact with
6379 the tablet, or at least one stylus button is pressed,
6380 while the stylus is being moved.
6381
6382 If tablet tracking is enabled, the widget receives tablet move
6383 events even while hovering in proximity. This is useful for
6384 monitoring position as well as the auxiliary properties such
6385 as rotation and tilt, and providing feedback in the UI.
6386
6387 \sa tabletEvent()
6388*/
6389
6390
6391/*!
6392 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6393 function resets this widget to have no focus proxy.
6394
6395 Some widgets can "have focus", but create a child widget, such as
6396 QLineEdit, to actually handle the focus. In this case, the widget
6397 can set the line edit to be its focus proxy.
6398
6399 setFocusProxy() sets the widget which will actually get focus when
6400 "this widget" gets it. If there is a focus proxy, setFocus() and
6401 hasFocus() operate on the focus proxy. If "this widget" is the focus
6402 widget, then setFocusProxy() moves focus to the new focus proxy.
6403
6404 \sa focusProxy()
6405*/
6406
6407void QWidget::setFocusProxy(QWidget * w)
6408{
6409 Q_D(QWidget);
6410 if (!w && !d->extra)
6411 return;
6412
6413 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6414 if (Q_UNLIKELY(fp == this)) {
6415 qWarning(msg: "QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6416 return;
6417 }
6418 }
6419
6420 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6421
6422 d->createExtra();
6423 d->extra->focus_proxy = w;
6424
6425 if (w && isAncestorOf(child: w)) {
6426 // If the focus proxy is a child of this (so this is a compound widget), then
6427 // we need to make sure that this widget is immediately in front of its own children
6428 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6429 // widgets that are positioned between this compound widget, and its proxy in
6430 // the focus chain.
6431 const QWidget *parentOfW = w->parentWidget();
6432 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6433 QWidget *firstChild = nullptr;
6434 const auto childList = children();
6435 for (QObject *child : childList) {
6436 if ((firstChild = qobject_cast<QWidget *>(o: child)))
6437 break;
6438 }
6439 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6440 d->insertIntoFocusChainBefore(position: firstChild);
6441 } else if (w && w->isAncestorOf(child: this)) {
6442 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6443 // remove it from the chain and insert this into the focus chain after its parent
6444
6445 // is this the case already?
6446 QWidget *parentsNext = w->nextInFocusChain();
6447 if (parentsNext == this) {
6448 // nothing to do.
6449 Q_ASSERT(previousInFocusChain() == w);
6450 } else {
6451 d->QWidgetPrivate::insertIntoFocusChainAfter(position: w);
6452 }
6453 }
6454
6455 if (moveFocusToProxy)
6456 setFocus(Qt::OtherFocusReason);
6457}
6458
6459
6460/*!
6461 Returns the focus proxy, or \nullptr if there is no focus proxy.
6462
6463 \sa setFocusProxy()
6464*/
6465
6466QWidget *QWidget::focusProxy() const
6467{
6468 Q_D(const QWidget);
6469 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6470}
6471
6472
6473/*!
6474 \property QWidget::focus
6475 \brief whether this widget (or its focus proxy) has the keyboard
6476 input focus
6477
6478 By default, this property is \c false.
6479
6480 \note Obtaining the value of this property for a widget is effectively equivalent
6481 to checking whether QApplication::focusWidget() refers to the widget.
6482
6483 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6484*/
6485bool QWidget::hasFocus() const
6486{
6487 const QWidget* w = this;
6488 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6489 w = w->d_func()->extra->focus_proxy;
6490#if QT_CONFIG(graphicsview)
6491 if (QWidget *window = w->window()) {
6492 const auto &e = window->d_func()->extra;
6493 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6494 return true;
6495 }
6496#endif // QT_CONFIG(graphicsview)
6497 return (QApplication::focusWidget() == w);
6498}
6499
6500/*!
6501 Gives the keyboard input focus to this widget (or its focus
6502 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6503 be passed into any focus event sent from this function, it is used
6504 to give an explanation of what caused the widget to get focus.
6505 If the window is not active, the widget will be given the focus when
6506 the window becomes active.
6507
6508 First, a focus about to change event is sent to the focus widget (if any) to
6509 tell it that it is about to lose the focus. Then focus is changed, a
6510 focus out event is sent to the previous focus item and a focus in event is sent
6511 to the new item to tell it that it just received the focus.
6512 (Nothing happens if the focus in and focus out widgets are the
6513 same.)
6514
6515 \note On embedded platforms, setFocus() will not cause an input panel
6516 to be opened by the input method. If you want this to happen, you
6517 have to send a QEvent::RequestSoftwareInputPanel event to the
6518 widget yourself.
6519
6520 setFocus() gives focus to a widget regardless of its focus policy,
6521 but does not clear any keyboard grab (see grabKeyboard()).
6522
6523 Be aware that if the widget is hidden, it will not accept focus
6524 until it is shown.
6525
6526 \warning If you call setFocus() in a function which may itself be
6527 called from focusOutEvent() or focusInEvent(), you may get an
6528 infinite recursion.
6529
6530 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6531 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6532 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6533*/
6534
6535void QWidget::setFocus(Qt::FocusReason reason)
6536{
6537 if (!isEnabled())
6538 return;
6539
6540 QWidget *f = d_func()->deepestFocusProxy();
6541 if (!f)
6542 f = this;
6543
6544 if (QApplication::focusWidget() == f)
6545 return;
6546
6547#if QT_CONFIG(graphicsview)
6548 QWidget *previousProxyFocus = nullptr;
6549 if (const auto &topData = window()->d_func()->extra) {
6550 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6551 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6552 if (previousProxyFocus && previousProxyFocus->focusProxy())
6553 previousProxyFocus = previousProxyFocus->focusProxy();
6554 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6555 return;
6556 }
6557 }
6558#endif
6559
6560#if QT_CONFIG(graphicsview)
6561 // Update proxy state
6562 if (const auto &topData = window()->d_func()->extra) {
6563 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6564 f->d_func()->updateFocusChild();
6565 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6566 topData->proxyWidget->setFocus(reason);
6567 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6568 }
6569 }
6570#endif
6571
6572 if (f->isActiveWindow()) {
6573 QWidget *prev = QApplicationPrivate::focus_widget;
6574 if (prev) {
6575 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6576 && prev->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
6577 QGuiApplication::inputMethod()->commit();
6578 }
6579
6580 if (reason != Qt::NoFocusReason) {
6581 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6582 QCoreApplication::sendEvent(receiver: prev, event: &focusAboutToChange);
6583 }
6584 }
6585
6586 f->d_func()->updateFocusChild();
6587
6588 QApplicationPrivate::setFocusWidget(focus: f, reason);
6589#if QT_CONFIG(accessibility)
6590 // menus update the focus manually and this would create bogus events
6591 if (!(f->inherits(classname: "QMenuBar") || f->inherits(classname: "QMenu") || f->inherits(classname: "QMenuItem")))
6592 {
6593 QAccessibleEvent event(f, QAccessible::Focus);
6594 QAccessible::updateAccessibility(event: &event);
6595 }
6596#endif
6597#if QT_CONFIG(graphicsview)
6598 if (const auto &topData = window()->d_func()->extra) {
6599 if (topData->proxyWidget) {
6600 if (previousProxyFocus && previousProxyFocus != f) {
6601 // Send event to self
6602 QFocusEvent event(QEvent::FocusOut, reason);
6603 QPointer<QWidget> that = previousProxyFocus;
6604 QCoreApplication::sendEvent(receiver: previousProxyFocus, event: &event);
6605 if (that)
6606 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6607 }
6608 if (!isHidden()) {
6609#if QT_CONFIG(graphicsview)
6610 // Update proxy state
6611 if (const auto &topData = window()->d_func()->extra)
6612 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6613 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6614#endif
6615 // Send event to self
6616 QFocusEvent event(QEvent::FocusIn, reason);
6617 QPointer<QWidget> that = f;
6618 QCoreApplication::sendEvent(receiver: f, event: &event);
6619 if (that)
6620 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6621 }
6622 }
6623 }
6624#endif
6625 } else {
6626 f->d_func()->updateFocusChild();
6627 }
6628}
6629
6630
6631/*!\internal
6632 * A focus proxy can have its own focus proxy, which can have its own
6633 * proxy, and so on. This helper function returns the widget that sits
6634 * at the bottom of the proxy chain, and therefore the one that should
6635 * normally get focus if this widget receives a focus request.
6636 */
6637QWidget *QWidgetPrivate::deepestFocusProxy() const
6638{
6639 Q_Q(const QWidget);
6640
6641 QWidget *focusProxy = q->focusProxy();
6642 if (!focusProxy)
6643 return nullptr;
6644
6645 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6646 focusProxy = nextFocusProxy;
6647
6648 return focusProxy;
6649}
6650
6651static inline bool isEmbedded(const QWindow *w)
6652{
6653 const auto platformWindow = w->handle();
6654 return platformWindow && platformWindow->isEmbedded();
6655}
6656
6657void QWidgetPrivate::setFocus_sys()
6658{
6659 Q_Q(QWidget);
6660 // Embedded native widget may have taken the focus; get it back to toplevel
6661 // if that is the case (QTBUG-25852), unless widget is a window container.
6662 if (extra && extra->hasWindowContainer)
6663 return;
6664 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6665 // unless the application is embedded (QTBUG-71991).
6666 if (QWindow *nativeWindow = q->testAttribute(attribute: Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6667 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6668 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6669 || QCoreApplication::testAttribute(attribute: Qt::AA_PluginApplication)
6670 || isEmbedded(w: nativeWindow))) {
6671 nativeWindow->requestActivate();
6672 }
6673 }
6674}
6675
6676// updates focus_child on parent widgets to point into this widget
6677void QWidgetPrivate::updateFocusChild()
6678{
6679 Q_Q(QWidget);
6680
6681 QWidget *w = q;
6682 if (q->isHidden()) {
6683 while (w && w->isHidden()) {
6684 w->d_func()->focus_child = q;
6685 w = w->isWindow() ? nullptr : w->parentWidget();
6686 }
6687 } else {
6688 while (w) {
6689 w->d_func()->focus_child = q;
6690 w = w->isWindow() ? nullptr : w->parentWidget();
6691 }
6692 }
6693
6694 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6695 if (extra->window)
6696 emit extra->window->focusObjectChanged(object: q);
6697 }
6698}
6699
6700/*!
6701 \fn void QWidget::setFocus()
6702 \overload
6703
6704 Gives the keyboard input focus to this widget (or its focus
6705 proxy) if this widget or one of its parents is the
6706 \l{isActiveWindow()}{active window}.
6707*/
6708
6709/*!
6710 Takes keyboard input focus from the widget.
6711
6712 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6713 lost the focus.
6714
6715 This widget must enable focus setting to get the keyboard
6716 input focus; that is, it must call setFocusPolicy().
6717
6718 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6719 setFocusPolicy(), QApplication::focusWidget()
6720*/
6721
6722void QWidget::clearFocus()
6723{
6724 if (hasFocus()) {
6725 if (testAttribute(attribute: Qt::WA_InputMethodEnabled))
6726 QGuiApplication::inputMethod()->commit();
6727
6728 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6729 QCoreApplication::sendEvent(receiver: this, event: &focusAboutToChange);
6730 }
6731
6732 QTLWExtra *extra = window()->d_func()->maybeTopData();
6733 QObject *originalFocusObject = nullptr;
6734 if (extra && extra->window) {
6735 originalFocusObject = extra->window->focusObject();
6736 // the window's focus object might already be nullptr if we are in the destructor, but we still
6737 // need to update QGuiApplication and input context if we have a focus widget.
6738 if (!originalFocusObject)
6739 originalFocusObject = focusWidget();
6740 }
6741
6742 QWidget *w = this;
6743 while (w) {
6744 // Just like setFocus(), we update (clear) the focus_child of our parents
6745 if (w->d_func()->focus_child == this)
6746 w->d_func()->focus_child = nullptr;
6747 w = w->parentWidget();
6748 }
6749
6750 // We've potentially cleared the focus_child of our parents, so we need
6751 // to report this to the rest of Qt. Note that the focus_child is not the same
6752 // thing as the application's focusWidget, which is why this piece of code is
6753 // not inside a hasFocus() block.
6754 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6755 emit extra->window->focusObjectChanged(object: extra->window->focusObject());
6756
6757#if QT_CONFIG(graphicsview)
6758 const auto &topData = d_func()->extra;
6759 if (topData && topData->proxyWidget)
6760 topData->proxyWidget->clearFocus();
6761#endif
6762
6763 if (hasFocus()) {
6764 // Update proxy state
6765 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::OtherFocusReason);
6766#if QT_CONFIG(accessibility)
6767 QAccessibleEvent event(this, QAccessible::Focus);
6768 QAccessible::updateAccessibility(event: &event);
6769#endif
6770 }
6771}
6772
6773
6774/*!
6775 \fn bool QWidget::focusNextChild()
6776
6777 Finds a new widget to give the keyboard focus to, as appropriate
6778 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6779 false if it can't.
6780
6781 \sa focusPreviousChild()
6782*/
6783
6784/*!
6785 \fn bool QWidget::focusPreviousChild()
6786
6787 Finds a new widget to give the keyboard focus to, as appropriate
6788 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6789 or false if it can't.
6790
6791 \sa focusNextChild()
6792*/
6793
6794/*!
6795 Finds a new widget to give the keyboard focus to, as appropriate
6796 for Tab and Shift+Tab, and returns \c true if it can find a new
6797 widget, or false if it can't.
6798
6799 If \a next is true, this function searches forward, if \a next
6800 is false, it searches backward.
6801
6802 Sometimes, you will want to reimplement this function. For
6803 example, a web browser might reimplement it to move its "current
6804 active link" forward or backward, and call
6805 focusNextPrevChild() only when it reaches the last or
6806 first link on the "page".
6807
6808 Child widgets call focusNextPrevChild() on their parent widgets,
6809 but only the window that contains the child widgets decides where
6810 to redirect focus. By reimplementing this function for an object,
6811 you thus gain control of focus traversal for all child widgets.
6812
6813 \sa focusNextChild(), focusPreviousChild()
6814*/
6815
6816bool QWidget::focusNextPrevChild(bool next)
6817{
6818 QWidget* p = parentWidget();
6819 bool isSubWindow = (windowType() == Qt::SubWindow);
6820 if (!isWindow() && !isSubWindow && p)
6821 return p->focusNextPrevChild(next);
6822#if QT_CONFIG(graphicsview)
6823 Q_D(QWidget);
6824 if (d->extra && d->extra->proxyWidget)
6825 return d->extra->proxyWidget->focusNextPrevChild(next);
6826#endif
6827
6828 bool wrappingOccurred = false;
6829 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(toplevel: this, next,
6830 wrappingOccurred: &wrappingOccurred);
6831 if (!w) return false;
6832
6833 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6834
6835 /* If we are about to wrap the focus chain, give the platform
6836 * implementation a chance to alter the wrapping behavior. This is
6837 * especially needed when the window is embedded in a window created by
6838 * another process.
6839 */
6840 if (wrappingOccurred) {
6841 QWindow *window = windowHandle();
6842 if (window != nullptr) {
6843 QWindowPrivate *winp = qt_window_private(window);
6844
6845 if (winp->platformWindow != nullptr) {
6846 QFocusEvent event(QEvent::FocusIn, reason);
6847 event.ignore();
6848 winp->platformWindow->windowEvent(event: &event);
6849 if (event.isAccepted()) return true;
6850 }
6851 }
6852 }
6853
6854 w->setFocus(reason);
6855 return true;
6856}
6857
6858/*!
6859 Returns the last child of this widget that setFocus had been
6860 called on. For top level widgets this is the widget that will get
6861 focus in case this window gets activated
6862
6863 This is not the same as QApplication::focusWidget(), which returns
6864 the focus widget in the currently active window.
6865*/
6866
6867QWidget *QWidget::focusWidget() const
6868{
6869 return const_cast<QWidget *>(d_func()->focus_child);
6870}
6871
6872QObject *QWidgetPrivate::focusObject()
6873{
6874 Q_Q(QWidget);
6875 QWidget *proxy = deepestFocusProxy();
6876 return proxy ? proxy : q;
6877}
6878
6879/*!
6880 Returns the next widget in this widget's focus chain.
6881
6882 \sa previousInFocusChain()
6883*/
6884QWidget *QWidget::nextInFocusChain() const
6885{
6886 Q_D(const QWidget);
6887 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Next);
6888}
6889
6890/*!
6891 \brief The previousInFocusChain function returns the previous
6892 widget in this widget's focus chain.
6893
6894 \sa nextInFocusChain()
6895
6896 \since 4.6
6897*/
6898QWidget *QWidget::previousInFocusChain() const
6899{
6900 Q_D(const QWidget);
6901 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Previous);
6902}
6903
6904/*!
6905 \property QWidget::isActiveWindow
6906 \brief whether this widget's window is the active window
6907
6908 The active window is the window that contains the widget that has
6909 keyboard focus (The window may still have focus if it has no
6910 widgets or none of its widgets accepts keyboard focus).
6911
6912 When popup windows are visible, this property is \c true for both the
6913 active window \e and for the popup.
6914
6915 By default, this property is \c false.
6916
6917 \sa activateWindow(), QApplication::activeWindow()
6918*/
6919bool QWidget::isActiveWindow() const
6920{
6921 QWidget *tlw = window();
6922 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6923 return true;
6924
6925#if QT_CONFIG(graphicsview)
6926 if (const auto &tlwExtra = tlw->d_func()->extra) {
6927 if (isVisible() && tlwExtra->proxyWidget)
6928 return tlwExtra->proxyWidget->isActiveWindow();
6929 }
6930#endif
6931
6932 if (style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: this)) {
6933 if (tlw->windowType() == Qt::Tool &&
6934 !tlw->isModal() &&
6935 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6936 return true;
6937 QWidget *w = QApplication::activeWindow();
6938 while(w && tlw->windowType() == Qt::Tool &&
6939 !w->isModal() && w->parentWidget()) {
6940 w = w->parentWidget()->window();
6941 if (w == tlw)
6942 return true;
6943 }
6944 }
6945
6946 // Check for an active window container
6947 if (QWindow *ww = QGuiApplication::focusWindow()) {
6948 while (ww) {
6949 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(object: ww);
6950 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(object: qww->widget()) : 0;
6951 if (qwc && qwc->topLevelWidget() == tlw)
6952 return true;
6953 ww = ww->parent();
6954 }
6955 }
6956
6957 // Check if platform adaptation thinks the window is active. This is necessary for
6958 // example in case of ActiveQt servers that are embedded into another application.
6959 // Those are separate processes that are not part of the parent application Qt window/widget
6960 // hierarchy, so they need to rely on native methods to determine if they are part of the
6961 // active window.
6962 if (const QWindow *w = tlw->windowHandle()) {
6963 if (w->handle())
6964 return w->handle()->isActive();
6965 }
6966
6967 return false;
6968}
6969
6970/*!
6971 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6972 \overload
6973 \since 6.6
6974
6975 Sets the tab order for the widgets in the \a widgets list by calling
6976 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6977 pair of widgets.
6978
6979 Instead of setting up each pair manually like this:
6980
6981 \snippet code/src_gui_kernel_qwidget.cpp 9
6982
6983 you can call:
6984
6985 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6986
6987 The call does not create a closed tab focus loop. If there are more widgets
6988 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
6989 of those widgets, not back to \c{a}.
6990
6991 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6992*/
6993
6994/*!
6995 Puts the \a second widget after the \a first widget in the focus order.
6996
6997 It effectively removes the \a second widget from its focus chain and
6998 inserts it after the \a first widget.
6999
7000 Note that since the tab order of the \a second widget is changed, you
7001 should order a chain like this:
7002
7003 \snippet code/src_gui_kernel_qwidget.cpp 9
7004
7005 \e not like this:
7006
7007 \snippet code/src_gui_kernel_qwidget.cpp 10
7008
7009 If \a first or \a second has a focus proxy, setTabOrder()
7010 correctly substitutes the proxy.
7011
7012 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7013 a compound widget. When setting a tab order between one or two compound widgets, the
7014 local tab order inside each will be preserved. This means that if both widgets are
7015 compound widgets, the resulting tab order will be from the last child inside
7016 \a first, to the first child inside \a second.
7017
7018 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7019*/
7020void QWidget::setTabOrder(QWidget* first, QWidget *second)
7021{
7022 if (!first || !second || first == second
7023 || first->focusPolicy() == Qt::NoFocus
7024 || second->focusPolicy() == Qt::NoFocus)
7025 return;
7026
7027 if (Q_UNLIKELY(first->window() != second->window())) {
7028 qWarning(msg: "QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7029 return;
7030 }
7031
7032 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7033 {
7034 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7035 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7036 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7037 // 'lastFocusChild' will be set to the target itself.
7038 QWidget *lastFocusChild = target;
7039
7040 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7041 if (!focusProxy) {
7042 // QTBUG-81097: Another case is possible here. We can have a child
7043 // widget, that sets its focusProxy() to the parent (target).
7044 // An example of such widget is a QLineEdit, nested into
7045 // a QAbstractSpinBox. In this case such widget should be considered
7046 // the last focus child.
7047 for (auto *object : target->children()) {
7048 QWidget *w = qobject_cast<QWidget*>(o: object);
7049 if (w && w->focusProxy() == target) {
7050 lastFocusChild = w;
7051 break;
7052 }
7053 }
7054 } else if (target->isAncestorOf(child: focusProxy)) {
7055 lastFocusChild = focusProxy;
7056 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7057 focusNext != focusProxy && target->isAncestorOf(child: focusNext) && focusNext->window() == focusProxy->window();
7058 focusNext = focusNext->nextInFocusChain()) {
7059 if (focusNext == noFurtherThan)
7060 break;
7061 if (focusNext->focusPolicy() != Qt::NoFocus)
7062 lastFocusChild = focusNext;
7063 }
7064 }
7065 return lastFocusChild;
7066 };
7067 // detect inflection in case we have compound widgets
7068 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7069 if (lastFocusChildOfFirst == second)
7070 lastFocusChildOfFirst = first;
7071 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7072 if (lastFocusChildOfSecond == first)
7073 lastFocusChildOfSecond = second;
7074
7075 // Return if only NoFocus widgets are between first and second
7076 QWidget *oldPrev = second->previousInFocusChain();
7077 QWidget *prevWithFocus = oldPrev;
7078 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7079 prevWithFocus = prevWithFocus->previousInFocusChain();
7080 if (prevWithFocus == first)
7081 return;
7082 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(from: second, to: lastFocusChildOfSecond);
7083 QWidgetPrivate::insertIntoFocusChain(toBeInserted: chain, direction: QWidgetPrivate::FocusDirection::Next, position: lastFocusChildOfFirst);
7084}
7085
7086void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7087{
7088 QWidget *prev = nullptr;
7089 for (const auto &widget : widgets) {
7090 if (!prev) {
7091 prev = widget;
7092 } else {
7093 QWidget::setTabOrder(first: prev, second: widget);
7094 prev = widget;
7095 }
7096 }
7097}
7098
7099
7100/*!\internal
7101
7102 Moves the relevant subwidgets of this widget from the \a oldtlw's
7103 tab chain to that of the new parent, if there's anything to move and
7104 we're really moving
7105
7106 This function is called from QWidget::reparent() *after* the widget
7107 has been reparented.
7108
7109 \sa reparent()
7110*/
7111
7112void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7113{
7114 Q_Q(QWidget);
7115 if (oldtlw == q->window())
7116 return; // nothing to do
7117
7118 if (focus_child)
7119 focus_child->clearFocus();
7120
7121 reparentFocusChildren(direction: QWidgetPrivate::FocusDirection::Next);
7122}
7123
7124/*!
7125 \property QWidget::frameSize
7126 \brief the size of the widget including any window frame
7127
7128 By default, this property contains a value that depends on the user's
7129 platform and screen geometry.
7130*/
7131QSize QWidget::frameSize() const
7132{
7133 Q_D(const QWidget);
7134 if (isWindow() && !(windowType() == Qt::Popup)) {
7135 QRect fs = d->frameStrut();
7136 return QSize(data->crect.width() + fs.left() + fs.right(),
7137 data->crect.height() + fs.top() + fs.bottom());
7138 }
7139 return data->crect.size();
7140}
7141
7142/*! \fn void QWidget::move(int x, int y)
7143
7144 \overload
7145
7146 This corresponds to move(QPoint(\a x, \a y)).
7147*/
7148
7149void QWidget::move(const QPoint &p)
7150{
7151 Q_D(QWidget);
7152 setAttribute(Qt::WA_Moved);
7153 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7154 if (isWindow())
7155 d->topData()->posIncludesFrame = false;
7156 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7157 p.y() + geometry().y() - QWidget::y(),
7158 width(), height(), true);
7159 d->setDirtyOpaqueRegion();
7160 } else {
7161 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7162 if (isWindow())
7163 d->topData()->posIncludesFrame = true;
7164 data->crect.moveTopLeft(p); // no frame yet
7165 setAttribute(Qt::WA_PendingMoveEvent);
7166 }
7167
7168 if (d->extra && d->extra->hasWindowContainer)
7169 QWindowContainer::parentWasMoved(parent: this);
7170}
7171
7172// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7173// unknown), that is, crect has a position including the frame.
7174// If we can determine the frame strut, fix that and clear the flag.
7175// FIXME: This does not play well with window states other than
7176// Qt::WindowNoState, as we depend on calling setGeometry() on the
7177// platform window after fixing up the position so that the new
7178// geometry is reflected in the platform window, but when the frame
7179// comes in after the window has been shown (e.g. maximized), we're
7180// not in a position to do that kind of fixup.
7181void QWidgetPrivate::fixPosIncludesFrame()
7182{
7183 Q_Q(QWidget);
7184 if (QTLWExtra *te = maybeTopData()) {
7185 if (te->posIncludesFrame) {
7186 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7187 // example, in QGraphicsProxyWidget).
7188 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
7189 te->posIncludesFrame = 0;
7190 } else {
7191 if (q->windowHandle() && q->windowHandle()->handle()) {
7192 updateFrameStrut();
7193 if (!q->data->fstrut_dirty) {
7194 data.crect.translate(dx: te->frameStrut.x(), dy: te->frameStrut.y());
7195 te->posIncludesFrame = 0;
7196 }
7197 } // windowHandle()
7198 } // !WA_DontShowOnScreen
7199 } // posIncludesFrame
7200 } // QTLWExtra
7201}
7202
7203/*! \fn void QWidget::resize(int w, int h)
7204 \overload
7205
7206 This corresponds to resize(QSize(\a w, \a h)).
7207*/
7208
7209void QWidget::resize(const QSize &s)
7210{
7211 Q_D(QWidget);
7212 setAttribute(Qt::WA_Resized);
7213 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7214 d->fixPosIncludesFrame();
7215 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7216 d->setDirtyOpaqueRegion();
7217 } else {
7218 const auto oldRect = data->crect;
7219 data->crect.setSize(s.boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7220 if (oldRect != data->crect)
7221 setAttribute(Qt::WA_PendingResizeEvent);
7222 }
7223}
7224
7225void QWidget::setGeometry(const QRect &r)
7226{
7227 Q_D(QWidget);
7228 setAttribute(Qt::WA_Resized);
7229 setAttribute(Qt::WA_Moved);
7230 if (isWindow())
7231 d->topData()->posIncludesFrame = 0;
7232 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7233 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7234 d->setDirtyOpaqueRegion();
7235 } else {
7236 const auto oldRect = data->crect;
7237 data->crect.setTopLeft(r.topLeft());
7238 data->crect.setSize(r.size().boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7239 if (oldRect != data->crect) {
7240 setAttribute(Qt::WA_PendingMoveEvent);
7241 setAttribute(Qt::WA_PendingResizeEvent);
7242 }
7243 }
7244
7245 if (d->extra && d->extra->hasWindowContainer)
7246 QWindowContainer::parentWasMoved(parent: this);
7247}
7248
7249void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7250{
7251 Q_Q(QWidget);
7252 if (extra) { // any size restrictions?
7253 w = qMin(a: w,b: extra->maxw);
7254 h = qMin(a: h,b: extra->maxh);
7255 w = qMax(a: w,b: extra->minw);
7256 h = qMax(a: h,b: extra->minh);
7257 }
7258
7259 if (q->isWindow() && q->windowHandle()) {
7260 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7261 if (!integration->hasCapability(cap: QPlatformIntegration::NonFullScreenWindows)) {
7262 x = 0;
7263 y = 0;
7264 w = q->windowHandle()->width();
7265 h = q->windowHandle()->height();
7266 }
7267 }
7268
7269 QPoint oldp = q->geometry().topLeft();
7270 QSize olds = q->size();
7271 QRect r(x, y, w, h);
7272
7273 bool isResize = olds != r.size();
7274 if (!isMove)
7275 isMove = oldp != r.topLeft();
7276
7277
7278 // We only care about stuff that changes the geometry, or may
7279 // cause the window manager to change its state
7280 if (r.size() == olds && oldp == r.topLeft())
7281 return;
7282
7283 if (!data.in_set_window_state) {
7284 q->data->window_state &= ~Qt::WindowMaximized;
7285 q->data->window_state &= ~Qt::WindowFullScreen;
7286 if (q->isWindow())
7287 topData()->normalGeometry = QRect(0, 0, -1, -1);
7288 }
7289
7290 QPoint oldPos = q->pos();
7291 data.crect = r;
7292
7293 bool needsShow = false;
7294
7295 if (q->isWindow() || q->windowHandle()) {
7296 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7297 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
7298 if (q->isVisible())
7299 hide_sys();
7300 data.crect = QRect(x, y, w, h);
7301 } else if (q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7302 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
7303 needsShow = true;
7304 }
7305 }
7306
7307 if (q->isVisible()) {
7308 if (!q->testAttribute(attribute: Qt::WA_DontShowOnScreen) && !q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7309 if (QWindow *win = q->windowHandle()) {
7310 if (q->isWindow()) {
7311 if (isResize && !isMove)
7312 win->resize(w, h);
7313 else if (isMove && !isResize)
7314 win->setPosition(posx: x, posy: y);
7315 else
7316 win->setGeometry(q->geometry());
7317 } else {
7318 QPoint posInNativeParent = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
7319 win->setGeometry(QRect(posInNativeParent,r.size()));
7320 }
7321
7322 if (needsShow)
7323 show_sys();
7324 }
7325
7326 if (!q->isWindow()) {
7327 if (renderToTexture) {
7328 QRegion updateRegion(q->geometry());
7329 updateRegion += QRect(oldPos, olds);
7330 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7331 } else if (isMove && !isResize) {
7332 moveRect(QRect(oldPos, olds), dx: x - oldPos.x(), dy: y - oldPos.y());
7333 } else {
7334 invalidateBackingStore_resizeHelper(oldPos, oldSize: olds);
7335 }
7336 }
7337 }
7338
7339 if (isMove) {
7340 QMoveEvent e(q->pos(), oldPos);
7341 QCoreApplication::sendEvent(receiver: q, event: &e);
7342 }
7343 if (isResize) {
7344 QResizeEvent e(r.size(), olds);
7345 QCoreApplication::sendEvent(receiver: q, event: &e);
7346 if (q->windowHandle())
7347 q->update();
7348 }
7349 } else { // not visible
7350 if (isMove && q->pos() != oldPos)
7351 q->setAttribute(Qt::WA_PendingMoveEvent, on: true);
7352 if (isResize)
7353 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7354 }
7355
7356#if QT_CONFIG(accessibility)
7357 if (QAccessible::isActive() && q->isVisible()) {
7358 QAccessibleEvent event(q, QAccessible::LocationChanged);
7359 QAccessible::updateAccessibility(event: &event);
7360 }
7361#endif
7362}
7363
7364/*!
7365 \since 4.2
7366 Saves the current geometry and state for top-level widgets.
7367
7368 To save the geometry when the window closes, you can
7369 implement a close event like this:
7370
7371 \snippet code/src_gui_kernel_qwidget.cpp 11
7372
7373 See the \l{Window Geometry} documentation for an overview of geometry
7374 issues with windows.
7375
7376 Use QMainWindow::saveState() to save the geometry and the state of
7377 toolbars and dock widgets.
7378
7379 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7380*/
7381QByteArray QWidget::saveGeometry() const
7382{
7383 QByteArray array;
7384 QDataStream stream(&array, QIODevice::WriteOnly);
7385 stream.setVersion(QDataStream::Qt_4_0);
7386 const quint32 magicNumber = 0x1D9D0CB;
7387 // Version history:
7388 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7389 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7390 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7391 quint16 majorVersion = 3;
7392 quint16 minorVersion = 0;
7393 const int screenNumber = QGuiApplication::screens().indexOf(t: screen());
7394 stream << magicNumber
7395 << majorVersion
7396 << minorVersion
7397 << frameGeometry()
7398 << normalGeometry()
7399 << qint32(screenNumber)
7400 << quint8(windowState() & Qt::WindowMaximized)
7401 << quint8(windowState() & Qt::WindowFullScreen)
7402 << qint32(screen()->geometry().width()) // added in 2.0
7403 << geometry(); // added in 3.0
7404 return array;
7405}
7406
7407/*!
7408 \internal
7409
7410 Check a if \a restoredGeometry fits into \a availableGeometry
7411 This method is used to verify that a widget is restored to a geometry, which
7412 fits into the target screen.
7413
7414 \param frameHeight represents the height of the widget's title bar, which is expected
7415 to be on its top.
7416
7417 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7418 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7419 be full screen.
7420
7421 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7422 \a restoredGeometry will be moved
7423 \list
7424 \li down if its top is off screen
7425 \li up if its bottom is off screen
7426 \li right if its left edge is off screen
7427 \li left if its right edge is off screen
7428 \endlist
7429 */
7430void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7431 int frameHeight)
7432{
7433 // compare with restored geometry's height increased by frameHeight
7434 const int height = restoredGeometry->height() + frameHeight;
7435
7436 // Step 1: Resize if necessary:
7437 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7438 if (availableGeometry.height() <= height)
7439 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7440 if (availableGeometry.width() <= restoredGeometry->width())
7441 restoredGeometry->setWidth(availableGeometry.width() - 2);
7442
7443 // Step 2: Move if necessary:
7444 // Construct a rectangle from restored Geometry adjusted by frameHeight
7445 const QRect restored = restoredGeometry->adjusted(xp1: 0, yp1: -frameHeight, xp2: 0, yp2: 0);
7446
7447 // Return if restoredGeometry (including frame) fits into screen
7448 if (availableGeometry.contains(r: restored))
7449 return;
7450
7451 // (size is correct, but at least one edge is off screen)
7452
7453 // Top out of bounds => move down
7454 if (restored.top() <= availableGeometry.top()) {
7455 restoredGeometry->moveTop(pos: availableGeometry.top() + 1 + frameHeight);
7456 } else if (restored.bottom() >= availableGeometry.bottom()) {
7457 // Bottom out of bounds => move up
7458 restoredGeometry->moveBottom(pos: availableGeometry.bottom() - 1);
7459 }
7460
7461 // Left edge out of bounds => move right
7462 if (restored.left() <= availableGeometry.left()) {
7463 restoredGeometry->moveLeft(pos: availableGeometry.left() + 1);
7464 } else if (restored.right() >= availableGeometry.right()) {
7465 // Right edge out of bounds => move left
7466 restoredGeometry->moveRight(pos: availableGeometry.right() - 1);
7467 }
7468}
7469
7470/*!
7471 \since 4.2
7472
7473 Restores the geometry and state of top-level widgets stored in the
7474 byte array \a geometry. Returns \c true on success; otherwise
7475 returns \c false.
7476
7477 If the restored geometry is off-screen, it will be modified to be
7478 inside the available screen geometry.
7479
7480 To restore geometry saved using QSettings, you can use code like
7481 this:
7482
7483 \snippet code/src_gui_kernel_qwidget.cpp 12
7484
7485 See the \l{Window Geometry} documentation for an overview of geometry
7486 issues with windows.
7487
7488 Use QMainWindow::restoreState() to restore the geometry and the
7489 state of toolbars and dock widgets.
7490
7491 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7492*/
7493bool QWidget::restoreGeometry(const QByteArray &geometry)
7494{
7495 if (geometry.size() < 4)
7496 return false;
7497 QDataStream stream(geometry);
7498 stream.setVersion(QDataStream::Qt_4_0);
7499
7500 const quint32 magicNumber = 0x1D9D0CB;
7501 quint32 storedMagicNumber;
7502 stream >> storedMagicNumber;
7503 if (storedMagicNumber != magicNumber)
7504 return false;
7505
7506 const quint16 currentMajorVersion = 3;
7507 quint16 majorVersion = 0;
7508 quint16 minorVersion = 0;
7509
7510 stream >> majorVersion >> minorVersion;
7511
7512 if (majorVersion > currentMajorVersion)
7513 return false;
7514 // (Allow all minor versions.)
7515
7516 QRect restoredFrameGeometry;
7517 QRect restoredGeometry;
7518 QRect restoredNormalGeometry;
7519 qint32 restoredScreenNumber;
7520 quint8 maximized;
7521 quint8 fullScreen;
7522 qint32 restoredScreenWidth = 0;
7523
7524 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7525 >> restoredNormalGeometry
7526 >> restoredScreenNumber
7527 >> maximized
7528 >> fullScreen;
7529
7530 if (majorVersion > 1)
7531 stream >> restoredScreenWidth;
7532 if (majorVersion > 2)
7533 stream >> restoredGeometry;
7534
7535 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7536
7537 if (restoredScreenNumber >= qMax(a: QGuiApplication::screens().size(), b: 1))
7538 restoredScreenNumber = 0;
7539 const QScreen *restoredScreen = QGuiApplication::screens().value(i: restoredScreenNumber, defaultValue: nullptr);
7540 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7541 // Sanity check bailing out when large variations of screen sizes occur due to
7542 // high DPI scaling or different levels of DPI awareness.
7543 if (restoredScreenWidth) {
7544 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7545 if (factor < 0.8 || factor > 1.25)
7546 return false;
7547 } else {
7548 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7549 // unless the size will be adapted by maximized or fullscreen.
7550 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7551 return false;
7552 }
7553
7554 const int frameHeight = QApplication::style()
7555 ? QApplication::style()->pixelMetric(metric: QStyle::PM_TitleBarHeight, option: nullptr, widget: this)
7556 : 20;
7557
7558 if (!restoredNormalGeometry.isValid())
7559 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7560 if (!restoredNormalGeometry.isValid()) {
7561 // use the widget's adjustedSize if the sizeHint() doesn't help
7562 restoredNormalGeometry.setSize(restoredNormalGeometry
7563 .size()
7564 .expandedTo(otherSize: d_func()->adjustedSize()));
7565 }
7566
7567 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7568 : QRect();
7569
7570 // Modify the restored geometry if we are about to restore to coordinates
7571 // that would make the window "lost". This happens if:
7572 // - The restored geometry is completely or partly oustside the available geometry
7573 // - The title bar is outside the available geometry.
7574
7575 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredGeometry, frameHeight);
7576 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredNormalGeometry, frameHeight);
7577
7578 if (maximized || fullScreen) {
7579 // set geometry before setting the window state to make
7580 // sure the window is maximized to the right screen.
7581 Qt::WindowStates ws = windowState();
7582#ifndef Q_OS_WIN
7583 setGeometry(restoredNormalGeometry);
7584#else
7585 if (ws & Qt::WindowFullScreen) {
7586 // Full screen is not a real window state on Windows.
7587 move(availableGeometry.topLeft());
7588 } else if (ws & Qt::WindowMaximized) {
7589 // Setting a geometry on an already maximized window causes this to be
7590 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7591 // Move the window in normal state if needed.
7592 if (restoredScreen != screen()) {
7593 setWindowState(Qt::WindowNoState);
7594 setGeometry(restoredNormalGeometry);
7595 }
7596 } else {
7597 setGeometry(restoredNormalGeometry);
7598 }
7599#endif // Q_OS_WIN
7600 if (maximized)
7601 ws |= Qt::WindowMaximized;
7602 if (fullScreen)
7603 ws |= Qt::WindowFullScreen;
7604 setWindowState(ws);
7605 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7606 } else {
7607 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7608
7609 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7610 if (majorVersion > 2)
7611 setGeometry(restoredGeometry);
7612 else
7613 setGeometry(restoredNormalGeometry);
7614 }
7615 return true;
7616}
7617
7618/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7619 \overload
7620
7621 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7622*/
7623
7624/*!
7625 Sets the margins around the contents of the widget to have the sizes
7626 \a left, \a top, \a right, and \a bottom. The margins are used by
7627 the layout system, and may be used by subclasses to specify the area
7628 to draw in (e.g. excluding the frame).
7629
7630 Changing the margins will trigger a resizeEvent().
7631
7632 \sa contentsRect(), contentsMargins()
7633*/
7634void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7635{
7636 Q_D(QWidget);
7637 if (left == d->leftmargin && top == d->topmargin
7638 && right == d->rightmargin && bottom == d->bottommargin)
7639 return;
7640 d->leftmargin = left;
7641 d->topmargin = top;
7642 d->rightmargin = right;
7643 d->bottommargin = bottom;
7644
7645 d->updateContentsRect();
7646}
7647
7648/*!
7649 \overload
7650 \since 4.6
7651
7652 \brief The setContentsMargins function sets the margins around the
7653 widget's contents.
7654
7655 Sets the margins around the contents of the widget to have the
7656 sizes determined by \a margins. The margins are
7657 used by the layout system, and may be used by subclasses to
7658 specify the area to draw in (e.g. excluding the frame).
7659
7660 Changing the margins will trigger a resizeEvent().
7661
7662 \sa contentsRect(), contentsMargins()
7663*/
7664void QWidget::setContentsMargins(const QMargins &margins)
7665{
7666 setContentsMargins(left: margins.left(), top: margins.top(),
7667 right: margins.right(), bottom: margins.bottom());
7668}
7669
7670void QWidgetPrivate::updateContentsRect()
7671{
7672 Q_Q(QWidget);
7673
7674 if (layout)
7675 layout->update(); //force activate; will do updateGeometry
7676 else
7677 q->updateGeometry();
7678
7679 if (q->isVisible()) {
7680 q->update();
7681 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7682 QCoreApplication::sendEvent(receiver: q, event: &e);
7683 } else {
7684 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7685 }
7686
7687 QEvent e(QEvent::ContentsRectChange);
7688 QCoreApplication::sendEvent(receiver: q, event: &e);
7689}
7690
7691/*!
7692 \since 4.6
7693
7694 \brief The contentsMargins function returns the widget's contents margins.
7695
7696 \sa setContentsMargins(), contentsRect()
7697 */
7698QMargins QWidget::contentsMargins() const
7699{
7700 Q_D(const QWidget);
7701 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7702 return testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea) ?
7703 userMargins | d->safeAreaMargins() : userMargins;
7704}
7705
7706/*!
7707 Returns the area inside the widget's margins.
7708
7709 \sa setContentsMargins(), contentsMargins()
7710*/
7711QRect QWidget::contentsRect() const
7712{
7713 return rect() - contentsMargins();
7714}
7715
7716QMargins QWidgetPrivate::safeAreaMargins() const
7717{
7718 Q_Q(const QWidget);
7719 QWidget *nativeWidget = q->window();
7720 if (!nativeWidget->windowHandle())
7721 return QMargins();
7722
7723 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7724
7725 if (!q->isWindow()) {
7726 // In theory the native parent widget already has a contents rect reflecting
7727 // the safe area of that widget, but we can't be sure that the widget or child
7728 // widgets of that widget have respected the contents rect when setting their
7729 // geometry, so we need to manually compute the safe area.
7730
7731 // Unless the native widget doesn't have any margins, in which case there's
7732 // nothing for us to compute.
7733 if (safeAreaMargins.isNull())
7734 return QMargins();
7735
7736 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7737 // set, and the widget respects the safe area, then we know that the layout has already
7738 // taken care of placing us inside the safe area, by taking the contents rect of its
7739 // parent widget into account.
7740 const QWidget *assumedSafeWidget = nullptr;
7741 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7742 QWidget *parentWidget = w->parentWidget();
7743 if (!parentWidget->testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea))
7744 continue; // Layout can't help us
7745
7746 if (parentWidget->testAttribute(attribute: Qt::WA_LayoutOnEntireRect))
7747 continue; // Layout not going to help us
7748
7749 QLayout *layout = parentWidget->layout();
7750 if (!layout)
7751 continue;
7752
7753 if (layout->geometry().isNull())
7754 continue; // Layout hasn't been activated yet
7755
7756 if (layout->indexOf(w) < 0)
7757 continue; // Widget is not in layout
7758
7759 assumedSafeWidget = w;
7760 break;
7761 }
7762
7763#if !defined(QT_DEBUG)
7764 if (assumedSafeWidget) {
7765 // We found a layout that we assume will take care of keeping us within the safe area
7766 // For debug builds we still map the safe area using the fallback logic, so that we
7767 // can detect any misbehaving layouts.
7768 return QMargins();
7769 }
7770#endif
7771
7772 // In all other cases we need to map the safe area of the native parent to the widget.
7773 // This depends on the widget being positioned and sized already, which means the initial
7774 // layout will be wrong, but the layout will then adjust itself.
7775 QPoint topLeftMargins = q->mapFrom(parent: nativeWidget, pos: QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7776 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7777 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(parent: nativeWidget,
7778 pos: nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7779
7780 // Margins should never be negative
7781 safeAreaMargins = QMargins(qMax(a: 0, b: topLeftMargins.x()), qMax(a: 0, b: topLeftMargins.y()),
7782 qMax(a: 0, b: bottomRightMargins.x()), qMax(a: 0, b: bottomRightMargins.y()));
7783
7784 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7785 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7786 qWarning() << layout << "is laying out" << assumedSafeWidget
7787 << "outside of the contents rect of" << layout->parentWidget();
7788 return QMargins(); // Return empty margin to visually highlight the error
7789 }
7790 }
7791
7792 return safeAreaMargins;
7793}
7794
7795/*!
7796 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7797
7798 This signal is emitted when the widget's \l contextMenuPolicy is
7799 Qt::CustomContextMenu, and the user has requested a context menu on
7800 the widget. The position \a pos is the position of the context menu
7801 event that the widget receives. Normally this is in widget
7802 coordinates. The exception to this rule is QAbstractScrollArea and
7803 its subclasses that map the context menu event to coordinates of the
7804 \l{QAbstractScrollArea::viewport()}{viewport()}.
7805
7806
7807 \sa mapToGlobal(), QMenu, contextMenuPolicy
7808*/
7809
7810
7811/*!
7812 \property QWidget::contextMenuPolicy
7813 \brief how the widget shows a context menu
7814
7815 The default value of this property is Qt::DefaultContextMenu,
7816 which means the contextMenuEvent() handler is called. Other values
7817 are Qt::NoContextMenu, Qt::PreventContextMenu,
7818 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7819 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7820 emitted.
7821
7822 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7823*/
7824
7825Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7826{
7827 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7828}
7829
7830void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7831{
7832 data->context_menu_policy = (uint) policy;
7833}
7834
7835/*!
7836 \property QWidget::focusPolicy
7837 \brief the way the widget accepts keyboard focus
7838
7839 The policy is Qt::TabFocus if the widget accepts keyboard
7840 focus by tabbing, Qt::ClickFocus if the widget accepts
7841 focus by clicking, Qt::StrongFocus if it accepts both, and
7842 Qt::NoFocus (the default) if it does not accept focus at
7843 all.
7844
7845 You must enable keyboard focus for a widget if it processes
7846 keyboard events. This is normally done from the widget's
7847 constructor. For instance, the QLineEdit constructor calls
7848 setFocusPolicy(Qt::StrongFocus).
7849
7850 If the widget has a focus proxy, then the focus policy will
7851 be propagated to it.
7852
7853 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7854*/
7855
7856
7857Qt::FocusPolicy QWidget::focusPolicy() const
7858{
7859 return (Qt::FocusPolicy)data->focus_policy;
7860}
7861
7862void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7863{
7864 data->focus_policy = (uint) policy;
7865 Q_D(QWidget);
7866 if (d->extra && d->extra->focus_proxy)
7867 d->extra->focus_proxy->setFocusPolicy(policy);
7868}
7869
7870/*!
7871 \property QWidget::updatesEnabled
7872 \brief whether updates are enabled
7873
7874 An updates enabled widget receives paint events and has a system
7875 background; a disabled widget does not. This also implies that
7876 calling update() and repaint() has no effect if updates are
7877 disabled.
7878
7879 By default, this property is \c true.
7880
7881 setUpdatesEnabled() is normally used to disable updates for a
7882 short period of time, for instance to avoid screen flicker during
7883 large changes. In Qt, widgets normally do not generate screen
7884 flicker, but on X11 the server might erase regions on the screen
7885 when widgets get hidden before they can be replaced by other
7886 widgets. Disabling updates solves this.
7887
7888 Example:
7889 \snippet code/src_gui_kernel_qwidget.cpp 13
7890
7891 Disabling a widget implicitly disables all its children. Enabling a widget
7892 enables all child widgets \e except top-level widgets or those that
7893 have been explicitly disabled. Re-enabling updates implicitly calls
7894 update() on the widget.
7895
7896 \sa paintEvent()
7897*/
7898void QWidget::setUpdatesEnabled(bool enable)
7899{
7900 Q_D(QWidget);
7901 setAttribute(Qt::WA_ForceUpdatesDisabled, on: !enable);
7902 d->setUpdatesEnabled_helper(enable);
7903}
7904
7905/*!
7906 Shows the widget and its child widgets.
7907
7908 For child windows, this is equivalent to calling setVisible(true).
7909 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7910 or setVisible(true), depending on the platform's default behavior for the window flags.
7911
7912 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7913 showNormal(), isVisible(), windowFlags()
7914*/
7915void QWidget::show()
7916{
7917 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7918
7919 if (!isWindow()) {
7920 setVisible(true);
7921 } else {
7922 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7923 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7924 if (defaultState == Qt::WindowFullScreen)
7925 showFullScreen();
7926 else if (defaultState == Qt::WindowMaximized)
7927 showMaximized();
7928 else
7929 setVisible(true);
7930 }
7931}
7932
7933/*! \internal
7934
7935 Makes the widget visible in the isVisible() meaning of the word.
7936 It is only called for toplevels or widgets with visible parents.
7937 */
7938void QWidgetPrivate::show_recursive()
7939{
7940 Q_Q(QWidget);
7941 // polish if necessary
7942
7943 if (!q->testAttribute(attribute: Qt::WA_WState_Created))
7944 createRecursively();
7945 q->ensurePolished();
7946
7947 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7948 q->parentWidget()->d_func()->layout->activate();
7949 // activate our layout before we and our children become visible
7950 if (layout)
7951 layout->activate();
7952
7953 show_helper();
7954}
7955
7956void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7957{
7958 Q_Q(QWidget);
7959
7960 disableUpdates = disableUpdates && q->updatesEnabled();
7961 if (disableUpdates)
7962 q->setAttribute(Qt::WA_UpdatesDisabled);
7963
7964 if (q->testAttribute(attribute: Qt::WA_PendingMoveEvent)) {
7965 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7966 QCoreApplication::sendEvent(receiver: q, event: &e);
7967 q->setAttribute(Qt::WA_PendingMoveEvent, on: false);
7968 }
7969
7970 if (q->testAttribute(attribute: Qt::WA_PendingResizeEvent)) {
7971 QResizeEvent e(data.crect.size(), QSize());
7972 QCoreApplication::sendEvent(receiver: q, event: &e);
7973 q->setAttribute(Qt::WA_PendingResizeEvent, on: false);
7974 }
7975
7976 if (disableUpdates)
7977 q->setAttribute(Qt::WA_UpdatesDisabled, on: false);
7978
7979 if (!recursive)
7980 return;
7981
7982 for (int i = 0; i < children.size(); ++i) {
7983 if (QWidget *child = qobject_cast<QWidget *>(o: children.at(i)))
7984 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7985 }
7986}
7987
7988void QWidgetPrivate::activateChildLayoutsRecursively()
7989{
7990 sendPendingMoveAndResizeEvents(recursive: false, disableUpdates: true);
7991
7992 for (int i = 0; i < children.size(); ++i) {
7993 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
7994 if (!child || child->isHidden() || child->isWindow())
7995 continue;
7996
7997 child->ensurePolished();
7998
7999 // Activate child's layout
8000 QWidgetPrivate *childPrivate = child->d_func();
8001 if (childPrivate->layout)
8002 childPrivate->layout->activate();
8003
8004 // Pretend we're visible.
8005 const bool wasVisible = child->isVisible();
8006 if (!wasVisible)
8007 child->setAttribute(Qt::WA_WState_Visible);
8008
8009 // Do the same for all my children.
8010 childPrivate->activateChildLayoutsRecursively();
8011
8012 // We're not cheating anymore.
8013 if (!wasVisible)
8014 child->setAttribute(Qt::WA_WState_Visible, on: false);
8015 }
8016}
8017
8018void QWidgetPrivate::show_helper()
8019{
8020 Q_Q(QWidget);
8021 data.in_show = true; // qws optimization
8022 // make sure we receive pending move and resize events
8023 sendPendingMoveAndResizeEvents();
8024
8025 // become visible before showing all children
8026 q->setAttribute(Qt::WA_WState_Visible);
8027
8028 // finally show all children recursively
8029 showChildren(spontaneous: false);
8030
8031
8032
8033 const bool isWindow = q->isWindow();
8034#if QT_CONFIG(graphicsview)
8035 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8036#else
8037 bool isEmbedded = false;
8038#endif
8039
8040 // popup handling: new popups and tools need to be raised, and
8041 // existing popups must be closed. Also propagate the current
8042 // windows's KeyboardFocusChange status.
8043 if (isWindow && !isEmbedded) {
8044 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8045 q->raise();
8046 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(attribute: Qt::WA_KeyboardFocusChange))
8047 q->setAttribute(Qt::WA_KeyboardFocusChange);
8048 } else {
8049 while (QApplication::activePopupWidget()) {
8050 if (!QApplication::activePopupWidget()->close())
8051 break;
8052 }
8053 }
8054 }
8055
8056 // Automatic embedding of child windows of widgets already embedded into
8057 // QGraphicsProxyWidget when they are shown the first time.
8058#if QT_CONFIG(graphicsview)
8059 if (isWindow) {
8060 if (!isEmbedded && !bypassGraphicsProxyWidget(p: q)) {
8061 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(origin: q->parentWidget());
8062 if (ancestorProxy) {
8063 isEmbedded = true;
8064 ancestorProxy->d_func()->embedSubWindow(q);
8065 }
8066 }
8067 }
8068#else
8069 Q_UNUSED(isEmbedded);
8070#endif
8071
8072 // send the show event before showing the window
8073 QShowEvent showEvent;
8074 QCoreApplication::sendEvent(receiver: q, event: &showEvent);
8075
8076 show_sys();
8077
8078 if (!isEmbedded && q->windowType() == Qt::Popup)
8079 qApp->d_func()->openPopup(popup: q);
8080
8081#if QT_CONFIG(accessibility)
8082 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8083 QAccessibleEvent event(q, QAccessible::ObjectShow);
8084 QAccessible::updateAccessibility(event: &event);
8085 }
8086#endif
8087
8088 if (QApplicationPrivate::hidden_focus_widget == q) {
8089 QApplicationPrivate::hidden_focus_widget = nullptr;
8090 q->setFocus(Qt::OtherFocusReason);
8091 }
8092
8093 // Process events when showing a Qt::SplashScreen widget before the event loop
8094 // is spinnning; otherwise it might not show up on particular platforms.
8095 // This makes QSplashScreen behave the same on all platforms.
8096 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8097 QCoreApplication::processEvents();
8098
8099 data.in_show = false; // reset qws optimization
8100}
8101
8102void QWidgetPrivate::show_sys()
8103{
8104 Q_Q(QWidget);
8105
8106 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8107
8108 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8109 invalidateBackingStore(q->rect());
8110 q->setAttribute(Qt::WA_Mapped);
8111 // add our window the modal window list (native dialogs)
8112 if (window && q->isWindow()
8113#if QT_CONFIG(graphicsview)
8114 && (!extra || !extra->proxyWidget)
8115#endif
8116 && q->windowModality() != Qt::NonModal) {
8117 QGuiApplicationPrivate::showModalWindow(window);
8118 }
8119 return;
8120 }
8121
8122 if (renderToTexture && !q->isWindow())
8123 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QUpdateLaterEvent(q->geometry()));
8124 else
8125 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(q->rect()));
8126
8127 if ((!q->isWindow() && !q->testAttribute(attribute: Qt::WA_NativeWindow))
8128 || q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
8129 return;
8130 }
8131
8132 if (window) {
8133 if (q->isWindow())
8134 fixPosIncludesFrame();
8135 QRect geomRect = q->geometry();
8136 if (!q->isWindow()) {
8137 QPoint topLeftOfWindow = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
8138 geomRect.moveTopLeft(p: topLeftOfWindow);
8139 }
8140 const QRect windowRect = window->geometry();
8141 if (windowRect != geomRect) {
8142 if (q->testAttribute(attribute: Qt::WA_Moved)
8143 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
8144 window->setGeometry(geomRect);
8145 else
8146 window->resize(newSize: geomRect.size());
8147 }
8148
8149#ifndef QT_NO_CURSOR
8150 qt_qpa_set_cursor(w: q, force: false); // Needed in case cursor was set before show
8151#endif
8152 invalidateBackingStore(q->rect());
8153 window->setNativeWindowVisibility(true);
8154 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8155 if (window->isTopLevel()) {
8156 const QPoint crectTopLeft = q->data->crect.topLeft();
8157 const QPoint windowTopLeft = window->geometry().topLeft();
8158 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8159 q->data->crect.moveTopLeft(p: windowTopLeft);
8160 }
8161 }
8162}
8163
8164/*!
8165 Hides the widget. This function is equivalent to
8166 setVisible(false).
8167
8168
8169 \note If you are working with QDialog or its subclasses and you invoke
8170 the show() function after this function, the dialog will be displayed in
8171 its original position.
8172
8173 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8174*/
8175void QWidget::hide()
8176{
8177 setVisible(false);
8178}
8179
8180/*!\internal
8181 */
8182void QWidgetPrivate::hide_helper()
8183{
8184 Q_Q(QWidget);
8185
8186 bool isEmbedded = false;
8187#if QT_CONFIG(graphicsview)
8188 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(p: q) && nearestGraphicsProxyWidget(origin: q->parentWidget()) != nullptr;
8189#else
8190 Q_UNUSED(isEmbedded);
8191#endif
8192
8193 if (!isEmbedded && (q->windowType() == Qt::Popup))
8194 qApp->d_func()->closePopup(popup: q);
8195
8196 q->setAttribute(Qt::WA_Mapped, on: false);
8197 hide_sys();
8198
8199 bool wasVisible = q->testAttribute(attribute: Qt::WA_WState_Visible);
8200
8201 if (wasVisible) {
8202 q->setAttribute(Qt::WA_WState_Visible, on: false);
8203
8204 }
8205
8206 QHideEvent hideEvent;
8207 QCoreApplication::sendEvent(receiver: q, event: &hideEvent);
8208 hideChildren(spontaneous: false);
8209
8210 // next bit tries to move the focus if the focus widget is now
8211 // hidden.
8212 if (wasVisible) {
8213 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8214 QWidget *fw = QApplication::focusWidget();
8215 while (fw && !fw->isWindow()) {
8216 if (fw == q) {
8217 q->focusNextPrevChild(next: true);
8218 break;
8219 }
8220 fw = fw->parentWidget();
8221 }
8222 }
8223
8224 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8225 repaintManager->removeDirtyWidget(w: q);
8226
8227#if QT_CONFIG(accessibility)
8228 if (wasVisible) {
8229 QAccessibleEvent event(q, QAccessible::ObjectHide);
8230 QAccessible::updateAccessibility(event: &event);
8231 }
8232#endif
8233}
8234
8235void QWidgetPrivate::hide_sys()
8236{
8237 Q_Q(QWidget);
8238
8239 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8240
8241 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8242 q->setAttribute(Qt::WA_Mapped, on: false);
8243 // remove our window from the modal window list (native dialogs)
8244 if (window && q->isWindow()
8245#if QT_CONFIG(graphicsview)
8246 && (!extra || !extra->proxyWidget)
8247#endif
8248 && q->windowModality() != Qt::NonModal) {
8249 QGuiApplicationPrivate::hideModalWindow(window);
8250 }
8251 // do not return here, if window non-zero, we must hide it
8252 }
8253
8254 deactivateWidgetCleanup();
8255
8256 if (!q->isWindow()) {
8257 QWidget *p = q->parentWidget();
8258 if (p &&p->isVisible()) {
8259 if (renderToTexture)
8260 p->d_func()->invalidateBackingStore(q->geometry());
8261 else
8262 invalidateBackingStore(q->rect());
8263 }
8264 } else {
8265 invalidateBackingStore(q->rect());
8266 }
8267
8268 if (window)
8269 window->setNativeWindowVisibility(false);
8270}
8271
8272/*!
8273 \fn bool QWidget::isHidden() const
8274
8275 Returns \c true if the widget is hidden, otherwise returns \c false.
8276
8277 A hidden widget will only become visible when show() is called on
8278 it. It will not be automatically shown when the parent is shown.
8279
8280 To check visibility, use !isVisible() instead (notice the exclamation mark).
8281
8282 isHidden() implies !isVisible(), but a widget can be not visible
8283 and not hidden at the same time. This is the case for widgets that are children of
8284 widgets that are not visible.
8285
8286
8287 Widgets are hidden if:
8288 \list
8289 \li they were created as independent windows,
8290 \li they were created as children of visible widgets,
8291 \li hide() or setVisible(false) was called.
8292 \endlist
8293*/
8294
8295void QWidget::setVisible(bool visible)
8296{
8297 Q_D(QWidget);
8298 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8299 << "with attributes" << WidgetAttributes{.widget: this}
8300 << "to" << visible << "via QWidget";
8301
8302 if (testAttribute(attribute: Qt::WA_WState_ExplicitShowHide) && testAttribute(attribute: Qt::WA_WState_Hidden) == !visible)
8303 return;
8304
8305 if (d->dontSetExplicitShowHide) {
8306 d->dontSetExplicitShowHide = false;
8307 } else {
8308 // Remember that setVisible was called explicitly
8309 setAttribute(Qt::WA_WState_ExplicitShowHide);
8310 }
8311
8312 d->setVisible(visible);
8313}
8314
8315// This method is called from QWidgetWindow in response to QWindow::setVisible,
8316// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8317// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8318void QWidgetPrivate::setVisible(bool visible)
8319{
8320 Q_Q(QWidget);
8321 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8322 << "with attributes" << WidgetAttributes{.widget: q}
8323 << "to" << visible << "via QWidgetPrivate";
8324
8325 if (visible) { // show
8326 // Designer uses a trick to make grabWidget work without showing
8327 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8328 && !q->parentWidget()->testAttribute(attribute: Qt::WA_WState_Created))
8329 q->parentWidget()->window()->d_func()->createRecursively();
8330
8331 //create toplevels but not children of non-visible parents
8332 QWidget *pw = q->parentWidget();
8333 if (!q->testAttribute(attribute: Qt::WA_WState_Created)
8334 && (q->isWindow() || pw->testAttribute(attribute: Qt::WA_WState_Created))) {
8335 q->create();
8336 }
8337
8338 bool wasResized = q->testAttribute(attribute: Qt::WA_Resized);
8339 Qt::WindowStates initialWindowState = q->windowState();
8340
8341 // polish if necessary
8342 q->ensurePolished();
8343
8344 // whether we need to inform the parent widget immediately
8345 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(attribute: Qt::WA_WState_Hidden);
8346 // we are no longer hidden
8347 q->setAttribute(Qt::WA_WState_Hidden, on: false);
8348
8349 if (needUpdateGeometry)
8350 updateGeometry_helper(forceUpdate: true);
8351
8352 // activate our layout before we and our children become visible
8353 if (layout)
8354 layout->activate();
8355
8356 if (!q->isWindow()) {
8357 QWidget *parent = q->parentWidget();
8358 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8359 parent->d_func()->layout->activate();
8360 if (parent->isWindow())
8361 break;
8362 parent = parent->parentWidget();
8363 }
8364 if (parent)
8365 parent->d_func()->setDirtyOpaqueRegion();
8366 }
8367
8368 // adjust size if necessary
8369 if (!wasResized
8370 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8371 if (q->isWindow()) {
8372 q->adjustSize();
8373 if (q->windowState() != initialWindowState)
8374 q->setWindowState(initialWindowState);
8375 } else {
8376 q->adjustSize();
8377 }
8378 q->setAttribute(Qt::WA_Resized, on: false);
8379 }
8380
8381 q->setAttribute(Qt::WA_KeyboardFocusChange, on: false);
8382
8383 if (q->isWindow() || q->parentWidget()->isVisible()) {
8384 show_helper();
8385
8386 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8387 }
8388
8389 QEvent showToParentEvent(QEvent::ShowToParent);
8390 QCoreApplication::sendEvent(receiver: q, event: &showToParentEvent);
8391 } else { // hide
8392 if (QApplicationPrivate::hidden_focus_widget == q)
8393 QApplicationPrivate::hidden_focus_widget = nullptr;
8394
8395 // hw: The test on getOpaqueRegion() needs to be more intelligent
8396 // currently it doesn't work if the widget is hidden (the region will
8397 // be clipped). The real check should be testing the cached region
8398 // (and dirty flag) directly.
8399 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8400 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8401
8402 if (!q->testAttribute(attribute: Qt::WA_WState_Hidden)) {
8403 q->setAttribute(Qt::WA_WState_Hidden);
8404 hide_helper();
8405 }
8406
8407 // invalidate layout similar to updateGeometry()
8408 if (!q->isWindow() && q->parentWidget()) {
8409 if (q->parentWidget()->d_func()->layout)
8410 q->parentWidget()->d_func()->layout->invalidate();
8411 else if (q->parentWidget()->isVisible())
8412 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QEvent(QEvent::LayoutRequest));
8413 }
8414
8415 QEvent hideToParentEvent(QEvent::HideToParent);
8416 QCoreApplication::sendEvent(receiver: q, event: &hideToParentEvent);
8417 }
8418}
8419
8420/*!
8421 Convenience function, equivalent to setVisible(!\a hidden).
8422*/
8423void QWidget::setHidden(bool hidden)
8424{
8425 setVisible(!hidden);
8426}
8427
8428bool QWidgetPrivate::isExplicitlyHidden() const
8429{
8430 Q_Q(const QWidget);
8431 return q->isHidden() && q->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide);
8432}
8433
8434void QWidgetPrivate::_q_showIfNotHidden()
8435{
8436 Q_Q(QWidget);
8437 if (!isExplicitlyHidden())
8438 q->setVisible(true);
8439}
8440
8441void QWidgetPrivate::showChildren(bool spontaneous)
8442{
8443 Q_Q(QWidget);
8444 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8445 << "spontaneously" << spontaneous;
8446
8447 QList<QObject*> childList = children;
8448 for (int i = 0; i < childList.size(); ++i) {
8449 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8450 if (!widget)
8451 continue;
8452 qCDebug(lcWidgetShowHide) << "Considering" << widget
8453 << "with attributes" << WidgetAttributes{.widget: widget};
8454 if (widget->windowHandle() && !widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
8455 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
8456 if (widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8457 continue;
8458 if (spontaneous) {
8459 widget->setAttribute(Qt::WA_Mapped);
8460 widget->d_func()->showChildren(spontaneous: true);
8461 QShowEvent e;
8462 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8463 } else {
8464 if (widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide)) {
8465 widget->d_func()->show_recursive();
8466 } else {
8467 // Call QWidget::setVisible() here, so that subclasses
8468 // that (wrongly) override setVisible to do initialization
8469 // will still be notified that they are made visible, but
8470 // do so without triggering ExplicitShowHide.
8471 widget->d_func()->dontSetExplicitShowHide = true;
8472 widget->setVisible(true);
8473 widget->d_func()->dontSetExplicitShowHide = false;
8474 }
8475 }
8476 }
8477}
8478
8479void QWidgetPrivate::hideChildren(bool spontaneous)
8480{
8481 Q_Q(QWidget);
8482 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8483 << "spontaneously" << spontaneous;
8484
8485 QList<QObject*> childList = children;
8486 for (int i = 0; i < childList.size(); ++i) {
8487 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8488 if (!widget)
8489 continue;
8490 qCDebug(lcWidgetShowHide) << "Considering" << widget
8491 << "with attributes" << WidgetAttributes{.widget: widget};
8492 if (widget->isWindow() || !widget->isVisible())
8493 continue;
8494
8495 if (spontaneous)
8496 widget->setAttribute(Qt::WA_Mapped, on: false);
8497 else
8498 widget->setAttribute(Qt::WA_WState_Visible, on: false);
8499 widget->d_func()->hideChildren(spontaneous);
8500 QHideEvent e;
8501 if (spontaneous) {
8502 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8503 } else {
8504 QCoreApplication::sendEvent(receiver: widget, event: &e);
8505 if (widget->internalWinId()
8506 && widget->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
8507 // hide_sys() on an ancestor won't have any affect on this
8508 // widget, so it needs an explicit hide_sys() of its own
8509 widget->d_func()->hide_sys();
8510 }
8511 }
8512 qApp->d_func()->sendSyntheticEnterLeave(widget);
8513#if QT_CONFIG(accessibility)
8514 if (!spontaneous) {
8515 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8516 QAccessible::updateAccessibility(event: &event);
8517 }
8518#endif
8519 }
8520
8521 // If the window of this widget is not closed, then the leave event
8522 // will eventually handle the widget under mouse use case.
8523 // Otherwise, we need to explicitly handle it here.
8524 if (QWidget* widgetWindow = q->window();
8525 widgetWindow && widgetWindow->data->is_closing) {
8526 q->setAttribute(Qt::WA_UnderMouse, on: false);
8527 }
8528}
8529
8530/*!
8531 \internal
8532
8533 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8534 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8535 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8536 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8537 system (i.e. the user clicked the close button in the title bar).
8538
8539 QDialog calls this method directly in its hide() implementation, which might be
8540 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8541 to prevent recursion.
8542
8543 For non-windows, this is called directly by QWidget::close, and \a mode will be
8544 CloseWithEvent.
8545
8546 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8547*/
8548bool QWidgetPrivate::handleClose(CloseMode mode)
8549{
8550 Q_Q(QWidget);
8551 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8552
8553 if (data.is_closing)
8554 return true;
8555
8556 // We might not have initiated the close, so update the state now that we know
8557 data.is_closing = true;
8558
8559 QPointer<QWidget> that = q;
8560
8561 if (data.in_destructor)
8562 mode = CloseNoEvent;
8563
8564 if (mode != CloseNoEvent) {
8565 QCloseEvent e;
8566 if (mode == CloseWithSpontaneousEvent)
8567 QApplication::sendSpontaneousEvent(receiver: q, event: &e);
8568 else
8569 QCoreApplication::sendEvent(receiver: q, event: &e);
8570 if (!that.isNull() && !e.isAccepted()) {
8571 data.is_closing = false;
8572 return false;
8573 }
8574 }
8575
8576 // even for windows, make sure we deliver a hide event and that all children get hidden
8577 if (!that.isNull() && !q->isHidden())
8578 q->hide();
8579
8580 if (!that.isNull()) {
8581 data.is_closing = false;
8582 if (q->testAttribute(attribute: Qt::WA_DeleteOnClose)) {
8583 q->setAttribute(Qt::WA_DeleteOnClose, on: false);
8584 q->deleteLater();
8585 }
8586 }
8587 return true;
8588}
8589
8590
8591/*!
8592 Closes this widget. Returns \c true if the widget was closed;
8593 otherwise returns \c false.
8594
8595 First it sends the widget a QCloseEvent. The widget is
8596 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8597 the close event. If it \l{QEvent::ignore()}{ignores}
8598 the event, nothing happens. The default
8599 implementation of QWidget::closeEvent() accepts the close event.
8600
8601 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8602 is also deleted. A close events is delivered to the widget no
8603 matter if the widget is visible or not.
8604
8605 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8606 last visible primary window (i.e. window with no parent) with the
8607 Qt::WA_QuitOnClose attribute set is closed. By default this
8608 attribute is set for all widgets except transient windows such as
8609 splash screens, tool windows, and popup menus.
8610
8611*/
8612
8613bool QWidget::close()
8614{
8615 return d_func()->close();
8616}
8617
8618bool QWidgetPrivate::close()
8619{
8620 // FIXME: We're not setting is_closing here, even though that would
8621 // make sense, as the code below will not end up in handleClose to
8622 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8623 // and we can't assume close is synchronous so we can't reset it here.
8624
8625 // Close native widgets via QWindow::close() in order to run QWindow
8626 // close code. The QWidget-specific close code in handleClose() will
8627 // in this case be called from the Close event handler in QWidgetWindow.
8628 if (QWindow *widgetWindow = windowHandle()) {
8629 if (widgetWindow->isTopLevel())
8630 return widgetWindow->close();
8631 }
8632
8633 return handleClose(mode: QWidgetPrivate::CloseWithEvent);
8634}
8635
8636/*!
8637 \property QWidget::visible
8638 \brief whether the widget is visible
8639
8640 Calling setVisible(true) or show() sets the widget to visible
8641 status if all its parent widgets up to the window are visible. If
8642 an ancestor is not visible, the widget won't become visible until
8643 all its ancestors are shown. If its size or position has changed,
8644 Qt guarantees that a widget gets move and resize events just
8645 before it is shown. If the widget has not been resized yet, Qt
8646 will adjust the widget's size to a useful default using
8647 adjustSize().
8648
8649 Calling setVisible(false) or hide() hides a widget explicitly. An
8650 explicitly hidden widget will never become visible, even if all
8651 its ancestors become visible, unless you show it.
8652
8653 A widget receives show and hide events when its visibility status
8654 changes. Between a hide and a show event, there is no need to
8655 waste CPU cycles preparing or displaying information to the user.
8656 A video application, for example, might simply stop generating new
8657 frames.
8658
8659 A widget that happens to be obscured by other windows on the
8660 screen is considered to be visible. The same applies to iconified
8661 windows and windows that exist on another virtual
8662 desktop (on platforms that support this concept). A widget
8663 receives spontaneous show and hide events when its mapping status
8664 is changed by the window system, e.g. a spontaneous hide event
8665 when the user minimizes the window, and a spontaneous show event
8666 when the window is restored again.
8667
8668 You seldom have to reimplement the setVisible() function. If
8669 you need to change some settings before a widget is shown, use
8670 showEvent() instead. If you need to do some delayed initialization
8671 use the Polish event delivered to the event() function.
8672
8673 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8674 showEvent(), hideEvent()
8675*/
8676
8677
8678/*!
8679 Returns \c true if this widget would become visible if \a ancestor is
8680 shown; otherwise returns \c false.
8681
8682 The true case occurs if neither the widget itself nor any parent
8683 up to but excluding \a ancestor has been explicitly hidden.
8684
8685 This function will still return true if the widget is obscured by
8686 other windows on the screen, but could be physically visible if it
8687 or they were to be moved.
8688
8689 isVisibleTo(0) is identical to isVisible().
8690
8691 \sa show(), hide(), isVisible()
8692*/
8693
8694bool QWidget::isVisibleTo(const QWidget *ancestor) const
8695{
8696 if (!ancestor)
8697 return isVisible();
8698 const QWidget * w = this;
8699 while (!w->isHidden()
8700 && !w->isWindow()
8701 && w->parentWidget()
8702 && w->parentWidget() != ancestor)
8703 w = w->parentWidget();
8704 return !w->isHidden();
8705}
8706
8707
8708/*!
8709 Returns the unobscured region where paint events can occur.
8710
8711 For visible widgets, this is an approximation of the area not
8712 covered by other widgets; otherwise, this is an empty region.
8713
8714 The repaint() function calls this function if necessary, so in
8715 general you do not need to call it.
8716
8717*/
8718QRegion QWidget::visibleRegion() const
8719{
8720 Q_D(const QWidget);
8721
8722 QRect clipRect = d->clipRect();
8723 if (clipRect.isEmpty())
8724 return QRegion();
8725 QRegion r(clipRect);
8726 d->subtractOpaqueChildren(source&: r, clipRect);
8727 d->subtractOpaqueSiblings(sourceRegion&: r);
8728 return r;
8729}
8730
8731
8732QSize QWidgetPrivate::adjustedSize() const
8733{
8734 Q_Q(const QWidget);
8735
8736 QSize s = q->sizeHint();
8737
8738 if (q->isWindow()) {
8739 Qt::Orientations exp;
8740 if (layout) {
8741 if (layout->hasHeightForWidth())
8742 s.setHeight(layout->totalHeightForWidth(w: s.width()));
8743 exp = layout->expandingDirections();
8744 } else
8745 {
8746 if (q->sizePolicy().hasHeightForWidth())
8747 s.setHeight(q->heightForWidth(s.width()));
8748 exp = q->sizePolicy().expandingDirections();
8749 }
8750 if (exp & Qt::Horizontal)
8751 s.setWidth(qMax(a: s.width(), b: 200));
8752 if (exp & Qt::Vertical)
8753 s.setHeight(qMax(a: s.height(), b: 100));
8754
8755 QRect screen;
8756 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(point: q->pos()))
8757 screen = screenAtPoint->geometry();
8758 else
8759 screen = QGuiApplication::primaryScreen()->geometry();
8760
8761 s.setWidth(qMin(a: s.width(), b: screen.width()*2/3));
8762 s.setHeight(qMin(a: s.height(), b: screen.height()*2/3));
8763
8764 if (QTLWExtra *extra = maybeTopData())
8765 extra->sizeAdjusted = true;
8766 }
8767
8768 if (!s.isValid()) {
8769 QRect r = q->childrenRect(); // get children rectangle
8770 if (r.isNull())
8771 return s;
8772 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8773 }
8774
8775 return s;
8776}
8777
8778/*!
8779 Adjusts the size of the widget to fit its contents.
8780
8781 This function uses sizeHint() if it is valid, i.e., the size hint's width
8782 and height are \>= 0. Otherwise, it sets the size to the children
8783 rectangle that covers all child widgets (the union of all child widget
8784 rectangles).
8785
8786 For windows, the screen size is also taken into account. If the sizeHint()
8787 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8788 {expanding}, the window will be at least (200, 100). The maximum size of
8789 a window is 2/3 of the screen's width and height.
8790
8791 \sa sizeHint(), childrenRect()
8792*/
8793
8794void QWidget::adjustSize()
8795{
8796 Q_D(QWidget);
8797 ensurePolished();
8798 QSize s = d->adjustedSize();
8799
8800 if (d->layout)
8801 d->layout->activate();
8802
8803 if (s.isValid())
8804 resize(s);
8805}
8806
8807
8808/*!
8809 \property QWidget::sizeHint
8810 \brief the recommended size for the widget
8811
8812 If the value of this property is an invalid size, no size is
8813 recommended.
8814
8815 The default implementation of sizeHint() returns an invalid size
8816 if there is no layout for this widget, and returns the layout's
8817 preferred size otherwise.
8818
8819 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8820 setMinimumSize(), updateGeometry()
8821*/
8822
8823QSize QWidget::sizeHint() const
8824{
8825 Q_D(const QWidget);
8826 if (d->layout)
8827 return d->layout->totalSizeHint();
8828 return QSize(-1, -1);
8829}
8830
8831/*!
8832 \property QWidget::minimumSizeHint
8833 \brief the recommended minimum size for the widget
8834
8835 If the value of this property is an invalid size, no minimum size
8836 is recommended.
8837
8838 The default implementation of minimumSizeHint() returns an invalid
8839 size if there is no layout for this widget, and returns the
8840 layout's minimum size otherwise. Most built-in widgets reimplement
8841 minimumSizeHint().
8842
8843 \l QLayout will never resize a widget to a size smaller than the
8844 minimum size hint unless minimumSize() is set or the size policy is
8845 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8846 size hint will be ignored.
8847
8848 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8849*/
8850QSize QWidget::minimumSizeHint() const
8851{
8852 Q_D(const QWidget);
8853 if (d->layout)
8854 return d->layout->totalMinimumSize();
8855 return QSize(-1, -1);
8856}
8857
8858
8859/*!
8860 \fn QWidget *QWidget::parentWidget() const
8861
8862 Returns the parent of this widget, or \nullptr if it does not have any
8863 parent widget.
8864*/
8865
8866
8867/*!
8868 Returns \c true if this widget is a parent, (or grandparent and so on
8869 to any level), of the given \a child, and both widgets are within
8870 the same window; otherwise returns \c false.
8871*/
8872
8873bool QWidget::isAncestorOf(const QWidget *child) const
8874{
8875 while (child) {
8876 if (child == this)
8877 return true;
8878 if (child->isWindow())
8879 return false;
8880 child = child->parentWidget();
8881 }
8882 return false;
8883}
8884
8885/*****************************************************************************
8886 QWidget event handling
8887 *****************************************************************************/
8888
8889/*!
8890 This is the main event handler; it handles event \a event. You can
8891 reimplement this function in a subclass, but we recommend using
8892 one of the specialized event handlers instead.
8893
8894 Key press and release events are treated differently from other
8895 events. event() checks for Tab and Shift+Tab and tries to move the
8896 focus appropriately. If there is no widget to move the focus to
8897 (or the key press is not Tab or Shift+Tab), event() calls
8898 keyPressEvent().
8899
8900 Mouse and tablet event handling is also slightly special: only
8901 when the widget is \l enabled, event() will call the specialized
8902 handlers such as mousePressEvent(); otherwise it will discard the
8903 event.
8904
8905 This function returns \c true if the event was recognized, otherwise
8906 it returns \c false. If the recognized event was accepted (see \l
8907 QEvent::accepted), any further processing such as event
8908 propagation to the parent widget stops.
8909
8910 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8911 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8912 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8913 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8914 QObject::event(), QObject::timerEvent()
8915*/
8916
8917bool QWidget::event(QEvent *event)
8918{
8919 Q_D(QWidget);
8920
8921 // ignore mouse and key events when disabled
8922 if (!isEnabled()) {
8923 switch(event->type()) {
8924 case QEvent::TabletPress:
8925 case QEvent::TabletRelease:
8926 case QEvent::TabletMove:
8927 case QEvent::MouseButtonPress:
8928 case QEvent::MouseButtonRelease:
8929 case QEvent::MouseButtonDblClick:
8930 case QEvent::MouseMove:
8931 case QEvent::TouchBegin:
8932 case QEvent::TouchUpdate:
8933 case QEvent::TouchEnd:
8934 case QEvent::TouchCancel:
8935 case QEvent::ContextMenu:
8936 case QEvent::KeyPress:
8937 case QEvent::KeyRelease:
8938#if QT_CONFIG(wheelevent)
8939 case QEvent::Wheel:
8940#endif
8941 return false;
8942 default:
8943 break;
8944 }
8945 }
8946 switch (event->type()) {
8947 case QEvent::PlatformSurface: {
8948 // Sync up QWidget's view of whether or not the widget has been created
8949 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8950 case QPlatformSurfaceEvent::SurfaceCreated:
8951 if (!testAttribute(attribute: Qt::WA_WState_Created))
8952 create();
8953 break;
8954 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8955 if (testAttribute(attribute: Qt::WA_WState_Created)) {
8956 // Child windows have already been destroyed by QWindow,
8957 // so we skip them here.
8958 destroy(destroyWindow: false, destroySubWindows: false);
8959 }
8960 break;
8961 }
8962 break;
8963 }
8964 case QEvent::MouseMove:
8965 mouseMoveEvent(event: (QMouseEvent*)event);
8966 break;
8967
8968 case QEvent::MouseButtonPress:
8969 mousePressEvent(event: (QMouseEvent*)event);
8970 break;
8971
8972 case QEvent::MouseButtonRelease:
8973 mouseReleaseEvent(event: (QMouseEvent*)event);
8974 break;
8975
8976 case QEvent::MouseButtonDblClick:
8977 mouseDoubleClickEvent(event: (QMouseEvent*)event);
8978 break;
8979#if QT_CONFIG(wheelevent)
8980 case QEvent::Wheel:
8981 wheelEvent(event: (QWheelEvent*)event);
8982 break;
8983#endif
8984#if QT_CONFIG(tabletevent)
8985 case QEvent::TabletMove:
8986 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(attribute: Qt::WA_TabletTracking))
8987 break;
8988 Q_FALLTHROUGH();
8989 case QEvent::TabletPress:
8990 case QEvent::TabletRelease:
8991 tabletEvent(event: (QTabletEvent*)event);
8992 break;
8993#endif
8994 case QEvent::KeyPress: {
8995 QKeyEvent *k = static_cast<QKeyEvent *>(event);
8996 bool res = false;
8997 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
8998 if (k->key() == Qt::Key_Backtab
8999 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9000 res = focusNextPrevChild(next: false);
9001 else if (k->key() == Qt::Key_Tab)
9002 res = focusNextPrevChild(next: true);
9003 if (res)
9004 break;
9005 }
9006 keyPressEvent(event: k);
9007#ifdef QT_KEYPAD_NAVIGATION
9008 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9009 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9010 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9011 if (k->key() == Qt::Key_Up)
9012 res = focusNextPrevChild(false);
9013 else if (k->key() == Qt::Key_Down)
9014 res = focusNextPrevChild(true);
9015 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9016 if (k->key() == Qt::Key_Up)
9017 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9018 else if (k->key() == Qt::Key_Right)
9019 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9020 else if (k->key() == Qt::Key_Down)
9021 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9022 else if (k->key() == Qt::Key_Left)
9023 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9024 }
9025 if (res) {
9026 k->accept();
9027 break;
9028 }
9029 }
9030#endif
9031#if QT_CONFIG(whatsthis)
9032 if (!k->isAccepted()
9033 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9034 && d->whatsThis.size()) {
9035 QWhatsThis::showText(pos: mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), text: d->whatsThis, w: this);
9036 k->accept();
9037 }
9038#endif
9039 }
9040 break;
9041
9042 case QEvent::KeyRelease:
9043 keyReleaseEvent(event: (QKeyEvent*)event);
9044 Q_FALLTHROUGH();
9045 case QEvent::ShortcutOverride:
9046 break;
9047
9048 case QEvent::InputMethod:
9049 inputMethodEvent((QInputMethodEvent *) event);
9050 break;
9051
9052 case QEvent::InputMethodQuery: {
9053 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9054 Qt::InputMethodQueries queries = query->queries();
9055 for (uint i = 0; i < 32; ++i) {
9056 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9057 if (q) {
9058 QVariant v = inputMethodQuery(q);
9059 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9060 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9061 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9062 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9063 // will only be set if the widget supports IM _and_ is not read-only. So for
9064 // read-only widgets, not all IM features will be supported when ImEnabled is
9065 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9066 v = QVariant(testAttribute(attribute: Qt::WA_InputMethodEnabled));
9067 }
9068 query->setValue(query: q, value: v);
9069 }
9070 }
9071 query->accept();
9072 }
9073 break;
9074
9075 case QEvent::PolishRequest:
9076 ensurePolished();
9077 break;
9078
9079 case QEvent::Polish: {
9080 style()->polish(widget: this);
9081 setAttribute(Qt::WA_WState_Polished);
9082 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9083 d->resolveFont();
9084 if (!QApplication::palette(this).isCopyOf(p: QGuiApplication::palette()))
9085 d->resolvePalette();
9086 }
9087 break;
9088
9089 case QEvent::ApplicationWindowIconChange:
9090 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon)) {
9091 d->setWindowIcon_sys();
9092 d->setWindowIcon_helper();
9093 }
9094 break;
9095 case QEvent::FocusIn:
9096 focusInEvent(event: (QFocusEvent*)event);
9097 d->updateWidgetTransform(event);
9098 break;
9099
9100 case QEvent::FocusOut:
9101 focusOutEvent(event: (QFocusEvent*)event);
9102 break;
9103
9104 case QEvent::Enter:
9105#if QT_CONFIG(statustip)
9106 if (d->statusTip.size()) {
9107 QStatusTipEvent tip(d->statusTip);
9108 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9109 }
9110#endif
9111 enterEvent(event: static_cast<QEnterEvent*>(event));
9112 break;
9113
9114 case QEvent::Leave:
9115#if QT_CONFIG(statustip)
9116 if (d->statusTip.size()) {
9117 QString empty;
9118 QStatusTipEvent tip(empty);
9119 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9120 }
9121#endif
9122 leaveEvent(event);
9123 break;
9124
9125 case QEvent::HoverEnter:
9126 case QEvent::HoverLeave:
9127 update();
9128 break;
9129
9130 case QEvent::Paint:
9131 // At this point the event has to be delivered, regardless
9132 // whether the widget isVisible() or not because it
9133 // already went through the filters
9134 paintEvent(event: (QPaintEvent*)event);
9135 break;
9136
9137 case QEvent::Move:
9138 moveEvent(event: (QMoveEvent*)event);
9139 d->updateWidgetTransform(event);
9140 break;
9141
9142 case QEvent::Resize:
9143 resizeEvent(event: (QResizeEvent*)event);
9144 d->updateWidgetTransform(event);
9145 break;
9146
9147 case QEvent::Close:
9148 closeEvent(event: (QCloseEvent *)event);
9149 break;
9150
9151#ifndef QT_NO_CONTEXTMENU
9152 case QEvent::ContextMenu:
9153 switch (data->context_menu_policy) {
9154 case Qt::PreventContextMenu:
9155 break;
9156 case Qt::DefaultContextMenu:
9157 contextMenuEvent(event: static_cast<QContextMenuEvent *>(event));
9158 break;
9159 case Qt::CustomContextMenu:
9160 emit customContextMenuRequested(pos: static_cast<QContextMenuEvent *>(event)->pos());
9161 break;
9162#if QT_CONFIG(menu)
9163 case Qt::ActionsContextMenu:
9164 if (d->actions.size()) {
9165 QMenu::exec(actions: d->actions, pos: static_cast<QContextMenuEvent *>(event)->globalPos(),
9166 at: nullptr, parent: this);
9167 break;
9168 }
9169 Q_FALLTHROUGH();
9170#endif
9171 default:
9172 event->ignore();
9173 break;
9174 }
9175 break;
9176#endif // QT_NO_CONTEXTMENU
9177
9178#if QT_CONFIG(draganddrop)
9179 case QEvent::Drop:
9180 dropEvent(event: (QDropEvent*) event);
9181 break;
9182
9183 case QEvent::DragEnter:
9184 dragEnterEvent(event: (QDragEnterEvent*) event);
9185 break;
9186
9187 case QEvent::DragMove:
9188 dragMoveEvent(event: (QDragMoveEvent*) event);
9189 break;
9190
9191 case QEvent::DragLeave:
9192 dragLeaveEvent(event: (QDragLeaveEvent*) event);
9193 break;
9194#endif
9195
9196 case QEvent::Show:
9197 showEvent(event: (QShowEvent*) event);
9198 break;
9199
9200 case QEvent::Hide:
9201 hideEvent(event: (QHideEvent*) event);
9202 break;
9203
9204 case QEvent::ShowWindowRequest:
9205 if (!isHidden())
9206 d->show_sys();
9207 break;
9208
9209 case QEvent::ApplicationFontChange:
9210 d->resolveFont();
9211 break;
9212 case QEvent::ApplicationPaletteChange:
9213 if (!(windowType() == Qt::Desktop))
9214 d->resolvePalette();
9215 break;
9216
9217 case QEvent::ToolBarChange:
9218 case QEvent::ActivationChange:
9219 case QEvent::EnabledChange:
9220 case QEvent::FontChange:
9221 case QEvent::StyleChange:
9222 case QEvent::PaletteChange:
9223 case QEvent::WindowTitleChange:
9224 case QEvent::IconTextChange:
9225 case QEvent::ModifiedChange:
9226 case QEvent::MouseTrackingChange:
9227 case QEvent::TabletTrackingChange:
9228 case QEvent::ParentChange:
9229 case QEvent::LocaleChange:
9230 case QEvent::MacSizeChange:
9231 case QEvent::ContentsRectChange:
9232 case QEvent::ThemeChange:
9233 case QEvent::ReadOnlyChange:
9234 changeEvent(event);
9235 break;
9236
9237 case QEvent::WindowStateChange: {
9238 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9239 if (wasMinimized != isMinimized()) {
9240 QWidget *widget = const_cast<QWidget *>(this);
9241 if (wasMinimized) {
9242 // Always send the spontaneous events here, otherwise it can break the application!
9243 if (!d->childrenShownByExpose) {
9244 // Show widgets only when they are not yet shown by the expose event
9245 d->showChildren(spontaneous: true);
9246 QShowEvent showEvent;
9247 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &showEvent);
9248 }
9249 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9250 } else {
9251 QHideEvent hideEvent;
9252 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &hideEvent);
9253 d->hideChildren(spontaneous: true);
9254 d->childrenHiddenByWState = true;
9255 }
9256 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9257 }
9258 changeEvent(event);
9259 }
9260 break;
9261
9262 case QEvent::WindowActivate:
9263 case QEvent::WindowDeactivate: {
9264 if (isVisible() && !palette().isEqual(cr1: QPalette::Active, cr2: QPalette::Inactive))
9265 update();
9266 QList<QObject*> childList = d->children;
9267 for (int i = 0; i < childList.size(); ++i) {
9268 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9269 if (w && w->isVisible() && !w->isWindow())
9270 QCoreApplication::sendEvent(receiver: w, event);
9271 }
9272 break; }
9273
9274 case QEvent::LanguageChange:
9275 changeEvent(event);
9276 {
9277 QList<QObject*> childList = d->children;
9278 for (int i = 0; i < childList.size(); ++i) {
9279 QObject *o = childList.at(i);
9280 if (o)
9281 QCoreApplication::sendEvent(receiver: o, event);
9282 }
9283 }
9284 update();
9285 break;
9286
9287 case QEvent::ApplicationLayoutDirectionChange:
9288 d->resolveLayoutDirection();
9289 break;
9290
9291 case QEvent::LayoutDirectionChange:
9292 if (d->layout)
9293 d->layout->invalidate();
9294 update();
9295 changeEvent(event);
9296 break;
9297 case QEvent::UpdateRequest:
9298 d->syncBackingStore();
9299 break;
9300 case QEvent::UpdateLater:
9301 update(static_cast<QUpdateLaterEvent*>(event)->region());
9302 break;
9303 case QEvent::StyleAnimationUpdate:
9304 if (isVisible() && !window()->isMinimized()) {
9305 event->accept();
9306 update();
9307 }
9308 break;
9309
9310 case QEvent::WindowBlocked:
9311 case QEvent::WindowUnblocked:
9312 if (!d->children.isEmpty()) {
9313 QWidget *modalWidget = QApplication::activeModalWidget();
9314 for (int i = 0; i < d->children.size(); ++i) {
9315 QObject *o = d->children.at(i);
9316 if (o && o != modalWidget && o->isWidgetType()) {
9317 QWidget *w = static_cast<QWidget *>(o);
9318 // do not forward the event to child windows; QApplication does this for us
9319 if (!w->isWindow())
9320 QCoreApplication::sendEvent(receiver: w, event);
9321 }
9322 }
9323 }
9324 break;
9325#if QT_CONFIG(tooltip)
9326 case QEvent::ToolTip:
9327 if (!d->toolTip.isEmpty())
9328 QToolTip::showText(pos: static_cast<QHelpEvent*>(event)->globalPos(), text: d->toolTip, w: this, rect: QRect(), msecShowTime: d->toolTipDuration);
9329 else
9330 event->ignore();
9331 break;
9332#endif
9333#if QT_CONFIG(whatsthis)
9334 case QEvent::WhatsThis:
9335 if (d->whatsThis.size())
9336 QWhatsThis::showText(pos: static_cast<QHelpEvent *>(event)->globalPos(), text: d->whatsThis, w: this);
9337 else
9338 event->ignore();
9339 break;
9340 case QEvent::QueryWhatsThis:
9341 if (d->whatsThis.isEmpty())
9342 event->ignore();
9343 break;
9344#endif
9345 case QEvent::EmbeddingControl:
9346 d->topData()->frameStrut.setCoords(xp1: 0 ,yp1: 0, xp2: 0, yp2: 0);
9347 data->fstrut_dirty = false;
9348 break;
9349#ifndef QT_NO_ACTION
9350 case QEvent::ActionAdded:
9351 case QEvent::ActionRemoved:
9352 case QEvent::ActionChanged:
9353 actionEvent(event: (QActionEvent*)event);
9354 break;
9355#endif
9356
9357 case QEvent::KeyboardLayoutChange:
9358 {
9359 changeEvent(event);
9360
9361 // inform children of the change
9362 QList<QObject*> childList = d->children;
9363 for (int i = 0; i < childList.size(); ++i) {
9364 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9365 if (w && w->isVisible() && !w->isWindow())
9366 QCoreApplication::sendEvent(receiver: w, event);
9367 }
9368 break;
9369 }
9370 case QEvent::TouchBegin:
9371 case QEvent::TouchUpdate:
9372 case QEvent::TouchEnd:
9373 case QEvent::TouchCancel:
9374 {
9375 event->ignore();
9376 break;
9377 }
9378#ifndef QT_NO_GESTURES
9379 case QEvent::Gesture:
9380 event->ignore();
9381 break;
9382#endif
9383 case QEvent::ScreenChangeInternal:
9384 if (const QTLWExtra *te = d->maybeTopData()) {
9385 const QWindow *win = te->window;
9386 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9387 }
9388 break;
9389 case QEvent::DevicePixelRatioChange:
9390 if (d->data.fnt.d->dpi != logicalDpiY())
9391 d->updateFont(font: d->data.fnt);
9392 d->renderToTextureReallyDirty = 1;
9393 break;
9394 case QEvent::DynamicPropertyChange: {
9395 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9396 if (propName.size() == 13 && !qstrncmp(str1: propName, str2: "_q_customDpi", len: 12)) {
9397 uint value = property(name: propName.constData()).toUInt();
9398 if (!d->extra)
9399 d->createExtra();
9400 const char axis = propName.at(i: 12);
9401 if (axis == 'X')
9402 d->extra->customDpiX = value;
9403 else if (axis == 'Y')
9404 d->extra->customDpiY = value;
9405 d->updateFont(font: d->data.fnt);
9406 }
9407 if (windowHandle() && !qstrncmp(str1: propName, str2: "_q_platform_", len: 12))
9408 windowHandle()->setProperty(name: propName, value: property(name: propName));
9409 Q_FALLTHROUGH();
9410 }
9411 default:
9412 return QObject::event(event);
9413 }
9414 return true;
9415}
9416
9417/*!
9418 This event handler can be reimplemented to handle state changes.
9419
9420 The state being changed in this event can be retrieved through the \a event
9421 supplied.
9422
9423 Change events include: QEvent::ToolBarChange,
9424 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9425 QEvent::StyleChange, QEvent::PaletteChange,
9426 QEvent::WindowTitleChange, QEvent::IconTextChange,
9427 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9428 QEvent::ParentChange, QEvent::WindowStateChange,
9429 QEvent::LanguageChange, QEvent::LocaleChange,
9430 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9431
9432*/
9433void QWidget::changeEvent(QEvent * event)
9434{
9435 switch(event->type()) {
9436 case QEvent::EnabledChange: {
9437 update();
9438#if QT_CONFIG(accessibility)
9439 QAccessible::State s;
9440 s.disabled = true;
9441 QAccessibleStateChangeEvent event(this, s);
9442 QAccessible::updateAccessibility(event: &event);
9443#endif
9444 break;
9445 }
9446
9447 case QEvent::FontChange:
9448 case QEvent::StyleChange: {
9449 Q_D(QWidget);
9450 update();
9451 updateGeometry();
9452 if (d->layout)
9453 d->layout->invalidate();
9454 break;
9455 }
9456
9457 case QEvent::PaletteChange:
9458 update();
9459 break;
9460
9461 case QEvent::ThemeChange:
9462 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9463 && qApp && !QCoreApplication::closingDown()) {
9464 if (testAttribute(attribute: Qt::WA_WState_Polished))
9465 QApplication::style()->unpolish(widget: this);
9466 if (testAttribute(attribute: Qt::WA_WState_Polished))
9467 QApplication::style()->polish(widget: this);
9468 QEvent styleChangedEvent(QEvent::StyleChange);
9469 QCoreApplication::sendEvent(receiver: this, event: &styleChangedEvent);
9470 if (isVisible())
9471 update();
9472 }
9473 break;
9474
9475#ifdef Q_OS_MAC
9476 case QEvent::MacSizeChange:
9477 updateGeometry();
9478 break;
9479#endif
9480
9481 default:
9482 break;
9483 }
9484}
9485
9486/*!
9487 This event handler, for event \a event, can be reimplemented in a
9488 subclass to receive mouse move events for the widget.
9489
9490 If mouse tracking is switched off, mouse move events only occur if
9491 a mouse button is pressed while the mouse is being moved. If mouse
9492 tracking is switched on, mouse move events occur even if no mouse
9493 button is pressed.
9494
9495 QMouseEvent::position() reports the position of the mouse cursor,
9496 relative to this widget. For press and release events, the
9497 position is usually the same as the position of the last mouse
9498 move event, but it might be different if the user's hand shakes.
9499 This is a feature of the underlying window system, not Qt.
9500
9501 If you want to show a tooltip immediately, while the mouse is
9502 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9503 and show them as a tooltip), you must first enable mouse tracking
9504 as described above. Then, to ensure that the tooltip is updated
9505 immediately, you must call QToolTip::showText() instead of
9506 setToolTip() in your implementation of mouseMoveEvent().
9507
9508 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9509 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9510*/
9511
9512void QWidget::mouseMoveEvent(QMouseEvent *event)
9513{
9514 event->ignore();
9515}
9516
9517/*!
9518 This event handler, for event \a event, can be reimplemented in a
9519 subclass to receive mouse press events for the widget.
9520
9521 If you create new widgets in the mousePressEvent() the
9522 mouseReleaseEvent() may not end up where you expect, depending on
9523 the underlying window system (or X11 window manager), the widgets'
9524 location and maybe more.
9525
9526 The default implementation implements the closing of popup widgets
9527 when you click outside the window. For other widget types it does
9528 nothing.
9529
9530 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9531 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9532*/
9533
9534void QWidget::mousePressEvent(QMouseEvent *event)
9535{
9536 event->ignore();
9537 if ((windowType() == Qt::Popup)) {
9538 event->accept();
9539 QWidget* w;
9540 while ((w = QApplication::activePopupWidget()) && w != this){
9541 w->close();
9542 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9543 w->hide(); // hide at least
9544 }
9545 if (!rect().contains(p: event->position().toPoint())){
9546 close();
9547 }
9548 }
9549}
9550
9551/*!
9552 This event handler, for event \a event, can be reimplemented in a
9553 subclass to receive mouse release events for the widget.
9554
9555 \sa mousePressEvent(), mouseDoubleClickEvent(),
9556 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9557*/
9558
9559void QWidget::mouseReleaseEvent(QMouseEvent *event)
9560{
9561 event->ignore();
9562}
9563
9564/*!
9565 This event handler, for event \a event, can be reimplemented in a
9566 subclass to receive mouse double click events for the widget.
9567
9568 The default implementation calls mousePressEvent().
9569
9570 \note The widget will also receive mouse press and mouse release
9571 events in addition to the double click event. And if another widget
9572 that overlaps this widget disappears in response to press or
9573 release events, then this widget will only receive the double click
9574 event. It is up to the developer to ensure that the application
9575 interprets these events correctly.
9576
9577 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9578 event(), QMouseEvent
9579*/
9580
9581void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9582{
9583 mousePressEvent(event);
9584}
9585
9586#if QT_CONFIG(wheelevent)
9587/*!
9588 This event handler, for event \a event, can be reimplemented in a
9589 subclass to receive wheel events for the widget.
9590
9591 If you reimplement this handler, it is very important that you
9592 \l{QEvent}{ignore()} the event if you do not handle
9593 it, so that the widget's parent can interpret it.
9594
9595 The default implementation ignores the event.
9596
9597 \sa QEvent::ignore(), QEvent::accept(), event(),
9598 QWheelEvent
9599*/
9600
9601void QWidget::wheelEvent(QWheelEvent *event)
9602{
9603 event->ignore();
9604}
9605#endif // QT_CONFIG(wheelevent)
9606
9607#if QT_CONFIG(tabletevent)
9608/*!
9609 This event handler, for event \a event, can be reimplemented in a
9610 subclass to receive tablet events for the widget.
9611
9612 If you reimplement this handler, it is very important that you
9613 \l{QEvent}{ignore()} the event if you do not handle
9614 it, so that the widget's parent can interpret it.
9615
9616 The default implementation ignores the event.
9617
9618 If tablet tracking is switched off, tablet move events only occur if the
9619 stylus is in contact with the tablet, or at least one stylus button is
9620 pressed, while the stylus is being moved. If tablet tracking is switched on,
9621 tablet move events occur even while the stylus is hovering in proximity of
9622 the tablet, with no buttons pressed.
9623
9624 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9625 QTabletEvent
9626*/
9627
9628void QWidget::tabletEvent(QTabletEvent *event)
9629{
9630 event->ignore();
9631}
9632#endif // QT_CONFIG(tabletevent)
9633
9634/*!
9635 This event handler, for event \a event, can be reimplemented in a
9636 subclass to receive key press events for the widget.
9637
9638 A widget must call setFocusPolicy() to accept focus initially and
9639 have focus in order to receive a key press event.
9640
9641 If you reimplement this handler, it is very important that you
9642 call the base class implementation if you do not act upon the key.
9643
9644 The default implementation closes popup widgets if the user
9645 presses the key sequence for QKeySequence::Cancel (typically the
9646 Escape key). Otherwise the event is ignored, so that the widget's
9647 parent can interpret it.
9648
9649 Note that QKeyEvent starts with isAccepted() == true, so you do not
9650 need to call QKeyEvent::accept() - just do not call the base class
9651 implementation if you act upon the key.
9652
9653 \sa keyReleaseEvent(), setFocusPolicy(),
9654 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9655*/
9656
9657void QWidget::keyPressEvent(QKeyEvent *event)
9658{
9659#ifndef QT_NO_SHORTCUT
9660 if ((windowType() == Qt::Popup) && event->matches(key: QKeySequence::Cancel)) {
9661 event->accept();
9662 close();
9663 } else
9664#endif
9665 {
9666 event->ignore();
9667 }
9668}
9669
9670/*!
9671 This event handler, for event \a event, can be reimplemented in a
9672 subclass to receive key release events for the widget.
9673
9674 A widget must \l{setFocusPolicy()}{accept focus}
9675 initially and \l{hasFocus()}{have focus} in order to
9676 receive a key release event.
9677
9678 If you reimplement this handler, it is very important that you
9679 call the base class implementation if you do not act upon the key.
9680
9681 The default implementation ignores the event, so that the widget's
9682 parent can interpret it.
9683
9684 Note that QKeyEvent starts with isAccepted() == true, so you do not
9685 need to call QKeyEvent::accept() - just do not call the base class
9686 implementation if you act upon the key.
9687
9688 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9689 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9690*/
9691
9692void QWidget::keyReleaseEvent(QKeyEvent *event)
9693{
9694 event->ignore();
9695}
9696
9697/*!
9698 \fn void QWidget::focusInEvent(QFocusEvent *event)
9699
9700 This event handler can be reimplemented in a subclass to receive
9701 keyboard focus events (focus received) for the widget. The event
9702 is passed in the \a event parameter
9703
9704 A widget normally must setFocusPolicy() to something other than
9705 Qt::NoFocus to receive focus events. (Note that the
9706 application programmer can call setFocus() on any widget, even
9707 those that do not normally accept focus.)
9708
9709 The default implementation updates the widget (except for windows
9710 that do not specify a focusPolicy()).
9711
9712 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9713 keyReleaseEvent(), event(), QFocusEvent
9714*/
9715
9716void QWidget::focusInEvent(QFocusEvent *)
9717{
9718 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9719 update();
9720 }
9721}
9722
9723/*!
9724 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9725
9726 This event handler can be reimplemented in a subclass to receive
9727 keyboard focus events (focus lost) for the widget. The events is
9728 passed in the \a event parameter.
9729
9730 A widget normally must setFocusPolicy() to something other than
9731 Qt::NoFocus to receive focus events. (Note that the
9732 application programmer can call setFocus() on any widget, even
9733 those that do not normally accept focus.)
9734
9735 The default implementation updates the widget (except for windows
9736 that do not specify a focusPolicy()).
9737
9738 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9739 keyReleaseEvent(), event(), QFocusEvent
9740*/
9741
9742void QWidget::focusOutEvent(QFocusEvent *)
9743{
9744 if (focusPolicy() != Qt::NoFocus || !isWindow())
9745 update();
9746
9747#if !defined(QT_PLATFORM_UIKIT)
9748 // FIXME: revisit autoSIP logic, QTBUG-42906
9749 if (qApp->autoSipEnabled() && testAttribute(attribute: Qt::WA_InputMethodEnabled))
9750 QGuiApplication::inputMethod()->hide();
9751#endif
9752}
9753
9754/*!
9755 \fn void QWidget::enterEvent(QEnterEvent *event)
9756
9757 This event handler can be reimplemented in a subclass to receive
9758 widget enter events which are passed in the \a event parameter.
9759
9760 An event is sent to the widget when the mouse cursor enters the
9761 widget.
9762
9763 \sa leaveEvent(), mouseMoveEvent(), event()
9764*/
9765
9766void QWidget::enterEvent(QEnterEvent *)
9767{
9768}
9769
9770/*!
9771 \fn void QWidget::leaveEvent(QEvent *event)
9772
9773 This event handler can be reimplemented in a subclass to receive
9774 widget leave events which are passed in the \a event parameter.
9775
9776 A leave event is sent to the widget when the mouse cursor leaves
9777 the widget.
9778
9779 \sa enterEvent(), mouseMoveEvent(), event()
9780*/
9781
9782void QWidget::leaveEvent(QEvent *)
9783{
9784}
9785
9786/*!
9787 \fn void QWidget::paintEvent(QPaintEvent *event)
9788
9789 This event handler can be reimplemented in a subclass to receive paint
9790 events passed in \a event.
9791
9792 A paint event is a request to repaint all or part of a widget. It can
9793 happen for one of the following reasons:
9794
9795 \list
9796 \li repaint() or update() was invoked,
9797 \li the widget was obscured and has now been uncovered, or
9798 \li many other reasons.
9799 \endlist
9800
9801 Many widgets can simply repaint their entire surface when asked to, but
9802 some slow widgets need to optimize by painting only the requested region:
9803 QPaintEvent::region(). This speed optimization does not change the result,
9804 as painting is clipped to that region during event processing. QListView
9805 and QTableView do this, for example.
9806
9807 Qt also tries to speed up painting by merging multiple paint events into
9808 one. When update() is called several times or the window system sends
9809 several paint events, Qt merges these events into one event with a larger
9810 region (see QRegion::united()). The repaint() function does not permit this
9811 optimization, so we suggest using update() whenever possible.
9812
9813 When the paint event occurs, the update region has normally been erased, so
9814 you are painting on the widget's background.
9815
9816 The background can be set using setBackgroundRole() and setPalette().
9817
9818 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9819 is no need to write double-buffering code in paintEvent() to avoid flicker.
9820
9821 \note Generally, you should refrain from calling update() or repaint()
9822 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9823 children inside a paintEvent() results in undefined behavior; the child may
9824 or may not get a paint event.
9825
9826 \warning If you are using a custom paint engine without Qt's backingstore,
9827 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9828 never be called; the backingstore will be used instead.
9829
9830 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9831 {Analog Clock}
9832*/
9833
9834void QWidget::paintEvent(QPaintEvent *)
9835{
9836}
9837
9838
9839/*!
9840 \fn void QWidget::moveEvent(QMoveEvent *event)
9841
9842 This event handler can be reimplemented in a subclass to receive
9843 widget move events which are passed in the \a event parameter.
9844 When the widget receives this event, it is already at the new
9845 position.
9846
9847 The old position is accessible through QMoveEvent::oldPos().
9848
9849 \sa resizeEvent(), event(), move(), QMoveEvent
9850*/
9851
9852void QWidget::moveEvent(QMoveEvent *)
9853{
9854}
9855
9856
9857/*!
9858 This event handler can be reimplemented in a subclass to receive
9859 widget resize events which are passed in the \a event parameter.
9860 When resizeEvent() is called, the widget already has its new
9861 geometry. The old size is accessible through
9862 QResizeEvent::oldSize().
9863
9864 The widget will be erased and receive a paint event immediately
9865 after processing the resize event. No drawing need be (or should
9866 be) done inside this handler.
9867
9868
9869 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9870 {Scribble Example}
9871*/
9872
9873void QWidget::resizeEvent(QResizeEvent * /* event */)
9874{
9875}
9876
9877#ifndef QT_NO_ACTION
9878/*!
9879 \fn void QWidget::actionEvent(QActionEvent *event)
9880
9881 This event handler is called with the given \a event whenever the
9882 widget's actions are changed.
9883
9884 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9885*/
9886void QWidget::actionEvent(QActionEvent *)
9887{
9888
9889}
9890#endif
9891
9892/*!
9893 This event handler is called with the given \a event when Qt receives a window
9894 close request for a top-level widget from the window system.
9895
9896 By default, the event is accepted and the widget is closed. You can reimplement
9897 this function to change the way the widget responds to window close requests.
9898 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9899 on all events.
9900
9901 Main window applications typically use reimplementations of this function to check
9902 whether the user's work has been saved and ask for permission before closing.
9903
9904 \sa event(), hide(), close(), QCloseEvent
9905*/
9906
9907void QWidget::closeEvent(QCloseEvent *event)
9908{
9909 event->accept();
9910}
9911
9912#ifndef QT_NO_CONTEXTMENU
9913/*!
9914 This event handler, for event \a event, can be reimplemented in a
9915 subclass to receive widget context menu events.
9916
9917 The handler is called when the widget's \l contextMenuPolicy is
9918 Qt::DefaultContextMenu.
9919
9920 The default implementation ignores the context event.
9921 See the \l QContextMenuEvent documentation for more details.
9922
9923 \sa event(), QContextMenuEvent, customContextMenuRequested()
9924*/
9925
9926void QWidget::contextMenuEvent(QContextMenuEvent *event)
9927{
9928 event->ignore();
9929}
9930#endif // QT_NO_CONTEXTMENU
9931
9932
9933/*!
9934 This event handler, for event \a event, can be reimplemented in a
9935 subclass to receive Input Method composition events. This handler
9936 is called when the state of the input method changes.
9937
9938 Note that when creating custom text editing widgets, the
9939 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9940 (using the setAttribute() function) in order to receive input
9941 method events.
9942
9943 The default implementation calls event->ignore(), which rejects the
9944 Input Method event. See the \l QInputMethodEvent documentation for more
9945 details.
9946
9947 \sa event(), QInputMethodEvent
9948*/
9949void QWidget::inputMethodEvent(QInputMethodEvent *event)
9950{
9951 event->ignore();
9952}
9953
9954/*!
9955 This method is only relevant for input widgets. It is used by the
9956 input method to query a set of properties of the widget to be
9957 able to support complex input method operations as support for
9958 surrounding text and reconversions.
9959
9960 \a query specifies which property is queried.
9961
9962 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9963*/
9964QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9965{
9966 switch(query) {
9967 case Qt::ImCursorRectangle:
9968 return QRect(width()/2, 0, 1, height());
9969 case Qt::ImFont:
9970 return font();
9971 case Qt::ImAnchorPosition:
9972 // Fallback.
9973 return inputMethodQuery(query: Qt::ImCursorPosition);
9974 case Qt::ImHints:
9975 return (int)inputMethodHints();
9976 case Qt::ImInputItemClipRectangle:
9977 return d_func()->clipRect();
9978 default:
9979 return QVariant();
9980 }
9981}
9982
9983/*!
9984 \property QWidget::inputMethodHints
9985 \brief What input method specific hints the widget has.
9986
9987 This is only relevant for input widgets. It is used by
9988 the input method to retrieve hints as to how the input method
9989 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9990 is set, the input method may change its visual components to reflect
9991 that only numbers can be entered.
9992
9993 \warning Some widgets require certain flags to work as
9994 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9995 instead of \c{w->setInputMethodHints(f)}.
9996
9997 \note The flags are only hints, so the particular input method
9998 implementation is free to ignore them. If you want to be
9999 sure that a certain type of characters are entered,
10000 you should also set a QValidator on the widget.
10001
10002 The default value is Qt::ImhNone.
10003
10004 \since 4.6
10005
10006 \sa inputMethodQuery()
10007*/
10008Qt::InputMethodHints QWidget::inputMethodHints() const
10009{
10010#if QT_CONFIG(im)
10011 const QWidgetPrivate *priv = d_func();
10012 while (priv->inheritsInputMethodHints) {
10013 priv = priv->q_func()->parentWidget()->d_func();
10014 Q_ASSERT(priv);
10015 }
10016 return priv->imHints;
10017#else
10018 return Qt::ImhNone;
10019#endif
10020}
10021
10022void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10023{
10024#ifndef QT_NO_IM
10025 Q_D(QWidget);
10026 if (d->imHints == hints)
10027 return;
10028 d->imHints = hints;
10029 if (this == QGuiApplication::focusObject())
10030 QGuiApplication::inputMethod()->update(queries: Qt::ImHints);
10031#else
10032 Q_UNUSED(hints);
10033#endif //QT_NO_IM
10034}
10035
10036
10037#if QT_CONFIG(draganddrop)
10038
10039/*!
10040 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10041
10042 This event handler is called when a drag is in progress and the
10043 mouse enters this widget. The event is passed in the \a event parameter.
10044
10045 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10046 move events}.
10047
10048 See the \l{dnd.html}{Drag-and-drop documentation} for an
10049 overview of how to provide drag-and-drop in your application.
10050
10051 \sa QDrag, QDragEnterEvent
10052*/
10053void QWidget::dragEnterEvent(QDragEnterEvent *)
10054{
10055}
10056
10057/*!
10058 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10059
10060 This event handler is called if a drag is in progress, and when
10061 any of the following conditions occur: the cursor enters this widget,
10062 the cursor moves within this widget, or a modifier key is pressed on
10063 the keyboard while this widget has the focus. The event is passed
10064 in the \a event parameter.
10065
10066 See the \l{dnd.html}{Drag-and-drop documentation} for an
10067 overview of how to provide drag-and-drop in your application.
10068
10069 \sa QDrag, QDragMoveEvent
10070*/
10071void QWidget::dragMoveEvent(QDragMoveEvent *)
10072{
10073}
10074
10075/*!
10076 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10077
10078 This event handler is called when a drag is in progress and the
10079 mouse leaves this widget. The event is passed in the \a event
10080 parameter.
10081
10082 See the \l{dnd.html}{Drag-and-drop documentation} for an
10083 overview of how to provide drag-and-drop in your application.
10084
10085 \sa QDrag, QDragLeaveEvent
10086*/
10087void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10088{
10089}
10090
10091/*!
10092 \fn void QWidget::dropEvent(QDropEvent *event)
10093
10094 This event handler is called when the drag is dropped on this
10095 widget. The event is passed in the \a event parameter.
10096
10097 See the \l{dnd.html}{Drag-and-drop documentation} for an
10098 overview of how to provide drag-and-drop in your application.
10099
10100 \sa QDrag, QDropEvent
10101*/
10102void QWidget::dropEvent(QDropEvent *)
10103{
10104}
10105
10106#endif // QT_CONFIG(draganddrop)
10107
10108/*!
10109 \fn void QWidget::showEvent(QShowEvent *event)
10110
10111 This event handler can be reimplemented in a subclass to receive
10112 widget show events which are passed in the \a event parameter.
10113
10114 Non-spontaneous show events are sent to widgets immediately
10115 before they are shown. The spontaneous show events of windows are
10116 delivered afterwards.
10117
10118 Note: A widget receives spontaneous show and hide events when its
10119 mapping status is changed by the window system, e.g. a spontaneous
10120 hide event when the user minimizes the window, and a spontaneous
10121 show event when the window is restored again. After receiving a
10122 spontaneous hide event, a widget is still considered visible in
10123 the sense of isVisible().
10124
10125 \sa visible, event(), QShowEvent
10126*/
10127void QWidget::showEvent(QShowEvent *)
10128{
10129}
10130
10131/*!
10132 \fn void QWidget::hideEvent(QHideEvent *event)
10133
10134 This event handler can be reimplemented in a subclass to receive
10135 widget hide events. The event is passed in the \a event parameter.
10136
10137 Hide events are sent to widgets immediately after they have been
10138 hidden.
10139
10140 Note: A widget receives spontaneous show and hide events when its
10141 mapping status is changed by the window system, e.g. a spontaneous
10142 hide event when the user minimizes the window, and a spontaneous
10143 show event when the window is restored again. After receiving a
10144 spontaneous hide event, a widget is still considered visible in
10145 the sense of isVisible().
10146
10147 \sa visible, event(), QHideEvent
10148*/
10149void QWidget::hideEvent(QHideEvent *)
10150{
10151}
10152
10153/*!
10154 This special event handler can be reimplemented in a subclass to
10155 receive native platform events identified by \a eventType
10156 which are passed in the \a message parameter.
10157
10158 In your reimplementation of this function, if you want to stop the
10159 event being handled by Qt, return true and set \a result. The \a result
10160 parameter has meaning only on Windows. If you return false, this native
10161 event is passed back to Qt, which translates the event into a Qt event
10162 and sends it to the widget.
10163
10164 \note Events are only delivered to this event handler if the widget
10165 has a native window handle.
10166
10167 \note This function superseedes the event filter functions
10168 x11Event(), winEvent() and macEvent() of Qt 4.
10169
10170 \sa QAbstractNativeEventFilter
10171
10172 \table
10173 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10174 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10175 \row \li macOS \li "NSEvent" \li NSEvent * \li
10176 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10177 \endtable
10178*/
10179
10180bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10181{
10182 Q_UNUSED(eventType);
10183 Q_UNUSED(message);
10184 Q_UNUSED(result);
10185 return false;
10186}
10187
10188/*!
10189 Ensures that the widget and its children have been polished by
10190 QStyle (i.e., have a proper font and palette).
10191
10192 QWidget calls this function after it has been fully constructed
10193 but before it is shown the very first time. You can call this
10194 function if you want to ensure that the widget is polished before
10195 doing an operation, e.g., the correct font size might be needed in
10196 the widget's sizeHint() reimplementation. Note that this function
10197 \e is called from the default implementation of sizeHint().
10198
10199 Polishing is useful for final initialization that must happen after
10200 all constructors (from base classes as well as from subclasses)
10201 have been called.
10202
10203 If you need to change some settings when a widget is polished,
10204 reimplement event() and handle the QEvent::Polish event type.
10205
10206 \b{Note:} The function is declared const so that it can be called from
10207 other const functions (e.g., sizeHint()).
10208
10209 \sa event()
10210*/
10211void QWidget::ensurePolished() const
10212{
10213 Q_D(const QWidget);
10214
10215 const QMetaObject *m = metaObject();
10216 if (m == d->polished)
10217 return;
10218 d->polished = m;
10219
10220 QEvent e(QEvent::Polish);
10221 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &e);
10222
10223 // polish children after 'this'
10224 QList<QObject*> children = d->children;
10225 for (int i = 0; i < children.size(); ++i) {
10226 QObject *o = children.at(i);
10227 if (!o->isWidgetType())
10228 continue;
10229 if (QWidget *w = qobject_cast<QWidget *>(o))
10230 w->ensurePolished();
10231 }
10232
10233 if (d->parent && d->sendChildEvents) {
10234 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10235 QCoreApplication::sendEvent(receiver: d->parent, event: &e);
10236 }
10237}
10238
10239/*!
10240 Returns the mask currently set on a widget. If no mask is set the
10241 return value will be an empty region.
10242
10243 \sa setMask(), clearMask(), QRegion::isEmpty()
10244*/
10245QRegion QWidget::mask() const
10246{
10247 Q_D(const QWidget);
10248 return d->extra ? d->extra->mask : QRegion();
10249}
10250
10251/*!
10252 Returns the layout manager that is installed on this widget, or \nullptr
10253 if no layout manager is installed.
10254
10255 The layout manager sets the geometry of the widget's children
10256 that have been added to the layout.
10257
10258 \sa setLayout(), sizePolicy(), {Layout Management}
10259*/
10260QLayout *QWidget::layout() const
10261{
10262 return d_func()->layout;
10263}
10264
10265
10266/*!
10267 \fn void QWidget::setLayout(QLayout *layout)
10268
10269 Sets the layout manager for this widget to \a layout.
10270
10271 If there already is a layout manager installed on this widget,
10272 QWidget won't let you install another. You must first delete the
10273 existing layout manager (returned by layout()) before you can
10274 call setLayout() with the new layout.
10275
10276 If \a layout is the layout manager on a different widget, setLayout()
10277 will reparent the layout and make it the layout manager for this widget.
10278
10279 Example:
10280
10281 \snippet layouts/layouts.cpp 24
10282
10283 An alternative to calling this function is to pass this widget to
10284 the layout's constructor.
10285
10286 The QWidget will take ownership of \a layout.
10287
10288 \sa layout(), {Layout Management}
10289*/
10290
10291void QWidget::setLayout(QLayout *l)
10292{
10293 if (Q_UNLIKELY(!l)) {
10294 qWarning(msg: "QWidget::setLayout: Cannot set layout to 0");
10295 return;
10296 }
10297 if (layout()) {
10298 if (Q_UNLIKELY(layout() != l))
10299 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10300 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10301 objectName().toLocal8Bit().data());
10302 return;
10303 }
10304
10305 QObject *oldParent = l->parent();
10306 if (oldParent && oldParent != this) {
10307 if (oldParent->isWidgetType()) {
10308 // Steal the layout off a widget parent. Takes effect when
10309 // morphing laid-out container widgets in Designer.
10310 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10311 oldParentWidget->takeLayout();
10312 } else {
10313 qWarning(msg: "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10314 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10315 objectName().toLocal8Bit().data());
10316 return;
10317 }
10318 }
10319
10320 Q_D(QWidget);
10321 l->d_func()->topLevel = true;
10322 d->layout = l;
10323 if (oldParent != this) {
10324 l->setParent(this);
10325 l->d_func()->reparentChildWidgets(mw: this);
10326 l->invalidate();
10327 }
10328
10329 if (isWindow() && d->maybeTopData())
10330 d->topData()->sizeAdjusted = false;
10331}
10332
10333/*!
10334 \fn QLayout *QWidget::takeLayout()
10335
10336 Remove the layout from the widget.
10337 \since 4.5
10338*/
10339
10340QLayout *QWidget::takeLayout()
10341{
10342 Q_D(QWidget);
10343 QLayout *l = layout();
10344 if (!l)
10345 return nullptr;
10346 d->layout = nullptr;
10347 l->setParent(nullptr);
10348 return l;
10349}
10350
10351/*!
10352 \property QWidget::sizePolicy
10353 \brief the default layout behavior of the widget
10354
10355 If there is a QLayout that manages this widget's children, the
10356 size policy specified by that layout is used. If there is no such
10357 QLayout, the result of this function is used.
10358
10359 The default policy is Preferred/Preferred, which means that the
10360 widget can be freely resized, but prefers to be the size
10361 sizeHint() returns. Button-like widgets set the size policy to
10362 specify that they may stretch horizontally, but are fixed
10363 vertically. The same applies to lineedit controls (such as
10364 QLineEdit, QSpinBox or an editable QComboBox) and other
10365 horizontally orientated widgets (such as QProgressBar).
10366 QToolButton's are normally square, so they allow growth in both
10367 directions. Widgets that support different directions (such as
10368 QSlider, QScrollBar or QHeader) specify stretching in the
10369 respective direction only. Widgets that can provide scroll bars
10370 (usually subclasses of QScrollArea) tend to specify that they can
10371 use additional space, and that they can make do with less than
10372 sizeHint().
10373
10374 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10375*/
10376QSizePolicy QWidget::sizePolicy() const
10377{
10378 Q_D(const QWidget);
10379 return d->size_policy;
10380}
10381
10382void QWidget::setSizePolicy(QSizePolicy policy)
10383{
10384 Q_D(QWidget);
10385 setAttribute(Qt::WA_WState_OwnSizePolicy);
10386 if (policy == d->size_policy)
10387 return;
10388
10389 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10390 d->retainSizeWhenHiddenChanged = 1;
10391
10392 d->size_policy = policy;
10393
10394#if QT_CONFIG(graphicsview)
10395 if (const auto &extra = d->extra) {
10396 if (extra->proxyWidget)
10397 extra->proxyWidget->setSizePolicy(policy);
10398 }
10399#endif
10400
10401 updateGeometry();
10402 d->retainSizeWhenHiddenChanged = 0;
10403
10404 if (isWindow() && d->maybeTopData())
10405 d->topData()->sizeAdjusted = false;
10406}
10407
10408/*!
10409 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10410 \overload
10411
10412 Sets the size policy of the widget to \a horizontal and \a
10413 vertical, with standard stretch and no height-for-width.
10414
10415 \sa QSizePolicy::QSizePolicy()
10416*/
10417
10418/*!
10419 Returns the preferred height for this widget, given the width \a w.
10420
10421 If this widget has a layout, the default implementation returns
10422 the layout's preferred height. if there is no layout, the default
10423 implementation returns -1 indicating that the preferred height
10424 does not depend on the width.
10425*/
10426
10427int QWidget::heightForWidth(int w) const
10428{
10429 if (layout() && layout()->hasHeightForWidth())
10430 return layout()->totalHeightForWidth(w);
10431 return -1;
10432}
10433
10434
10435/*!
10436 \since 5.0
10437
10438 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10439*/
10440bool QWidget::hasHeightForWidth() const
10441{
10442 Q_D(const QWidget);
10443 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10444}
10445
10446/*!
10447 \fn QWidget *QWidget::childAt(int x, int y) const
10448
10449 Returns the visible child widget at the position (\a{x}, \a{y})
10450 in the widget's coordinate system. If there is no visible child
10451 widget at the specified position, the function returns \nullptr.
10452*/
10453
10454/*!
10455 \overload
10456
10457 Returns the visible child widget at point \a p in the widget's own
10458 coordinate system.
10459*/
10460
10461QWidget *QWidget::childAt(const QPoint &p) const
10462{
10463 return d_func()->childAt_helper(QPointF(p), false);
10464}
10465
10466/*!
10467 \overload
10468 \since 6.8
10469
10470 Returns the visible child widget at point \a p in the widget's own
10471 coordinate system.
10472*/
10473
10474QWidget *QWidget::childAt(const QPointF &p) const
10475{
10476 return d_func()->childAt_helper(p, false);
10477}
10478
10479QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10480{
10481 if (children.isEmpty())
10482 return nullptr;
10483
10484 if (!pointInsideRectAndMask(p))
10485 return nullptr;
10486 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10487}
10488
10489QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10490{
10491 for (int i = children.size() - 1; i >= 0; --i) {
10492 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
10493 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(attribute: Qt::WA_TransparentForMouseEvents)
10494 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10495 continue;
10496 }
10497
10498 // Map the point 'p' from parent coordinates to child coordinates.
10499 QPointF childPoint = p;
10500 childPoint -= child->data->crect.topLeft();
10501
10502 // Check if the point hits the child.
10503 if (!child->d_func()->pointInsideRectAndMask(p: childPoint))
10504 continue;
10505
10506 // Do the same for the child's descendants.
10507 if (QWidget *w = child->d_func()->childAtRecursiveHelper(p: childPoint, ignoreChildrenInDestructor))
10508 return w;
10509
10510 // We have found our target; namely the child at position 'p'.
10511 return child;
10512 }
10513 return nullptr;
10514}
10515
10516void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10517{
10518 Q_Q(QWidget);
10519 if (widgetItem)
10520 widgetItem->invalidateSizeCache();
10521 QWidget *parent;
10522 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10523 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10524
10525 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10526 if (parent->d_func()->layout)
10527 parent->d_func()->layout->invalidate();
10528 else if (parent->isVisible())
10529 QCoreApplication::postEvent(receiver: parent, event: new QEvent(QEvent::LayoutRequest));
10530 }
10531 }
10532}
10533
10534/*!
10535 Notifies the layout system that this widget has changed and may
10536 need to change geometry.
10537
10538 Call this function if the sizeHint() or sizePolicy() have changed.
10539
10540 For explicitly hidden widgets, updateGeometry() is a no-op. The
10541 layout system will be notified as soon as the widget is shown.
10542*/
10543
10544void QWidget::updateGeometry()
10545{
10546 Q_D(QWidget);
10547 d->updateGeometry_helper(forceUpdate: false);
10548}
10549
10550/*! \property QWidget::windowFlags
10551
10552 Window flags are a combination of a type (e.g. Qt::Dialog) and
10553 zero or more hints to the window system (e.g.
10554 Qt::FramelessWindowHint).
10555
10556 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10557 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10558 0) on the desktop. If the widget is a window and becomes a
10559 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10560 relative to its parent widget.
10561
10562 \note This function calls setParent() when changing the flags for
10563 a window, causing the widget to be hidden. You must call show() to make
10564 the widget visible again..
10565
10566 \sa windowType(), setWindowFlag(), {Window Flags Example}
10567*/
10568void QWidget::setWindowFlags(Qt::WindowFlags flags)
10569{
10570 Q_D(QWidget);
10571 d->setWindowFlags(flags);
10572}
10573
10574/*!
10575 \since 5.9
10576
10577 Sets the window flag \a flag on this widget if \a on is true;
10578 otherwise clears the flag.
10579
10580 \sa setWindowFlags(), windowFlags(), windowType()
10581*/
10582void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10583{
10584 Q_D(QWidget);
10585 if (on)
10586 d->setWindowFlags(data->window_flags | flag);
10587 else
10588 d->setWindowFlags(data->window_flags & ~flag);
10589}
10590
10591/*! \internal
10592
10593 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10594*/
10595void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10596{
10597 Q_Q(QWidget);
10598 if (q->data->window_flags == flags)
10599 return;
10600
10601 if ((q->data->window_flags | flags) & Qt::Window) {
10602 // the old type was a window and/or the new type is a window
10603 QPoint oldPos = q->pos();
10604 bool visible = q->isVisible();
10605 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10606 q->setParent(parent: q->parentWidget(), f: flags);
10607
10608 // if both types are windows or neither of them are, we restore
10609 // the old position
10610 if (!windowFlagChanged && (visible || q->testAttribute(attribute: Qt::WA_Moved)))
10611 q->move(p: oldPos);
10612 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10613 adjustQuitOnCloseAttribute();
10614 } else {
10615 q->data->window_flags = flags;
10616 }
10617}
10618
10619/*!
10620 Sets the window flags for the widget to \a flags,
10621 \e without telling the window system.
10622
10623 \warning Do not call this function unless you really know what
10624 you're doing.
10625
10626 \sa setWindowFlags()
10627*/
10628void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10629{
10630 data->window_flags = flags;
10631}
10632
10633/*!
10634 \fn Qt::WindowType QWidget::windowType() const
10635
10636 Returns the window type of this widget. This is identical to
10637 windowFlags() & Qt::WindowType_Mask.
10638
10639 \sa windowFlags
10640*/
10641
10642/*!
10643 Sets the parent of the widget to \a parent, and resets the window
10644 flags. The widget is moved to position (0, 0) in its new parent.
10645
10646 If the new parent widget is in a different window, the
10647 reparented widget and its children are appended to the end of the
10648 \l{setFocusPolicy()}{tab chain} of the new parent
10649 widget, in the same internal order as before. If one of the moved
10650 widgets had keyboard focus, setParent() calls clearFocus() for that
10651 widget.
10652
10653 If the new parent widget is in the same window as the
10654 old parent, setting the parent doesn't change the tab order or
10655 keyboard focus.
10656
10657 If the "new" parent widget is the old parent widget, this function
10658 does nothing.
10659
10660 \note The widget becomes invisible as part of changing its parent,
10661 even if it was previously visible. You must call show() to make the
10662 widget visible again.
10663
10664 \warning It is very unlikely that you will ever need this
10665 function. If you have a widget that changes its content
10666 dynamically, it is far easier to use \l QStackedWidget.
10667
10668 \sa setWindowFlags()
10669*/
10670void QWidget::setParent(QWidget *parent)
10671{
10672 if (parent == parentWidget())
10673 return;
10674 setParent(parent: (QWidget*)parent, f: windowFlags() & ~Qt::WindowType_Mask);
10675}
10676
10677void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10678{
10679 QWidgetPrivate *d = QWidgetPrivate::get(w: widget);
10680 if (d->renderToTexture) {
10681 QEvent e(eventType);
10682 QCoreApplication::sendEvent(receiver: widget, event: &e);
10683 }
10684
10685 for (int i = 0; i < d->children.size(); ++i) {
10686 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
10687 if (w && !w->isWindow())
10688 qSendWindowChangeToTextureChildrenRecursively(widget: w, eventType);
10689 }
10690
10691 // Notify QWidgetWindow after we've notified all child QWidgets
10692 if (auto *window = d->windowHandle(mode: QWidgetPrivate::WindowHandleMode::Direct)) {
10693 QEvent e(eventType);
10694 QCoreApplication::sendEvent(receiver: window, event: &e);
10695 }
10696}
10697
10698/*!
10699 \overload
10700
10701 This function also takes widget flags, \a f as an argument.
10702*/
10703
10704void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10705{
10706 Q_D(QWidget);
10707 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10708#ifdef QT_DEBUG
10709 const auto checkForParentChildLoops = qScopeGuard(f: [&](){
10710 int depth = 0;
10711 auto p = parentWidget();
10712 while (p) {
10713 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10714 qWarning(msg: "QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10715 "this is undefined behavior",
10716 this, metaObject()->className(), qPrintable(objectName()));
10717 }
10718 p = p->parentWidget();
10719 }
10720 });
10721#endif
10722
10723 const bool resized = testAttribute(attribute: Qt::WA_Resized);
10724 const bool wasCreated = testAttribute(attribute: Qt::WA_WState_Created);
10725 QWidget *oldtlw = window();
10726 Q_ASSERT(oldtlw);
10727 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10728
10729 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10730 d->data.fstrut_dirty = true;
10731
10732 QWidget *desktopWidget = nullptr;
10733 if (parent && parent->windowType() == Qt::Desktop)
10734 desktopWidget = parent;
10735 bool newParent = (parent != parentWidget()) || desktopWidget;
10736
10737 if (newParent && parent && !desktopWidget) {
10738 if (testAttribute(attribute: Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings))
10739 parent->d_func()->enforceNativeChildren();
10740 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(attribute: Qt::WA_PaintOnScreen))
10741 setAttribute(Qt::WA_NativeWindow);
10742 }
10743
10744 if (wasCreated) {
10745 if (!testAttribute(attribute: Qt::WA_WState_Hidden)) {
10746 // Hiding the widget will set WA_WState_Hidden as well, which would
10747 // normally require the widget to be explicitly shown again to become
10748 // visible, even as a child widget. But we refine this value later in
10749 // setParent_sys(), applying WA_WState_Hidden based on whether the
10750 // widget is a top level or not.
10751 hide();
10752
10753 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10754 // when we only had QWidget::setVisible(), which is treated as an
10755 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10756 // that allows us to hide a widget without affecting ExplicitShowHide.
10757 // Though it can be argued that ExplicitShowHide should reflect the
10758 // last update of the widget's state, so if we hide the widget as a
10759 // side effect of changing parent, perhaps we _should_ reset it?
10760 setAttribute(Qt::WA_WState_ExplicitShowHide, on: false);
10761 }
10762 if (newParent) {
10763 QEvent e(QEvent::ParentAboutToChange);
10764 QCoreApplication::sendEvent(receiver: this, event: &e);
10765 }
10766 }
10767
10768 // texture-based widgets need a pre-notification when their associated top-level window changes
10769 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10770 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10771 : oldtlw->d_func()->usesRhiFlush;
10772 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10773 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowAboutToChangeInternal);
10774
10775 // If we get parented into another window, children will be folded
10776 // into the new parent's focus chain, so clear focus now.
10777 if (newParent && isAncestorOf(child: focusWidget()) && !(f & Qt::Window))
10778 focusWidget()->clearFocus();
10779
10780 d->setParent_sys(parent, f);
10781
10782 if (desktopWidget)
10783 parent = nullptr;
10784
10785 if (d->textureChildSeen && parent) {
10786 // set the textureChildSeen flag up the whole parent chain
10787 QWidgetPrivate::get(w: parent)->setTextureChildSeen();
10788 }
10789
10790 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10791 if (newParent)
10792 oldPaintManager->removeDirtyWidget(w: this);
10793 // Move the widget and all its static children from
10794 // the old backing store to the new one.
10795 oldPaintManager->moveStaticWidgets(reparented: this);
10796 }
10797
10798 d->reparentFocusWidgets(oldtlw);
10799 setAttribute(Qt::WA_Resized, on: resized);
10800
10801 const bool useStyleSheetPropagationInWidgetStyles =
10802 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10803
10804 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(attribute: Qt::WA_StyleSheet)
10805 && (!parent || !parent->testAttribute(attribute: Qt::WA_StyleSheet))) {
10806 // if the parent has a font set or inherited, then propagate the mask to the new child
10807 if (parent) {
10808 const auto pd = parent->d_func();
10809 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10810 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10811 }
10812 d->resolveFont();
10813 d->resolvePalette();
10814 }
10815 d->resolveLayoutDirection();
10816 d->resolveLocale();
10817
10818 // Note: GL widgets under WGL or EGL will always need a ParentChange
10819 // event to handle recreation/rebinding of the GL context, hence the
10820 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10821 // platforms).
10822 if (newParent || !wasCreated
10823#if QT_CONFIG(opengles2)
10824 || (f & Qt::MSWindowsOwnDC)
10825#endif
10826 ) {
10827 // propagate enabled updates enabled state to non-windows
10828 if (!isWindow()) {
10829 if (!testAttribute(attribute: Qt::WA_ForceDisabled))
10830 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10831 if (!testAttribute(attribute: Qt::WA_ForceUpdatesDisabled))
10832 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10833 }
10834 d->inheritStyle();
10835
10836 // send and post remaining QObject events
10837 if (parent && d->sendChildEvents) {
10838 QChildEvent e(QEvent::ChildAdded, this);
10839 QCoreApplication::sendEvent(receiver: parent, event: &e);
10840 }
10841
10842 if (parent && d->sendChildEvents && d->polished) {
10843 QChildEvent e(QEvent::ChildPolished, this);
10844 QCoreApplication::sendEvent(receiver: parent, event: &e);
10845 }
10846
10847 QEvent e(QEvent::ParentChange);
10848 QCoreApplication::sendEvent(receiver: this, event: &e);
10849 }
10850
10851 // texture-based widgets need another event when their top-level window
10852 // changes (more precisely, has already changed at this point)
10853 if (oldWidgetUsesRhiFlush && oldtlw != window())
10854 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowChangeInternal);
10855
10856 if (!wasCreated) {
10857 if (isWindow() || parentWidget()->isVisible())
10858 setAttribute(Qt::WA_WState_Hidden, on: true);
10859 else if (!testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
10860 setAttribute(Qt::WA_WState_Hidden, on: false);
10861 }
10862
10863 d->updateIsOpaque();
10864
10865#if QT_CONFIG(graphicsview)
10866 // Embed the widget into a proxy if the parent is embedded.
10867 // ### Doesn't handle reparenting out of an embedded widget.
10868 if (oldtlw->graphicsProxyWidget()) {
10869 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: oldtlw))
10870 ancestorProxy->d_func()->unembedSubWindow(this);
10871 }
10872 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(p: this)) {
10873 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: parent))
10874 ancestorProxy->d_func()->embedSubWindow(this);
10875 }
10876#endif
10877
10878 if (d->extra && d->extra->hasWindowContainer)
10879 QWindowContainer::parentWasChanged(parent: this);
10880
10881 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10882 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10883 // Check if the native parent now needs to switch to RHI
10884 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10885 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10886
10887 QPlatformBackingStoreRhiConfig rhiConfig;
10888 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10889
10890 // First evaluate whether the reparented widget uses RHI.
10891 // We do this as a separate step because the performance
10892 // implications of always checking the native parent are
10893 // problematic when it comes to large widget trees.
10894 if (q_evaluateRhiConfig(w: this, outConfig: &rhiConfig, outType: &surfaceType)) {
10895 // Then check whether the native parent requires RHI
10896 // as a result. It may not, if this widget is a native
10897 // window, and can handle its own RHI flushing.
10898 if (q_evaluateRhiConfig(w: newParentWithWindow, outConfig: nullptr, outType: nullptr)) {
10899 // Finally, check whether we need to recreate the
10900 // native parent to enable RHI flushing.
10901 auto *existingWindow = newParentWithWindow->windowHandle();
10902 auto existingSurfaceType = existingWindow->surfaceType();
10903 if (existingSurfaceType != surfaceType) {
10904 qCDebug(lcWidgetPainting)
10905 << "Recreating" << existingWindow
10906 << "with current type" << existingSurfaceType
10907 << "to support" << surfaceType;
10908 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10909 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10910 const auto positionBeforeDestroy = newParentWithWindow->pos();
10911 newParentWithWindow->destroy();
10912 newParentWithWindow->create();
10913 Q_ASSERT(newParentWithWindow->windowHandle());
10914 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10915 newParentWithWindow->move(p: positionBeforeDestroy);
10916 QWidgetPrivate::get(w: newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10917 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10918 // If we don't recreate we still need to make sure the native parent
10919 // widget has a RHI config that the reparented widget can use.
10920 backingStore->handle()->createRhi(window: existingWindow, config: rhiConfig);
10921 // And that it knows it's now flushing with RHI
10922 QWidgetPrivate::get(w: newParentWithWindow)->usesRhiFlush = true;
10923 }
10924 }
10925 }
10926 }
10927}
10928
10929void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10930{
10931 Q_Q(QWidget);
10932
10933 Qt::WindowFlags oldFlags = data.window_flags;
10934 bool wasCreated = q->testAttribute(attribute: Qt::WA_WState_Created);
10935
10936 QScreen *targetScreen = nullptr;
10937 // Handle a request to move the widget to a particular screen
10938 if (newparent && newparent->windowType() == Qt::Desktop) {
10939 // make sure the widget is created on the same screen as the
10940 // programmer specified desktop widget
10941 targetScreen = newparent->screen();
10942 newparent = nullptr;
10943 }
10944
10945 setWinId(0);
10946
10947 if (!newparent) {
10948 f |= Qt::Window;
10949 if (parent)
10950 targetScreen = q->parentWidget()->window()->screen();
10951 }
10952
10953 const bool destroyWindow = (
10954 // Reparenting top level to child
10955 (oldFlags & Qt::Window) && !(f & Qt::Window)
10956 // And we can dispose of the window
10957 && wasCreated && !q->testAttribute(attribute: Qt::WA_NativeWindow)
10958 );
10959
10960 if (parent != newparent) {
10961 // Update object parent now, so we can resolve new parent window below
10962 QObjectPrivate::setParent_helper(newparent);
10963
10964 if (q->windowHandle())
10965 q->windowHandle()->setFlags(f);
10966
10967 // If the widget itself or any of its children have been created,
10968 // we need to reparent their QWindows as well.
10969 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10970 // But if the widget is about to be destroyed we must skip the
10971 // widget itself, and only reparent children.
10972 if (destroyWindow) {
10973 reparentWidgetWindowChildren(parentWithWindow);
10974 } else {
10975 // During reparentWidgetWindows() we need to know whether the reparented
10976 // QWindow should be a top level (with a transient parent) or not. This
10977 // widget has not updated its window flags yet, so we can't ask the widget
10978 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10979 // the QWindow flags always reflect Qt::Window, even for child windows. And
10980 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10981 // which we are in the process of updating. So we propagate the
10982 // new flags of the reparented window here.
10983 reparentWidgetWindows(parentWithWindow, windowFlags: f);
10984 }
10985 }
10986
10987 bool explicitlyHidden = isExplicitlyHidden();
10988
10989 if (destroyWindow) {
10990 if (extra && extra->hasWindowContainer)
10991 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
10992
10993 // There shouldn't be any QWindow children left, but if there
10994 // are, re-parent them now, before we destroy.
10995 if (!q->windowHandle()->children().isEmpty()) {
10996 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10997 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
10998 for (QObject *child : q->windowHandle()->children()) {
10999 if (QWindow *childWindow = qobject_cast<QWindow *>(o: child)) {
11000 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11001 << "before destroying" << this;
11002 childWindow->setParent(newParentWindow);
11003 }
11004 }
11005 }
11006
11007 // We have reparented any child windows of the widget we are
11008 // about to destroy to the new parent window handle, so we can
11009 // safely destroy this widget without destroying sub windows.
11010 q->destroy(destroyWindow: true, destroySubWindows: false);
11011 }
11012
11013 adjustFlags(flags&: f, w: q);
11014 data.window_flags = f;
11015 q->setAttribute(Qt::WA_WState_Created, on: false);
11016 q->setAttribute(Qt::WA_WState_Visible, on: false);
11017 q->setAttribute(Qt::WA_WState_Hidden, on: false);
11018
11019 if (newparent && wasCreated && (q->testAttribute(attribute: Qt::WA_NativeWindow) || (f & Qt::Window)))
11020 q->createWinId();
11021
11022 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11023 q->setAttribute(Qt::WA_WState_Hidden);
11024 q->setAttribute(Qt::WA_WState_ExplicitShowHide, on: explicitlyHidden);
11025
11026 // move the window to the selected screen
11027 if (!newparent && targetScreen) {
11028 // only if it is already created
11029 if (q->testAttribute(attribute: Qt::WA_WState_Created))
11030 q->windowHandle()->setScreen(targetScreen);
11031 else
11032 topData()->initialScreen = targetScreen;
11033 }
11034}
11035
11036void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11037{
11038 if (QWindow *window = windowHandle()) {
11039 // Reparent this QWindow, and all QWindow children will follow
11040 if (parentWithWindow) {
11041 if (windowFlags & Qt::Window) {
11042 // Top level windows can only have transient parents,
11043 // and the transient parent must be another top level.
11044 QWidget *topLevel = parentWithWindow->window();
11045 auto *transientParent = topLevel->windowHandle();
11046 Q_ASSERT(transientParent);
11047 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11048 window->setTransientParent(transientParent);
11049 window->setParent(nullptr);
11050 } else {
11051 auto *parentWindow = parentWithWindow->windowHandle();
11052 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11053 window->setTransientParent(nullptr);
11054 window->setParent(parentWindow);
11055 }
11056 } else {
11057 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11058 window->setTransientParent(nullptr);
11059 window->setParent(nullptr);
11060 }
11061 } else {
11062 reparentWidgetWindowChildren(parentWithWindow);
11063 }
11064}
11065
11066void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11067{
11068 for (auto *child : std::as_const(t&: children)) {
11069 if (auto *childWidget = qobject_cast<QWidget*>(o: child)) {
11070 auto *childPrivate = QWidgetPrivate::get(w: childWidget);
11071 // Child widgets with QWindows should always continue to be child
11072 // windows, so we pass on the child's current window flags here.
11073 childPrivate->reparentWidgetWindows(parentWithWindow, windowFlags: childWidget->windowFlags());
11074 }
11075 }
11076}
11077
11078/*!
11079 Scrolls the widget including its children \a dx pixels to the
11080 right and \a dy downward. Both \a dx and \a dy may be negative.
11081
11082 After scrolling, the widgets will receive paint events for
11083 the areas that need to be repainted. For widgets that Qt knows to
11084 be opaque, this is only the newly exposed parts.
11085 For example, if an opaque widget is scrolled 8 pixels to the left,
11086 only an 8-pixel wide stripe at the right edge needs updating.
11087
11088 Since widgets propagate the contents of their parents by default,
11089 you need to set the \l autoFillBackground property, or use
11090 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11091 a widget opaque.
11092
11093 For widgets that use contents propagation, a scroll will cause an
11094 update of the entire scroll area.
11095
11096 \sa {Transparency and Double Buffering}
11097*/
11098
11099void QWidget::scroll(int dx, int dy)
11100{
11101 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11102 return;
11103 if (dx == 0 && dy == 0)
11104 return;
11105 Q_D(QWidget);
11106#if QT_CONFIG(graphicsview)
11107 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11108 // Graphics View maintains its own dirty region as a list of rects;
11109 // until we can connect item updates directly to the view, we must
11110 // separately add a translated dirty region.
11111 for (const QRect &rect : d->dirty)
11112 proxy->update(rect: rect.translated(dx, dy));
11113 proxy->scroll(dx, dy, rect: proxy->subWidgetRect(widget: this));
11114 return;
11115 }
11116#endif
11117 d->setDirtyOpaqueRegion();
11118 d->scroll_sys(dx, dy);
11119}
11120
11121void QWidgetPrivate::scroll_sys(int dx, int dy)
11122{
11123 Q_Q(QWidget);
11124 scrollChildren(dx, dy);
11125 scrollRect(q->rect(), dx, dy);
11126}
11127
11128/*!
11129 \overload
11130
11131 This version only scrolls \a r and does not move the children of
11132 the widget.
11133
11134 If \a r is empty or invalid, the result is undefined.
11135
11136 \sa QScrollArea
11137*/
11138void QWidget::scroll(int dx, int dy, const QRect &r)
11139{
11140
11141 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11142 return;
11143 if (dx == 0 && dy == 0)
11144 return;
11145 Q_D(QWidget);
11146#if QT_CONFIG(graphicsview)
11147 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11148 // Graphics View maintains its own dirty region as a list of rects;
11149 // until we can connect item updates directly to the view, we must
11150 // separately add a translated dirty region.
11151 if (!d->dirty.isEmpty()) {
11152 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11153 proxy->update(rect);
11154 }
11155 proxy->scroll(dx, dy, rect: r.translated(p: proxy->subWidgetRect(widget: this).topLeft().toPoint()));
11156 return;
11157 }
11158#endif
11159 d->scroll_sys(dx, dy, r);
11160}
11161
11162void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11163{
11164 scrollRect(r, dx, dy);
11165}
11166
11167/*!
11168 Repaints the widget directly by calling paintEvent() immediately,
11169 unless updates are disabled or the widget is hidden.
11170
11171 We suggest only using repaint() if you need an immediate repaint,
11172 for example during animation. In most circumstances update()
11173 is better, as it permits Qt to optimize for speed and minimize
11174 flicker.
11175
11176 \warning If you call repaint() in a function which may itself be
11177 called from paintEvent(), you may get infinite recursion. The
11178 update() function never causes recursion.
11179
11180 \sa update(), paintEvent(), setUpdatesEnabled()
11181*/
11182
11183void QWidget::repaint()
11184{
11185 repaint(rect());
11186}
11187
11188/*! \overload
11189
11190 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11191 the widget.
11192
11193 If \a w is negative, it is replaced with \c{width() - x}, and if
11194 \a h is negative, it is replaced width \c{height() - y}.
11195*/
11196void QWidget::repaint(int x, int y, int w, int h)
11197{
11198 if (x > data->crect.width() || y > data->crect.height())
11199 return;
11200
11201 if (w < 0)
11202 w = data->crect.width() - x;
11203 if (h < 0)
11204 h = data->crect.height() - y;
11205
11206 repaint(QRect(x, y, w, h));
11207}
11208
11209/*! \overload
11210
11211 This version repaints a rectangle \a rect inside the widget.
11212*/
11213void QWidget::repaint(const QRect &rect)
11214{
11215 Q_D(QWidget);
11216 d->repaint(r: rect);
11217}
11218
11219/*!
11220 \overload
11221
11222 This version repaints a region \a rgn inside the widget.
11223*/
11224void QWidget::repaint(const QRegion &rgn)
11225{
11226 Q_D(QWidget);
11227 d->repaint(r: rgn);
11228}
11229
11230template <typename T>
11231void QWidgetPrivate::repaint(T r)
11232{
11233 Q_Q(QWidget);
11234
11235 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11236 return;
11237
11238 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11239 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11240 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11241}
11242
11243/*!
11244 Updates the widget unless updates are disabled or the widget is
11245 hidden.
11246
11247 This function does not cause an immediate repaint; instead it
11248 schedules a paint event for processing when Qt returns to the main
11249 event loop. This permits Qt to optimize for more speed and less
11250 flicker than a call to repaint() does.
11251
11252 Calling update() several times normally results in just one
11253 paintEvent() call.
11254
11255 Qt normally erases the widget's area before the paintEvent() call.
11256 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11257 responsible for painting all its pixels with an opaque color.
11258
11259 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11260*/
11261void QWidget::update()
11262{
11263 update(rect());
11264}
11265
11266/*! \fn void QWidget::update(int x, int y, int w, int h)
11267 \overload
11268
11269 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11270 the widget.
11271*/
11272
11273/*!
11274 \overload
11275
11276 This version updates a rectangle \a rect inside the widget.
11277*/
11278void QWidget::update(const QRect &rect)
11279{
11280 Q_D(QWidget);
11281 d->update(r: rect);
11282}
11283
11284/*!
11285 \overload
11286
11287 This version repaints a region \a rgn inside the widget.
11288*/
11289void QWidget::update(const QRegion &rgn)
11290{
11291 Q_D(QWidget);
11292 d->update(r: rgn);
11293}
11294
11295template <typename T>
11296void QWidgetPrivate::update(T r)
11297{
11298 Q_Q(QWidget);
11299
11300 if (renderToTexture && !q->isVisible()) {
11301 renderToTextureReallyDirty = 1;
11302 return;
11303 }
11304
11305 if (!q->isVisible() || !q->updatesEnabled())
11306 return;
11307
11308 T clipped = r & q->rect();
11309
11310 if (clipped.isEmpty())
11311 return;
11312
11313 if (q->testAttribute(attribute: Qt::WA_WState_InPaintEvent)) {
11314 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(clipped));
11315 return;
11316 }
11317
11318 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11319 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11320 tlwExtra->repaintManager->markDirty(clipped, q);
11321}
11322
11323 /*!
11324 \internal
11325
11326 This just sets the corresponding attribute bit to 1 or 0
11327 */
11328static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11329 QWidgetPrivate *d)
11330{
11331 if (attribute < int(8*sizeof(uint))) {
11332 if (on)
11333 data->widget_attributes |= (1<<attribute);
11334 else
11335 data->widget_attributes &= ~(1<<attribute);
11336 } else {
11337 const int x = attribute - 8*sizeof(uint);
11338 const int int_off = x / (8*sizeof(uint));
11339 if (on)
11340 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11341 else
11342 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11343 }
11344}
11345
11346#ifdef Q_OS_MAC
11347void QWidgetPrivate::macUpdateSizeAttribute()
11348{
11349 Q_Q(QWidget);
11350 QEvent event(QEvent::MacSizeChange);
11351 QCoreApplication::sendEvent(q, &event);
11352 for (int i = 0; i < children.size(); ++i) {
11353 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11354 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11355 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11356 && !w->testAttribute(Qt::WA_MacSmallSize)
11357 && !w->testAttribute(Qt::WA_MacNormalSize))
11358 w->d_func()->macUpdateSizeAttribute();
11359 }
11360 resolveFont();
11361}
11362#endif
11363
11364/*!
11365 Sets the attribute \a attribute on this widget if \a on is true;
11366 otherwise clears the attribute.
11367
11368 \sa testAttribute()
11369*/
11370void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11371{
11372 Q_D(QWidget);
11373
11374 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11375 if (isWindow()) {
11376 auto *topExtra = d->topData();
11377 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11378 }
11379 }
11380
11381 if (testAttribute(attribute) == on)
11382 return;
11383
11384 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11385 "QWidget::setAttribute(WidgetAttribute, bool): "
11386 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11387#ifdef Q_OS_WIN
11388 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11389 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
11390 // see ::paintEngine for details
11391 paintEngine();
11392 if (d->noPaintOnScreen)
11393 return;
11394 }
11395#endif
11396
11397 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11398 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11399 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11400 if (!platformIntegration->hasCapability(cap: QPlatformIntegration::NativeWidgets))
11401 return;
11402 }
11403
11404 setAttribute_internal(attribute, on, data, d);
11405
11406 switch (attribute) {
11407
11408#if QT_CONFIG(draganddrop)
11409 case Qt::WA_AcceptDrops: {
11410 if (on && !testAttribute(attribute: Qt::WA_DropSiteRegistered))
11411 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: true);
11412 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered)))
11413 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: false);
11414 QEvent e(QEvent::AcceptDropsChange);
11415 QCoreApplication::sendEvent(receiver: this, event: &e);
11416 break;
11417 }
11418 case Qt::WA_DropSiteRegistered: {
11419 for (int i = 0; i < d->children.size(); ++i) {
11420 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
11421 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_AcceptDrops) && w->testAttribute(attribute: Qt::WA_DropSiteRegistered) != on)
11422 w->setAttribute(attribute: Qt::WA_DropSiteRegistered, on);
11423 }
11424 break;
11425 }
11426#endif
11427
11428 case Qt::WA_NoChildEventsForParent:
11429 d->sendChildEvents = !on;
11430 break;
11431 case Qt::WA_NoChildEventsFromChildren:
11432 d->receiveChildEvents = !on;
11433 break;
11434 case Qt::WA_MacNormalSize:
11435 case Qt::WA_MacSmallSize:
11436 case Qt::WA_MacMiniSize:
11437#ifdef Q_OS_MAC
11438 {
11439 // We can only have one of these set at a time
11440 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11441 Qt::WA_MacMiniSize };
11442 for (int i = 0; i < 3; ++i) {
11443 if (MacSizes[i] != attribute)
11444 setAttribute_internal(MacSizes[i], false, data, d);
11445 }
11446 d->macUpdateSizeAttribute();
11447 }
11448#endif
11449 break;
11450 case Qt::WA_ShowModal:
11451 if (!on) {
11452 // reset modality type to NonModal when clearing WA_ShowModal
11453 data->window_modality = Qt::NonModal;
11454 } else if (data->window_modality == Qt::NonModal) {
11455 // If modality hasn't been set prior to setting WA_ShowModal, use
11456 // ApplicationModal.
11457 data->window_modality = Qt::ApplicationModal;
11458 // Some window managers do not allow us to enter modality after the
11459 // window is visible.The window must be hidden before changing the
11460 // windowModality property and then reshown.
11461 }
11462 if (testAttribute(attribute: Qt::WA_WState_Created)) {
11463 // don't call setModal_sys() before create()
11464 d->setModal_sys();
11465 }
11466 break;
11467 case Qt::WA_MouseTracking: {
11468 QEvent e(QEvent::MouseTrackingChange);
11469 QCoreApplication::sendEvent(receiver: this, event: &e);
11470 break; }
11471 case Qt::WA_TabletTracking: {
11472 QEvent e(QEvent::TabletTrackingChange);
11473 QCoreApplication::sendEvent(receiver: this, event: &e);
11474 break; }
11475 case Qt::WA_NativeWindow: {
11476 d->createTLExtra();
11477 if (on)
11478 d->createTLSysExtra();
11479#ifndef QT_NO_IM
11480 QWidget *focusWidget = d->effectiveFocusWidget();
11481 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11482 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11483 QGuiApplication::inputMethod()->commit();
11484 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11485 }
11486 if (!QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11487 parentWidget()->d_func()->enforceNativeChildren();
11488 if (on && !internalWinId() && testAttribute(attribute: Qt::WA_WState_Created))
11489 d->createWinId();
11490 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11491 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11492 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11493 }
11494#endif //QT_NO_IM
11495 break;
11496 }
11497 case Qt::WA_PaintOnScreen:
11498 d->updateIsOpaque();
11499 Q_FALLTHROUGH();
11500 case Qt::WA_OpaquePaintEvent:
11501 d->updateIsOpaque();
11502 break;
11503 case Qt::WA_NoSystemBackground:
11504 d->updateIsOpaque();
11505 Q_FALLTHROUGH();
11506 case Qt::WA_UpdatesDisabled:
11507 d->updateSystemBackground();
11508 break;
11509 case Qt::WA_TransparentForMouseEvents:
11510 break;
11511 case Qt::WA_InputMethodEnabled: {
11512#ifndef QT_NO_IM
11513 if (QGuiApplication::focusObject() == this) {
11514 if (!on)
11515 QGuiApplication::inputMethod()->commit();
11516 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11517 }
11518#endif //QT_NO_IM
11519 break;
11520 }
11521 case Qt::WA_WindowPropagation:
11522 d->resolvePalette();
11523 d->resolveFont();
11524 d->resolveLocale();
11525 break;
11526 case Qt::WA_DontShowOnScreen: {
11527 if (on && isVisible()) {
11528 // Make sure we keep the current state and only hide the widget
11529 // from the desktop. show_sys will only update platform specific
11530 // attributes at this point.
11531 d->hide_sys();
11532 d->show_sys();
11533 }
11534 break;
11535 }
11536
11537 case Qt::WA_X11NetWmWindowTypeDesktop:
11538 case Qt::WA_X11NetWmWindowTypeDock:
11539 case Qt::WA_X11NetWmWindowTypeToolBar:
11540 case Qt::WA_X11NetWmWindowTypeMenu:
11541 case Qt::WA_X11NetWmWindowTypeUtility:
11542 case Qt::WA_X11NetWmWindowTypeSplash:
11543 case Qt::WA_X11NetWmWindowTypeDialog:
11544 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11545 case Qt::WA_X11NetWmWindowTypePopupMenu:
11546 case Qt::WA_X11NetWmWindowTypeToolTip:
11547 case Qt::WA_X11NetWmWindowTypeNotification:
11548 case Qt::WA_X11NetWmWindowTypeCombo:
11549 case Qt::WA_X11NetWmWindowTypeDND:
11550 d->setNetWmWindowTypes();
11551 break;
11552
11553 case Qt::WA_StaticContents:
11554 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11555 if (on)
11556 repaintManager->addStaticWidget(widget: this);
11557 else
11558 repaintManager->removeStaticWidget(widget: this);
11559 }
11560 break;
11561 case Qt::WA_TranslucentBackground:
11562 if (on)
11563 setAttribute(attribute: Qt::WA_NoSystemBackground);
11564 d->updateIsTranslucent();
11565
11566 break;
11567 case Qt::WA_AcceptTouchEvents:
11568 break;
11569 default:
11570 break;
11571 }
11572}
11573
11574/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11575
11576 Returns \c true if attribute \a attribute is set on this widget;
11577 otherwise returns \c false.
11578
11579 \sa setAttribute()
11580 */
11581bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11582{
11583 Q_D(const QWidget);
11584 const int x = attribute - 8*sizeof(uint);
11585 const int int_off = x / (8*sizeof(uint));
11586 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11587}
11588
11589/*!
11590 \property QWidget::windowOpacity
11591
11592 \brief The level of opacity for the window.
11593
11594 The valid range of opacity is from 1.0 (completely opaque) to
11595 0.0 (completely transparent).
11596
11597 By default the value of this property is 1.0.
11598
11599 This feature is available on Embedded Linux, \macos, Windows,
11600 and X11 platforms that support the Composite extension.
11601
11602 \note On X11 you need to have a composite manager running,
11603 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11604 supported by the window manager you are using.
11605
11606 \warning Changing this property from opaque to transparent might issue a
11607 paint event that needs to be processed before the window is displayed
11608 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11609 that semi-transparent windows update and resize significantly slower than
11610 opaque windows.
11611
11612 \sa setMask()
11613*/
11614qreal QWidget::windowOpacity() const
11615{
11616 Q_D(const QWidget);
11617 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11618}
11619
11620void QWidget::setWindowOpacity(qreal opacity)
11621{
11622 Q_D(QWidget);
11623 if (!isWindow())
11624 return;
11625
11626 opacity = qBound(min: qreal(0.0), val: opacity, max: qreal(1.0));
11627 QTLWExtra *extra = d->topData();
11628 extra->opacity = uint(opacity * 255);
11629 setAttribute(attribute: Qt::WA_WState_WindowOpacitySet);
11630 d->setWindowOpacity_sys(opacity);
11631
11632 if (!testAttribute(attribute: Qt::WA_WState_Created))
11633 return;
11634
11635#if QT_CONFIG(graphicsview)
11636 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11637 // Avoid invalidating the cache if set.
11638 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11639 proxy->update();
11640 else if (QGraphicsScene *scene = proxy->scene())
11641 scene->update(rect: proxy->sceneBoundingRect());
11642 return;
11643 }
11644#endif
11645}
11646
11647void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11648{
11649 Q_Q(QWidget);
11650 if (q->windowHandle())
11651 q->windowHandle()->setOpacity(level);
11652}
11653
11654/*!
11655 \property QWidget::windowModified
11656 \brief whether the document shown in the window has unsaved changes
11657
11658 A modified window is a window whose content has changed but has
11659 not been saved to disk. This flag will have different effects
11660 varied by the platform. On \macos the close button will have a
11661 modified look; on other platforms, the window title will have an
11662 '*' (asterisk).
11663
11664 The window title must contain a "[*]" placeholder, which
11665 indicates where the '*' should appear. Normally, it should appear
11666 right after the file name (e.g., "document1.txt[*] - Text
11667 Editor"). If the window isn't modified, the placeholder is simply
11668 removed.
11669
11670 Note that if a widget is set as modified, all its ancestors will
11671 also be set as modified. However, if you call \c
11672 {setWindowModified(false)} on a widget, this will not propagate to
11673 its parent because other children of the parent might have been
11674 modified.
11675
11676 \sa windowTitle
11677*/
11678bool QWidget::isWindowModified() const
11679{
11680 return testAttribute(attribute: Qt::WA_WindowModified);
11681}
11682
11683void QWidget::setWindowModified(bool mod)
11684{
11685 Q_D(QWidget);
11686 setAttribute(attribute: Qt::WA_WindowModified, on: mod);
11687
11688 d->setWindowModified_helper();
11689
11690 QEvent e(QEvent::ModifiedChange);
11691 QCoreApplication::sendEvent(receiver: this, event: &e);
11692}
11693
11694void QWidgetPrivate::setWindowModified_helper()
11695{
11696 Q_Q(QWidget);
11697 QWindow *window = q->windowHandle();
11698 if (!window)
11699 return;
11700 QPlatformWindow *platformWindow = window->handle();
11701 if (!platformWindow)
11702 return;
11703 bool on = q->testAttribute(attribute: Qt::WA_WindowModified);
11704 if (!platformWindow->setWindowModified(on)) {
11705 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11706 qWarning(msg: "QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11707 setWindowTitle_helper(q->windowTitle());
11708 setWindowIconText_helper(q->windowIconText());
11709 }
11710}
11711
11712#if QT_CONFIG(tooltip)
11713/*!
11714 \property QWidget::toolTip
11715
11716 \brief the widget's tooltip
11717
11718 Note that by default tooltips are only shown for widgets that are
11719 children of the active window. You can change this behavior by
11720 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11721 not on the widget with the tooltip.
11722
11723 If you want to control a tooltip's behavior, you can intercept the
11724 event() function and catch the QEvent::ToolTip event (e.g., if you
11725 want to customize the area for which the tooltip should be shown).
11726
11727 By default, this property contains an empty string.
11728
11729 \sa QToolTip, statusTip, whatsThis
11730*/
11731void QWidget::setToolTip(const QString &s)
11732{
11733 Q_D(QWidget);
11734 d->toolTip = s;
11735
11736 QEvent event(QEvent::ToolTipChange);
11737 QCoreApplication::sendEvent(receiver: this, event: &event);
11738}
11739
11740QString QWidget::toolTip() const
11741{
11742 Q_D(const QWidget);
11743 return d->toolTip;
11744}
11745
11746/*!
11747 \property QWidget::toolTipDuration
11748 \brief the widget's tooltip duration
11749 \since 5.2
11750
11751 Specifies how long time the tooltip will be displayed, in milliseconds.
11752 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11753
11754 \sa toolTip
11755*/
11756
11757void QWidget::setToolTipDuration(int msec)
11758{
11759 Q_D(QWidget);
11760 d->toolTipDuration = msec;
11761}
11762
11763int QWidget::toolTipDuration() const
11764{
11765 Q_D(const QWidget);
11766 return d->toolTipDuration;
11767}
11768
11769#endif // QT_CONFIG(tooltip)
11770
11771
11772#if QT_CONFIG(statustip)
11773/*!
11774 \property QWidget::statusTip
11775 \brief the widget's status tip
11776
11777 By default, this property contains an empty string.
11778
11779 \sa toolTip, whatsThis
11780*/
11781void QWidget::setStatusTip(const QString &s)
11782{
11783 Q_D(QWidget);
11784 d->statusTip = s;
11785}
11786
11787QString QWidget::statusTip() const
11788{
11789 Q_D(const QWidget);
11790 return d->statusTip;
11791}
11792#endif // QT_CONFIG(statustip)
11793
11794#if QT_CONFIG(whatsthis)
11795/*!
11796 \property QWidget::whatsThis
11797
11798 \brief the widget's What's This help text.
11799
11800 By default, this property contains an empty string.
11801
11802 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11803*/
11804void QWidget::setWhatsThis(const QString &s)
11805{
11806 Q_D(QWidget);
11807 d->whatsThis = s;
11808}
11809
11810QString QWidget::whatsThis() const
11811{
11812 Q_D(const QWidget);
11813 return d->whatsThis;
11814}
11815#endif // QT_CONFIG(whatsthis)
11816
11817#if QT_CONFIG(accessibility)
11818/*!
11819 \property QWidget::accessibleName
11820
11821 \brief the widget's name as seen by assistive technologies
11822
11823 This is the primary name by which assistive technology such as screen readers
11824 announce this widget. For most widgets setting this property is not required.
11825 For example for QPushButton the button's text will be used.
11826
11827 It is important to set this property when the widget does not provide any
11828 text. For example a button that only contains an icon needs to set this
11829 property to work with screen readers.
11830 The name should be short and equivalent to the visual information conveyed
11831 by the widget.
11832
11833 This property has to be \l{Internationalization with Qt}{localized}.
11834
11835 By default, this property contains an empty string.
11836
11837 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11838*/
11839void QWidget::setAccessibleName(const QString &name)
11840{
11841 Q_D(QWidget);
11842 if (d->accessibleName == name)
11843 return;
11844
11845 d->accessibleName = name;
11846 QAccessibleEvent event(this, QAccessible::NameChanged);
11847 QAccessible::updateAccessibility(event: &event);
11848}
11849
11850QString QWidget::accessibleName() const
11851{
11852 Q_D(const QWidget);
11853 return d->accessibleName;
11854}
11855
11856/*!
11857 \property QWidget::accessibleDescription
11858
11859 \brief the widget's description as seen by assistive technologies
11860
11861 The accessible description of a widget should convey what a widget does.
11862 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11863 the description should give more context, such as \gui{Saves the current document}.
11864
11865 This property has to be \l{Internationalization with Qt}{localized}.
11866
11867 By default, this property contains an empty string and Qt falls back
11868 to using the tool tip to provide this information.
11869
11870 \sa QWidget::accessibleName, QAccessibleInterface::text()
11871*/
11872void QWidget::setAccessibleDescription(const QString &description)
11873{
11874 Q_D(QWidget);
11875 if (d->accessibleDescription == description)
11876 return;
11877
11878 d->accessibleDescription = description;
11879 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11880 QAccessible::updateAccessibility(event: &event);
11881}
11882
11883QString QWidget::accessibleDescription() const
11884{
11885 Q_D(const QWidget);
11886 return d->accessibleDescription;
11887}
11888
11889/*!
11890 \property QWidget::accessibleIdentifier
11891
11892 \brief the widget's identifier as seen by assistive technologies
11893
11894 If set, the accessible identifier of a widget can be used by assistive
11895 technologies in order to identify a specific widget, e.g. in automated
11896 tests.
11897
11898 \since 6.9
11899*/
11900void QWidget::setAccessibleIdentifier(const QString &identifier)
11901{
11902 Q_D(QWidget);
11903 if (d->accessibleIdentifier == identifier)
11904 return;
11905
11906 d->accessibleIdentifier = identifier;
11907 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11908 QAccessible::updateAccessibility(event: &event);
11909}
11910
11911QString QWidget::accessibleIdentifier() const
11912{
11913 Q_D(const QWidget);
11914 return d->accessibleIdentifier;
11915}
11916
11917#endif // QT_CONFIG(accessibility)
11918
11919#ifndef QT_NO_SHORTCUT
11920/*!
11921 Adds a shortcut to Qt's shortcut system that watches for the given
11922 \a key sequence in the given \a context. If the \a context is
11923 Qt::ApplicationShortcut, the shortcut applies to the application as a
11924 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11925 or to the window itself, Qt::WindowShortcut.
11926
11927 If the same \a key sequence has been grabbed by several widgets,
11928 when the \a key sequence occurs a QEvent::Shortcut event is sent
11929 to all the widgets to which it applies in a non-deterministic
11930 order, but with the ``ambiguous'' flag set to true.
11931
11932 \warning You should not normally need to use this function;
11933 instead create \l{QAction}s with the shortcut key sequences you
11934 require (if you also want equivalent menu options and toolbar
11935 buttons), or create \l{QShortcut}s if you just need key sequences.
11936 Both QAction and QShortcut handle all the event filtering for you,
11937 and provide signals which are triggered when the user triggers the
11938 key sequence, so are much easier to use than this low-level
11939 function.
11940
11941 \sa releaseShortcut(), setShortcutEnabled()
11942*/
11943int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11944{
11945 Q_ASSERT(qApp);
11946 if (key.isEmpty())
11947 return 0;
11948 setAttribute(attribute: Qt::WA_GrabbedShortcut);
11949 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(owner: this, key, context, matcher: qWidgetShortcutContextMatcher);
11950}
11951
11952/*!
11953 Removes the shortcut with the given \a id from Qt's shortcut
11954 system. The widget will no longer receive QEvent::Shortcut events
11955 for the shortcut's key sequence (unless it has other shortcuts
11956 with the same key sequence).
11957
11958 \warning You should not normally need to use this function since
11959 Qt's shortcut system removes shortcuts automatically when their
11960 parent widget is destroyed. It is best to use QAction or
11961 QShortcut to handle shortcuts, since they are easier to use than
11962 this low-level function. Note also that this is an expensive
11963 operation.
11964
11965 \sa grabShortcut(), setShortcutEnabled()
11966*/
11967void QWidget::releaseShortcut(int id)
11968{
11969 Q_ASSERT(qApp);
11970 if (id)
11971 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, owner: this, key: 0);
11972}
11973
11974/*!
11975 If \a enable is true, the shortcut with the given \a id is
11976 enabled; otherwise the shortcut is disabled.
11977
11978 \warning You should not normally need to use this function since
11979 Qt's shortcut system enables/disables shortcuts automatically as
11980 widgets become hidden/visible and gain or lose focus. It is best
11981 to use QAction or QShortcut to handle shortcuts, since they are
11982 easier to use than this low-level function.
11983
11984 \sa grabShortcut(), releaseShortcut()
11985*/
11986void QWidget::setShortcutEnabled(int id, bool enable)
11987{
11988 Q_ASSERT(qApp);
11989 if (id)
11990 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, owner: this, key: 0);
11991}
11992
11993/*!
11994 \since 4.2
11995
11996 If \a enable is true, auto repeat of the shortcut with the
11997 given \a id is enabled; otherwise it is disabled.
11998
11999 \sa grabShortcut(), releaseShortcut()
12000*/
12001void QWidget::setShortcutAutoRepeat(int id, bool enable)
12002{
12003 Q_ASSERT(qApp);
12004 if (id)
12005 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on: enable, id, owner: this, key: 0);
12006}
12007#endif // QT_NO_SHORTCUT
12008
12009/*!
12010 Updates the widget's micro focus and informs input methods
12011 that the state specified by \a query has changed.
12012*/
12013void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12014{
12015 if (this == QGuiApplication::focusObject())
12016 QGuiApplication::inputMethod()->update(queries: query);
12017}
12018
12019/*!
12020 Raises this widget to the top of the parent widget's stack.
12021
12022 After this call the widget will be visually in front of any
12023 overlapping sibling widgets.
12024
12025 \note When using activateWindow(), you can call this function to
12026 ensure that the window is stacked on top.
12027
12028 \sa lower(), stackUnder()
12029*/
12030
12031void QWidget::raise()
12032{
12033 Q_D(QWidget);
12034 if (!isWindow()) {
12035 QWidget *p = parentWidget();
12036 const int parentChildCount = p->d_func()->children.size();
12037 if (parentChildCount < 2)
12038 return;
12039 const int from = p->d_func()->children.indexOf(t: this);
12040 Q_ASSERT(from >= 0);
12041 // Do nothing if the widget is already in correct stacking order _and_ created.
12042 if (from != parentChildCount -1)
12043 p->d_func()->children.move(from, to: parentChildCount - 1);
12044 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12045 create();
12046 else if (from == parentChildCount - 1)
12047 return;
12048
12049 QRegion region(rect());
12050 d->subtractOpaqueSiblings(sourceRegion&: region);
12051 d->invalidateBackingStore(region);
12052 }
12053 if (testAttribute(attribute: Qt::WA_WState_Created))
12054 d->raise_sys();
12055
12056 if (d->extra && d->extra->hasWindowContainer)
12057 QWindowContainer::parentWasRaised(parent: this);
12058
12059 QEvent e(QEvent::ZOrderChange);
12060 QCoreApplication::sendEvent(receiver: this, event: &e);
12061}
12062
12063void QWidgetPrivate::raise_sys()
12064{
12065 Q_Q(QWidget);
12066 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12067 q->windowHandle()->raise();
12068 } else if (renderToTexture) {
12069 if (QWidget *p = q->parentWidget()) {
12070 setDirtyOpaqueRegion();
12071 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12072 }
12073 }
12074}
12075
12076/*!
12077 Lowers the widget to the bottom of the parent widget's stack.
12078
12079 After this call the widget will be visually behind (and therefore
12080 obscured by) any overlapping sibling widgets.
12081
12082 \sa raise(), stackUnder()
12083*/
12084
12085void QWidget::lower()
12086{
12087 Q_D(QWidget);
12088 if (!isWindow()) {
12089 QWidget *p = parentWidget();
12090 const int parentChildCount = p->d_func()->children.size();
12091 if (parentChildCount < 2)
12092 return;
12093 const int from = p->d_func()->children.indexOf(t: this);
12094 Q_ASSERT(from >= 0);
12095 // Do nothing if the widget is already in correct stacking order _and_ created.
12096 if (from != 0)
12097 p->d_func()->children.move(from, to: 0);
12098 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12099 create();
12100 else if (from == 0)
12101 return;
12102 }
12103 if (testAttribute(attribute: Qt::WA_WState_Created))
12104 d->lower_sys();
12105
12106 if (d->extra && d->extra->hasWindowContainer)
12107 QWindowContainer::parentWasLowered(parent: this);
12108
12109 QEvent e(QEvent::ZOrderChange);
12110 QCoreApplication::sendEvent(receiver: this, event: &e);
12111}
12112
12113void QWidgetPrivate::lower_sys()
12114{
12115 Q_Q(QWidget);
12116 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12117 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12118 q->windowHandle()->lower();
12119 } else if (QWidget *p = q->parentWidget()) {
12120 setDirtyOpaqueRegion();
12121 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12122 }
12123}
12124
12125/*!
12126 Places the widget under \a w in the parent widget's stack.
12127
12128 To make this work, the widget itself and \a w must be siblings.
12129
12130 \sa raise(), lower()
12131*/
12132void QWidget::stackUnder(QWidget* w)
12133{
12134 Q_D(QWidget);
12135 QWidget *p = parentWidget();
12136 if (!w || isWindow() || p != w->parentWidget() || this == w)
12137 return;
12138 if (p) {
12139 int from = p->d_func()->children.indexOf(t: this);
12140 int to = p->d_func()->children.indexOf(t: w);
12141 Q_ASSERT(from >= 0);
12142 Q_ASSERT(to >= 0);
12143 if (from < to)
12144 --to;
12145 // Do nothing if the widget is already in correct stacking order _and_ created.
12146 if (from != to)
12147 p->d_func()->children.move(from, to);
12148 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12149 create();
12150 else if (from == to)
12151 return;
12152 }
12153 if (testAttribute(attribute: Qt::WA_WState_Created))
12154 d->stackUnder_sys(w);
12155
12156 QEvent e(QEvent::ZOrderChange);
12157 QCoreApplication::sendEvent(receiver: this, event: &e);
12158}
12159
12160void QWidgetPrivate::stackUnder_sys(QWidget*)
12161{
12162 Q_Q(QWidget);
12163 if (QWidget *p = q->parentWidget()) {
12164 setDirtyOpaqueRegion();
12165 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12166 }
12167}
12168
12169/*!
12170 \fn bool QWidget::isTopLevel() const
12171 \deprecated
12172
12173 Use isWindow() instead.
12174*/
12175
12176/*!
12177 \fn bool QWidget::isRightToLeft() const
12178 \internal
12179*/
12180
12181/*!
12182 \fn bool QWidget::isLeftToRight() const
12183 \internal
12184*/
12185
12186/*!
12187 \macro QWIDGETSIZE_MAX
12188 \relates QWidget
12189
12190 Defines the maximum size for a QWidget object.
12191
12192 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12193 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12194
12195 \sa QWidget::setMaximumSize()
12196*/
12197
12198/*!
12199 \fn QWidget::setupUi(QWidget *widget)
12200
12201 Sets up the user interface for the specified \a widget.
12202
12203 \note This function is available with widgets that derive from user
12204 interface descriptions created using \l{uic}.
12205
12206 \sa {Using a Designer UI File in Your Application}
12207*/
12208
12209QRect QWidgetPrivate::frameStrut() const
12210{
12211 Q_Q(const QWidget);
12212 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
12213 // x2 = x1 + w - 1, so w/h = 1
12214 return QRect(0, 0, 1, 1);
12215 }
12216
12217 if (data.fstrut_dirty
12218 // ### Fix properly for 4.3
12219 && q->isVisible()
12220 && q->testAttribute(attribute: Qt::WA_WState_Created))
12221 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12222
12223 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12224}
12225
12226void QWidgetPrivate::updateFrameStrut()
12227{
12228 Q_Q(QWidget);
12229 if (q->data->fstrut_dirty) {
12230 if (QTLWExtra *te = maybeTopData()) {
12231 if (te->window && te->window->handle()) {
12232 const QMargins margins = te->window->frameMargins();
12233 if (!margins.isNull()) {
12234 te->frameStrut.setCoords(xp1: margins.left(), yp1: margins.top(), xp2: margins.right(), yp2: margins.bottom());
12235 q->data->fstrut_dirty = false;
12236 }
12237 }
12238 }
12239 }
12240}
12241
12242#ifdef QT_KEYPAD_NAVIGATION
12243/*!
12244 \internal
12245
12246 Changes the focus from the current focusWidget to a widget in
12247 the \a direction.
12248
12249 Returns \c true, if there was a widget in that direction
12250*/
12251bool QWidgetPrivate::navigateToDirection(Direction direction)
12252{
12253 QWidget *targetWidget = widgetInNavigationDirection(direction);
12254 if (targetWidget)
12255 targetWidget->setFocus();
12256 return (targetWidget != 0);
12257}
12258
12259/*!
12260 \internal
12261
12262 Searches for a widget that is positioned in the \a direction, starting
12263 from the current focusWidget.
12264
12265 Returns the pointer to a found widget or \nullptr, if there was no widget
12266 in that direction.
12267*/
12268QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12269{
12270 const QWidget *sourceWidget = QApplication::focusWidget();
12271 if (!sourceWidget)
12272 return nullptr;
12273 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12274 const int sourceX =
12275 (direction == DirectionNorth || direction == DirectionSouth) ?
12276 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12277 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12278 const int sourceY =
12279 (direction == DirectionEast || direction == DirectionWest) ?
12280 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12281 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12282 const QPoint sourcePoint(sourceX, sourceY);
12283 const QPoint sourceCenter = sourceRect.center();
12284 const QWidget *sourceWindow = sourceWidget->window();
12285
12286 QWidget *targetWidget = nullptr;
12287 int shortestDistance = INT_MAX;
12288
12289 const auto targetCandidates = QApplication::allWidgets();
12290 for (QWidget *targetCandidate : targetCandidates) {
12291
12292 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12293
12294 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12295 // but the owner of the proxy cannot.
12296 // Additionally, empty widgets should be ignored.
12297 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12298 continue;
12299
12300 // Only navigate to a target widget that...
12301 if ( targetCandidate != sourceWidget
12302 // ...takes the focus,
12303 && targetCandidate->focusPolicy() & Qt::TabFocus
12304 // ...is above if DirectionNorth,
12305 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12306 // ...is on the right if DirectionEast,
12307 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12308 // ...is below if DirectionSouth,
12309 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12310 // ...is on the left if DirectionWest,
12311 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12312 // ...is enabled,
12313 && targetCandidate->isEnabled()
12314 // ...is visible,
12315 && targetCandidate->isVisible()
12316 // ...is in the same window,
12317 && targetCandidate->window() == sourceWindow) {
12318 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12319 const QRect &targetCandidateRect) {
12320 int dx = 0;
12321 int dy = 0;
12322 if (p.x() < r.left())
12323 dx = r.left() - p.x();
12324 else if (p.x() > r.right())
12325 dx = p.x() - r.right();
12326 if (p.y() < r.top())
12327 dy = r.top() - p.y();
12328 else if (p.y() > r.bottom())
12329 dy = p.y() - r.bottom();
12330 return dx + dy;
12331 }();
12332 if (targetCandidateDistance < shortestDistance) {
12333 shortestDistance = targetCandidateDistance;
12334 targetWidget = targetCandidate;
12335 }
12336 }
12337 }
12338 return targetWidget;
12339}
12340
12341/*!
12342 \internal
12343
12344 Tells us if it there is currently a reachable widget by keypad navigation in
12345 a certain \a orientation.
12346 If no navigation is possible, occurring key events in that \a orientation may
12347 be used to interact with the value in the focused widget, even though it
12348 currently has not the editFocus.
12349
12350 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12351*/
12352bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12353{
12354 return orientation == Qt::Horizontal?
12355 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12356 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12357 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12358 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12359}
12360/*!
12361 \internal
12362
12363 Checks, if the \a widget is inside a QTabWidget. If is is inside
12364 one, left/right key events will be used to switch between tabs in keypad
12365 navigation. If there is no QTabWidget, the horizontal key events can be used
12366to
12367 interact with the value in the focused widget, even though it currently has
12368 not the editFocus.
12369
12370 \sa QWidget::hasEditFocus()
12371*/
12372bool QWidgetPrivate::inTabWidget(QWidget *widget)
12373{
12374 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12375 if (qobject_cast<const QTabWidget*>(tabWidget))
12376 return true;
12377 return false;
12378}
12379#endif
12380
12381/*!
12382 \since 5.0
12383 \internal
12384
12385 Sets the backing store to be the \a store specified.
12386 The QWidget will take ownership of the \a store.
12387*/
12388void QWidget::setBackingStore(QBackingStore *store)
12389{
12390 // ### createWinId() ??
12391
12392 if (!isWindow())
12393 return;
12394
12395 Q_D(QWidget);
12396
12397 QTLWExtra *topData = d->topData();
12398 if (topData->backingStore == store)
12399 return;
12400
12401 QBackingStore *oldStore = topData->backingStore;
12402 delete topData->backingStore;
12403 topData->backingStore = store;
12404
12405 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12406 if (!repaintManager)
12407 return;
12408
12409 if (isWindow()) {
12410 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12411 delete repaintManager->backingStore();
12412 repaintManager->setBackingStore(store);
12413 }
12414}
12415
12416/*!
12417 \since 5.0
12418
12419 Returns the QBackingStore this widget will be drawn into.
12420*/
12421QBackingStore *QWidget::backingStore() const
12422{
12423 Q_D(const QWidget);
12424 QTLWExtra *extra = d->maybeTopData();
12425 if (extra && extra->backingStore)
12426 return extra->backingStore;
12427
12428 if (!isWindow())
12429 return window()->backingStore();
12430
12431 return nullptr;
12432}
12433
12434void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12435{
12436 if (left)
12437 *left = (int)leftLayoutItemMargin;
12438 if (top)
12439 *top = (int)topLayoutItemMargin;
12440 if (right)
12441 *right = (int)rightLayoutItemMargin;
12442 if (bottom)
12443 *bottom = (int)bottomLayoutItemMargin;
12444}
12445
12446void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12447{
12448 if (leftLayoutItemMargin == left
12449 && topLayoutItemMargin == top
12450 && rightLayoutItemMargin == right
12451 && bottomLayoutItemMargin == bottom)
12452 return;
12453
12454 Q_Q(QWidget);
12455 leftLayoutItemMargin = (signed char)left;
12456 topLayoutItemMargin = (signed char)top;
12457 rightLayoutItemMargin = (signed char)right;
12458 bottomLayoutItemMargin = (signed char)bottom;
12459 q->updateGeometry();
12460}
12461
12462void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12463{
12464 Q_Q(QWidget);
12465 QStyleOption myOpt;
12466 if (!opt) {
12467 myOpt.initFrom(w: q);
12468 myOpt.rect.setRect(ax: 0, ay: 0, aw: 32768, ah: 32768); // arbitrary
12469 opt = &myOpt;
12470 }
12471
12472 QRect liRect = q->style()->subElementRect(subElement: element, option: opt, widget: q);
12473 if (liRect.isValid()) {
12474 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12475 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12476 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12477 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12478 } else {
12479 leftLayoutItemMargin = 0;
12480 topLayoutItemMargin = 0;
12481 rightLayoutItemMargin = 0;
12482 bottomLayoutItemMargin = 0;
12483 }
12484}
12485// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12486void QWidgetPrivate::adjustQuitOnCloseAttribute()
12487{
12488 Q_Q(QWidget);
12489
12490 if (!q->parentWidget()) {
12491 Qt::WindowType type = q->windowType();
12492 if (type == Qt::Widget || type == Qt::SubWindow)
12493 type = Qt::Window;
12494 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12495 q->setAttribute(attribute: Qt::WA_QuitOnClose, on: false);
12496 }
12497}
12498
12499void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12500{
12501 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12502 if (!wd->textureChildSeen)
12503 return;
12504 if (end)
12505 wd->endCompose();
12506 else
12507 wd->beginCompose();
12508 for (int i = 0; i < wd->children.size(); ++i) {
12509 w = qobject_cast<QWidget *>(o: wd->children.at(i));
12510 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12511 sendComposeStatus(w, end);
12512 }
12513}
12514
12515Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12516{
12517 return widget->data;
12518}
12519
12520Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12521{
12522 return widget->d_func();
12523}
12524
12525
12526#if QT_CONFIG(graphicsview)
12527/*!
12528 \since 4.5
12529
12530 Returns the proxy widget for the corresponding embedded widget in a graphics
12531 view; otherwise returns \nullptr.
12532
12533 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12534 QGraphicsScene::addWidget()
12535 */
12536QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12537{
12538 Q_D(const QWidget);
12539 if (d->extra) {
12540 return d->extra->proxyWidget;
12541 }
12542 return nullptr;
12543}
12544#endif
12545
12546#ifndef QT_NO_GESTURES
12547/*!
12548 Subscribes the widget to a given \a gesture with specific \a flags.
12549
12550 \sa ungrabGesture(), QGestureEvent
12551 \since 4.6
12552*/
12553void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12554{
12555 Q_D(QWidget);
12556 d->gestureContext.insert(key: gesture, value: flags);
12557 (void)QGestureManager::instance(); // create a gesture manager
12558}
12559
12560/*!
12561 Unsubscribes the widget from a given \a gesture type
12562
12563 \sa grabGesture(), QGestureEvent
12564 \since 4.6
12565*/
12566void QWidget::ungrabGesture(Qt::GestureType gesture)
12567{
12568 // if you modify this function, check the inlined version in ~QWidget, too
12569 Q_D(QWidget);
12570 if (d->gestureContext.remove(key: gesture)) {
12571 if (QGestureManager *manager = QGestureManager::instance())
12572 manager->cleanupCachedGestures(target: this, type: gesture);
12573 }
12574}
12575#endif // QT_NO_GESTURES
12576
12577/*!
12578 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12579
12580 Frees up window system resources. Destroys the widget window if \a
12581 destroyWindow is true.
12582
12583 destroy() calls itself recursively for all the child widgets,
12584 passing \a destroySubWindows for the \a destroyWindow parameter.
12585 To have more control over destruction of subwidgets, destroy
12586 subwidgets selectively first.
12587
12588 This function is usually called from the QWidget destructor.
12589*/
12590void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12591{
12592 Q_D(QWidget);
12593
12594 d->aboutToDestroy();
12595 if (!isWindow() && parentWidget())
12596 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(rect: geometry()));
12597 d->deactivateWidgetCleanup();
12598
12599 if ((windowType() == Qt::Popup) && qApp)
12600 qApp->d_func()->closePopup(popup: this);
12601
12602 if (this == qApp->activeWindow())
12603 QApplicationPrivate::setActiveWindow(nullptr);
12604 if (QWidget::mouseGrabber() == this)
12605 releaseMouse();
12606 if (QWidget::keyboardGrabber() == this)
12607 releaseKeyboard();
12608
12609 setAttribute(attribute: Qt::WA_WState_Created, on: false);
12610
12611 if (windowType() != Qt::Desktop) {
12612 if (destroySubWindows) {
12613 QObjectList childList(children());
12614 for (int i = 0; i < childList.size(); i++) {
12615 QWidget *widget = qobject_cast<QWidget *>(o: childList.at(i));
12616 if (widget && widget->testAttribute(attribute: Qt::WA_NativeWindow)) {
12617 if (widget->windowHandle()) {
12618 widget->destroy();
12619 }
12620 }
12621 }
12622 }
12623 if (destroyWindow) {
12624 d->deleteTLSysExtra();
12625 } else {
12626 if (parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_WState_Created)) {
12627 d->hide_sys();
12628 }
12629 }
12630
12631 d->setWinId(0);
12632 }
12633}
12634
12635/*!
12636 \fn QPaintEngine *QWidget::paintEngine() const
12637
12638 Returns the widget's paint engine.
12639
12640 Note that this function should not be called explicitly by the
12641 user, since it's meant for reimplementation purposes only. The
12642 function is called by Qt internally, and the default
12643 implementation may not always return a valid pointer.
12644*/
12645QPaintEngine *QWidget::paintEngine() const
12646{
12647 qWarning(msg: "QWidget::paintEngine: Should no longer be called");
12648
12649#ifdef Q_OS_WIN
12650 // We set this bit which is checked in setAttribute for
12651 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12652 //
12653 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12654 // Windows which would mean suddenly their widgets stop working.
12655 //
12656 // 2. Users set paint on screen and subclass paintEngine() to
12657 // return 0, in which case we have a "hole" in the backingstore
12658 // allowing use of GDI or DirectX directly.
12659 //
12660 // 1 is WRONG, but to minimize silent failures, we have set this
12661 // bit to ignore the setAttribute call. 2. needs to be
12662 // supported because its our only means of embedding native
12663 // graphics stuff.
12664 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12665#endif
12666
12667 return nullptr; //##### @@@
12668}
12669
12670// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12671static inline bool canMapPosition(QWindow *window)
12672{
12673 return window->handle() && !qt_window_private(window)->resizeEventPending;
12674}
12675
12676#if QT_CONFIG(graphicsview)
12677static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12678{
12679 QGraphicsProxyWidget *result = nullptr;
12680 const QWidgetPrivate *d = qt_widget_private(widget: const_cast<QWidget *>(w));
12681 if (d->extra)
12682 result = d->extra->proxyWidget;
12683 return result;
12684}
12685#endif // QT_CONFIG(graphicsview)
12686
12687struct MapToGlobalTransformResult {
12688 QTransform transform;
12689 QWindow *window;
12690};
12691
12692static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12693{
12694 MapToGlobalTransformResult result;
12695 result.window = nullptr;
12696 for ( ; w ; w = w->parentWidget()) {
12697#if QT_CONFIG(graphicsview)
12698 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12699 if (const QGraphicsScene *scene = qgpw->scene()) {
12700 const QList <QGraphicsView *> views = scene->views();
12701 if (!views.isEmpty()) {
12702 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(widget: views.constFirst()));
12703 result.transform *= viewP->mapToViewTransform(item: qgpw);
12704 w = views.first()->viewport();
12705 }
12706 }
12707 }
12708#endif // QT_CONFIG(graphicsview)
12709 QWindow *window = w->windowHandle();
12710 if (window && canMapPosition(window)) {
12711 result.window = window;
12712 break;
12713 }
12714
12715 const auto &geometry = w->geometry();
12716 result.transform *= QTransform::fromTranslate(dx: geometry.x(), dy: geometry.y());
12717 if (w->isWindow())
12718 break;
12719 }
12720 return result;
12721}
12722
12723/*!
12724 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12725
12726 Translates the widget coordinate \a pos to global screen
12727 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12728 the global coordinates of the top-left pixel of the widget.
12729
12730 \sa mapFromGlobal(), mapTo(), mapToParent()
12731 \since 6.0
12732*/
12733QPointF QWidget::mapToGlobal(const QPointF &pos) const
12734{
12735 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12736 const QPointF g = t.transform.map(p: pos);
12737 return t.window ? t.window->mapToGlobal(pos: g) : g;
12738}
12739
12740/*!
12741 \overload
12742*/
12743QPoint QWidget::mapToGlobal(const QPoint &pos) const
12744{
12745 return mapToGlobal(pos: QPointF(pos)).toPoint();
12746}
12747
12748/*!
12749 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12750
12751 Translates the global screen coordinate \a pos to widget
12752 coordinates.
12753
12754 \sa mapToGlobal(), mapFrom(), mapFromParent()
12755 \since 6.0
12756*/
12757QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12758{
12759 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12760 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12761 return t.transform.inverted().map(p: windowLocal);
12762}
12763
12764/*!
12765 \overload
12766*/
12767QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12768{
12769 return mapFromGlobal(pos: QPointF(pos)).toPoint();
12770}
12771
12772QWidget *qt_mouseGrb = nullptr;
12773static bool mouseGrabWithCursor = false;
12774static QWidget *keyboardGrb = nullptr;
12775
12776static inline QWindow *grabberWindow(const QWidget *w)
12777{
12778 QWindow *window = w->windowHandle();
12779 if (!window)
12780 if (const QWidget *nativeParent = w->nativeParentWidget())
12781 window = nativeParent->windowHandle();
12782 return window;
12783}
12784
12785#ifndef QT_NO_CURSOR
12786static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12787#else
12788static void grabMouseForWidget(QWidget *widget)
12789#endif
12790{
12791 if (qt_mouseGrb)
12792 qt_mouseGrb->releaseMouse();
12793
12794 mouseGrabWithCursor = false;
12795 if (QWindow *window = grabberWindow(w: widget)) {
12796#ifndef QT_NO_CURSOR
12797 if (cursor) {
12798 mouseGrabWithCursor = true;
12799 QGuiApplication::setOverrideCursor(*cursor);
12800 }
12801#endif // !QT_NO_CURSOR
12802 window->setMouseGrabEnabled(true);
12803 }
12804
12805 qt_mouseGrb = widget;
12806}
12807
12808static void releaseMouseGrabOfWidget(QWidget *widget)
12809{
12810 if (qt_mouseGrb == widget) {
12811 if (QWindow *window = grabberWindow(w: widget)) {
12812#ifndef QT_NO_CURSOR
12813 if (mouseGrabWithCursor) {
12814 QGuiApplication::restoreOverrideCursor();
12815 mouseGrabWithCursor = false;
12816 }
12817#endif // !QT_NO_CURSOR
12818 window->setMouseGrabEnabled(false);
12819 }
12820 }
12821 qt_mouseGrb = nullptr;
12822}
12823
12824/*!
12825 \fn void QWidget::grabMouse()
12826
12827 Grabs the mouse input.
12828
12829 This widget receives all mouse events until releaseMouse() is
12830 called; other widgets get no mouse events at all. Keyboard
12831 events are not affected. Use grabKeyboard() if you want to grab
12832 that.
12833
12834 \warning Bugs in mouse-grabbing applications very often lock the
12835 terminal. Use this function with extreme caution, and consider
12836 using the \c -nograb command line option while debugging.
12837
12838 It is seldom necessary to grab the mouse when using Qt, as
12839 Qt grabs and releases it sensibly. In particular, Qt grabs the
12840 mouse when a mouse button is pressed and keeps it until the last
12841 button is released.
12842
12843 \note Only visible widgets can grab mouse input. If isVisible()
12844 returns \c false for a widget, that widget cannot call grabMouse().
12845
12846 \note On Windows, grabMouse() only works when the mouse is inside a window
12847 owned by the process.
12848 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12849
12850 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12851*/
12852void QWidget::grabMouse()
12853{
12854 grabMouseForWidget(widget: this);
12855}
12856
12857/*!
12858 \fn void QWidget::grabMouse(const QCursor &cursor)
12859 \overload grabMouse()
12860
12861 Grabs the mouse input and changes the cursor shape.
12862
12863 The cursor will assume shape \a cursor (for as long as the mouse
12864 focus is grabbed) and this widget will be the only one to receive
12865 mouse events until releaseMouse() is called().
12866
12867 \warning Grabbing the mouse might lock the terminal.
12868
12869 \note See the note in QWidget::grabMouse().
12870
12871 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12872*/
12873#ifndef QT_NO_CURSOR
12874void QWidget::grabMouse(const QCursor &cursor)
12875{
12876 grabMouseForWidget(widget: this, cursor: &cursor);
12877}
12878#endif
12879
12880bool QWidgetPrivate::stealMouseGrab(bool grab)
12881{
12882 // This is like a combination of grab/releaseMouse() but with error checking
12883 // and it has no effect on the result of mouseGrabber().
12884 Q_Q(QWidget);
12885 QWindow *window = grabberWindow(w: q);
12886 return window ? window->setMouseGrabEnabled(grab) : false;
12887}
12888
12889/*!
12890 \fn void QWidget::releaseMouse()
12891
12892 Releases the mouse grab.
12893
12894 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12895*/
12896void QWidget::releaseMouse()
12897{
12898 releaseMouseGrabOfWidget(widget: this);
12899}
12900
12901/*!
12902 \fn void QWidget::grabKeyboard()
12903
12904 Grabs the keyboard input.
12905
12906 This widget receives all keyboard events until releaseKeyboard()
12907 is called; other widgets get no keyboard events at all. Mouse
12908 events are not affected. Use grabMouse() if you want to grab that.
12909
12910 The focus widget is not affected, except that it doesn't receive
12911 any keyboard events. setFocus() moves the focus as usual, but the
12912 new focus widget receives keyboard events only after
12913 releaseKeyboard() is called.
12914
12915 If a different widget is currently grabbing keyboard input, that
12916 widget's grab is released first.
12917
12918 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12919*/
12920void QWidget::grabKeyboard()
12921{
12922 if (keyboardGrb)
12923 keyboardGrb->releaseKeyboard();
12924 if (QWindow *window = grabberWindow(w: this))
12925 window->setKeyboardGrabEnabled(true);
12926 keyboardGrb = this;
12927}
12928
12929bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12930{
12931 // This is like a combination of grab/releaseKeyboard() but with error
12932 // checking and it has no effect on the result of keyboardGrabber().
12933 Q_Q(QWidget);
12934 QWindow *window = grabberWindow(w: q);
12935 return window ? window->setKeyboardGrabEnabled(grab) : false;
12936}
12937
12938/*!
12939 \fn void QWidget::releaseKeyboard()
12940
12941 Releases the keyboard grab.
12942
12943 \sa grabKeyboard(), grabMouse(), releaseMouse()
12944*/
12945void QWidget::releaseKeyboard()
12946{
12947 if (keyboardGrb == this) {
12948 if (QWindow *window = grabberWindow(w: this))
12949 window->setKeyboardGrabEnabled(false);
12950 keyboardGrb = nullptr;
12951 }
12952}
12953
12954/*!
12955 \fn QWidget *QWidget::mouseGrabber()
12956
12957 Returns the widget that is currently grabbing the mouse input.
12958
12959 If no widget in this application is currently grabbing the mouse,
12960 \nullptr is returned.
12961
12962 \sa grabMouse(), keyboardGrabber()
12963*/
12964QWidget *QWidget::mouseGrabber()
12965{
12966 return qt_mouseGrb;
12967}
12968
12969/*!
12970 \fn QWidget *QWidget::keyboardGrabber()
12971
12972 Returns the widget that is currently grabbing the keyboard input.
12973
12974 If no widget in this application is currently grabbing the
12975 keyboard, \nullptr is returned.
12976
12977 \sa grabMouse(), mouseGrabber()
12978*/
12979QWidget *QWidget::keyboardGrabber()
12980{
12981 return keyboardGrb;
12982}
12983
12984/*!
12985 \fn void QWidget::activateWindow()
12986
12987 Sets the top-level widget containing this widget to be the active
12988 window.
12989
12990 An active window is a visible top-level window that has the
12991 keyboard input focus.
12992
12993 This function performs the same operation as clicking the mouse on
12994 the title bar of a top-level window. On X11, the result depends on
12995 the Window Manager. If you want to ensure that the window is
12996 stacked on top as well you should also call raise(). Note that the
12997 window must be visible, otherwise activateWindow() has no effect.
12998
12999 On Windows, if you are calling this when the application is not
13000 currently the active one then it will not make it the active
13001 window. It will change the color of the taskbar entry to indicate
13002 that the window has changed in some way. This is because Microsoft
13003 does not allow an application to interrupt what the user is currently
13004 doing in another application.
13005
13006 \sa isActiveWindow(), window(), show()
13007*/
13008void QWidget::activateWindow()
13009{
13010 QWindow *const wnd = window()->windowHandle();
13011
13012 if (wnd)
13013 wnd->requestActivate();
13014}
13015
13016/*!
13017
13018 Internal implementation of the virtual QPaintDevice::metric()
13019 function.
13020
13021 \a m is the metric to get.
13022*/
13023int QWidget::metric(PaintDeviceMetric m) const
13024{
13025 QScreen *screen = this->screen();
13026
13027 if (!screen) {
13028 if (m == PdmDpiX || m == PdmDpiY)
13029 return 72;
13030 return QPaintDevice::metric(metric: m);
13031 }
13032
13033 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
13034
13035 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
13036 static bool downscale = qEnvironmentVariableIntValue(varName: "QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
13037 QWindow *window = this->window()->windowHandle();
13038 if (window)
13039 return downscale ? std::ceil(x: window->devicePixelRatio()) : window->devicePixelRatio();
13040 return screen->devicePixelRatio();
13041 };
13042
13043 switch (m) {
13044 case PdmWidth:
13045 return data->crect.width();
13046 case PdmWidthMM:
13047 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
13048 case PdmHeight:
13049 return data->crect.height();
13050 case PdmHeightMM:
13051 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13052 case PdmDepth:
13053 return screen->depth();
13054 case PdmDpiX:
13055 for (const QWidget *p = this; p; p = p->parentWidget()) {
13056 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13057 return p->d_func()->extra->customDpiX;
13058 }
13059 return qRound(d: screen->logicalDotsPerInchX());
13060 case PdmDpiY:
13061 for (const QWidget *p = this; p; p = p->parentWidget()) {
13062 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13063 return p->d_func()->extra->customDpiY;
13064 }
13065 return qRound(d: screen->logicalDotsPerInchY());
13066 case PdmPhysicalDpiX:
13067 return qRound(d: screen->physicalDotsPerInchX());
13068 case PdmPhysicalDpiY:
13069 return qRound(d: screen->physicalDotsPerInchY());
13070 case PdmDevicePixelRatio:
13071 return resolveDevicePixelRatio();
13072 case PdmDevicePixelRatioScaled:
13073 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13074 case PdmDevicePixelRatioF_EncodedA:
13075 Q_FALLTHROUGH();
13076 case PdmDevicePixelRatioF_EncodedB:
13077 return QPaintDevice::encodeMetricF(metric: m, value: resolveDevicePixelRatio());
13078 default:
13079 break;
13080 }
13081 return QPaintDevice::metric(metric: m);
13082}
13083
13084/*!
13085 Initializes the \a painter pen, background and font to the same as
13086 the given widget's. This function is called automatically when the
13087 painter is opened on a QWidget.
13088*/
13089void QWidget::initPainter(QPainter *painter) const
13090{
13091 const QPalette &pal = palette();
13092 painter->d_func()->state->pen = QPen(pal.brush(cr: foregroundRole()), 1);
13093 painter->d_func()->state->bgBrush = pal.brush(cr: backgroundRole());
13094 QFont f(font(), const_cast<QWidget *>(this));
13095 painter->d_func()->state->deviceFont = f;
13096 painter->d_func()->state->font = f;
13097}
13098
13099/*!
13100 \internal
13101
13102 Do PaintDevice rendering with the specified \a offset.
13103*/
13104QPaintDevice *QWidget::redirected(QPoint *offset) const
13105{
13106 return d_func()->redirected(offset);
13107}
13108
13109/*!
13110 \internal
13111
13112 A painter that is shared among other instances of QPainter.
13113*/
13114QPainter *QWidget::sharedPainter() const
13115{
13116 // Someone sent a paint event directly to the widget
13117 if (!d_func()->redirectDev)
13118 return nullptr;
13119
13120 QPainter *sp = d_func()->sharedPainter();
13121 if (!sp || !sp->isActive())
13122 return nullptr;
13123
13124 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13125 return nullptr;
13126
13127 return sp;
13128}
13129
13130/*!
13131 \fn void QWidget::setMask(const QRegion &region)
13132 \overload
13133
13134 Causes only the parts of the widget which overlap \a region to be
13135 visible. If the region includes pixels outside the rect() of the
13136 widget, window system controls in that area may or may not be
13137 visible, depending on the platform.
13138
13139 Since QRegion allows arbitrarily complex regions to be created, widget
13140 masks can be made to suit the most unconventionally-shaped windows, and
13141 even allow widgets to be displayed with holes in them. Note that this
13142 effect can be slow if the region is particularly complex.
13143
13144 Widget masks are used to hint to the window system that the application
13145 does not want mouse events for areas outside the mask. On most systems,
13146 they also result in coarse visual clipping. To get smooth window edges, use
13147 translucent background and anti-aliased painting instead, as shown in the
13148 \l{Translucent Background} example.
13149
13150 \sa windowOpacity
13151*/
13152void QWidget::setMask(const QRegion &newMask)
13153{
13154 Q_D(QWidget);
13155
13156 d->createExtra();
13157 if (newMask == d->extra->mask)
13158 return;
13159
13160#ifndef QT_NO_BACKINGSTORE
13161 const QRegion oldMask(d->extra->mask);
13162#endif
13163
13164 d->extra->mask = newMask;
13165 d->extra->hasMask = !newMask.isEmpty();
13166
13167 if (!testAttribute(attribute: Qt::WA_WState_Created))
13168 return;
13169
13170 d->setMask_sys(newMask);
13171
13172#ifndef QT_NO_BACKINGSTORE
13173 if (!isVisible())
13174 return;
13175
13176 if (!d->extra->hasMask) {
13177 // Mask was cleared; update newly exposed area.
13178 QRegion expose(rect());
13179 expose -= oldMask;
13180 if (!expose.isEmpty()) {
13181 d->setDirtyOpaqueRegion();
13182 update(rgn: expose);
13183 }
13184 return;
13185 }
13186
13187 if (!isWindow()) {
13188 // Update newly exposed area on the parent widget.
13189 QRegion parentExpose(rect());
13190 parentExpose -= newMask;
13191 if (!parentExpose.isEmpty()) {
13192 d->setDirtyOpaqueRegion();
13193 parentExpose.translate(p: data->crect.topLeft());
13194 parentWidget()->update(rgn: parentExpose);
13195 }
13196
13197 // Update newly exposed area on this widget
13198 if (!oldMask.isEmpty())
13199 update(rgn: newMask - oldMask);
13200 }
13201#endif
13202}
13203
13204void QWidgetPrivate::setMask_sys(const QRegion &region)
13205{
13206 Q_Q(QWidget);
13207 if (QWindow *window = q->windowHandle())
13208 window->setMask(region);
13209}
13210
13211/*!
13212 \fn void QWidget::setMask(const QBitmap &bitmap)
13213
13214 Causes only the pixels of the widget for which \a bitmap has a
13215 corresponding 1 bit to be visible. If the region includes pixels
13216 outside the rect() of the widget, window system controls in that
13217 area may or may not be visible, depending on the platform.
13218
13219 Note that this effect can be slow if the region is particularly
13220 complex.
13221
13222 The following code shows how an image with an alpha channel can be
13223 used to generate a mask for a widget:
13224
13225 \snippet widget-mask/main.cpp 0
13226
13227 The label shown by this code is masked using the image it contains,
13228 giving the appearance that an irregularly-shaped image is being drawn
13229 directly onto the screen.
13230
13231 Masked widgets receive mouse events only on their visible
13232 portions.
13233
13234 \sa clearMask(), windowOpacity()
13235*/
13236void QWidget::setMask(const QBitmap &bitmap)
13237{
13238 setMask(QRegion(bitmap));
13239}
13240
13241/*!
13242 \fn void QWidget::clearMask()
13243
13244 Removes any mask set by setMask().
13245
13246 \sa setMask()
13247*/
13248void QWidget::clearMask()
13249{
13250 Q_D(QWidget);
13251 if (!d->extra || !d->extra->hasMask)
13252 return;
13253 setMask(QRegion());
13254}
13255
13256void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13257{
13258 Q_ASSERT(widgetAsObject->isWidgetType());
13259 Q_ASSERT(!newParent || newParent->isWidgetType());
13260 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13261 widget->setParent(static_cast<QWidget*>(newParent));
13262}
13263
13264std::string QWidgetPrivate::flagsForDumping() const
13265{
13266 Q_Q(const QWidget);
13267 std::string flags = QObjectPrivate::flagsForDumping();
13268 if (QApplication::focusWidget() == q)
13269 flags += 'F';
13270 if (q->isVisible()) {
13271 std::stringstream s;
13272 s << '<'
13273 << q->width() << 'x' << q->height()
13274 << std::showpos << q->x() << q->y()
13275 << '>';
13276 flags += s.str();
13277 } else {
13278 flags += 'I';
13279 }
13280 return flags;
13281}
13282
13283void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13284{
13285#if QT_CONFIG(xcb)
13286 Q_Q(QWidget);
13287
13288 if (!q->windowHandle())
13289 return;
13290
13291 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13292 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDesktop))
13293 wmWindowType |= QXcbWindow::Desktop;
13294 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDock))
13295 wmWindowType |= QXcbWindow::Dock;
13296 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolBar))
13297 wmWindowType |= QXcbWindow::Toolbar;
13298 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeMenu))
13299 wmWindowType |= QXcbWindow::Menu;
13300 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeUtility))
13301 wmWindowType |= QXcbWindow::Utility;
13302 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeSplash))
13303 wmWindowType |= QXcbWindow::Splash;
13304 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDialog))
13305 wmWindowType |= QXcbWindow::Dialog;
13306 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDropDownMenu))
13307 wmWindowType |= QXcbWindow::DropDownMenu;
13308 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypePopupMenu))
13309 wmWindowType |= QXcbWindow::PopupMenu;
13310 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolTip))
13311 wmWindowType |= QXcbWindow::Tooltip;
13312 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeNotification))
13313 wmWindowType |= QXcbWindow::Notification;
13314 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeCombo))
13315 wmWindowType |= QXcbWindow::Combo;
13316 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDND))
13317 wmWindowType |= QXcbWindow::Dnd;
13318
13319 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13320 return;
13321
13322 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13323 xcbWindow->setWindowType(wmWindowType);
13324#else
13325 Q_UNUSED(skipIfMissing);
13326#endif
13327}
13328
13329/*!
13330 \internal
13331 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13332 Return false otherwise.
13333 */
13334bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13335{
13336 Q_Q(const QWidget);
13337 const QWidgetList &children = q->findChildren<QWidget *>(options: Qt::FindChildrenRecursively);
13338 for (const auto *child : children) {
13339 if (child->focusPolicy() == policy && child->isEnabled()
13340 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13341 return true;
13342 }
13343 }
13344 return false;
13345}
13346
13347#ifndef QT_NO_DEBUG_STREAM
13348
13349namespace {
13350QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13351{
13352 const QDebugStateSaver saver(debug);
13353 debug.nospace();
13354 debug << '[';
13355 if (const QWidget *widget = attributes.widget) {
13356 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13357 const QMetaEnum me = qtMo->enumerator(index: qtMo->indexOfEnumerator(name: "WidgetAttribute"));
13358 int count = 0;
13359 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13360 if (widget->testAttribute(attribute: static_cast<Qt::WidgetAttribute>(a))) {
13361 if (count++)
13362 debug << ',';
13363 debug << me.valueToKey(value: a);
13364 }
13365 }
13366 }
13367 debug << ']';
13368 return debug;
13369}
13370}
13371
13372QDebug operator<<(QDebug debug, const QWidget *widget)
13373{
13374 const QDebugStateSaver saver(debug);
13375 debug.nospace();
13376 if (widget) {
13377 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13378 if (!widget->objectName().isEmpty())
13379 debug << ", name=" << widget->objectName();
13380 if (debug.verbosity() > 2) {
13381 const QRect geometry = widget->geometry();
13382 const QRect frameGeometry = widget->frameGeometry();
13383 if (widget->isVisible())
13384 debug << ", visible";
13385 if (!widget->isEnabled())
13386 debug << ", disabled";
13387 debug << ", states=" << widget->windowState()
13388 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13389 debug << ", attributes=" << WidgetAttributes{.widget: widget};
13390 if (widget->isWindow())
13391 debug << ", window";
13392 debug << ", " << geometry.width() << 'x' << geometry.height()
13393 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13394 if (frameGeometry != geometry) {
13395 const QMargins margins(geometry.x() - frameGeometry.x(),
13396 geometry.y() - frameGeometry.y(),
13397 frameGeometry.right() - geometry.right(),
13398 frameGeometry.bottom() - geometry.bottom());
13399 debug << ", margins=" << margins;
13400 }
13401 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13402 if (const WId wid = widget->internalWinId())
13403 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13404 }
13405 debug << ')';
13406 } else {
13407 debug << "QWidget(0x0)";
13408 }
13409 return debug;
13410}
13411#endif // !QT_NO_DEBUG_STREAM
13412
13413
13414// *************************** Focus abstraction ************************************
13415
13416#define FOCUS_NEXT(w) w->d_func()->focus_next
13417#define FOCUS_PREV(w) w->d_func()->focus_prev
13418
13419/*!
13420 \internal
13421 \return next or previous element in the focus chain, depending on
13422 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13423 */
13424QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13425{
13426 Q_Q(const QWidget);
13427 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13428}
13429
13430/*!
13431 \internal
13432 Removes a widget from the focus chain, respecting the flags set in \param rules.
13433 \list
13434 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13435 in the focus chain, depending on \param direction.
13436 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13437 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13438 \endlist
13439 \return \c true if the widget has been removed, otherwise \c false.
13440 */
13441bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13442{
13443 Q_Q(QWidget);
13444 if (!isFocusChainConsistent()) {
13445#ifdef QT_DEBUG
13446 if (rules.testFlag(flag: FocusChainRemovalRule::AssertConsistency))
13447 qFatal() << q << "has inconsistent focus chain.";
13448#endif
13449 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13450 return false;
13451 }
13452
13453 if (!isInFocusChain()) {
13454 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13455 return false;
13456 }
13457
13458 if (rules.testFlag(flag: FocusChainRemovalRule::EnsureFocusOut))
13459 q->focusNextPrevChild(next: direction == FocusDirection::Next);
13460
13461 FOCUS_NEXT(FOCUS_PREV(q)) = FOCUS_NEXT(q);
13462 FOCUS_PREV(FOCUS_NEXT(q)) = FOCUS_PREV(q);
13463 initFocusChain();
13464 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13465 return true;
13466}
13467
13468/*!
13469 \internal
13470 Initialises the focus chain by making the widget point to itself.
13471 */
13472void QWidgetPrivate::initFocusChain()
13473{
13474 Q_Q(QWidget);
13475 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13476 FOCUS_PREV(q) = q;
13477 FOCUS_NEXT(q) = q;
13478}
13479
13480/*!
13481 \internal
13482 Reads QWidget children, which are not part of a focus chain yet.
13483 Inserts them into the focus chain before or after the widget,
13484 depending on \param direction and in the order of their creation.
13485 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13486 */
13487void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13488{
13489 Q_Q(QWidget);
13490
13491 // separate the focus chain into new (children of myself) and old (the rest)
13492 QWidget *firstOld = nullptr;
13493 QWidget *lastOld = nullptr; // last in the old list
13494 QWidget *lastNew = q; // last in the new list
13495 bool prevWasNew = true;
13496 QWidget *widget = nextPrevElementInFocusChain(direction);
13497
13498 // For efficiency, do not maintain the list invariant inside the loop.
13499 // Append items to the relevant list, and we optimize by not changing pointers,
13500 // when subsequent items are going into the same list.
13501 while (widget != q) {
13502 bool currentIsNew = q->isAncestorOf(child: widget);
13503 if (currentIsNew) {
13504 if (!prevWasNew) {
13505 // previous was old => append to new list
13506 FOCUS_NEXT(lastNew) = widget;
13507 FOCUS_PREV(widget) = lastNew;
13508 }
13509 lastNew = widget;
13510 } else {
13511 if (prevWasNew) {
13512 // prev was new => append to old list, if it exists
13513 if (lastOld) {
13514 FOCUS_NEXT(lastOld) = widget;
13515 FOCUS_PREV(widget) = lastOld;
13516 } else {
13517 // start the old list
13518 firstOld = widget;
13519 }
13520 }
13521 lastOld = widget;
13522 }
13523 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13524 prevWasNew = currentIsNew;
13525 }
13526
13527 // repair old list:
13528 if (firstOld) {
13529 FOCUS_NEXT(lastOld) = firstOld;
13530 FOCUS_PREV(firstOld) = lastOld;
13531 }
13532
13533 if (!q->isWindow()) {
13534 QWidget *topLevel = q->window();
13535 // insert new chain into toplevel's chain
13536 QWidget *prev = FOCUS_PREV(topLevel);
13537 FOCUS_PREV(topLevel) = lastNew;
13538 FOCUS_NEXT(prev) = q;
13539 FOCUS_PREV(q) = prev;
13540 FOCUS_NEXT(lastNew) = topLevel;
13541 } else {
13542 // repair new list
13543 FOCUS_NEXT(lastNew) = q;
13544 FOCUS_PREV(q) = lastNew;
13545 }
13546}
13547
13548/*!
13549 \internal
13550 Inserts a widget into the focus chain before or after \param position, depending on
13551 \param direction.
13552 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13553 */
13554bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13555{
13556 Q_Q(QWidget);
13557 Q_ASSERT(position);
13558 QWidget *next = FOCUS_NEXT(q);
13559 QWidget *previous = FOCUS_PREV(q);
13560
13561 switch (direction) {
13562 case FocusDirection::Next:
13563 if (previous == position) {
13564 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13565 return false;
13566 }
13567
13568 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13569
13570 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13571 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13572 FOCUS_NEXT(position) = q;
13573 FOCUS_PREV(q) = position;
13574 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13575 break;
13576
13577 case FocusDirection::Previous:
13578 if (next == position) {
13579 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13580 return false;
13581 }
13582
13583 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13584
13585 FOCUS_PREV(q) = FOCUS_PREV(position);
13586 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13587 FOCUS_PREV(position) = q;
13588 FOCUS_NEXT(q) = position;
13589 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13590 break;
13591 }
13592
13593 Q_ASSERT(isFocusChainConsistent());
13594 return true;
13595}
13596
13597/*!
13598 \internal
13599 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13600 before or after \param position, depending on \param direction.
13601 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13602 \note
13603 \param toBeInserted must be a consistent focus chain.
13604 */
13605bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13606 FocusDirection direction, QWidget *position)
13607{
13608 if (toBeInserted.isEmpty()) {
13609 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13610 return false;
13611 }
13612
13613 Q_ASSERT_X(!toBeInserted.contains(position),
13614 Q_FUNC_INFO,
13615 "Coding error: toBeInserted contains position");
13616
13617 QWidget *first = toBeInserted.constFirst();
13618 QWidget *last = toBeInserted.constLast();
13619
13620 // Call QWidget override to log accordingly
13621 if (toBeInserted.count() == 1)
13622 return first->d_func()->insertIntoFocusChain(direction, position);
13623
13624 Q_ASSERT(first != last);
13625 switch (direction) {
13626 case FocusDirection::Previous:
13627 if (FOCUS_PREV(position) == last) {
13628 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13629 << position;
13630 return false;
13631 }
13632 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13633 FOCUS_PREV(first) = FOCUS_PREV(position);
13634 FOCUS_NEXT(last) = position;
13635 FOCUS_PREV(position) = last;
13636 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13637 break;
13638 case FocusDirection::Next:
13639 if (FOCUS_PREV(position) == last) {
13640 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13641 << position;
13642 return false;
13643 }
13644 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13645 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13646 FOCUS_PREV(first) = position;
13647 FOCUS_NEXT(position) = first;
13648 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13649 break;
13650 }
13651
13652 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13653 return true;
13654}
13655
13656/*!
13657 \internal
13658 \return a QWidgetList, representing the part of the focus chain,
13659 starting with \param from and ending with \param to, in \param direction.
13660 */
13661QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13662{
13663 QWidgetList path({from});
13664 if (from == to)
13665 return path;
13666
13667 QWidget *current = from;
13668 do {
13669 switch (direction) {
13670 case QWidgetPrivate::FocusDirection::Previous:
13671 current = current->previousInFocusChain();
13672 break;
13673 case QWidgetPrivate::FocusDirection::Next:
13674 current = current->nextInFocusChain();
13675 break;
13676 }
13677 if (path.contains(t: current))
13678 return QWidgetList();
13679 path << current;
13680 } while (current != to);
13681
13682 return path;
13683}
13684
13685/*!
13686 \internal
13687 Removes the part from the focus chain starting with \param from and ending with \param to,
13688 in \param direction.
13689 \return removed part as a QWidgetList.
13690 */
13691QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13692 QWidget *to,
13693 FocusDirection direction)
13694{
13695 // Check if there is a path from->to in direction
13696 const QWidgetList path = focusPath(from, to , direction);
13697 if (path.isEmpty()) {
13698 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13699 return QWidgetList();
13700 }
13701
13702 QWidget *first = path.constFirst();
13703 QWidget *last = path.constLast();
13704 if (first == last) {
13705 first->d_func()->removeFromFocusChain();
13706 return QWidgetList({first});
13707 }
13708
13709 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13710 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13711 FOCUS_PREV(first) = last;
13712 FOCUS_NEXT(last) = first;
13713 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13714 return path;
13715}
13716
13717/*!
13718 \internal
13719 \return The last focus child of the widget, traversing the focus chain no further than
13720 \param noFurtherThan.
13721 */
13722QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13723{
13724 Q_Q(QWidget);
13725 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13726 // that determines the last focus child for a widget, taking proxies and compound widgets into
13727 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13728 // to a child), 'lastFocusChild' will be set to the target itself.
13729 QWidget *lastFocusChild = q;
13730
13731 QWidget *focusProxy = deepestFocusProxy();
13732 if (!focusProxy) {
13733 // QTBUG-81097: Another case is possible here. We can have a child
13734 // widget, that sets its focusProxy() to the parent (target).
13735 // An example of such widget is a QLineEdit, nested into
13736 // a QAbstractSpinBox. In this case such widget should be considered
13737 // the last focus child.
13738 for (auto *object : std::as_const(t: q->children())) {
13739 QWidget *w = qobject_cast<QWidget *>(o: object);
13740 if (w && w->focusProxy() == q) {
13741 lastFocusChild = w;
13742 break;
13743 }
13744 }
13745 } else if (q->isAncestorOf(child: focusProxy)) {
13746 lastFocusChild = focusProxy;
13747 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13748 focusNext != focusProxy && q->isAncestorOf(child: focusNext)
13749 && focusNext->window() == focusProxy->window();
13750 focusNext = focusNext->nextInFocusChain()) {
13751 if (focusNext == noFurtherThan)
13752 break;
13753 if (focusNext->focusPolicy() != Qt::NoFocus)
13754 lastFocusChild = focusNext;
13755 }
13756 }
13757 return lastFocusChild;
13758};
13759
13760/*!
13761 \internal
13762 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13763 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13764 are pointing to the widget itself.
13765
13766 \note
13767 This method doesn't check the consistency of the focus chain.
13768 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13769 isInFocusChain() will return \c true for all of those widgets, even if they represent
13770 an inconsistent focus chain.
13771 */
13772bool QWidgetPrivate::isInFocusChain() const
13773{
13774 Q_Q(const QWidget);
13775 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13776}
13777
13778/*!
13779 \internal
13780 A focus chain is consistent, when it is circular: Following the chain in either direction
13781 has to return to the beginning. This is why a newly constructed widget points to itself,
13782 when the focus chain has been initialized. A newly constructed widget is considered to have
13783 a consistent focus chain, while not being part of a focus chain.
13784
13785 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13786 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13787 It returns \c false, if one of the following is detected:
13788 \list
13789 \li nullptr found in a previous/next pointer.
13790 \li broken chain: widget A is B's previous, but B isn't A's next.
13791 \li chain isn't closed: starting at A doesn't lead back to A.
13792 \endlist
13793 It return \c true, if none of the above is observed.
13794
13795 \note
13796 The focus chain is checked only in forward direction.
13797 This is sufficient, because the check for a broken chain asserts consistent paths
13798 in both directions.
13799 */
13800bool QWidgetPrivate::isFocusChainConsistent() const
13801{
13802 Q_Q(const QWidget);
13803 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13804 if (skip)
13805 return true;
13806
13807 if (!isInFocusChain())
13808 return true;
13809
13810 const QWidget *position = q;
13811
13812 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13813 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13814 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13815 << "Previous pointing to" << FOCUS_PREV(position)
13816 << "Next pointing to" << FOCUS_NEXT(position);
13817 return false;
13818 }
13819 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13820 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13821 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13822 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13823 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13824 return false;
13825 }
13826 position = FOCUS_NEXT(position);
13827 if (position == q)
13828 return true;
13829
13830 }
13831
13832 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13833 return false;
13834}
13835
13836#undef FOCUS_NEXT
13837#undef FOCUS_PREV
13838
13839
13840QT_END_NAMESPACE
13841
13842#include "moc_qwidget.cpp"
13843#include "moc_qwidget_p.cpp"
13844

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