Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwidget.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
5
6#include "qapplication.h"
8#include "qbrush.h"
9#include "qcursor.h"
10#include "private/qduplicatetracker_p.h"
11#include "qevent.h"
12#include "qlayout.h"
13#if QT_CONFIG(menu)
14#include "qmenu.h"
15#endif
16#include "qmetaobject.h"
17#include "qpixmap.h"
18#include "qpointer.h"
19#include "qstack.h"
20#include "qstyle.h"
21#include "qstylefactory.h"
22#include "qvariant.h"
23#include "qwidget.h"
24#include "qstyleoption.h"
25#include "qstylehints.h"
26#if QT_CONFIG(accessibility)
27# include "qaccessible.h"
28# include <private/qaccessiblecache_p.h>
29#endif
30#include <qpa/qplatformwindow.h>
31#include <qpa/qplatformwindow_p.h>
32#include "private/qwidgetwindow_p.h"
33#include "qpainter.h"
34#if QT_CONFIG(tooltip)
35#include "private/qtooltip_p.h"
36#endif
37#if QT_CONFIG(whatsthis)
38#include "qwhatsthis.h"
39#endif
40#include "qdebug.h"
41#if QT_CONFIG(style_stylesheet)
42#include "private/qstylesheetstyle_p.h"
43#endif
44#include "private/qstyle_p.h"
45#include "qfileinfo.h"
46#include "qscopeguard.h"
47#include <QtGui/qinputmethod.h>
48
49#if QT_CONFIG(graphicseffect)
50#include <private/qgraphicseffect_p.h>
51#endif
52#include <qbackingstore.h>
53#include <private/qwidgetrepaintmanager_p.h>
54#include <private/qpaintengine_raster_p.h>
55
56#include "qwidget_p.h"
57#include <QtGui/private/qwindow_p.h>
58#if QT_CONFIG(action)
59# include "QtGui/private/qaction_p.h"
60#endif
61#include "qlayout_p.h"
62#if QT_CONFIG(graphicsview)
63#include "QtWidgets/qgraphicsproxywidget.h"
64#include "QtWidgets/qgraphicsscene.h"
65#include "private/qgraphicsproxywidget_p.h"
66#include "private/qgraphicsview_p.h"
67#endif
68#include "QtWidgets/qabstractscrollarea.h"
69#include "private/qabstractscrollarea_p.h"
70#include "private/qevent_p.h"
71
72#include "private/qgesturemanager_p.h"
73
74#ifdef QT_KEYPAD_NAVIGATION
75#if QT_CONFIG(tabwidget)
76#include "qtabwidget.h" // Needed in inTabWidget()
77#endif
78#endif // QT_KEYPAD_NAVIGATION
79
81
82#include <sstream>
83
84QT_BEGIN_NAMESPACE
85
86using namespace QNativeInterface::Private;
87using namespace Qt::StringLiterals;
88
89Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
90Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
91Q_STATIC_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
92Q_STATIC_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
93
94#ifndef QT_NO_DEBUG_STREAM
95namespace {
96 struct WidgetAttributes { const QWidget *widget; };
97 QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
98}
99#endif
100
101static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
102{
103 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
104 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
105}
106
107extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
108
109static void setAttribute_internal(Qt::WidgetAttribute attribute,
110 bool on, QWidgetData *data, QWidgetPrivate *d);
111
112QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
113 : QObjectPrivate(version)
114 , focus_next(nullptr)
115 , focus_prev(nullptr)
116 , focus_child(nullptr)
117 , layout(nullptr)
118 , needsFlush(nullptr)
119 , redirectDev(nullptr)
120 , widgetItem(nullptr)
121 , extraPaintEngine(nullptr)
122 , polished(nullptr)
123 , graphicsEffect(nullptr)
124#if !defined(QT_NO_IM)
125 , imHints(Qt::ImhNone)
126#endif
127#if QT_CONFIG(tooltip)
128 , toolTipDuration(-1)
129#endif
130 , directFontResolveMask(0)
131 , inheritedFontResolveMask(0)
132 , directPaletteResolveMask(0)
133 , inheritedPaletteResolveMask(0)
134 , leftmargin(0)
135 , topmargin(0)
136 , rightmargin(0)
137 , bottommargin(0)
138 , leftLayoutItemMargin(0)
139 , topLayoutItemMargin(0)
140 , rightLayoutItemMargin(0)
141 , bottomLayoutItemMargin(0)
142 , hd(nullptr)
143 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
144 , fg_role(QPalette::NoRole)
145 , bg_role(QPalette::NoRole)
146 , dirtyOpaqueChildren(1)
147 , isOpaque(0)
148 , retainSizeWhenHiddenChanged(0)
149 , inDirtyList(0)
150 , isScrolled(0)
151 , isMoved(0)
152 , usesDoubleBufferedGLContext(0)
153 , mustHaveWindowHandle(0)
154 , renderToTexture(0)
155 , textureChildSeen(0)
156#ifndef QT_NO_IM
157 , inheritsInputMethodHints(0)
158#endif
159 , renderToTextureReallyDirty(1)
160 , usesRhiFlush(0)
161 , childrenHiddenByWState(0)
162 , childrenShownByExpose(0)
163 , dontSetExplicitShowHide(0)
164 , inheritStyleRecursionGuard(0)
165#if defined(Q_OS_WIN)
166 , noPaintOnScreen(0)
167#endif
168{
169 if (Q_UNLIKELY(!qApp)) {
170 qFatal("QWidget: Must construct a QApplication before a QWidget");
171 return;
172 }
173
174 willBeWidget = true; // used in QObject's ctor
175 memset(high_attributes, 0, sizeof(high_attributes));
176
177#ifdef QWIDGET_EXTRA_DEBUG
178 static int count = 0;
179 qDebug() << "widgets" << ++count;
180#endif
181}
182
183
184QWidgetPrivate::~QWidgetPrivate()
185{
186 if (widgetItem)
187 widgetItem->wid = nullptr;
188
189 if (extra)
190 deleteExtra();
191}
192
193/*!
194 \internal
195*/
196void QWidgetPrivate::scrollChildren(int dx, int dy)
197{
198 Q_Q(QWidget);
199 if (q->children().size() > 0) { // scroll children
200 QPoint pd(dx, dy);
201 QObjectList childObjects = q->children();
202 for (int i = 0; i < childObjects.size(); ++i) { // move all children
203 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
204 if (w && !w->isWindow()) {
205 QPoint oldp = w->pos();
206 QRect r(w->pos() + pd, w->size());
207 w->data->crect = r;
208 if (w->testAttribute(Qt::WA_WState_Created))
209 w->d_func()->setWSGeometry();
210 w->d_func()->setDirtyOpaqueRegion();
211 QMoveEvent e(r.topLeft(), oldp);
212 QCoreApplication::sendEvent(w, &e);
213 }
214 }
215 }
216}
217
218void QWidgetPrivate::setWSGeometry()
219{
220 Q_Q(QWidget);
221 if (QWindow *window = q->windowHandle())
222 window->setGeometry(data.crect);
223}
224
225void QWidgetPrivate::updateWidgetTransform(QEvent *event)
226{
227 Q_Q(QWidget);
228 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
229 QTransform t;
230 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
231 t.translate(p.x(), p.y());
232 QGuiApplication::inputMethod()->setInputItemTransform(t);
233 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
234 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
235 }
236}
237
238#ifdef QT_KEYPAD_NAVIGATION
239QPointer<QWidget> QWidgetPrivate::editingWidget;
240
241/*!
242 Returns \c true if this widget currently has edit focus; otherwise false.
243
244 This feature is only available in Qt for Embedded Linux.
245
246 \sa setEditFocus(), QApplication::navigationMode()
247*/
248bool QWidget::hasEditFocus() const
249{
250 const QWidget* w = this;
251 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
252 w = w->d_func()->extra->focus_proxy;
253 return QWidgetPrivate::editingWidget == w;
254}
255
256/*!
257 \fn void QWidget::setEditFocus(bool enable)
258
259 If \a enable is true, make this widget have edit focus, in which
260 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
261 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
262 change focus.
263
264 This feature is only available in Qt for Embedded Linux.
265
266 \sa hasEditFocus(), QApplication::navigationMode()
267*/
268void QWidget::setEditFocus(bool on)
269{
270 QWidget *f = this;
271 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
272 f = f->d_func()->extra->focus_proxy;
273
274 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
275 QWidgetPrivate::editingWidget->setEditFocus(false);
276
277 if (on && !f->hasFocus())
278 f->setFocus();
279
280 if ((!on && !QWidgetPrivate::editingWidget)
281 || (on && QWidgetPrivate::editingWidget == f)) {
282 return;
283 }
284
285 if (!on && QWidgetPrivate::editingWidget == f) {
286 QWidgetPrivate::editingWidget = 0;
287 QEvent event(QEvent::LeaveEditFocus);
288 QCoreApplication::sendEvent(f, &event);
289 QCoreApplication::sendEvent(f->style(), &event);
290 } else if (on) {
291 QWidgetPrivate::editingWidget = f;
292 QEvent event(QEvent::EnterEditFocus);
293 QCoreApplication::sendEvent(f, &event);
294 QCoreApplication::sendEvent(f->style(), &event);
295 }
296}
297#endif
298
299/*!
300 \property QWidget::autoFillBackground
301 \brief whether the widget background is filled automatically
302 \since 4.1
303
304 If enabled, this property will cause Qt to fill the background of the
305 widget before invoking the paint event. The color used is defined by the
306 QPalette::Window color role from the widget's \l{QPalette}{palette}.
307
308 In addition, Windows are always filled with QPalette::Window, unless the
309 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
310
311 This property cannot be turned off (i.e., set to false) if a widget's
312 parent has a static gradient for its background.
313
314 \warning Use this property with caution in conjunction with
315 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
316 background or a border-image, this property is automatically disabled.
317
318 By default, this property is \c false.
319
320 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
321 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
322*/
323bool QWidget::autoFillBackground() const
324{
325 Q_D(const QWidget);
326 return d->extra && d->extra->autoFillBackground;
327}
328
329void QWidget::setAutoFillBackground(bool enabled)
330{
331 Q_D(QWidget);
332 if (!d->extra)
333 d->createExtra();
334 if (d->extra->autoFillBackground == enabled)
335 return;
336
337 d->extra->autoFillBackground = enabled;
338 d->updateIsOpaque();
339 update();
340 d->updateIsOpaque();
341}
342
343/*!
344 \class QWidget
345 \brief The QWidget class is the base class of all user interface objects.
346
347 \ingroup basicwidgets
348 \inmodule QtWidgets
349
350 The widget is the atom of the user interface: it receives mouse, keyboard
351 and other events from the window system, and paints a representation of
352 itself on the screen. Every widget is rectangular, and they are sorted in a
353 Z-order. A widget is clipped by its parent and by the widgets in front of
354 it.
355
356 A widget that is not embedded in a parent widget is called a window.
357 Usually, windows have a frame and a title bar, although it is also possible
358 to create windows without such decoration using suitable
359 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
360 subclasses of QDialog are the most common window types.
361
362 Every widget's constructor accepts one or two standard arguments:
363
364 \list 1
365 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
366 If it is \nullptr (the default), the new widget will be a window.
367 If not, it will be a child of \e parent, and be constrained by
368 \e parent's geometry (unless you specify Qt::Window as window flag).
369 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
370 the default is suitable for most widgets, but to get, for
371 example, a window without a window system frame, you must use
372 special flags.
373 \endlist
374
375 QWidget has many member functions, but some of them have little direct
376 functionality; for example, QWidget has a font property, but never uses
377 this itself. There are many subclasses that provide real functionality,
378 such as QLabel, QPushButton, QListWidget, and QTabWidget.
379
380
381 \section1 Top-Level and Child Widgets
382
383 A widget without a parent widget is always an independent window (top-level
384 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
385 title bar and icon, respectively.
386
387 Non-window widgets are child widgets, displayed within their parent
388 widgets. Most widgets in Qt are mainly useful as child widgets. For
389 example, it is possible to display a button as a top-level window, but most
390 people prefer to put their buttons inside other widgets, such as QDialog.
391
392 \image parent-child-widgets.png
393 {Appointment widget with labeled child widgets}
394 \caption A parent widget containing various child widgets.
395
396 The diagram above shows a QGroupBox widget being used to hold various child
397 widgets in a layout provided by QGridLayout. The QLabel child widgets have
398 been outlined to indicate their full sizes.
399
400 If you want to use a QWidget to hold child widgets, you will usually want to
401 add a layout to the parent QWidget. See \l{Layout Management} for more
402 information.
403
404
405 \section1 Composite Widgets
406
407 When a widget is used as a container to group a number of child widgets, it
408 is known as a composite widget. These can be created by constructing a
409 widget with the required visual properties - a QFrame, for example - and
410 adding child widgets to it, usually managed by a layout.
411
412 Composite widgets can also be created by subclassing a standard widget,
413 such as QWidget or QFrame, and adding the necessary layout and child
414 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
415 {examples provided with Qt} use this approach, and it is also covered in
416 the Qt \l{Widgets Tutorial}.
417
418
419 \section1 Custom Widgets and Painting
420
421 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
422 display custom content that is composed using a series of painting
423 operations with an instance of the QPainter class. This approach contrasts
424 with the canvas-style approach used by the \l{Graphics View}
425 {Graphics View Framework} where items are added to a scene by the
426 application and are rendered by the framework itself.
427
428 Each widget performs all painting operations from within its paintEvent()
429 function. This is called whenever the widget needs to be redrawn, either
430 because of some external change or when requested by the application.
431
432 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
433 can handle paint events.
434
435
436 \section1 Size Hints and Size Policies
437
438 When implementing a new widget, it is almost always useful to reimplement
439 sizeHint() to provide a reasonable default size for the widget and to set
440 the correct size policy with setSizePolicy().
441
442 By default, composite widgets that do not provide a size hint will be
443 sized according to the space requirements of their child widgets.
444
445 The size policy lets you supply good default behavior for the layout
446 management system, so that other widgets can contain and manage yours
447 easily. The default size policy indicates that the size hint represents
448 the preferred size of the widget, and this is often good enough for many
449 widgets.
450
451 \note The size of top-level widgets are constrained to 2/3 of the desktop's
452 height and width. You can resize() the widget manually if these bounds are
453 inadequate.
454
455
456 \section1 Events
457
458 Widgets respond to events that are typically caused by user actions. Qt
459 delivers events to widgets by calling specific event handler functions with
460 instances of QEvent subclasses containing information about each event.
461
462 If your widget only contains child widgets, you probably don't need to
463 implement any event handlers. If you want to detect a mouse click in a
464 child widget, call the child's underMouse() function inside the widget's
465 mousePressEvent().
467 The \l{widgets/scribble}{Scribble example} implements a wider set of
468 events to handle mouse movement, button presses, and window resizing.
469
470 You will need to supply the behavior and content for your own widgets, but
471 here is a brief overview of the events that are relevant to QWidget,
472 starting with the most common ones:
473
474 \list
475 \li paintEvent() is called whenever the widget needs to be repainted.
476 Every widget displaying custom content must implement it. Painting
477 using a QPainter can only take place in a paintEvent() or a
478 function called by a paintEvent().
479 \li resizeEvent() is called when the widget has been resized.
480 \li mousePressEvent() is called when a mouse button is pressed while
481 the mouse cursor is inside the widget, or when the widget has
482 grabbed the mouse using grabMouse(). Pressing the mouse without
483 releasing it is effectively the same as calling grabMouse().
484 \li mouseReleaseEvent() is called when a mouse button is released. A
485 widget receives mouse release events when it has received the
486 corresponding mouse press event. This means that if the user
487 presses the mouse inside \e your widget, then drags the mouse
488 somewhere else before releasing the mouse button, \e your widget
489 receives the release event. There is one exception: if a popup menu
490 appears while the mouse button is held down, this popup immediately
491 steals the mouse events.
492 \li mouseDoubleClickEvent() is called when the user double-clicks in
493 the widget. If the user double-clicks, the widget receives a mouse
494 press event, a mouse release event, (a mouse click event,) a second
495 mouse press, this event and finally a second mouse release event.
496 (Some mouse move events may also be
497 received if the mouse is not held steady during this operation.) It
498 is \e{not possible} to distinguish a click from a double-click
499 until the second click arrives. (This is one reason why most GUI
500 books recommend that double-clicks be an extension of
501 single-clicks, rather than trigger a different action.)
502 \endlist
503
504 Widgets that accept keyboard input need to reimplement a few more event
505 handlers:
506
507 \list
508 \li keyPressEvent() is called whenever a key is pressed, and again when
509 a key has been held down long enough for it to auto-repeat. The
510 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
511 they are not used by the focus-change mechanisms. To force those
512 keys to be processed by your widget, you must reimplement
513 QWidget::event().
514 \li focusInEvent() is called when the widget gains keyboard focus
515 (assuming you have called setFocusPolicy()). Well-behaved widgets
516 indicate that they own the keyboard focus in a clear but discreet
517 way.
518 \li focusOutEvent() is called when the widget loses keyboard focus.
519 \endlist
520
521 You may be required to also reimplement some of the less common event
522 handlers:
523
524 \list
525 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
526 button is held down. This can be useful during drag and drop
527 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
528 you get mouse move events even when no buttons are held down.
529 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
530 \li keyReleaseEvent() is called whenever a key is released and while it
531 is held down (if the key is auto-repeating). In that case, the
532 widget will receive a pair of key release and key press event for
533 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
534 to the widget if they are not used by the focus-change mechanisms.
535 To force those keys to be processed by your widget, you must
536 reimplement QWidget::event().
537 \li wheelEvent() is called whenever the user turns the mouse wheel
538 while the widget has the focus.
539 \li enterEvent() is called when the mouse enters the widget's screen
540 space. (This excludes screen space owned by any of the widget's
541 children.)
542 \li leaveEvent() is called when the mouse leaves the widget's screen
543 space. If the mouse enters a child widget, it will not cause a
544 leaveEvent().
545 \li moveEvent() is called when the widget has been moved relative to
546 its parent.
547 \li closeEvent() is called when the user closes the widget (or when
548 close() is called).
549 \endlist
550
551 There are also some rather obscure events described in the documentation
552 for QEvent::Type. To handle these events, you need to reimplement event()
553 directly.
554
555 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
556 (to move the keyboard focus), and passes on most of the other events to
557 one of the more specialized handlers above.
559 Events and the mechanism used to deliver them are covered in
560 \l{The Event System}.
561
562 \section1 Groups of Functions and Properties
563
564 \table
565 \header \li Context \li Functions and Properties
567 \row \li Window functions \li
568 show(),
569 hide(),
570 raise(),
571 lower(),
572 close().
573
574 \row \li Top-level windows \li
575 \l windowModified, \l windowTitle, \l windowIcon,
576 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
577 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
578 showNormal().
579
580 \row \li Window contents \li
581 update(),
582 repaint(),
583 scroll().
584
585 \row \li Geometry \li
586 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
587 \l sizePolicy, sizeHint(), minimumSizeHint(),
588 updateGeometry(), layout(),
589 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
590 adjustSize(),
591 mapFromGlobal(), mapToGlobal(),
592 mapFromParent(), mapToParent(),
593 \l maximumSize, \l minimumSize, \l sizeIncrement,
594 \l baseSize, setFixedSize()
595
596 \row \li Mode \li
597 \l visible, isVisibleTo(),
598 \l enabled, isEnabledTo(),
599 \l modal,
600 isWindow(),
601 \l mouseTracking,
602 \l updatesEnabled,
603 visibleRegion().
604
605 \row \li Look and feel \li
606 style(),
607 setStyle(),
608 \l styleSheet,
609 \l cursor,
610 \l font,
611 \l palette,
612 backgroundRole(), setBackgroundRole(),
613 fontInfo(), fontMetrics().
614
615 \row \li Keyboard focus functions \li
616 \l focus, \l focusPolicy,
617 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
618 focusNextChild(), focusPreviousChild().
619
620 \row \li Mouse and keyboard grabbing \li
621 grabMouse(), releaseMouse(),
622 grabKeyboard(), releaseKeyboard(),
623 mouseGrabber(), keyboardGrabber().
624
625 \row \li Event handlers \li
626 event(),
627 mousePressEvent(),
628 mouseReleaseEvent(),
629 mouseDoubleClickEvent(),
630 mouseMoveEvent(),
631 keyPressEvent(),
632 keyReleaseEvent(),
633 focusInEvent(),
634 focusOutEvent(),
635 wheelEvent(),
636 enterEvent(),
637 leaveEvent(),
638 paintEvent(),
639 moveEvent(),
640 resizeEvent(),
641 closeEvent(),
642 dragEnterEvent(),
643 dragMoveEvent(),
644 dragLeaveEvent(),
645 dropEvent(),
646 childEvent(),
647 showEvent(),
648 hideEvent(),
649 customEvent().
650 changeEvent(),
651
652 \row \li System functions \li
653 parentWidget(), window(), setParent(), winId(),
654 find(), metric().
655
656 \row \li Context menu \li
657 contextMenuPolicy, contextMenuEvent(),
658 customContextMenuRequested(), actions()
659
660 \row \li Interactive help \li
661 setToolTip(), setWhatsThis()
662
663 \endtable
664
665
666 \section1 Widget Style Sheets
667
668 In addition to the standard widget styles for each platform, widgets can
669 also be styled according to rules specified in a \l{styleSheet}
670 {style sheet}. This feature enables you to customize the appearance of
671 specific widgets to provide visual cues to users about their purpose. For
672 example, a button could be styled in a particular way to indicate that it
673 performs a destructive action.
674
675 The use of widget style sheets is described in more detail in the
676 \l{Qt Style Sheets} document.
677
678
679 \section1 Transparency and Double Buffering
680
681 QWidget automatically double-buffers its painting, so there
682 is no need to write double-buffering code in paintEvent() to avoid
683 flicker.
684
685 The contents of parent widgets are propagated by
686 default to each of their children as long as Qt::WA_PaintOnScreen is not
687 set. Custom widgets can be written to take advantage of this feature by
688 updating irregular regions (to create non-rectangular child widgets), or
689 painting with colors that have less than full alpha component. The
690 following diagram shows how attributes and properties of a custom widget
691 can be fine-tuned to achieve different effects.
692
693 \image propagation-custom.png
694 {Three pixmaps of a house with different background properties:
695 transparent, filled with white, and uninitialized}
696
697 In the above diagram, a semi-transparent rectangular child widget with an
698 area removed is constructed and added to a parent widget (a QLabel showing
699 a pixmap). Then, different properties and widget attributes are set to
700 achieve different effects:
701
702 \list
703 \li The left widget has no additional properties or widget attributes
704 set. This default state suits most custom widgets that have
705 transparency, are irregularly-shaped, or do not paint over their
706 entire area with an opaque brush.
707 \li The center widget has the \l autoFillBackground property set. This
708 property is used with custom widgets that rely on the widget to
709 supply a default background, and do not paint over their entire
710 area with an opaque brush.
711 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
712 set. This indicates that the widget will paint over its entire area
713 with opaque colors. The widget's area will initially be
714 \e{uninitialized}, represented in the diagram with a red diagonal
715 grid pattern that shines through the overpainted area.
716 \endlist
717
718 To rapidly update custom widgets with simple background colors, such as
719 real-time plotting or graphing widgets, it is better to define a suitable
720 background color (using setBackgroundRole() with the
721 QPalette::Window role), set the \l autoFillBackground property, and only
722 implement the necessary drawing functionality in the widget's paintEvent().
723
724 To rapidly update custom widgets that constantly paint over their entire
725 areas with opaque content, for example, video streaming widgets, it is
726 better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
727 overhead associated with repainting the widget's background.
728
729 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
730 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
731 attribute takes precedence. Depending on your requirements, you should
732 choose either one of them.
733
734 The contents of parent widgets are also propagated to standard Qt widgets.
735 This can lead to some unexpected results if the parent widget is decorated
736 in a non-standard way, as shown in the diagram below.
737
738 \image propagation-standard.png
739 {One widget has a transparent background
740 and the other widget has a filled background}
741
742 The scope for customizing the painting behavior of standard Qt widgets,
743 without resorting to subclassing, is slightly less than that possible for
744 custom widgets. Usually, the desired appearance of a standard widget can be
745 achieved by setting its \l autoFillBackground property.
746
747
748 \section1 Creating Translucent Windows
749
750 You can create windows with translucent regions on window systems that
751 support compositing.
752
753 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
754 attribute with setAttribute() and ensure that its background is painted with
755 non-opaque colors in the regions you want to be partially transparent.
756
757 Platform notes:
758
759 \list
760 \li X11: This feature relies on the use of an X server that supports ARGB visuals
761 and a compositing window manager.
762 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
763 for the translucency to work.
764 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
765 for the translucency to work.
766 \endlist
767
768
769 \section1 Native Widgets vs Alien Widgets
770
771 Alien widgets are widgets unknown to the windowing system. They do not have
772 a native window handle associated with them. This feature significantly
773 speeds up widget painting, resizing, and removes flicker.
774
775 Should you require the old behavior with native windows, choose one of the
776 following options:
777
778 \list 1
779 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
780 \li Set the Qt::AA_NativeWindows attribute on your application. All
781 widgets will be native widgets.
782 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
783 and all its ancestors will become native (unless
784 Qt::WA_DontCreateNativeAncestors is set).
785 \li Call QWidget::winId to enforce a native window (this implies 3).
786 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
787 (this implies 3).
788 \endlist
789
790 \sa QEvent, QPainter, QGridLayout, QBoxLayout
791
792*/
793
794QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
795QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
796
797
798/*****************************************************************************
799 QWidget member functions
800 *****************************************************************************/
801
802/*
803 Widget state flags:
804 \list
805 \li Qt::WA_WState_Created The widget has a valid winId().
806 \li Qt::WA_WState_Visible The widget is currently visible.
807 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
808 become visible unless you call show() on it. Qt::WA_WState_Hidden
809 implies !Qt::WA_WState_Visible.
810 \li Qt::WA_WState_CompressKeys Compress keyboard events.
811 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
812 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
813 \li Qt::WA_WState_Reparented The widget has been reparented.
814 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
815 \endlist
816*/
817
819{
820 /* this cleans up when the constructor throws an exception */
821 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
822 {
823#ifdef QT_NO_EXCEPTIONS
824 Q_UNUSED(that);
825 Q_UNUSED(d);
826#else
827 QWidgetPrivate::allWidgets->remove(that);
828 d->removeFromFocusChain();
829#endif
830 }
831};
832
833/*!
834 Constructs a widget which is a child of \a parent, with widget
835 flags set to \a f.
836
837 If \a parent is \nullptr, the new widget becomes a window. If
838 \a parent is another widget, this widget becomes a child window
839 inside \a parent. The new widget is deleted when its \a parent is
840 deleted.
841
842 The widget flags argument, \a f, is normally 0, but it can be set
843 to customize the frame of a window (i.e. \a parent must be
844 \nullptr). To customize the frame, use a value composed
845 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
846
847 If you add a child widget to an already visible widget you must
848 explicitly show the child to make it visible.
849
850 Note that the X11 version of Qt may not be able to deliver all
851 combinations of style flags on all systems. This is because on
852 X11, Qt can only ask the window manager, and the window manager
853 can override the application's settings. On Windows, Qt can set
854 whatever flags you want.
855
856 \sa windowFlags
857*/
858QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
859 : QWidget(*new QWidgetPrivate, parent, f)
860{
861}
862
863
864/*! \internal
865*/
866QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
867 : QObject(dd, nullptr), QPaintDevice()
868 , data(&dd.data)
869{
870 Q_D(QWidget);
871 QT_TRY {
872 d->init(parent, f);
873 } QT_CATCH(...) {
874 QWidgetExceptionCleaner::cleanup(this, d_func());
875 QT_RETHROW;
876 }
877}
878
879/*!
880 \internal
881*/
882int QWidget::devType() const
883{
884 return QInternal::Widget;
885}
886
887
888//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
889void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
890{
891 bool customize = (flags & (Qt::CustomizeWindowHint
892 | Qt::FramelessWindowHint
893 | Qt::WindowTitleHint
894 | Qt::WindowSystemMenuHint
895 | Qt::WindowMinimizeButtonHint
896 | Qt::WindowMaximizeButtonHint
897 | Qt::WindowCloseButtonHint
898 | Qt::WindowContextHelpButtonHint));
899
900 uint type = (flags & Qt::WindowType_Mask);
901
902 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
903 type = Qt::Window;
904 flags |= Qt::Window;
905 }
906
907 if (flags & Qt::CustomizeWindowHint) {
908 // modify window flags to make them consistent.
909 // Only enable this on non-Mac platforms. Since the old way of doing this would
910 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
911 // we can't just add this in.
912 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
913# ifdef Q_OS_WIN
914 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
915# endif
916 ) {
917 flags |= Qt::WindowSystemMenuHint;
918 flags |= Qt::WindowTitleHint;
919 flags &= ~Qt::FramelessWindowHint;
920 }
921 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
922 // if any of the window hints that affect the titlebar are set
923 // and the window is supposed to have frame, we add a titlebar
924 // and system menu by default.
925 flags |= Qt::WindowSystemMenuHint;
926 flags |= Qt::WindowTitleHint;
927 }
928 if (!customize) { // don't modify window flags if the user explicitly set them.
929 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
930 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
931 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
932 }
933 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
934 flags |= Qt::WindowTransparentForInput;
935}
936
937void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
938{
939 Q_Q(QWidget);
940 isWidget = true;
941 wasWidget = true;
942
943#if QT_DEPRECATED_SINCE(6, 11)
944 QT_IGNORE_DEPRECATIONS(
945 const bool isDesktopWindow = (f & Qt::WindowType_Mask) == Qt::WindowType::Desktop;
946 Q_ASSERT_X(!isDesktopWindow, Q_FUNC_INFO, "Qt::WindowType::Desktop is not allowed.");
947 if (isDesktopWindow)
948 f.setFlag(Qt::WindowType::Desktop, false);
949 )
950#endif
951
952 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
953
954 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
955 qFatal("QWidget: Cannot create a QWidget without QApplication");
956
957 Q_ASSERT(allWidgets);
958 if (allWidgets)
959 allWidgets->insert(q);
960
961#if QT_CONFIG(thread)
962 if (!parent) {
963 Q_ASSERT_X(QThread::isMainThread(), "QWidget",
964 "Widgets must be created in the GUI thread.");
965 }
966#endif
967
968 data.fstrut_dirty = true;
969
970 data.winid = 0;
971 data.widget_attributes = 0;
972 data.window_flags = f;
973 data.window_state = 0;
974 data.focus_policy = 0;
975 data.context_menu_policy = Qt::DefaultContextMenu;
976 data.window_modality = Qt::NonModal;
977
978 data.sizehint_forced = 0;
979 data.is_closing = false;
980 data.in_show = 0;
981 data.in_set_window_state = 0;
982 data.in_destructor = false;
983
984 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
985 if (f & Qt::MSWindowsOwnDC) {
986 mustHaveWindowHandle = 1;
987 q->setAttribute(Qt::WA_NativeWindow);
988 }
989
990 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
991 adjustQuitOnCloseAttribute();
992
993 q->setAttribute(Qt::WA_WState_Hidden);
994
995 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
996 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
997 initFocusChain();
998
999 if (parentWidget)
1000 q->setParent(parentWidget, data.window_flags);
1001 else {
1002 adjustFlags(data.window_flags, q);
1003 resolveLayoutDirection();
1004 // opaque system background?
1005 const QBrush &background = q->palette().brush(QPalette::Window);
1006 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1007 }
1008 data.fnt = QFont(data.fnt, q);
1009
1010 q->setAttribute(Qt::WA_PendingMoveEvent);
1011 q->setAttribute(Qt::WA_PendingResizeEvent);
1012
1013 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1014 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1015
1016 QEvent e(QEvent::Create);
1017 QCoreApplication::sendEvent(q, &e);
1018 QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1019
1020 extraPaintEngine = nullptr;
1021}
1022
1023void QWidgetPrivate::createRecursively()
1024{
1025 Q_Q(QWidget);
1026 q->create(0, true, true);
1027 for (int i = 0; i < children.size(); ++i) {
1028 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1029 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1030 child->d_func()->createRecursively();
1031 }
1032}
1033
1034QRhi *QWidgetPrivate::rhi() const
1035{
1036 Q_Q(const QWidget);
1037 if (auto *backingStore = q->backingStore()) {
1038 auto *window = windowHandle(WindowHandleMode::Closest);
1039 return backingStore->handle()->rhi(window);
1040 } else {
1041 return nullptr;
1042 }
1043}
1044
1045/*!
1046 \internal
1047 Returns the closest parent widget that has a QWindow window handle
1048
1049 \note This behavior is different from nativeParentWidget(), which
1050 returns the closest parent that has a QWindow window handle with
1051 a created QPlatformWindow, and hence native window (winId).
1052*/
1053QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
1054{
1055 Q_Q(const QWidget);
1056 QWidget *parent = q->parentWidget();
1057 while (parent && !parent->windowHandle())
1058 parent = parent->parentWidget();
1059 return parent;
1060}
1061
1062QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1063{
1064 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1065 if (QTLWExtra *x = maybeTopData()) {
1066 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1067 return x->window;
1068 }
1069 }
1070 if (mode == WindowHandleMode::Closest) {
1071 // FIXME: Use closestParentWidgetWithWindowHandle instead
1072 if (auto nativeParent = q_func()->nativeParentWidget()) {
1073 if (auto window = nativeParent->windowHandle())
1074 return window;
1075 }
1076 }
1077 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1078 if (auto topLevel = q_func()->topLevelWidget()) {
1079 if (auto window = topLevel ->windowHandle())
1080 return window;
1081 }
1082 }
1083 return nullptr;
1084}
1085
1086/*!
1087 \internal
1088
1089 Used by clients outside of widgets to get a handle to the
1090 closest QWindow without having to link to widgets.
1091*/
1092QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1093{
1094 return windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
1095}
1096
1097QScreen *QWidgetPrivate::associatedScreen() const
1098{
1099#if QT_CONFIG(graphicsview)
1100 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1101 if (nearestGraphicsProxyWidget(q_func()))
1102 return nullptr;
1103#endif
1104 if (auto window = windowHandle(WindowHandleMode::Closest))
1105 return window->screen();
1106 return nullptr;
1107}
1108
1109// finds the first rhiconfig in the hierarchy that has enable==true
1110static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1111{
1112 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1113 if (config.isEnabled()) {
1114 if (outConfig)
1115 *outConfig = config;
1116 if (outType)
1117 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1118 return true;
1119 }
1120 for (const QObject *child : w->children()) {
1121 if (const QWidget *childWidget = qobject_cast<const QWidget *>(child)) {
1122 if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType)) {
1123 static bool optOut = qEnvironmentVariableIsSet("QT_WIDGETS_NO_CHILD_RHI");
1124 // Native child widgets should not trigger RHI for its parent
1125 // hierarchy, but will still flush the native child using RHI.
1126 if (!optOut && childWidget->testAttribute(Qt::WA_NativeWindow))
1127 continue;
1128
1129 return true;
1130 }
1131 }
1132 }
1133 return false;
1134}
1135
1136bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1137{
1138 // First, check env.vars. or other means that force the usage of rhi-based
1139 // flushing with a specific graphics API. This takes precedence over what
1140 // the widgets themselves declare. This is global, applying to all
1141 // top-levels.
1142 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1143 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1144 return true;
1145 }
1146
1147 // Otherwise, check the widget hierarchy to see if there is a child (or
1148 // ourselves) that declare the need for rhi-based composition.
1149 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1150 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1151 return true;
1152 }
1153
1154 return false;
1155}
1156
1157// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1158
1159/*!
1160 Creates a new widget window.
1161
1162 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1163 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1164 QWindow wrapping a foreign window and pass it to
1165 QWidget::createWindowContainer() instead.
1166
1167 \sa createWindowContainer(), QWindow::fromWinId()
1168*/
1169
1170void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1171{
1172 Q_UNUSED(initializeWindow);
1173 Q_UNUSED(destroyOldWindow);
1174
1175 Q_D(QWidget);
1176 if (Q_UNLIKELY(window))
1177 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1178 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1179 return;
1180
1181 if (d->data.in_destructor)
1182 return;
1183
1184 Qt::WindowType type = windowType();
1185 Qt::WindowFlags &flags = data->window_flags;
1186
1187 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1188 type = Qt::Window;
1189 flags |= Qt::Window;
1190 }
1191
1192 if (QWidget *parent = parentWidget()) {
1193 if (type & Qt::Window) {
1194 if (!parent->testAttribute(Qt::WA_WState_Created))
1195 parent->createWinId();
1196 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1197 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1198 // We're about to create a native child widget that doesn't have a native parent;
1199 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1200 // attribute is set.
1201 d->createWinId();
1202 // Nothing more to do.
1203 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1204 Q_ASSERT(internalWinId());
1205 return;
1206 }
1207 }
1208
1209
1210 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1211 if (paintOnScreenEnv)
1212 setAttribute(Qt::WA_PaintOnScreen);
1213
1214 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1215 setAttribute(Qt::WA_NativeWindow);
1216
1217 if (isWindow()
1218#if QT_CONFIG(graphicsview)
1219 && !graphicsProxyWidget()
1220#endif
1221 ) {
1222 // Make top levels automatically respect safe areas by default
1223 auto *topExtra = d->maybeTopData();
1224 if (!topExtra || !topExtra->explicitContentsMarginsRespectsSafeArea) {
1225 setAttribute_internal(Qt::WA_ContentsMarginsRespectsSafeArea,
1226 true, data, d);
1227 }
1228 }
1229
1230 d->updateIsOpaque();
1231
1232 setAttribute(Qt::WA_WState_Created); // set created flag
1233 d->create();
1234
1235 // A real toplevel window needs a paint manager
1236 if (isWindow())
1237 d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1238
1239 d->setModal_sys();
1240
1241 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1242 setAttribute(Qt::WA_DropSiteRegistered, true);
1243
1244 // need to force the resting of the icon after changing parents
1245 if (testAttribute(Qt::WA_SetWindowIcon))
1246 d->setWindowIcon_sys();
1247
1248 if (isWindow() && !d->topData()->iconText.isEmpty())
1249 d->setWindowIconText_helper(d->topData()->iconText);
1250 if (isWindow() && !d->topData()->caption.isEmpty())
1251 d->setWindowTitle_helper(d->topData()->caption);
1252 if (isWindow() && !d->topData()->filePath.isEmpty())
1253 d->setWindowFilePath_helper(d->topData()->filePath);
1254 d->updateSystemBackground();
1255
1256 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1257 d->setWindowIcon_sys();
1258
1259 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1260 // as those force native window creation on their ancestors before they are shown.
1261 // If the strut is not updated, any subsequent move of the top level window before show
1262 // will cause window frame to be ignored when positioning the window.
1263 // Note that this only helps on platforms that handle window creation synchronously.
1264 d->updateFrameStrut();
1265}
1266
1268{
1269 QObjectList children = parentWidget->children();
1270 for (int i = 0; i < children.size(); i++) {
1271 if (children.at(i)->isWidgetType()) {
1272 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1273 if (childWidget) { // should not be necessary
1274 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1275 if (!childWidget->internalWinId())
1276 childWidget->winId();
1277 if (childWidget->windowHandle()) {
1278 if (childWidget->isWindow()) {
1279 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1280 } else {
1281 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1282 }
1283 }
1284 } else {
1286 }
1287 }
1288 }
1289 }
1290
1291}
1292
1293void QWidgetPrivate::create()
1294{
1295 Q_Q(QWidget);
1296
1297 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1298 return; // we only care about real toplevels
1299
1300 QWidgetWindow *win = topData()->window;
1301 // topData() ensures the extra is created but does not ensure 'window' is non-null
1302 // in case the extra was already valid.
1303 if (!win) {
1304 createTLSysExtra();
1305 Q_ASSERT(topData()->window);
1306 win = topData()->window;
1307 }
1308
1309 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1310 for (const QByteArray &propertyName : dynamicPropertyNames) {
1311 if (!qstrncmp(propertyName, "_q_platform_", 12))
1312 win->setProperty(propertyName, q->property(propertyName));
1313 }
1314
1315 Qt::WindowFlags &flags = data.window_flags;
1316
1317#if defined(QT_PLATFORM_UIKIT)
1318 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1319 flags |= Qt::ExpandedClientAreaHint;
1320#endif
1321
1322 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1323 win->setProperty("_q_showWithoutActivating", QVariant(true));
1324 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1325 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1326 win->setFlags(flags);
1327 fixPosIncludesFrame();
1328 if (q->testAttribute(Qt::WA_Moved)
1329 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1330 win->setGeometry(q->geometry());
1331 else
1332 win->resize(q->size());
1333 if (win->isTopLevel()) {
1334 QScreen *targetScreen = topData()->initialScreen;
1335 topData()->initialScreen = nullptr;
1336 if (!targetScreen)
1337 targetScreen = q->screen();
1338 win->setScreen(targetScreen);
1339 }
1340
1341 QSurfaceFormat format = win->requestedFormat();
1342 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1343 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1344 format.setAlphaBufferSize(8);
1345 }
1346 win->setFormat(format);
1347
1348 if (QWidget *nativeParent = q->nativeParentWidget()) {
1349 if (nativeParent->windowHandle()) {
1350 if (flags & Qt::Window) {
1351 // When setting the transient parent for a top-level window, skip
1352 // past any popup-based windows (Popup, Tool, ToolTip, SplashScreen)
1353 // in the native parent chain. These window types are typically short-
1354 // lived and dismissed as a side-effect of showing other top-level
1355 // windows. On some platforms (e.g., Wayland), closing a parent window
1356 // sends close events to all registered transient children; if a stable
1357 // dialog retained a popup-based parent, it could be unexpectedly closed
1358 // when that parent is dismissed.
1359 //
1360 // Popup-based windows that are themselves children of popup-based
1361 // parents intentionally retain the popup parent relationship so they
1362 // stay visually stacked and are dismissed together.
1363 const auto winType = Qt::WindowType((flags & Qt::WindowType_Mask).toInt());
1364 auto isPopupBased = [](Qt::WindowType type) {
1365 return type == Qt::Popup || type == Qt::Tool || type == Qt::ToolTip
1366 || type == Qt::SplashScreen;
1367 };
1368
1369 QWindow *transientParent = nativeParent->window()->windowHandle();
1370 if (!isPopupBased(winType)) {
1371 // Walk up past popup-based ancestors to find a stable parent.
1372 while (transientParent) {
1373 const Qt::WindowType tp = transientParent->type();
1374 if (!isPopupBased(tp))
1375 break;
1376 transientParent = transientParent->transientParent();
1377 }
1378 }
1379 win->setTransientParent(transientParent);
1380 win->setParent(nullptr);
1381 } else {
1382 win->setTransientParent(nullptr);
1383 win->setParent(nativeParent->windowHandle());
1384 }
1385 }
1386 }
1387
1388 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1389 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1390
1391 win->create();
1392 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1393 if (QPlatformWindow *platformWindow = win->handle())
1394 platformWindow->setFrameStrutEventsEnabled(true);
1395
1396 data.window_flags = win->flags();
1397
1398#if QT_CONFIG(xcb)
1399 if (!topData()->role.isNull()) {
1400 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1401 xcbWindow->setWindowRole(topData()->role);
1402 }
1403#endif
1404#if QT_CONFIG(wayland)
1405 if (!topData()->role.isNull()) {
1406 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(win->handle()))
1407 waylandWindow->setSessionRestoreId(topData()->role);
1408 }
1409#endif
1410
1411 QBackingStore *store = q->backingStore();
1412 usesRhiFlush = false;
1413
1414 if (!store && q->isWindow())
1415 q->setBackingStore(new QBackingStore(win));
1416
1417 QPlatformBackingStoreRhiConfig rhiConfig;
1418 usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr);
1419 if (usesRhiFlush && q->backingStore()) {
1420 // Trigger creation of support infrastructure up front,
1421 // now that we have a specific RHI configuration.
1422 q->backingStore()->handle()->createRhi(win, rhiConfig);
1423 }
1424
1425 setWindowModified_helper();
1426
1427 if (win->handle()) {
1428 WId id = win->winId();
1429 // See the QPlatformWindow::winId() documentation
1430 Q_ASSERT(id != WId(0));
1431 setWinId(id);
1432 }
1433 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1434
1435 // Check children and create windows for them if necessary
1436 q_createNativeChildrenAndSetParent(q);
1437
1438 if (extra && !extra->mask.isEmpty())
1439 setMask_sys(extra->mask);
1440
1441 if (data.crect.width() == 0 || data.crect.height() == 0) {
1442 q->setAttribute(Qt::WA_OutsideWSRange, true);
1443 } else {
1444 q->setAttribute(Qt::WA_OutsideWSRange, false);
1445 if (q->isVisible()) {
1446 // If widget is already shown, set window visible, too
1447 win->setNativeWindowVisibility(true);
1448 }
1449 }
1450}
1451
1452#ifdef Q_OS_WIN
1453static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1454#endif
1455
1456void QWidgetPrivate::createTLSysExtra()
1457{
1458 Q_Q(QWidget);
1459 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1460 extra->topextra->window = new QWidgetWindow(q);
1461 if (extra->minw || extra->minh)
1462 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1463 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1464 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1465 if (extra->topextra->opacity != 255 && q->isWindow())
1466 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1467
1468#if QT_CONFIG(tooltip)
1469 const bool isTipLabel = qobject_cast<const QTipLabel *>(q) != nullptr;
1470#endif
1471 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1472#ifdef Q_OS_WIN
1473 // Pass on native parent handle for Widget embedded into Active X.
1474 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1475 if (activeXNativeParentHandle.isValid())
1476 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1477 if (isTipLabel || isAlphaWidget)
1478 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1479#endif
1480 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1481 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1482
1483 updateIsTranslucent();
1484 }
1485
1486}
1487
1488/*!
1489 Destroys the widget.
1490
1491 All this widget's children are deleted first. The application
1492 exits if this widget is the main widget.
1493*/
1494
1495QWidget::~QWidget()
1496{
1497 Q_D(QWidget);
1498 d->data.in_destructor = true;
1499
1500#if QT_CONFIG(accessibility)
1501 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive())
1502 QAccessibleCache::instance()->sendObjectDestroyedEvent(this);
1503#endif
1504
1505#if defined (QT_CHECK_STATE)
1506 if (Q_UNLIKELY(paintingActive()))
1507 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1508#endif
1509
1510#ifndef QT_NO_GESTURES
1511 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1512 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1513 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1514 manager->cleanupCachedGestures(this, *it);
1515 }
1516 d->gestureContext.clear();
1517#endif
1518
1519#ifndef QT_NO_ACTION
1520 // remove all actions from this widget
1521 for (auto action : std::as_const(d->actions)) {
1522 QActionPrivate *apriv = action->d_func();
1523 apriv->associatedObjects.removeAll(this);
1524 }
1525 d->actions.clear();
1526#endif
1527
1528#ifndef QT_NO_SHORTCUT
1529 // Remove all shortcuts grabbed by this
1530 // widget, unless application is closing
1531 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1532 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1533#endif
1534
1535 // delete layout while we still are a valid widget
1536 delete d->layout;
1537 d->layout = nullptr;
1538
1539 // Remove this from focus list
1540 d->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1541
1542 QT_TRY {
1543#if QT_CONFIG(graphicsview)
1544 const QWidget* w = this;
1545 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1546 w = w->d_func()->extra->focus_proxy;
1547 QWidget *window = w->window();
1548 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1549 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1550#endif
1551 clearFocus();
1552 } QT_CATCH(...) {
1553 // swallow this problem because we are in a destructor
1554 }
1555
1556 d->setDirtyOpaqueRegion();
1557
1558 if (isWindow() && isVisible() && internalWinId()) {
1559 QT_TRY {
1560 d->close();
1561 } QT_CATCH(...) {
1562 // if we're out of memory, at least hide the window.
1563 QT_TRY {
1564 hide();
1565 } QT_CATCH(...) {
1566 // and if that also doesn't work, then give up
1567 }
1568 }
1569 } else if (isVisible()) {
1570 qApp->d_func()->sendSyntheticEnterLeave(this);
1571 }
1572
1573 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1574 repaintManager->removeDirtyWidget(this);
1575 if (testAttribute(Qt::WA_StaticContents))
1576 repaintManager->removeStaticWidget(this);
1577 }
1578
1579 delete d->needsFlush;
1580 d->needsFlush = nullptr;
1581
1582 // The next 20 lines are duplicated from QObject, but required here
1583 // since QWidget deletes is children itself
1584 bool blocked = d->blockSig;
1585 d->blockSig = 0; // unblock signals so we always emit destroyed()
1586
1587 if (d->isSignalConnected(0)) {
1588 QT_TRY {
1589 emit destroyed(this);
1590 } QT_CATCH(...) {
1591 // all the signal/slots connections are still in place - if we don't
1592 // quit now, we will crash pretty soon.
1593 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1594 QT_RETHROW;
1595 }
1596 }
1597
1598 if (d->declarativeData) {
1599 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1600 if (QAbstractDeclarativeData::destroyed)
1601 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1602 d->declarativeData = nullptr; // don't activate again in ~QObject
1603 d->wasDeleted = false;
1604 }
1605
1606 d->blockSig = blocked;
1607
1608 if (!d->children.isEmpty())
1609 d->deleteChildren();
1610
1611 QCoreApplication::removePostedEvents(this);
1612
1613 QT_TRY {
1614 destroy(); // platform-dependent cleanup
1615 } QT_CATCH(...) {
1616 // if this fails we can't do anything about it but at least we are not allowed to throw.
1617 }
1618 --QWidgetPrivate::instanceCounter;
1619
1620 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1621 QWidgetPrivate::allWidgets->remove(this);
1622
1623 QT_TRY {
1624 QEvent e(QEvent::Destroy);
1625 QCoreApplication::sendEvent(this, &e);
1626 } QT_CATCH(const std::exception&) {
1627 // if this fails we can't do anything about it but at least we are not allowed to throw.
1628 }
1629
1630#if QT_CONFIG(graphicseffect)
1631 delete d->graphicsEffect;
1632#endif
1633 d->deleteExtra();
1634
1635 d->isWidget = false;
1636}
1637
1638int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1639int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1640
1641void QWidgetPrivate::setWinId(WId id) // set widget identifier
1642{
1643 Q_Q(QWidget);
1644 if (mapper && data.winid) {
1645 mapper->remove(data.winid);
1646 }
1647
1648 const WId oldWinId = data.winid;
1649
1650 data.winid = id;
1651 if (mapper && id) {
1652 mapper->insert(data.winid, q);
1653 }
1654
1655 if (oldWinId != id) {
1656 QEvent e(QEvent::WinIdChange);
1657 QCoreApplication::sendEvent(q, &e);
1658 }
1659}
1660
1661void QWidgetPrivate::createTLExtra()
1662{
1663 if (!extra)
1664 createExtra();
1665 if (!extra->topextra) {
1666 extra->topextra = std::make_unique<QTLWExtra>();
1667 QTLWExtra* x = extra->topextra.get();
1668 x->backingStore = nullptr;
1669 x->sharedPainter = nullptr;
1670 x->incw = x->inch = 0;
1671 x->basew = x->baseh = 0;
1672 x->frameStrut.setCoords(0, 0, 0, 0);
1673 x->normalGeometry = QRect(0,0,-1,-1);
1674 x->savedFlags = { };
1675 x->opacity = 255;
1676 x->posIncludesFrame = 0;
1677 x->sizeAdjusted = false;
1678 x->embedded = 0;
1679 x->explicitContentsMarginsRespectsSafeArea = 0;
1680 x->window = nullptr;
1681 x->initialScreen = nullptr;
1682
1683#ifdef QWIDGET_EXTRA_DEBUG
1684 static int count = 0;
1685 qDebug() << "tlextra" << ++count;
1686#endif
1687 }
1688}
1689
1690/*!
1691 \internal
1692 Creates the widget extra data.
1693*/
1694
1695void QWidgetPrivate::createExtra()
1696{
1697 if (!extra) { // if not exists
1698 extra = std::make_unique<QWExtra>();
1699 extra->glContext = nullptr;
1700#if QT_CONFIG(graphicsview)
1701 extra->proxyWidget = nullptr;
1702#endif
1703 extra->minw = 0;
1704 extra->minh = 0;
1705 extra->maxw = QWIDGETSIZE_MAX;
1706 extra->maxh = QWIDGETSIZE_MAX;
1707 extra->customDpiX = 0;
1708 extra->customDpiY = 0;
1709 extra->explicitMinSize = 0;
1710 extra->explicitMaxSize = 0;
1711 extra->autoFillBackground = 0;
1712 extra->nativeChildrenForced = 0;
1713 extra->inRenderWithPainter = 0;
1714 extra->hasWindowContainer = false;
1715 extra->hasMask = 0;
1716 createSysExtra();
1717#ifdef QWIDGET_EXTRA_DEBUG
1718 static int count = 0;
1719 qDebug() << "extra" << ++count;
1720#endif
1721 }
1722}
1723
1724void QWidgetPrivate::createSysExtra()
1725{
1726}
1727
1728/*!
1729 \internal
1730 Deletes the widget extra data.
1731*/
1732
1733void QWidgetPrivate::deleteExtra()
1734{
1735 if (extra) { // if exists
1736 deleteSysExtra();
1737#if QT_CONFIG(style_stylesheet)
1738 // dereference the stylesheet style
1739 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1740 proxy->deref();
1741#endif
1742 if (extra->topextra)
1743 deleteTLSysExtra();
1744
1745 // extra->xic destroyed in QWidget::destroy()
1746 extra.reset();
1747 }
1748}
1749
1750void QWidgetPrivate::deleteSysExtra()
1751{
1752}
1753
1754void QWidgetPrivate::deleteTLSysExtra()
1755{
1756 Q_Q(QWidget);
1757 if (extra && extra->topextra) {
1758 if (extra->hasWindowContainer)
1759 QWindowContainer::toplevelAboutToBeDestroyed(q);
1760
1761 delete extra->topextra->window;
1762 extra->topextra->window = nullptr;
1763 }
1764}
1765
1766/*
1767 Returns \c region of widgets above this which overlap with
1768 \a rect, which is in parent's coordinate system (same as crect).
1769*/
1770
1771QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1772{
1773 Q_Q(const QWidget);
1774
1775 const QWidget *w = q;
1776 QRect r = rect;
1777 QPoint p;
1778 QRegion region;
1779 while (w) {
1780 if (w->isWindow())
1781 break;
1782 QWidgetPrivate *pd = w->parentWidget()->d_func();
1783 bool above = false;
1784 for (int i = 0; i < pd->children.size(); ++i) {
1785 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1786 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1787 continue;
1788 if (!above) {
1789 above = (sibling == w);
1790 continue;
1791 }
1792
1793 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1794 if (qRectIntersects(siblingRect, r)) {
1795 const auto &siblingExtra = sibling->d_func()->extra;
1796 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1797 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1798 continue;
1799 }
1800 region += siblingRect.translated(-p);
1801 if (breakAfterFirst)
1802 break;
1803 }
1804 }
1805 w = w->parentWidget();
1806 r.translate(pd->data.crect.topLeft());
1807 p += pd->data.crect.topLeft();
1808 }
1809 return region;
1810}
1811
1812void QWidgetPrivate::syncBackingStore()
1813{
1814 if (shouldPaintOnScreen()) {
1815 paintOnScreen(dirty);
1816 dirty = QRegion();
1817 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1818 repaintManager->sync();
1819 }
1820}
1821
1822void QWidgetPrivate::syncBackingStore(const QRegion &region)
1823{
1824 if (shouldPaintOnScreen())
1825 paintOnScreen(region);
1826 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1827 repaintManager->sync(q_func(), region);
1828 }
1829}
1830
1831void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1832{
1833 if (data.in_destructor)
1834 return;
1835
1836 if (shouldDiscardSyncRequest())
1837 return;
1838
1839 Q_Q(QWidget);
1840 if (q->testAttribute(Qt::WA_StaticContents)) {
1841 if (!extra)
1842 createExtra();
1843 extra->staticContentsSize = data.crect.size();
1844 }
1845
1846 QPaintEngine *engine = q->paintEngine();
1847
1848 // QGLWidget does not support partial updates if:
1849 // 1) The context is double buffered
1850 // 2) The context is single buffered and auto-fill background is enabled.
1851 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1852 || engine->type() == QPaintEngine::OpenGL2))
1853 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1854 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1855
1856 toBePainted &= clipRect();
1857 clipToEffectiveMask(toBePainted);
1858 if (toBePainted.isEmpty())
1859 return; // Nothing to repaint.
1860
1861 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1862
1863 if (Q_UNLIKELY(q->paintingActive()))
1864 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1865}
1866
1867void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1868{
1869 Q_Q(QWidget);
1870
1871 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1872 return; // nothing we can do
1873
1874 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1875 return; // nothing to do
1876
1877 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1878 if (enable)
1879 q->update();
1880
1881 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1882 for (int i = 0; i < children.size(); ++i) {
1883 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1884 if (w && !w->isWindow() && !w->testAttribute(attribute))
1885 w->d_func()->setUpdatesEnabled_helper(enable);
1886 }
1887}
1888
1889/*!
1890 \internal
1891
1892 Propagate this widget's palette to all children, except style sheet
1893 widgets, and windows that don't enable window propagation (palettes don't
1894 normally propagate to windows).
1895*/
1896void QWidgetPrivate::propagatePaletteChange()
1897{
1898 Q_Q(QWidget);
1899 // Propagate a new inherited mask to all children.
1900#if QT_CONFIG(graphicsview)
1901 if (!q->parentWidget() && extra && extra->proxyWidget) {
1902 QGraphicsProxyWidget *p = extra->proxyWidget;
1903 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1904 } else
1905#endif // QT_CONFIG(graphicsview)
1906 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1907 inheritedPaletteResolveMask = 0;
1908 }
1909
1910 directPaletteResolveMask = data.pal.resolveMask();
1911 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1912
1913 const bool useStyleSheetPropagationInWidgetStyles =
1914 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1915
1916 QEvent pc(QEvent::PaletteChange);
1917 QCoreApplication::sendEvent(q, &pc);
1918 for (int i = 0; i < children.size(); ++i) {
1919 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1920 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1921 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1922 QWidgetPrivate *wd = w->d_func();
1923 wd->inheritedPaletteResolveMask = mask;
1924 wd->resolvePalette();
1925 }
1926 }
1927}
1928
1929/*
1930 Returns the widget's clipping rectangle.
1931*/
1932QRect QWidgetPrivate::clipRect() const
1933{
1934 Q_Q(const QWidget);
1935 const QWidget * w = q;
1936 if (!w->isVisible())
1937 return QRect();
1938 QRect r = effectiveRectFor(q->rect());
1939 int ox = 0;
1940 int oy = 0;
1941 while (w
1942 && w->isVisible()
1943 && !w->isWindow()
1944 && w->parentWidget()) {
1945 ox -= w->x();
1946 oy -= w->y();
1947 w = w->parentWidget();
1948 r &= QRect(ox, oy, w->width(), w->height());
1949 }
1950 return r;
1951}
1952
1953/*
1954 Returns the widget's clipping region (without siblings).
1955*/
1956QRegion QWidgetPrivate::clipRegion() const
1957{
1958 Q_Q(const QWidget);
1959 if (!q->isVisible())
1960 return QRegion();
1961 QRegion r(q->rect());
1962 const QWidget * w = q;
1963 const QWidget *ignoreUpTo;
1964 int ox = 0;
1965 int oy = 0;
1966 while (w
1967 && w->isVisible()
1968 && !w->isWindow()
1969 && w->parentWidget()) {
1970 ox -= w->x();
1971 oy -= w->y();
1972 ignoreUpTo = w;
1973 w = w->parentWidget();
1974 r &= QRegion(ox, oy, w->width(), w->height());
1975
1976 int i = 0;
1977 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1978 ;
1979 for ( ; i < w->d_func()->children.size(); ++i) {
1980 if (QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1981 if (sibling->isVisible() && !sibling->isWindow()) {
1982 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1983 sibling->width(), sibling->height());
1984 if (qRectIntersects(siblingRect, q->rect()))
1985 r -= QRegion(siblingRect);
1986 }
1987 }
1988 }
1989 }
1990 return r;
1991}
1992
1993void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1994{
1995// Transform the system clip region from device-independent pixels to device pixels
1996 QTransform scaleTransform;
1997 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1998
1999 paintEngine->d_func()->baseSystemClip = region;
2000 paintEngine->d_func()->setSystemTransform(scaleTransform);
2001
2002}
2003
2004#if QT_CONFIG(graphicseffect)
2005void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
2006{
2007 Q_Q(QWidget);
2008 QWidget *w = q;
2009 do {
2010 if (w->graphicsEffect()) {
2011 QWidgetEffectSourcePrivate *sourced =
2012 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
2013 if (!sourced->updateDueToGraphicsEffect)
2014 w->graphicsEffect()->source()->d_func()->invalidateCache();
2015 }
2016 w = w->parentWidget();
2017 } while (w);
2018}
2019#endif // QT_CONFIG(graphicseffect)
2020
2021void QWidgetPrivate::setDirtyOpaqueRegion()
2022{
2023 Q_Q(QWidget);
2024
2025 dirtyOpaqueChildren = true;
2026
2027#if QT_CONFIG(graphicseffect)
2028 invalidateGraphicsEffectsRecursively();
2029#endif // QT_CONFIG(graphicseffect)
2030
2031 if (q->isWindow())
2032 return;
2033
2034 QWidget *parent = q->parentWidget();
2035 if (!parent)
2036 return;
2037
2038 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2039 QWidgetPrivate *pd = parent->d_func();
2040 if (!pd->dirtyOpaqueChildren)
2041 pd->setDirtyOpaqueRegion();
2042}
2043
2044const QRegion &QWidgetPrivate::getOpaqueChildren() const
2045{
2046 if (!dirtyOpaqueChildren)
2047 return opaqueChildren;
2048
2049 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2050 that->opaqueChildren = QRegion();
2051
2052 for (int i = 0; i < children.size(); ++i) {
2053 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2054 if (!child || !child->isVisible() || child->isWindow())
2055 continue;
2056
2057 const QPoint offset = child->geometry().topLeft();
2058 QWidgetPrivate *childd = child->d_func();
2059 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2060 if (childd->extra && childd->extra->hasMask)
2061 r &= childd->extra->mask;
2062 if (r.isEmpty())
2063 continue;
2064 r.translate(offset);
2065 that->opaqueChildren += r;
2066 }
2067
2068 that->opaqueChildren &= q_func()->rect();
2069 that->dirtyOpaqueChildren = false;
2070
2071 return that->opaqueChildren;
2072}
2073
2074void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2075{
2076 if (children.isEmpty() || clipRect.isEmpty())
2077 return;
2078
2079 const QRegion &r = getOpaqueChildren();
2080 if (!r.isEmpty())
2081 source -= (r & clipRect);
2082}
2083
2084//subtract any relatives that are higher up than me --- this is too expensive !!!
2085void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2086 bool alsoNonOpaque) const
2087{
2088 Q_Q(const QWidget);
2089 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2090 if (disableSubtractOpaqueSiblings || q->isWindow())
2091 return;
2092
2093 QRect clipBoundingRect;
2094 bool dirtyClipBoundingRect = true;
2095
2096 QRegion parentClip;
2097 bool dirtyParentClip = true;
2098
2099 QPoint parentOffset = data.crect.topLeft();
2100
2101 const QWidget *w = q;
2102
2103 while (w) {
2104 if (w->isWindow())
2105 break;
2106 QWidgetPrivate *pd = w->parentWidget()->d_func();
2107 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2108 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2109 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2110 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2111 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2112 continue;
2113
2114 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2115 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2116 continue;
2117
2118 if (dirtyClipBoundingRect) {
2119 clipBoundingRect = sourceRegion.boundingRect();
2120 dirtyClipBoundingRect = false;
2121 }
2122
2123 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2124 continue;
2125
2126 if (dirtyParentClip) {
2127 parentClip = sourceRegion.translated(parentOffset);
2128 dirtyParentClip = false;
2129 }
2130
2131 const QPoint siblingPos(sibling->data->crect.topLeft());
2132 const QRect siblingClipRect(sibling->d_func()->clipRect());
2133 QRegion siblingDirty(parentClip);
2134 siblingDirty &= (siblingClipRect.translated(siblingPos));
2135 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2136 && !sibling->d_func()->graphicsEffect;
2137 if (hasMask)
2138 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2139 if (siblingDirty.isEmpty())
2140 continue;
2141
2142 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2143 if (hasMask) {
2144 siblingDirty.translate(-parentOffset);
2145 sourceRegion -= siblingDirty;
2146 } else {
2147 sourceRegion -= siblingGeometry.translated(-parentOffset);
2148 }
2149 } else {
2150 if (hasDirtySiblingsAbove)
2151 *hasDirtySiblingsAbove = true;
2152 if (sibling->d_func()->children.isEmpty())
2153 continue;
2154 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2155 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2156 sourceRegion -= opaqueSiblingChildren;
2157 }
2158 if (sourceRegion.isEmpty())
2159 return;
2160
2161 dirtyClipBoundingRect = true;
2162 dirtyParentClip = true;
2163 }
2164
2165 w = w->parentWidget();
2166 parentOffset += pd->data.crect.topLeft();
2167 dirtyParentClip = true;
2168 }
2169}
2170
2171void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2172{
2173 Q_Q(const QWidget);
2174
2175 const QWidget *w = q;
2176 QPoint offset;
2177
2178#if QT_CONFIG(graphicseffect)
2179 if (graphicsEffect && !w->isWindow()) {
2180 w = q->parentWidget();
2181 offset -= data.crect.topLeft();
2182 }
2183#endif // QT_CONFIG(graphicseffect)
2184
2185 while (w) {
2186 const QWidgetPrivate *wd = w->d_func();
2187 if (wd->extra && wd->extra->hasMask)
2188 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2189 if (w->isWindow())
2190 return;
2191 offset -= wd->data.crect.topLeft();
2192 w = w->parentWidget();
2193 }
2194}
2195
2196bool QWidgetPrivate::shouldPaintOnScreen() const
2197{
2198#if defined(QT_NO_BACKINGSTORE)
2199 return true;
2200#else
2201 Q_Q(const QWidget);
2202 if (q->testAttribute(Qt::WA_PaintOnScreen)
2203 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2204 return true;
2205 }
2206
2207 return false;
2208#endif
2209}
2210
2211void QWidgetPrivate::updateIsOpaque()
2212{
2213 // hw: todo: only needed if opacity actually changed
2214 setDirtyOpaqueRegion();
2215
2216#if QT_CONFIG(graphicseffect)
2217 if (graphicsEffect) {
2218 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2219 setOpaque(false);
2220 return;
2221 }
2222#endif // QT_CONFIG(graphicseffect)
2223
2224 Q_Q(QWidget);
2225 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2226 setOpaque(true);
2227 return;
2228 }
2229
2230 const QPalette &pal = q->palette();
2231
2232 if (q->autoFillBackground()) {
2233 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2234 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2235 setOpaque(true);
2236 return;
2237 }
2238 }
2239
2240 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2241 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2242 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2243 setOpaque(true);
2244 return;
2245 }
2246 }
2247 setOpaque(false);
2248}
2249
2250void QWidgetPrivate::setOpaque(bool opaque)
2251{
2252 if (isOpaque != opaque) {
2253 isOpaque = opaque;
2254 updateIsTranslucent();
2255 }
2256}
2257
2258void QWidgetPrivate::updateIsTranslucent()
2259{
2260 Q_Q(QWidget);
2261 if (QWindow *window = q->windowHandle()) {
2262 QSurfaceFormat format = window->format();
2263 const int oldAlpha = format.alphaBufferSize();
2264 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
2265 if (oldAlpha != newAlpha) {
2266 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2267 //
2268 // If that is not the case, then the setFormat() is not just futile
2269 // but downright dangerous. Futile because the format matters only
2270 // when creating the native window, no point in changing it
2271 // afterwards. Dangerous because a QOpenGLContext or something else
2272 // may eventually query the QWindow's format(), in order to ensure
2273 // compatibility (in terms of native concepts such as pixel format,
2274 // EGLConfig, etc.), and if we change it here, then the returned
2275 // format does not describe reality anymore. (reality being the
2276 // settings with which the native resource was created).
2277 //
2278 // Whereas if one does a destroy()-create() then this all here
2279 // won't matter because the format is updated in
2280 // QWidgetPrivate::create() again.
2281 //
2282 if (!window->handle()) {
2283 format.setAlphaBufferSize(newAlpha);
2284 window->setFormat(format);
2285 }
2286 }
2287 }
2288}
2289
2290static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2291{
2292 Q_ASSERT(painter);
2293
2294 if (brush.style() == Qt::TexturePattern) {
2295 const QRect rect(rgn.boundingRect());
2296 painter->setClipRegion(rgn);
2297 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2298 } else if (brush.gradient()
2299 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2300 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2301 painter->save();
2302 painter->setClipRegion(rgn);
2303 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2304 painter->restore();
2305 } else {
2306 for (const QRect &rect : rgn)
2307 painter->fillRect(rect, brush);
2308 }
2309}
2310
2311bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2312{
2313#if QT_CONFIG(scrollarea)
2314 Q_Q(const QWidget);
2315 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2316 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2317 return false;
2318 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2319 if (scrollArea && scrollArea->viewport() == q) {
2320 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2321 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2322 painter->setBrushOrigin(-priv->contentsOffset());
2323 }
2324#endif // QT_CONFIG(scrollarea)
2325 return true;
2326}
2327
2328void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2329{
2330 Q_Q(const QWidget);
2331
2332 bool brushOriginSet = false;
2333 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2334
2335 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2336 const QBrush bg = q->palette().brush(QPalette::Window);
2337 if (!brushOriginSet)
2338 brushOriginSet = updateBrushOrigin(painter, bg);
2339 if (!(flags & DontSetCompositionMode)) {
2340 //copy alpha straight in
2341 QPainter::CompositionMode oldMode = painter->compositionMode();
2342 painter->setCompositionMode(QPainter::CompositionMode_Source);
2343 fillRegion(painter, rgn, bg);
2344 painter->setCompositionMode(oldMode);
2345 } else {
2346 fillRegion(painter, rgn, bg);
2347 }
2348 }
2349
2350 if (q->autoFillBackground()) {
2351 if (!brushOriginSet)
2352 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2353 fillRegion(painter, rgn, autoFillBrush);
2354 }
2355
2356 if (q->testAttribute(Qt::WA_StyledBackground)) {
2357 painter->setClipRegion(rgn);
2358 QStyleOption opt;
2359 opt.initFrom(q);
2360 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2361 }
2362}
2363
2364/*
2365 \internal
2366 This function is called when a widget is hidden or destroyed.
2367 It resets some application global pointers that should only refer active,
2368 visible widgets.
2369*/
2370
2372
2373void QWidgetPrivate::deactivateWidgetCleanup()
2374{
2375 Q_Q(QWidget);
2376 // If this was the active application window, reset it
2377 if (QApplication::activeWindow() == q)
2378 QApplicationPrivate::setActiveWindow(nullptr);
2379 // If the is the active mouse press widget, reset it
2380 if (q == qt_button_down)
2381 qt_button_down = nullptr;
2382}
2383
2384
2385/*!
2386 Returns a pointer to the widget with window identifier/handle \a
2387 id.
2388
2389 The window identifier type depends on the underlying window
2390 system, see \c qwindowdefs.h for the actual definition. If there
2391 is no widget with this identifier, \nullptr is returned.
2392*/
2393
2394QWidget *QWidget::find(WId id)
2395{
2396 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2397}
2398
2399
2400
2401/*!
2402 \fn WId QWidget::internalWinId() const
2403 \internal
2404 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2405
2406*/
2407
2408/*!
2409 \fn WId QWidget::winId() const
2410
2411 Returns the window system identifier of the widget.
2412
2413 Portable in principle, but if you use it you are probably about to
2414 do something non-portable. Be careful.
2415
2416 If a widget is non-native (alien) and winId() is invoked on it, that widget
2417 will be provided a native handle.
2418
2419 This value may change at run-time. An event with type QEvent::WinIdChange
2420 will be sent to the widget following a change in window system identifier.
2421
2422 \sa find()
2423*/
2424WId QWidget::winId() const
2425{
2426 if (!data->in_destructor
2427 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2428 {
2429 QWidget *that = const_cast<QWidget*>(this);
2430 that->setAttribute(Qt::WA_NativeWindow);
2431 that->d_func()->createWinId();
2432 return that->data->winid;
2433 }
2434 return data->winid;
2435}
2436
2437void QWidgetPrivate::createWinId()
2438{
2439 Q_Q(QWidget);
2440
2441 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2442 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2443 if (!q->isWindow()) {
2444 QWidget *parent = q->parentWidget();
2445 QWidgetPrivate *pd = parent->d_func();
2446 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2447 parent->setAttribute(Qt::WA_NativeWindow);
2448 if (!parent->internalWinId()) {
2449 pd->createWinId();
2450 }
2451
2452 for (int i = 0; i < pd->children.size(); ++i) {
2453 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2454 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2455 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2456 w->create();
2457 }
2458 }
2459 } else {
2460 q->create();
2461 }
2462 }
2463}
2464
2465/*!
2466\internal
2467Ensures that the widget is set on the screen point is on. This is handy getting a correct
2468size hint before a resize in e.g QMenu and QToolTip.
2469Returns if the screen was changed.
2470*/
2471
2472bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2473{
2474 Q_Q(QWidget);
2475 if (!q->isWindow())
2476 return false;
2477 // Find the screen for pos and make the widget understand it is on that screen.
2478 return setScreen(QGuiApplication::screenAt(pos));
2479}
2480
2481/*!
2482\internal
2483Ensures that the widget's QWindow is set to be on the given \a screen.
2484Returns true if the screen was changed.
2485*/
2486
2487bool QWidgetPrivate::setScreen(QScreen *screen)
2488{
2489 Q_Q(QWidget);
2490 if (!screen || !q->isWindow())
2491 return false;
2492 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2493 if (currentScreen != screen) {
2494 topData()->initialScreen = screen;
2495 if (windowHandle())
2496 windowHandle()->setScreen(screen);
2497 return true;
2498 }
2499 return false;
2500}
2501
2502/*!
2503\internal
2504Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2505
2506*/
2507
2508void QWidget::createWinId()
2509{
2510 Q_D(QWidget);
2511 d->createWinId();
2512}
2513
2514/*!
2515 \since 4.4
2516
2517 Returns the effective window system identifier of the widget, i.e. the
2518 native parent's window system identifier.
2519
2520 If the widget is native, this function returns the native widget ID.
2521 Otherwise, the window ID of the first native parent widget, i.e., the
2522 top-level widget that contains this widget, is returned.
2523
2524 \note We recommend that you do not store this value as it is likely to
2525 change at run-time.
2526
2527 \sa nativeParentWidget()
2528*/
2529WId QWidget::effectiveWinId() const
2530{
2531 const WId id = internalWinId();
2532 if (id || !testAttribute(Qt::WA_WState_Created))
2533 return id;
2534 if (const QWidget *realParent = nativeParentWidget())
2535 return realParent->internalWinId();
2536 return 0;
2537}
2538
2539/*!
2540 If this is a native widget, return the associated QWindow.
2541 Otherwise return null.
2542
2543 Native widgets include toplevel widgets, QGLWidget, and child widgets
2544 on which winId() was called.
2545
2546 \since 5.0
2547
2548 \sa winId(), screen()
2549*/
2550QWindow *QWidget::windowHandle() const
2551{
2552 Q_D(const QWidget);
2553 return d->windowHandle();
2554}
2555
2556/*!
2557 Returns the screen the widget is on.
2558
2559 \since 5.14
2560
2561 \sa windowHandle()
2562*/
2563QScreen *QWidget::screen() const
2564{
2565 Q_D(const QWidget);
2566 if (auto associatedScreen = d->associatedScreen())
2567 return associatedScreen;
2568 if (auto topLevel = window()) {
2569 if (auto topData = qt_widget_private(topLevel)->topData()) {
2570 if (topData->initialScreen)
2571 return topData->initialScreen;
2572 }
2573 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2574 return screenByPos;
2575 }
2576 return QGuiApplication::primaryScreen();
2577}
2578
2579/*!
2580 Sets the screen on which the widget should be shown to \a screen.
2581
2582 Setting the screen only makes sense for windows. If necessary, the widget's
2583 window will get recreated on \a screen.
2584
2585 \note If the screen is part of a virtual desktop of multiple screens,
2586 the window will not move automatically to \a screen. To place the
2587 window relative to the screen, use the screen's topLeft() position.
2588
2589 \sa QWindow::setScreen()
2590*/
2591void QWidget::setScreen(QScreen *screen)
2592{
2593 Q_D(QWidget);
2594 d->setScreen(screen);
2595}
2596
2597#if QT_CONFIG(style_stylesheet)
2598
2599/*!
2600 \property QWidget::styleSheet
2601 \brief the widget's style sheet
2602 \since 4.2
2603
2604 The style sheet contains a textual description of customizations to the
2605 widget's style, as described in the \l{Qt Style Sheets} document.
2606
2607 Since Qt 4.5, Qt style sheets fully supports \macos.
2608
2609 \warning Qt style sheets are currently not supported for custom QStyle
2610 subclasses. We plan to address this in some future release.
2611
2612 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2613*/
2614QString QWidget::styleSheet() const
2615{
2616 Q_D(const QWidget);
2617 if (!d->extra)
2618 return QString();
2619 return d->extra->styleSheet;
2620}
2621
2622void QWidget::setStyleSheet(const QString& styleSheet)
2623{
2624 Q_D(QWidget);
2625 if (data->in_destructor)
2626 return;
2627 d->createExtra();
2628
2629 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2630 d->extra->styleSheet = styleSheet;
2631 if (styleSheet.isEmpty()) { // stylesheet removed
2632 if (!proxy)
2633 return;
2634
2635 d->inheritStyle();
2636 return;
2637 }
2638
2639 if (proxy) { // style sheet update
2640 bool repolish = d->polished;
2641 if (!repolish) {
2642 const auto childWidgets = findChildren<QWidget*>();
2643 for (auto child : childWidgets) {
2644 repolish = child->d_func()->polished;
2645 if (repolish)
2646 break;
2647 }
2648 }
2649 if (repolish)
2650 proxy->repolish(this);
2651 return;
2652 }
2653
2654 if (testAttribute(Qt::WA_SetStyle)) {
2655 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2656 } else {
2657 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2658 }
2659}
2660
2661#endif // QT_NO_STYLE_STYLESHEET
2662
2663/*!
2664 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2665*/
2666
2667QStyle *QWidget::style() const
2668{
2669 Q_D(const QWidget);
2670
2671 if (d->extra && d->extra->style)
2672 return d->extra->style;
2673 return QApplication::style();
2674}
2675
2676/*!
2677 Sets the widget's GUI style to \a style. The ownership of the style
2678 object is not transferred.
2679
2680 If no style is set, the widget uses the application's style,
2681 QApplication::style() instead.
2682
2683 Setting a widget's style has no effect on existing or future child
2684 widgets.
2685
2686 \warning This function is particularly useful for demonstration
2687 purposes, where you want to show Qt's styling capabilities. Real
2688 applications should avoid it and use one consistent GUI style
2689 instead.
2690
2691 \warning Qt style sheets are currently not supported for custom QStyle
2692 subclasses. We plan to address this in some future release.
2693
2694 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2695*/
2696
2697void QWidget::setStyle(QStyle *style)
2698{
2699 Q_D(QWidget);
2700 setAttribute(Qt::WA_SetStyle, style != nullptr);
2701 d->createExtra();
2702#if QT_CONFIG(style_stylesheet)
2703 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2704 //if for some reason someone try to set a QStyleSheetStyle, ref it
2705 //(this may happen for example in QButtonDialogBox which propagates its style)
2706 styleSheetStyle->ref();
2707 d->setStyle_helper(style, false);
2708 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2709 // if we have an application stylesheet or have a proxy already, propagate
2710 d->setStyle_helper(new QStyleSheetStyle(style), true);
2711 } else
2712#endif
2713 d->setStyle_helper(style, false);
2714}
2715
2716void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2717{
2718 Q_Q(QWidget);
2719 QStyle *oldStyle = q->style();
2720
2721 createExtra();
2722
2723#if QT_CONFIG(style_stylesheet)
2724 QPointer<QStyle> origStyle = extra->style;
2725#endif
2726 extra->style = newStyle;
2727
2728 // repolish
2729 if (polished) {
2730 oldStyle->unpolish(q);
2731 q->style()->polish(q);
2732 }
2733
2734 if (propagate) {
2735 // We copy the list because the order may be modified
2736 const QObjectList childrenList = children;
2737 for (int i = 0; i < childrenList.size(); ++i) {
2738 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2739 if (c)
2740 c->d_func()->inheritStyle();
2741 }
2742 }
2743
2744#if QT_CONFIG(style_stylesheet)
2745 if (!qt_styleSheet(newStyle)) {
2746 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2747 cssStyle->clearWidgetFont(q);
2748 }
2749 }
2750#endif
2751
2752 QEvent e(QEvent::StyleChange);
2753 QCoreApplication::sendEvent(q, &e);
2754
2755#if QT_CONFIG(style_stylesheet)
2756 // dereference the old stylesheet style
2757 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2758 proxy->deref();
2759#endif
2760}
2761
2762// Inherits style from the current parent and propagates it as necessary
2763void QWidgetPrivate::inheritStyle()
2764{
2765#if QT_CONFIG(style_stylesheet)
2766 Q_Q(QWidget);
2767
2768 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2769
2770 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2771
2772 if (!q->styleSheet().isEmpty()) {
2773 Q_ASSERT(proxy);
2774 proxy->repolish(q);
2775 return;
2776 }
2777 if (inheritStyleRecursionGuard)
2778 return;
2779 inheritStyleRecursionGuard = true;
2780 const auto resetGuard = qScopeGuard([&]() {
2781 inheritStyleRecursionGuard = false;
2782 });
2783
2784 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2785 QWidget *parent = q->parentWidget();
2786 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2787 // If we have stylesheet on app or parent has stylesheet style, we need
2788 // to be running a proxy
2789 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2790 QStyle *newStyle = parentStyle;
2791 if (q->testAttribute(Qt::WA_SetStyle) && qt_styleSheet(origStyle) == nullptr)
2792 newStyle = new QStyleSheetStyle(origStyle);
2793 else if (auto *styleSheetStyle = qt_styleSheet(origStyle))
2794 newStyle = styleSheetStyle;
2795 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2796 newProxy->ref();
2797
2798 setStyle_helper(newStyle, true);
2799 return;
2800 }
2801
2802 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2803 // we just need our original style back
2804 if (origStyle == extraStyle) // is it any different?
2805 return;
2806
2807 // We could have inherited the proxy from our parent (which has a custom style)
2808 // In such a case we need to start following the application style (i.e revert
2809 // the propagation behavior of QStyleSheetStyle)
2810 if (!q->testAttribute(Qt::WA_SetStyle))
2811 origStyle = nullptr;
2812
2813 setStyle_helper(origStyle, true);
2814#endif // QT_NO_STYLE_STYLESHEET
2815}
2816
2817
2818/*!
2819 \fn bool QWidget::isWindow() const
2820
2821 Returns \c true if the widget is an independent window, otherwise
2822 returns \c false.
2823
2824 A window is a widget that isn't visually the child of any other
2825 widget and that usually has a frame and a
2826 \l{QWidget::setWindowTitle()}{window title}.
2827
2828 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2829 It will then be grouped with its parent and deleted when the
2830 parent is deleted, minimized when the parent is minimized etc. If
2831 supported by the window manager, it will also have a common
2832 taskbar entry with its parent.
2833
2834 QDialog and QMainWindow widgets are by default windows, even if a
2835 parent widget is specified in the constructor. This behavior is
2836 specified by the Qt::Window flag.
2837
2838 \sa window(), isModal(), parentWidget()
2839*/
2840
2841/*!
2842 \property QWidget::modal
2843 \brief whether the widget is a modal widget
2844
2845 This property only makes sense for windows. A modal widget
2846 prevents widgets in all other windows from getting any input.
2847
2848 By default, this property is \c false.
2849
2850 \sa isWindow(), windowModality, QDialog
2851*/
2852
2853/*!
2854 \property QWidget::windowModality
2855 \brief which windows are blocked by the modal widget
2856 \since 4.1
2857
2858 This property only makes sense for windows. A modal widget
2859 prevents widgets in other windows from getting input. The value of
2860 this property controls which windows are blocked when the widget
2861 is visible. Changing this property while the window is visible has
2862 no effect; you must hide() the widget first, then show() it again.
2863
2864 By default, this property is Qt::NonModal.
2865
2866 \sa isWindow(), QWidget::modal, QDialog
2867*/
2868
2869Qt::WindowModality QWidget::windowModality() const
2870{
2871 return static_cast<Qt::WindowModality>(data->window_modality);
2872}
2873
2874void QWidget::setWindowModality(Qt::WindowModality windowModality)
2875{
2876 data->window_modality = windowModality;
2877 // setModal_sys() will be called by setAttribute()
2878 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2879 setAttribute(Qt::WA_SetWindowModality, true);
2880}
2881
2882void QWidgetPrivate::setModal_sys()
2883{
2884 Q_Q(QWidget);
2885 if (q->windowHandle())
2886 q->windowHandle()->setModality(q->windowModality());
2887}
2888
2889/*!
2890 \fn bool QWidget::underMouse() const
2891
2892 Returns \c true if the widget is under the mouse cursor; otherwise
2893 returns \c false.
2894
2895 This value is not updated properly during drag and drop
2896 operations.
2897
2898 \sa enterEvent(), leaveEvent()
2899*/
2900
2901/*!
2902 \property QWidget::minimized
2903 \brief whether this widget is minimized (iconified)
2904
2905 This property is only relevant for windows.
2906
2907 By default, this property is \c false.
2908
2909 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2910*/
2911bool QWidget::isMinimized() const
2912{ return data->window_state & Qt::WindowMinimized; }
2913
2914/*!
2915 Shows the widget minimized, as an icon.
2916
2917 Calling this function only affects \l{isWindow()}{windows}.
2918
2919 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2920 isMinimized()
2921*/
2922void QWidget::showMinimized()
2923{
2924 bool isMin = isMinimized();
2925 if (isMin && isVisible())
2926 return;
2927
2928 ensurePolished();
2929
2930 if (!isMin)
2931 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2932 setVisible(true);
2933}
2934
2935/*!
2936 \property QWidget::maximized
2937 \brief whether this widget is maximized
2938
2939 This property is only relevant for windows.
2940
2941 \note Due to limitations on some window systems, this does not always
2942 report the expected results (e.g., if the user on X11 maximizes the
2943 window via the window manager, Qt has no way of distinguishing this
2944 from any other resize). This is expected to improve as window manager
2945 protocols evolve.
2946
2947 By default, this property is \c false.
2948
2949 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2950*/
2951bool QWidget::isMaximized() const
2952{ return data->window_state & Qt::WindowMaximized; }
2953
2954
2955
2956/*!
2957 Returns the current window state. The window state is a OR'ed
2958 combination of Qt::WindowState: Qt::WindowMinimized,
2959 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2960
2961 \sa Qt::WindowState, setWindowState()
2962 */
2963Qt::WindowStates QWidget::windowState() const
2964{
2965 return Qt::WindowStates(data->window_state);
2966}
2967
2968/*!\internal
2969
2970 The function sets the window state on child widgets similar to
2971 setWindowState(). The difference is that the window state changed
2972 event has the isOverride() flag set. It exists mainly to keep
2973 QWorkspace working.
2974 */
2975void QWidget::overrideWindowState(Qt::WindowStates newstate)
2976{
2977 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2978 data->window_state = newstate;
2979 QCoreApplication::sendEvent(this, &e);
2980}
2981
2982/*!
2983 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2984
2985 Sets the window state to \a windowState. The window state is a OR'ed
2986 combination of Qt::WindowState: Qt::WindowMinimized,
2987 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2988
2989 If the window is not visible (i.e. isVisible() returns \c false), the
2990 window state will take effect when show() is called. For visible
2991 windows, the change is immediate. For example, to toggle between
2992 full-screen and normal mode, use the following code:
2993
2994 \snippet code/src_gui_kernel_qwidget.cpp 0
2995
2996 To restore and activate a minimized window (while
2997 preserving its maximized and/or full-screen state), use the following:
2998
2999 \snippet code/src_gui_kernel_qwidget.cpp 1
3000
3001 Calling this function will hide the widget. You must call show() to make
3002 the widget visible again.
3003
3004 \note On some window systems Qt::WindowActive is not immediate, and may be
3005 ignored in certain cases.
3006
3007 When the window state changes, the widget receives a changeEvent()
3008 of type QEvent::WindowStateChange.
3009
3010 \sa Qt::WindowState, windowState()
3011*/
3012void QWidget::setWindowState(Qt::WindowStates newstate)
3013{
3014 Q_D(QWidget);
3015 Qt::WindowStates oldstate = windowState();
3016 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
3017 newstate.setFlag(Qt::WindowActive, false);
3018 if (oldstate == newstate)
3019 return;
3020 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
3021 create();
3022
3023 data->window_state = newstate;
3024 data->in_set_window_state = 1;
3025 if (isWindow()) {
3026 // Ensure the initial size is valid, since we store it as normalGeometry below.
3027 if (!testAttribute(Qt::WA_Resized) && !isVisible())
3028 adjustSize();
3029
3030 d->createTLExtra();
3031 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3032 d->topData()->normalGeometry = geometry();
3033
3034 Q_ASSERT(windowHandle());
3035 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3036 }
3037 data->in_set_window_state = 0;
3038
3039 if (newstate & Qt::WindowActive)
3040 activateWindow();
3041
3042 QWindowStateChangeEvent e(oldstate);
3043 QCoreApplication::sendEvent(this, &e);
3044}
3045
3046/*!
3047 \property QWidget::fullScreen
3048 \brief whether the widget is shown in full screen mode
3049
3050 A widget in full screen mode occupies the whole screen area and does not
3051 display window decorations, such as a title bar.
3052
3053 By default, this property is \c false.
3054
3055 \sa windowState(), minimized, maximized
3056*/
3057bool QWidget::isFullScreen() const
3058{ return data->window_state & Qt::WindowFullScreen; }
3059
3060/*!
3061 Shows the widget in full-screen mode.
3062
3063 Calling this function only affects \l{isWindow()}{windows}.
3064
3065 To return from full-screen mode, call showNormal() or close().
3066
3067 \note Full-screen mode works fine under Windows, but has certain
3068 problems under X. These problems are due to limitations of the
3069 ICCCM protocol that specifies the communication between X11
3070 clients and the window manager. ICCCM simply does not understand
3071 the concept of non-decorated full-screen windows. Therefore, the
3072 best you can do is to request a borderless window and place and
3073 resize it to fill the entire screen. Depending on the window
3074 manager, this may or may not work. The borderless window is
3075 requested using MOTIF hints, which are at least partially
3076 supported by virtually all modern window managers.
3077
3078 An alternative would be to bypass the window manager entirely and
3079 create a window with the Qt::X11BypassWindowManagerHint flag. This
3080 has other severe problems though, like broken keyboard focus
3081 and very strange effects on desktop changes or when the user raises
3082 other windows.
3083
3084 X11 window managers that follow modern post-ICCCM specifications
3085 support full-screen mode properly.
3086
3087 On macOS, showing a window full screen puts the entire application in
3088 full-screen mode, providing it with a dedicated desktop. Showing another
3089 window while the application runs in full-screen mode might automatically
3090 make that window full screen as well. To prevent that, exit full-screen
3091 mode by calling showNormal() or by close() on the full screen window
3092 before showing another window.
3093
3094 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3095*/
3096void QWidget::showFullScreen()
3097{
3098 ensurePolished();
3099
3100 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3101 | Qt::WindowFullScreen);
3102 setVisible(true);
3103#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3104 // activating it here before libscreen activates it causes problems
3105 activateWindow();
3106#endif
3107}
3108
3109/*!
3110 Shows the widget maximized.
3111
3112 Calling this function only affects \l{isWindow()}{windows}.
3113
3114 On X11, this function may not work properly with certain window
3115 managers. See the \l{Window Geometry} documentation for an explanation.
3116
3117 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3118*/
3119void QWidget::showMaximized()
3120{
3121 ensurePolished();
3122
3123 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3124 | Qt::WindowMaximized);
3125 setVisible(true);
3126}
3127
3128/*!
3129 Restores the widget after it has been maximized or minimized.
3130
3131 Calling this function only affects \l{isWindow()}{windows}.
3132
3133 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3134*/
3135void QWidget::showNormal()
3136{
3137 ensurePolished();
3138
3139 setWindowState(windowState() & ~(Qt::WindowMinimized
3140 | Qt::WindowMaximized
3141 | Qt::WindowFullScreen));
3142 setVisible(true);
3143}
3144
3145/*!
3146 Returns \c true if this widget would become enabled if \a ancestor is
3147 enabled; otherwise returns \c false.
3148
3149
3150
3151 This is the case if neither the widget itself nor every parent up
3152 to but excluding \a ancestor has been explicitly disabled.
3153
3154 isEnabledTo(0) returns false if this widget or any if its ancestors
3155 was explicitly disabled.
3156
3157 The word ancestor here means a parent widget within the same window.
3158
3159 Therefore isEnabledTo(0) stops at this widget's window, unlike
3160 isEnabled() which also takes parent windows into considerations.
3161
3162 \sa setEnabled(), enabled
3163*/
3164
3165bool QWidget::isEnabledTo(const QWidget *ancestor) const
3166{
3167 const QWidget * w = this;
3168 while (!w->testAttribute(Qt::WA_ForceDisabled)
3169 && !w->isWindow()
3170 && w->parentWidget()
3171 && w->parentWidget() != ancestor)
3172 w = w->parentWidget();
3173 return !w->testAttribute(Qt::WA_ForceDisabled);
3174}
3175
3176#ifndef QT_NO_ACTION
3177/*!
3178 Appends the action \a action to this widget's list of actions.
3179
3180 All QWidgets have a list of \l{QAction}s. However, they can be
3181 represented graphically in many different ways. The default use of
3182 the QAction list (as returned by actions()) is to create a context
3183 QMenu.
3184
3185 A QWidget should only have one of each action and adding an action
3186 it already has will not cause the same action to be in the widget twice.
3187
3188 The ownership of \a action is not transferred to this QWidget.
3189
3190 \sa removeAction(), insertAction(), actions(), QMenu
3191*/
3192void QWidget::addAction(QAction *action)
3193{
3194 insertAction(nullptr, action);
3195}
3196
3197/*!
3198 Appends the actions \a actions to this widget's list of actions.
3199
3200 \sa removeAction(), QMenu, addAction()
3201*/
3202void QWidget::addActions(const QList<QAction *> &actions)
3203{
3204 for(int i = 0; i < actions.size(); i++)
3205 insertAction(nullptr, actions.at(i));
3206}
3207
3208/*!
3209 Inserts the action \a action to this widget's list of actions,
3210 before the action \a before. It appends the action if \a before is \nullptr or
3211 \a before is not a valid action for this widget.
3212
3213 A QWidget should only have one of each action.
3214
3215 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3216*/
3217void QWidget::insertAction(QAction *before, QAction *action)
3218{
3219 if (Q_UNLIKELY(!action)) {
3220 qWarning("QWidget::insertAction: Attempt to insert null action");
3221 return;
3222 }
3223
3224 Q_D(QWidget);
3225 if (d->actions.contains(action))
3226 removeAction(action);
3227
3228 int pos = d->actions.indexOf(before);
3229 if (pos < 0) {
3230 before = nullptr;
3231 pos = d->actions.size();
3232 }
3233 d->actions.insert(pos, action);
3234
3235 QActionPrivate *apriv = action->d_func();
3236 apriv->associatedObjects.append(this);
3237
3238 QActionEvent e(QEvent::ActionAdded, action, before);
3239 QCoreApplication::sendEvent(this, &e);
3240}
3241
3242/*!
3243 Inserts the actions \a actions to this widget's list of actions,
3244 before the action \a before. It appends the action if \a before is \nullptr or
3245 \a before is not a valid action for this widget.
3246
3247 A QWidget can have at most one of each action.
3248
3249 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3250*/
3251void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3252{
3253 for(int i = 0; i < actions.size(); ++i)
3254 insertAction(before, actions.at(i));
3255}
3256
3257/*!
3258 Removes the action \a action from this widget's list of actions.
3259 \sa insertAction(), actions(), insertAction()
3260*/
3261void QWidget::removeAction(QAction *action)
3262{
3263 if (!action)
3264 return;
3265
3266 Q_D(QWidget);
3267
3268 QActionPrivate *apriv = action->d_func();
3269 apriv->associatedObjects.removeAll(this);
3270
3271 if (d->actions.removeAll(action)) {
3272 QActionEvent e(QEvent::ActionRemoved, action);
3273 QCoreApplication::sendEvent(this, &e);
3274 }
3275}
3276
3277/*!
3278 Returns the (possibly empty) list of this widget's actions.
3279
3280 \sa contextMenuPolicy, insertAction(), removeAction()
3281*/
3282QList<QAction*> QWidget::actions() const
3283{
3284 Q_D(const QWidget);
3285 return d->actions;
3286}
3287
3288/*!
3289 \fn QAction *QWidget::addAction(const QString &text);
3290 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3291 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3292 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3293
3294 \since 6.3
3295
3296 These convenience functions create a new action with text \a text,
3297 icon \a icon and shortcut \a shortcut, if any.
3298
3299 The functions add the newly created action to the widget's
3300 list of actions, and return it.
3301
3302 QWidget takes ownership of the returned QAction.
3303*/
3304QAction *QWidget::addAction(const QString &text)
3305{
3306 QAction *ret = new QAction(text, this);
3307 addAction(ret);
3308 return ret;
3309}
3310
3311QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3312{
3313 QAction *ret = new QAction(icon, text, this);
3314 addAction(ret);
3315 return ret;
3316}
3317
3318#if QT_CONFIG(shortcut)
3319QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3320{
3321 QAction *ret = addAction(text);
3322 ret->setShortcut(shortcut);
3323 return ret;
3324}
3325
3326QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3327{
3328 QAction *ret = addAction(icon, text);
3329 ret->setShortcut(shortcut);
3330 return ret;
3331}
3332#endif
3333
3334/*!
3335 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3336 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3337 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3338 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3339
3340 \overload
3341 \since 6.3
3342
3343 This convenience function creates a new action with the text \a
3344 text, icon \a icon, and shortcut \a shortcut, if any.
3345
3346 The action's \l{QAction::triggered()}{triggered()} signal is connected
3347 to the \a receiver's \a member slot. The function adds the newly created
3348 action to the widget's list of actions and returns it.
3349
3350 QWidget takes ownership of the returned QAction.
3351*/
3352QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3353 Qt::ConnectionType type)
3354{
3355 QAction *action = addAction(text);
3356 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3357 return action;
3358}
3359
3360QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3361 const QObject *receiver, const char* member,
3362 Qt::ConnectionType type)
3363{
3364 QAction *action = addAction(icon, text);
3365 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3366 return action;
3367}
3368
3369#if QT_CONFIG(shortcut)
3370QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3371 const QObject *receiver, const char* member,
3372 Qt::ConnectionType type)
3373{
3374 QAction *action = addAction(text, receiver, member, type);
3375 action->setShortcut(shortcut);
3376 return action;
3377}
3378
3379QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3380 const QObject *receiver, const char* member,
3381 Qt::ConnectionType type)
3382{
3383 QAction *action = addAction(icon, text, receiver, member, type);
3384 action->setShortcut(shortcut);
3385 return action;
3386}
3387#endif // QT_CONFIG(shortcut)
3388
3389/*!
3390 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3391 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3392 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3393 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3394
3395 \since 6.3
3396 \overload
3397
3398 These convenience functions create a new action with the text \a text,
3399 icon \a icon, and shortcut \a shortcut, if any.
3400
3401 The action's \l{QAction::triggered()}{triggered()} signal is connected
3402 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3403 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3404
3405 The function adds the newly created action to the widget's list of
3406 actions and returns it.
3407
3408 QWidget takes ownership of the returned QAction.
3409*/
3410#endif // QT_NO_ACTION
3411
3412/*!
3413 \property QWidget::enabled
3414 \brief whether the widget is enabled
3415
3416 In general an enabled widget handles keyboard and mouse events; a disabled
3417 widget does not. An exception is made with \l{QAbstractButton}.
3418
3419 Some widgets display themselves differently when they are
3420 disabled. For example a button might draw its label grayed out. If
3421 your widget needs to know when it becomes enabled or disabled, you
3422 can use the changeEvent() with type QEvent::EnabledChange.
3423
3424 Disabling a widget implicitly disables all its children. Enabling
3425 respectively enables all child widgets unless they have been
3426 explicitly disabled. It it not possible to explicitly enable a child
3427 widget which is not a window while its parent widget remains disabled.
3428
3429 By default, this property is \c true.
3430
3431 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3432*/
3433void QWidget::setEnabled(bool enable)
3434{
3435 Q_D(QWidget);
3436
3437#if QT_CONFIG(accessibility)
3438 const bool wasEnabled = !testAttribute(Qt::WA_ForceDisabled);
3439#endif
3440
3441 setAttribute(Qt::WA_ForceDisabled, !enable);
3442 d->setEnabled_helper(enable);
3443
3444#if QT_CONFIG(accessibility)
3445 // A widget is enabled if it's parent and itself is enabled.
3446 // We do not send state changed events recursively. It is up
3447 // to the receiver of the events to check children if required.
3448 if (QAccessible::isActive() && wasEnabled != enable) {
3449 QAccessible::State states;
3450 states.disabled = 1;
3451 QAccessibleStateChangeEvent scEvent(this, states);
3452 QAccessible::updateAccessibility(&scEvent);
3453 }
3454#endif
3455}
3456
3457void QWidgetPrivate::setEnabled_helper(bool enable)
3458{
3459 Q_Q(QWidget);
3460
3461 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3462 return; // nothing we can do
3463
3464 if (enable != q->testAttribute(Qt::WA_Disabled))
3465 return; // nothing to do
3466
3467 q->setAttribute(Qt::WA_Disabled, !enable);
3468 updateSystemBackground();
3469
3470 if (!enable && q->window()->focusWidget() == q) {
3471 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3472 if (!parentIsEnabled || !q->focusNextChild())
3473 q->clearFocus();
3474 }
3475
3476 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3477 for (int i = 0; i < children.size(); ++i) {
3478 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3479 if (w && !w->testAttribute(attribute))
3480 w->d_func()->setEnabled_helper(enable);
3481 }
3482#ifndef QT_NO_CURSOR
3483 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3484 // enforce the windows behavior of clearing the cursor on
3485 // disabled widgets
3486 qt_qpa_set_cursor(q, false);
3487 }
3488#endif
3489#ifndef QT_NO_IM
3490 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3491 QWidget *focusWidget = effectiveFocusWidget();
3492
3493 if (enable) {
3494 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3495 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3496 } else {
3497 QGuiApplication::inputMethod()->commit();
3498 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3499 }
3500 }
3501#endif //QT_NO_IM
3502 QEvent e(QEvent::EnabledChange);
3503 QCoreApplication::sendEvent(q, &e);
3504}
3505
3506/*!
3507 \property QWidget::acceptDrops
3508 \brief whether drop events are enabled for this widget
3509
3510 Setting this property to true announces to the system that this
3511 widget \e may be able to accept drop events.
3512
3513 \warning Do not modify this property in a drag and drop event handler.
3514
3515 By default, this property is \c false.
3516
3517 \sa {Drag and Drop in Qt}{Drag and Drop}
3518*/
3519bool QWidget::acceptDrops() const
3520{
3521 return testAttribute(Qt::WA_AcceptDrops);
3522}
3523
3524void QWidget::setAcceptDrops(bool on)
3525{
3526 setAttribute(Qt::WA_AcceptDrops, on);
3527
3528}
3529
3530/*!
3531 Disables widget input events if \a disable is true; otherwise
3532 enables input events.
3533
3534 See the \l enabled documentation for more information.
3535
3536 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3537*/
3538void QWidget::setDisabled(bool disable)
3539{
3540 setEnabled(!disable);
3541}
3542
3543/*!
3544 \property QWidget::frameGeometry
3545 \brief geometry of the widget relative to its parent including any
3546 window frame
3547
3548 See the \l{Window Geometry} documentation for an overview of geometry
3549 issues with windows.
3550
3551 By default, this property contains a value that depends on the user's
3552 platform and screen geometry.
3553
3554 \sa geometry(), x(), y(), pos()
3555*/
3556QRect QWidget::frameGeometry() const
3557{
3558 Q_D(const QWidget);
3559 if (isWindow() && ! (windowType() == Qt::Popup)) {
3560 QRect fs = d->frameStrut();
3561 return QRect(data->crect.x() - fs.left(),
3562 data->crect.y() - fs.top(),
3563 data->crect.width() + fs.left() + fs.right(),
3564 data->crect.height() + fs.top() + fs.bottom());
3565 }
3566 return data->crect;
3567}
3568
3569/*!
3570 \property QWidget::x
3571
3572 \brief the x coordinate of the widget relative to its parent including
3573 any window frame
3574
3575 See the \l{Window Geometry} documentation for an overview of geometry
3576 issues with windows.
3577
3578 By default, this property has a value of 0.
3579
3580 \sa frameGeometry, y, pos
3581*/
3582int QWidget::x() const
3583{
3584 Q_D(const QWidget);
3585 if (isWindow() && ! (windowType() == Qt::Popup))
3586 return data->crect.x() - d->frameStrut().left();
3587 return data->crect.x();
3588}
3589
3590/*!
3591 \property QWidget::y
3592 \brief the y coordinate of the widget relative to its parent and
3593 including any window frame
3594
3595 See the \l{Window Geometry} documentation for an overview of geometry
3596 issues with windows.
3597
3598 By default, this property has a value of 0.
3599
3600 \sa frameGeometry, x, pos
3601*/
3602int QWidget::y() const
3603{
3604 Q_D(const QWidget);
3605 if (isWindow() && ! (windowType() == Qt::Popup))
3606 return data->crect.y() - d->frameStrut().top();
3607 return data->crect.y();
3608}
3609
3610/*!
3611 \property QWidget::pos
3612 \brief the position of the widget within its parent widget
3613
3614 If the widget is a window, the position is that of the widget on
3615 the desktop, including its frame.
3616
3617 When changing the position, the widget, if visible, receives a
3618 move event (moveEvent()) immediately. If the widget is not
3619 currently visible, it is guaranteed to receive an event before it
3620 is shown.
3621
3622 By default, this property contains a position that refers to the
3623 origin.
3624
3625 \warning Calling move() or setGeometry() inside moveEvent() can
3626 lead to infinite recursion.
3627
3628 See the \l{Window Geometry} documentation for an overview of geometry
3629 issues with windows.
3630
3631 \note Not all windowing systems support setting or querying top level window positions.
3632 On such a system, programmatically moving windows may not have any effect, and artificial
3633 values may be returned for the current positions, such as \c QPoint(0, 0).
3634
3635 \sa frameGeometry, size, x(), y()
3636*/
3637QPoint QWidget::pos() const
3638{
3639 Q_D(const QWidget);
3640 QPoint result = data->crect.topLeft();
3641 if (isWindow() && ! (windowType() == Qt::Popup))
3642 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3643 result -= d->frameStrut().topLeft();
3644 return result;
3645}
3646
3647/*!
3648 \property QWidget::geometry
3649 \brief the geometry of the widget relative to its parent and
3650 excluding the window frame
3651
3652 If the widget is a top-level widget (a window) its geometry is
3653 given in global screen coordinates.
3654
3655 When changing the geometry, the widget, if visible, receives a
3656 move event (moveEvent()) and/or a resize event (resizeEvent())
3657 immediately. If the widget is not currently visible, it is
3658 guaranteed to receive appropriate events before it is shown.
3659
3660 The size component is adjusted if it lies outside the range
3661 defined by minimumSize() and maximumSize().
3662
3663 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3664 can lead to infinite recursion.
3665
3666 See the \l{Window Geometry} documentation for an overview of geometry
3667 issues with windows.
3668
3669 By default, this property contains a value that depends on the user's
3670 platform and screen geometry.
3671
3672 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3673 resizeEvent(), minimumSize(), maximumSize()
3674*/
3675
3676/*!
3677 \property QWidget::size
3678 \brief the size of the widget excluding any window frame
3679
3680 If the widget is visible when it is being resized, it receives a resize event
3681 (resizeEvent()) immediately. If the widget is not currently
3682 visible, it is guaranteed to receive an event before it is shown.
3683
3684 The size is adjusted if it lies outside the range defined by
3685 minimumSize() and maximumSize().
3686
3687 By default, this property contains a value that depends on the user's
3688 platform and screen geometry.
3689
3690 \warning Calling resize() or setGeometry() inside resizeEvent() can
3691 lead to infinite recursion.
3692
3693 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3694 appear on screen. This also applies to windows.
3695
3696 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3697*/
3698
3699/*!
3700 \property QWidget::width
3701 \brief the width of the widget excluding any window frame
3702
3703 See the \l{Window Geometry} documentation for an overview of geometry
3704 issues with windows.
3705
3706 \note Do not use this function to find the width of a screen on
3707 a multi-screen desktop. See QScreen for details.
3708
3709 By default, this property contains a value that depends on the user's
3710 platform and screen geometry.
3711
3712 \sa geometry, height, size
3713*/
3714
3715/*!
3716 \property QWidget::height
3717 \brief the height of the widget excluding any window frame
3718
3719 See the \l{Window Geometry} documentation for an overview of geometry
3720 issues with windows.
3721
3722 By default, this property contains a value that depends on the user's
3723 platform and \l{QScreen::geometry}{screen geometry}.
3724
3725 \sa geometry, width, size
3726*/
3727
3728/*!
3729 \property QWidget::rect
3730 \brief the internal geometry of the widget excluding any window
3731 frame
3732
3733 The rect property equals QRect(0, 0, width(), height()).
3734
3735 See the \l{Window Geometry} documentation for an overview of geometry
3736 issues with windows.
3737
3738 By default, this property contains a value that depends on the user's
3739 platform and screen geometry.
3740
3741 \sa size
3742*/
3743
3744/*!
3745 \property QWidget::normalGeometry
3746
3747 \brief the geometry of the widget as it will appear when shown as
3748 a normal (not maximized or full screen) top-level widget
3749
3750 If the widget is already in this state the normal geometry will
3751 reflect the widget's current geometry().
3752
3753 For child widgets this property always holds an empty rectangle.
3754
3755 By default, this property contains an empty rectangle.
3756
3757 \sa QWidget::windowState(), QWidget::geometry
3758*/
3759QRect QWidget::normalGeometry() const
3760{
3761 Q_D(const QWidget);
3762 if (!isWindow())
3763 return QRect();
3764
3765 if (!isMaximized() && !isFullScreen())
3766 return geometry();
3767
3768 return d->topData()->normalGeometry;
3769}
3770
3771
3772/*!
3773 \property QWidget::childrenRect
3774 \brief the bounding rectangle of the widget's children
3775
3776 Hidden children are excluded.
3777
3778 By default, for a widget with no children, this property contains a
3779 rectangle with zero width and height located at the origin.
3780
3781 \sa childrenRegion(), geometry()
3782*/
3783
3784QRect QWidget::childrenRect() const
3785{
3786 Q_D(const QWidget);
3787 QRect r(0, 0, 0, 0);
3788 for (int i = 0; i < d->children.size(); ++i) {
3789 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3790 if (w && !w->isWindow() && !w->isHidden())
3791 r |= w->geometry();
3792 }
3793 return r;
3794}
3795
3796/*!
3797 \property QWidget::childrenRegion
3798 \brief the combined region occupied by the widget's children
3799
3800 Hidden children are excluded.
3801
3802 By default, for a widget with no children, this property contains an
3803 empty region.
3804
3805 \sa childrenRect(), geometry(), mask()
3806*/
3807
3808QRegion QWidget::childrenRegion() const
3809{
3810 Q_D(const QWidget);
3811 QRegion r;
3812 for (int i = 0; i < d->children.size(); ++i) {
3813 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3814 if (w && !w->isWindow() && !w->isHidden()) {
3815 QRegion mask = w->mask();
3816 if (mask.isEmpty())
3817 r |= w->geometry();
3818 else
3819 r |= mask.translated(w->pos());
3820 }
3821 }
3822 return r;
3823}
3824
3825
3826/*!
3827 \property QWidget::minimumSize
3828 \brief the widget's minimum size
3829
3830 The widget cannot be resized to a smaller size than the minimum
3831 widget size. The widget's size is forced to the minimum size if
3832 the current size is smaller.
3833
3834 The minimum size set by this function will override the minimum size
3835 defined by QLayout. To unset the minimum size, use a
3836 value of \c{QSize(0, 0)}.
3837
3838 By default, this property contains a size with zero width and height.
3839
3840 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3841*/
3842
3843QSize QWidget::minimumSize() const
3844{
3845 Q_D(const QWidget);
3846 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3847}
3848
3849/*!
3850 \property QWidget::maximumSize
3851 \brief the widget's maximum size in pixels
3852
3853 The widget cannot be resized to a larger size than the maximum
3854 widget size.
3855
3856 By default, this property contains a size in which both width and height
3857 have values of 16777215.
3858
3859 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3860 of widgets.
3861
3862 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3863*/
3864
3865QSize QWidget::maximumSize() const
3866{
3867 Q_D(const QWidget);
3868 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3870}
3871
3872
3873/*!
3874 \property QWidget::minimumWidth
3875 \brief the widget's minimum width in pixels
3876
3877 This property corresponds to the width held by the \l minimumSize property.
3878
3879 By default, this property has a value of 0.
3880
3881 \sa minimumSize, minimumHeight
3882*/
3883
3884/*!
3885 \property QWidget::minimumHeight
3886 \brief the widget's minimum height in pixels
3887
3888 This property corresponds to the height held by the \l minimumSize property.
3889
3890 By default, this property has a value of 0.
3891
3892 \sa minimumSize, minimumWidth
3893*/
3894
3895/*!
3896 \property QWidget::maximumWidth
3897 \brief the widget's maximum width in pixels
3898
3899 This property corresponds to the width held by the \l maximumSize property.
3900
3901 By default, this property contains a value of 16777215.
3902
3903 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3904 of widgets.
3905
3906 \sa maximumSize, maximumHeight
3907*/
3908
3909/*!
3910 \property QWidget::maximumHeight
3911 \brief the widget's maximum height in pixels
3912
3913 This property corresponds to the height held by the \l maximumSize property.
3914
3915 By default, this property contains a value of 16777215.
3916
3917 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3918 of widgets.
3919
3920 \sa maximumSize, maximumWidth
3921*/
3922
3923/*!
3924 \property QWidget::sizeIncrement
3925 \brief the size increment of the widget
3926
3927 When the user resizes the window, the size will move in steps of
3928 sizeIncrement().width() pixels horizontally and
3929 sizeIncrement.height() pixels vertically, with baseSize() as the
3930 basis. Preferred widget sizes are for non-negative integers \e i
3931 and \e j:
3932 \snippet code/src_gui_kernel_qwidget.cpp 2
3933
3934 Note that while you can set the size increment for all widgets, it
3935 only affects windows.
3936
3937 By default, this property contains a size with zero width and height.
3938
3939 \warning The size increment has no effect under Windows, and may
3940 be disregarded by the window manager on X11.
3941
3942 \sa size, minimumSize, maximumSize
3943*/
3944QSize QWidget::sizeIncrement() const
3945{
3946 Q_D(const QWidget);
3947 return (d->extra && d->extra->topextra)
3948 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3949 : QSize(0, 0);
3950}
3951
3952/*!
3953 \property QWidget::baseSize
3954 \brief the base size of the widget
3955
3956 The base size is used to calculate a proper widget size if the
3957 widget defines sizeIncrement().
3958
3959 By default, for a newly-created widget, this property contains a size with
3960 zero width and height.
3961
3962 \sa setSizeIncrement()
3963*/
3964
3965QSize QWidget::baseSize() const
3966{
3967 Q_D(const QWidget);
3968 return (d->extra && d->extra->topextra)
3969 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3970 : QSize(0, 0);
3971}
3972
3973bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3974{
3975 Q_Q(QWidget);
3976
3977 int mw = minw, mh = minh;
3978 if (mw == QWIDGETSIZE_MAX)
3979 mw = 0;
3980 if (mh == QWIDGETSIZE_MAX)
3981 mh = 0;
3982 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3983 qWarning("QWidget::setMinimumSize: (%s/%s) "
3984 "The largest allowed size is (%d,%d)",
3985 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3987 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3988 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3989 }
3990 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3991 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3992 "are not possible",
3993 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3994 minw = mw = qMax(minw, 0);
3995 minh = mh = qMax(minh, 0);
3996 }
3997 createExtra();
3998 if (extra->minw == mw && extra->minh == mh)
3999 return false;
4000 extra->minw = mw;
4001 extra->minh = mh;
4002 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
4003 return true;
4004}
4005
4006void QWidgetPrivate::setConstraints_sys()
4007{
4008 Q_Q(QWidget);
4009 if (extra && q->windowHandle()) {
4010 QWindow *win = q->windowHandle();
4011 QWindowPrivate *winp = qt_window_private(win);
4012
4013 winp->minimumSize = QSize(extra->minw, extra->minh);
4014 winp->maximumSize = QSize(extra->maxw, extra->maxh);
4015
4016 if (extra->topextra) {
4017 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
4018 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
4019 }
4020
4021 if (winp->platformWindow) {
4022 fixPosIncludesFrame();
4023 winp->platformWindow->propagateSizeHints();
4024 }
4025 }
4026}
4027
4028/*!
4029 \overload
4030
4031 This function corresponds to setMinimumSize(QSize(minw, minh)).
4032 Sets the minimum width to \a minw and the minimum height to \a
4033 minh.
4034*/
4035
4036void QWidget::setMinimumSize(int minw, int minh)
4037{
4038 Q_D(QWidget);
4039 if (!d->setMinimumSize_helper(minw, minh))
4040 return;
4041
4042 if (isWindow())
4043 d->setConstraints_sys();
4044 if (minw > width() || minh > height()) {
4045 bool resized = testAttribute(Qt::WA_Resized);
4046 bool maximized = isMaximized();
4047 resize(qMax(minw,width()), qMax(minh,height()));
4048 setAttribute(Qt::WA_Resized, resized); //not a user resize
4049 if (maximized)
4050 data->window_state = data->window_state | Qt::WindowMaximized;
4051 }
4052#if QT_CONFIG(graphicsview)
4053 if (d->extra) {
4054 if (d->extra->proxyWidget)
4055 d->extra->proxyWidget->setMinimumSize(minw, minh);
4056 }
4057#endif
4058 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4059}
4060
4061bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
4062{
4063 Q_Q(QWidget);
4064 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
4065 qWarning("QWidget::setMaximumSize: (%s/%s) "
4066 "The largest allowed size is (%d,%d)",
4067 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4069 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4070 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4071 }
4072 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4073 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4074 "are not possible",
4075 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4076 maxw = qMax(maxw, 0);
4077 maxh = qMax(maxh, 0);
4078 }
4079 createExtra();
4080 if (extra->maxw == maxw && extra->maxh == maxh)
4081 return false;
4082 extra->maxw = maxw;
4083 extra->maxh = maxh;
4084 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4085 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4086 return true;
4087}
4088
4089/*!
4090 \overload
4091
4092 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4093 maxh)). Sets the maximum width to \a maxw and the maximum height
4094 to \a maxh.
4095*/
4096void QWidget::setMaximumSize(int maxw, int maxh)
4097{
4098 Q_D(QWidget);
4099 if (!d->setMaximumSize_helper(maxw, maxh))
4100 return;
4101
4102 if (isWindow())
4103 d->setConstraints_sys();
4104 if (maxw < width() || maxh < height()) {
4105 bool resized = testAttribute(Qt::WA_Resized);
4106 resize(qMin(maxw,width()), qMin(maxh,height()));
4107 setAttribute(Qt::WA_Resized, resized); //not a user resize
4108 }
4109
4110#if QT_CONFIG(graphicsview)
4111 if (d->extra) {
4112 if (d->extra->proxyWidget)
4113 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4114 }
4115#endif
4116
4117 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4118}
4119
4120/*!
4121 \overload
4122
4123 Sets the x (width) size increment to \a w and the y (height) size
4124 increment to \a h.
4125*/
4126void QWidget::setSizeIncrement(int w, int h)
4127{
4128 Q_D(QWidget);
4129 d->createTLExtra();
4130 QTLWExtra* x = d->topData();
4131 if (x->incw == w && x->inch == h)
4132 return;
4133 x->incw = w;
4134 x->inch = h;
4135 if (isWindow())
4136 d->setConstraints_sys();
4137}
4138
4139/*!
4140 \overload
4141
4142 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4143 the widgets base size to width \a basew and height \a baseh.
4144*/
4145void QWidget::setBaseSize(int basew, int baseh)
4146{
4147 Q_D(QWidget);
4148 d->createTLExtra();
4149 QTLWExtra* x = d->topData();
4150 if (x->basew == basew && x->baseh == baseh)
4151 return;
4152 x->basew = basew;
4153 x->baseh = baseh;
4154 if (isWindow())
4155 d->setConstraints_sys();
4156}
4157
4158/*!
4159 Sets both the minimum and maximum sizes of the widget to \a s,
4160 thereby preventing it from ever growing or shrinking.
4161
4162 This will override the default size constraints set by QLayout.
4163
4164 To remove constraints, set the size to QWIDGETSIZE_MAX.
4165
4166 Alternatively, if you want the widget to have a
4167 fixed size based on its contents, you can call
4168 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4169
4170 \sa maximumSize, minimumSize
4171*/
4172
4173void QWidget::setFixedSize(const QSize & s)
4174{
4175 setFixedSize(s.width(), s.height());
4176}
4177
4178
4179/*!
4180 \fn void QWidget::setFixedSize(int w, int h)
4181 \overload
4182
4183 Sets the width of the widget to \a w and the height to \a h.
4184*/
4185
4186void QWidget::setFixedSize(int w, int h)
4187{
4188 Q_D(QWidget);
4189 bool minSizeSet = d->setMinimumSize_helper(w, h);
4190 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4191 if (!minSizeSet && !maxSizeSet)
4192 return;
4193
4194 if (isWindow())
4195 d->setConstraints_sys();
4196 else
4197 d->updateGeometry_helper(true);
4198
4199 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4200 resize(w, h);
4201}
4202
4203void QWidget::setMinimumWidth(int w)
4204{
4205 Q_D(QWidget);
4206 d->createExtra();
4207 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4208 setMinimumSize(w, minimumSize().height());
4209 d->extra->explicitMinSize = expl;
4210}
4211
4212void QWidget::setMinimumHeight(int h)
4213{
4214 Q_D(QWidget);
4215 d->createExtra();
4216 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4217 setMinimumSize(minimumSize().width(), h);
4218 d->extra->explicitMinSize = expl;
4219}
4220
4221void QWidget::setMaximumWidth(int w)
4222{
4223 Q_D(QWidget);
4224 d->createExtra();
4225 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4226 setMaximumSize(w, maximumSize().height());
4227 d->extra->explicitMaxSize = expl;
4228}
4229
4230void QWidget::setMaximumHeight(int h)
4231{
4232 Q_D(QWidget);
4233 d->createExtra();
4234 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4235 setMaximumSize(maximumSize().width(), h);
4236 d->extra->explicitMaxSize = expl;
4237}
4238
4239/*!
4240 Sets both the minimum and maximum width of the widget to \a w
4241 without changing the heights. Provided for convenience.
4242
4243 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4244*/
4245
4246void QWidget::setFixedWidth(int w)
4247{
4248 Q_D(QWidget);
4249 d->createExtra();
4250 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4251 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4252 setMinimumSize(w, minimumSize().height());
4253 setMaximumSize(w, maximumSize().height());
4254 d->extra->explicitMinSize = explMin;
4255 d->extra->explicitMaxSize = explMax;
4256}
4257
4258
4259/*!
4260 Sets both the minimum and maximum heights of the widget to \a h
4261 without changing the widths. Provided for convenience.
4262
4263 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4264*/
4265
4266void QWidget::setFixedHeight(int h)
4267{
4268 Q_D(QWidget);
4269 d->createExtra();
4270 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4271 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4272 setMinimumSize(minimumSize().width(), h);
4273 setMaximumSize(maximumSize().width(), h);
4274 d->extra->explicitMinSize = explMin;
4275 d->extra->explicitMaxSize = explMax;
4276}
4277
4278
4279/*!
4280 Translates the widget coordinate \a pos to the coordinate system
4281 of \a parent. The \a parent must not be \nullptr and must be a parent
4282 of the calling widget.
4283
4284 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4285 \since 6.0
4286*/
4287
4288QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4289{
4290 QPointF p = pos;
4291 if (parent) {
4292 const QWidget * w = this;
4293 while (w != parent) {
4294 p = w->mapToParent(p);
4295 w = w->parentWidget();
4296 if (!w) {
4297 qWarning("QWidget::mapTo(): parent must be in parent hierarchy");
4298 break;
4299 }
4300 }
4301 }
4302 return p;
4303}
4304
4305/*!
4306 \overload
4307*/
4308QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4309{
4310 return mapTo(parent, QPointF(pos)).toPoint();
4311}
4312
4313/*!
4314 Translates the widget coordinate \a pos from the coordinate system
4315 of \a parent to this widget's coordinate system. The \a parent
4316 must not be \nullptr and must be a parent of the calling widget.
4317
4318 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4319 \since 6.0
4320*/
4321
4322QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4323{
4324 QPointF p(pos);
4325 if (parent) {
4326 const QWidget * w = this;
4327 while (w != parent) {
4328 p = w->mapFromParent(p);
4329 w = w->parentWidget();
4330 if (!w) {
4331 qWarning("QWidget::mapFrom(): parent must be in parent hierarchy");
4332 break;
4333 }
4334 }
4335 }
4336 return p;
4337}
4338
4339/*!
4340 \overload
4341*/
4342QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4343{
4344 return mapFrom(parent, QPointF(pos)).toPoint();
4345}
4346
4347/*!
4348 Translates the widget coordinate \a pos to a coordinate in the
4349 parent widget.
4350
4351 Same as mapToGlobal() if the widget has no parent.
4352
4353 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4354 \since 6.0
4355*/
4356
4357QPointF QWidget::mapToParent(const QPointF &pos) const
4358{
4359 return pos + QPointF(data->crect.topLeft());
4360}
4361
4362/*!
4363 \overload
4364*/
4365QPoint QWidget::mapToParent(const QPoint &pos) const
4366{
4367 return pos + data->crect.topLeft();
4368}
4369
4370/*!
4371 Translates the parent widget coordinate \a pos to widget
4372 coordinates.
4373
4374 Same as mapFromGlobal() if the widget has no parent.
4375
4376 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4377 \since 6.0
4378*/
4379
4380QPointF QWidget::mapFromParent(const QPointF &pos) const
4381{
4382 return pos - QPointF(data->crect.topLeft());
4383}
4384
4385/*!
4386 \overload
4387*/
4388QPoint QWidget::mapFromParent(const QPoint &pos) const
4389{
4390 return pos - data->crect.topLeft();
4391}
4392
4393
4394/*!
4395 Returns the window for this widget, i.e. the next ancestor widget
4396 that has (or could have) a window-system frame.
4397
4398 If the widget is a window, the widget itself is returned.
4399
4400 Typical usage is changing the window title:
4401
4402 \snippet code/src_gui_kernel_qwidget.cpp 3
4403
4404 \sa isWindow()
4405*/
4406
4407QWidget *QWidget::window() const
4408{
4409 QWidget *w = const_cast<QWidget *>(this);
4410 QWidget *p = w->parentWidget();
4411 while (!w->isWindow() && p) {
4412 w = p;
4413 p = p->parentWidget();
4414 }
4415 return w;
4416}
4417
4418/*!
4419 \since 4.4
4420
4421 Returns the native parent for this widget, i.e. the next ancestor widget
4422 that has a system identifier, or \nullptr if it does not have any native
4423 parent.
4424
4425 \sa effectiveWinId()
4426*/
4427QWidget *QWidget::nativeParentWidget() const
4428{
4429 QWidget *parent = parentWidget();
4430 while (parent && !parent->internalWinId())
4431 parent = parent->parentWidget();
4432 return parent;
4433}
4434
4435/*! \fn QWidget *QWidget::topLevelWidget() const
4436 \deprecated
4437
4438 Use window() instead.
4439*/
4440
4441
4442
4443/*!
4444 Returns the background role of the widget.
4445
4446 The background role defines the brush from the widget's \l palette that
4447 is used to render the background.
4448
4449 If no explicit background role is set, the widget inherits its parent
4450 widget's background role.
4451
4452 \sa setBackgroundRole(), foregroundRole()
4453 */
4454QPalette::ColorRole QWidget::backgroundRole() const
4455{
4456
4457 const QWidget *w = this;
4458 do {
4459 QPalette::ColorRole role = w->d_func()->bg_role;
4460 if (role != QPalette::NoRole)
4461 return role;
4462 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4463 break;
4464 w = w->parentWidget();
4465 } while (w);
4466 return QPalette::Window;
4467}
4468
4469/*!
4470 Sets the background role of the widget to \a role.
4471
4472 The background role defines the brush from the widget's \l palette that
4473 is used to render the background.
4474
4475 If \a role is QPalette::NoRole, then the widget inherits its
4476 parent's background role.
4477
4478 Note that styles are free to choose any color from the palette.
4479 You can modify the palette or set a style sheet if you don't
4480 achieve the result you want with setBackgroundRole().
4481
4482 \sa backgroundRole(), foregroundRole()
4483 */
4484
4485void QWidget::setBackgroundRole(QPalette::ColorRole role)
4486{
4487 Q_D(QWidget);
4488 d->bg_role = role;
4489 d->updateSystemBackground();
4490 d->propagatePaletteChange();
4491 d->updateIsOpaque();
4492}
4493
4494/*!
4495 Returns the foreground role.
4496
4497 The foreground role defines the color from the widget's \l palette that
4498 is used to draw the foreground.
4499
4500 If no explicit foreground role is set, the function returns a role
4501 that contrasts with the background role.
4502
4503 \sa setForegroundRole(), backgroundRole()
4504 */
4505QPalette::ColorRole QWidget::foregroundRole() const
4506{
4507 Q_D(const QWidget);
4508 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4509 if (rl != QPalette::NoRole)
4510 return rl;
4511 QPalette::ColorRole role = QPalette::WindowText;
4512 switch (backgroundRole()) {
4513 case QPalette::Button:
4514 role = QPalette::ButtonText;
4515 break;
4516 case QPalette::Base:
4517 role = QPalette::Text;
4518 break;
4519 case QPalette::Dark:
4520 case QPalette::Shadow:
4521 role = QPalette::Light;
4522 break;
4523 case QPalette::Highlight:
4524 role = QPalette::HighlightedText;
4525 break;
4526 case QPalette::ToolTipBase:
4527 role = QPalette::ToolTipText;
4528 break;
4529 default:
4530 ;
4531 }
4532 return role;
4533}
4534
4535/*!
4536 Sets the foreground role of the widget to \a role.
4537
4538 The foreground role defines the color from the widget's \l palette that
4539 is used to draw the foreground.
4540
4541 If \a role is QPalette::NoRole, the widget uses a foreground role
4542 that contrasts with the background role.
4543
4544 Note that styles are free to choose any color from the palette.
4545 You can modify the palette or set a style sheet if you don't
4546 achieve the result you want with setForegroundRole().
4547
4548 \sa foregroundRole(), backgroundRole()
4549 */
4550void QWidget::setForegroundRole(QPalette::ColorRole role)
4551{
4552 Q_D(QWidget);
4553 d->fg_role = role;
4554 d->updateSystemBackground();
4555 d->propagatePaletteChange();
4556}
4557
4558/*!
4559 \property QWidget::palette
4560 \brief the widget's palette
4561
4562 This property describes the widget's palette. The palette is used by the
4563 widget's style when rendering standard components, and is available as a
4564 means to ensure that custom widgets can maintain consistency with the
4565 native platform's look and feel. It's common that different platforms, or
4566 different styles, have different palettes.
4567
4568 When you assign a new palette to a widget, the color roles from this
4569 palette are combined with the widget's default palette to form the
4570 widget's final palette. The palette entry for the widget's background role
4571 is used to fill the widget's background (see QWidget::autoFillBackground),
4572 and the foreground role initializes QPainter's pen.
4573
4574 The default depends on the system environment. QApplication maintains a
4575 system/theme palette which serves as a default for all widgets. There may
4576 also be special palette defaults for certain types of widgets (e.g., on
4577 Windows Vista, all classes that derive from QMenuBar have a special
4578 default palette). You can also define default palettes for widgets
4579 yourself by passing a custom palette and the name of a widget to
4580 QApplication::setPalette(). Finally, the style always has the option of
4581 polishing the palette as it's assigned (see QStyle::polish()).
4582
4583 QWidget propagates explicit palette roles from parent to child. If you
4584 assign a brush or color to a specific role on a palette and assign that
4585 palette to a widget, that role will propagate to all the widget's
4586 children, overriding any system defaults for that role. Note that palettes
4587 by default don't propagate to windows (see isWindow()) unless the
4588 Qt::WA_WindowPropagation attribute is enabled.
4589
4590 QWidget's palette propagation is similar to its font propagation.
4591
4592 The current style, which is used to render the content of all standard Qt
4593 widgets, is free to choose colors and brushes from the widget palette, or,
4594 in some cases, to ignore the palette (partially, or completely). In
4595 particular, certain styles like GTK style, Mac style, and Windows Vista
4596 style, depend on third party APIs to render the content of widgets,
4597 and these styles typically do not follow the palette. Because of this,
4598 assigning roles to a widget's palette is not guaranteed to change the
4599 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4600
4601 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4602 When using style sheets, the palette of a widget can be customized using
4603 the "color", "background-color", "selection-color",
4604 "selection-background-color" and "alternate-background-color".
4605
4606 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4607*/
4608const QPalette &QWidget::palette() const
4609{
4610 if (!isEnabled()) {
4611 data->pal.setCurrentColorGroup(QPalette::Disabled);
4612 } else if ((!isVisible() || isActiveWindow())
4613#if defined(Q_OS_WIN)
4614 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4615#endif
4616 ) {
4617 data->pal.setCurrentColorGroup(QPalette::Active);
4618 } else {
4619 data->pal.setCurrentColorGroup(QPalette::Inactive);
4620 }
4621 return data->pal;
4622}
4623
4624void QWidget::setPalette(const QPalette &palette)
4625{
4626 Q_D(QWidget);
4627 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4628
4629 // Determine which palette is inherited from this widget's ancestors and
4630 // QApplication::palette, resolve this against \a palette (attributes from
4631 // the inherited palette are copied over this widget's palette). Then
4632 // propagate this palette to this widget's children.
4633 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4634 QPalette resolvedPalette = palette.resolve(naturalPalette);
4635 d->setPalette_helper(resolvedPalette);
4636}
4637
4638/*!
4639 \internal
4640
4641 Returns the palette that the widget \a w inherits from its ancestors and
4642 QApplication::palette. \a inheritedMask is the combination of the widget's
4643 ancestors palette request masks (i.e., which attributes from the parent
4644 widget's palette are implicitly imposed on this widget by the user). Note
4645 that this font does not take into account the palette set on \a w itself.
4646*/
4647QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4648{
4649 Q_Q(const QWidget);
4650
4651 const bool useStyleSheetPropagationInWidgetStyles =
4652 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4653
4654 QPalette naturalPalette = QApplication::palette(q);
4655 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4656 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4657#if QT_CONFIG(graphicsview)
4658 || (extra && extra->proxyWidget)
4659#endif // QT_CONFIG(graphicsview)
4660 )) {
4661 if (QWidget *p = q->parentWidget()) {
4662 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4663 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4664 QPalette inheritedPalette = p->palette();
4665 inheritedPalette.setResolveMask(inheritedMask);
4666 naturalPalette = inheritedPalette.resolve(naturalPalette);
4667 } else {
4668 naturalPalette = p->palette();
4669 }
4670 }
4671 }
4672#if QT_CONFIG(graphicsview)
4673 else if (extra && extra->proxyWidget) {
4674 QPalette inheritedPalette = extra->proxyWidget->palette();
4675 inheritedPalette.setResolveMask(inheritedMask);
4676 naturalPalette = inheritedPalette.resolve(naturalPalette);
4677 }
4678#endif // QT_CONFIG(graphicsview)
4679 }
4680 naturalPalette.setResolveMask(0);
4681 return naturalPalette;
4682}
4683/*!
4684 \internal
4685
4686 Determine which palette is inherited from this widget's ancestors and
4687 QApplication::palette, resolve this against this widget's palette
4688 (attributes from the inherited palette are copied over this widget's
4689 palette). Then propagate this palette to this widget's children.
4690*/
4691void QWidgetPrivate::resolvePalette()
4692{
4693 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4694 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4695 setPalette_helper(resolvedPalette);
4696}
4697
4698void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4699{
4700 Q_Q(QWidget);
4701 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4702 return;
4703 data.pal = palette;
4704 updateSystemBackground();
4705 propagatePaletteChange();
4706 updateIsOpaque();
4707 q->update();
4708 updateIsOpaque();
4709}
4710
4711void QWidgetPrivate::updateSystemBackground()
4712{
4713}
4714
4715/*!
4716 \property QWidget::font
4717 \brief the font currently set for the widget
4718
4719 This property describes the widget's requested font. The font is used by
4720 the widget's style when rendering standard components, and is available as
4721 a means to ensure that custom widgets can maintain consistency with the
4722 native platform's look and feel. It's common that different platforms, or
4723 different styles, define different fonts for an application.
4724
4725 When you assign a new font to a widget, the properties from this font are
4726 combined with the widget's default font to form the widget's final
4727 font. You can call fontInfo() to get a copy of the widget's final
4728 font. The final font is also used to initialize QPainter's font.
4729
4730 The default depends on the system environment. QApplication maintains a
4731 system/theme font which serves as a default for all widgets. There may
4732 also be special font defaults for certain types of widgets. You can also
4733 define default fonts for widgets yourself by passing a custom font and the
4734 name of a widget to QApplication::setFont(). Finally, the font is matched
4735 against Qt's font database to find the best match.
4736
4737 QWidget propagates explicit font properties from parent to child. If you
4738 change a specific property on a font and assign that font to a widget,
4739 that property will propagate to all the widget's children, overriding any
4740 system defaults for that property. Note that fonts by default don't
4741 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4742 attribute is enabled.
4743
4744 QWidget's font propagation is similar to its palette propagation.
4745
4746 The current style, which is used to render the content of all standard Qt
4747 widgets, is free to choose to use the widget font, or in some cases, to
4748 ignore it (partially, or completely). In particular, certain styles like
4749 GTK style, Mac style, and Windows Vista style, apply special
4750 modifications to the widget font to match the platform's native look and
4751 feel. Because of this, assigning properties to a widget's font is not
4752 guaranteed to change the appearance of the widget. Instead, you may choose
4753 to apply a \l styleSheet.
4754
4755 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4756 style sheets will take precedence if the settings conflict.
4757
4758 \sa fontInfo(), fontMetrics()
4759*/
4760
4761void QWidget::setFont(const QFont &font)
4762{
4763 Q_D(QWidget);
4764
4765#if QT_CONFIG(style_stylesheet)
4766 const QStyleSheetStyle* style;
4767 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4768 style->saveWidgetFont(this, font);
4769#endif
4770
4771 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4772
4773 // Determine which font is inherited from this widget's ancestors and
4774 // QApplication::font, resolve this against \a font (attributes from the
4775 // inherited font are copied over). Then propagate this font to this
4776 // widget's children.
4777 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4778 QFont resolvedFont = font.resolve(naturalFont);
4779 d->setFont_helper(resolvedFont);
4780}
4781
4782/*
4783 \internal
4784
4785 Returns the font that the widget \a w inherits from its ancestors and
4786 QApplication::font. \a inheritedMask is the combination of the widget's
4787 ancestors font request masks (i.e., which attributes from the parent
4788 widget's font are implicitly imposed on this widget by the user). Note
4789 that this font does not take into account the font set on \a w itself.
4790
4791 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4792 is applied, fonts are not propagated anymore
4793*/
4794QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4795{
4796 Q_Q(const QWidget);
4797
4798 const bool useStyleSheetPropagationInWidgetStyles =
4799 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4800
4801 QFont naturalFont = QApplication::font(q);
4802 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4803 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4804#if QT_CONFIG(graphicsview)
4805 || (extra && extra->proxyWidget)
4806#endif // QT_CONFIG(graphicsview)
4807 )) {
4808 if (QWidget *p = q->parentWidget()) {
4809 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4810 if (!naturalFont.isCopyOf(QApplication::font())) {
4811 if (inheritedMask != 0) {
4812 QFont inheritedFont = p->font();
4813 inheritedFont.setResolveMask(inheritedMask);
4814 naturalFont = inheritedFont.resolve(naturalFont);
4815 } // else nothing to do (naturalFont = naturalFont)
4816 } else {
4817 naturalFont = p->font();
4818 }
4819 }
4820 }
4821#if QT_CONFIG(graphicsview)
4822 else if (extra && extra->proxyWidget) {
4823 if (inheritedMask != 0) {
4824 QFont inheritedFont = extra->proxyWidget->font();
4825 inheritedFont.setResolveMask(inheritedMask);
4826 naturalFont = inheritedFont.resolve(naturalFont);
4827 } // else nothing to do (naturalFont = naturalFont)
4828 }
4829#endif // QT_CONFIG(graphicsview)
4830 }
4831 naturalFont.setResolveMask(0);
4832 return naturalFont;
4833}
4834
4835/*!
4836 \internal
4837
4838 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4839*/
4840QFont QWidgetPrivate::localFont() const
4841{
4842 QFont localfont = data.fnt;
4843 localfont.setResolveMask(directFontResolveMask);
4844 return localfont;
4845}
4846
4847/*!
4848 \internal
4849
4850 Determine which font is implicitly imposed on this widget by its ancestors
4851 and QApplication::font, resolve this against its own font (attributes from
4852 the implicit font are copied over). Then propagate this font to this
4853 widget's children.
4854*/
4855void QWidgetPrivate::resolveFont()
4856{
4857 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4858 QFont resolvedFont = localFont().resolve(naturalFont);
4859 setFont_helper(resolvedFont);
4860}
4861
4862/*!
4863 \internal
4864
4865 Assign \a font to this widget, and propagate it to all children, except
4866 style sheet widgets (handled differently) and windows that don't enable
4867 window propagation. \a implicitMask is the union of all ancestor widgets'
4868 font request masks, and determines which attributes from this widget's
4869 font should propagate.
4870*/
4871void QWidgetPrivate::updateFont(const QFont &font)
4872{
4873 Q_Q(QWidget);
4874#if QT_CONFIG(style_stylesheet)
4875 const QStyleSheetStyle* cssStyle;
4876 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4877 const bool useStyleSheetPropagationInWidgetStyles =
4878 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4879#endif
4880
4881 data.fnt = QFont(font, q);
4882
4883 // Combine new mask with natural mask and propagate to children.
4884#if QT_CONFIG(graphicsview)
4885 if (!q->parentWidget() && extra && extra->proxyWidget) {
4886 QGraphicsProxyWidget *p = extra->proxyWidget;
4887 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4888 } else
4889#endif // QT_CONFIG(graphicsview)
4890 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4891 inheritedFontResolveMask = 0;
4892 }
4893 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4894 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4895 // isn't all weak information, but save the original mask to be able to let new changes on the
4896 // parent widget font propagate correctly.
4897 directFontResolveMask = data.fnt.resolveMask();
4898 data.fnt.setResolveMask(newMask);
4899
4900 for (int i = 0; i < children.size(); ++i) {
4901 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4902 if (w) {
4903 if (0) {
4904#if QT_CONFIG(style_stylesheet)
4905 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4906 // Style sheets follow a different font propagation scheme.
4907 if (cssStyle)
4908 cssStyle->updateStyleSheetFont(w);
4909#endif
4910 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4911 // Propagate font changes.
4912 QWidgetPrivate *wd = w->d_func();
4913 wd->inheritedFontResolveMask = newMask;
4914 wd->resolveFont();
4915 }
4916 }
4917 }
4918
4919#if QT_CONFIG(style_stylesheet)
4920 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4921 cssStyle->updateStyleSheetFont(q);
4922 }
4923#endif
4924
4925 QEvent e(QEvent::FontChange);
4926 QCoreApplication::sendEvent(q, &e);
4927}
4928
4929void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4930{
4931 Q_Q(QWidget);
4932
4933 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4934 return;
4935 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4936 if (!children.isEmpty()) {
4937 for (int i = 0; i < children.size(); ++i) {
4938 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4939 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4940 w->d_func()->setLayoutDirection_helper(direction);
4941 }
4942 }
4943 QEvent e(QEvent::LayoutDirectionChange);
4944 QCoreApplication::sendEvent(q, &e);
4945}
4946
4947void QWidgetPrivate::resolveLayoutDirection()
4948{
4949 Q_Q(const QWidget);
4950 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4951 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4952}
4953
4954/*!
4955 \property QWidget::layoutDirection
4956
4957 \brief the layout direction for this widget.
4958
4959 \note This method no longer affects text layout direction since Qt 4.7.
4960
4961 By default, this property is set to Qt::LeftToRight.
4962
4963 When the layout direction is set on a widget, it will propagate to
4964 the widget's children, but not to a child that is a window and not
4965 to a child for which setLayoutDirection() has been explicitly
4966 called. Also, child widgets added \e after setLayoutDirection()
4967 has been called for the parent do not inherit the parent's layout
4968 direction.
4969
4970
4971 \sa QApplication::layoutDirection
4972*/
4973void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4974{
4975 Q_D(QWidget);
4976
4977 if (direction == Qt::LayoutDirectionAuto) {
4978 unsetLayoutDirection();
4979 return;
4980 }
4981
4982 setAttribute(Qt::WA_SetLayoutDirection);
4983 d->setLayoutDirection_helper(direction);
4984}
4985
4986Qt::LayoutDirection QWidget::layoutDirection() const
4987{
4988 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4989}
4990
4991void QWidget::unsetLayoutDirection()
4992{
4993 Q_D(QWidget);
4994 setAttribute(Qt::WA_SetLayoutDirection, false);
4995 d->resolveLayoutDirection();
4996}
4997
4998/*!
4999 \fn QFontMetrics QWidget::fontMetrics() const
5000
5001 Returns the font metrics for the widget's current font.
5002 Equivalent to \c QFontMetrics(widget->font()).
5003
5004 \sa font(), fontInfo(), setFont()
5005*/
5006
5007/*!
5008 \fn QFontInfo QWidget::fontInfo() const
5009
5010 Returns the font info for the widget's current font.
5011 Equivalent to \c QFontInfo(widget->font()).
5012
5013 \sa font(), fontMetrics(), setFont()
5014*/
5015
5016
5017/*!
5018 \property QWidget::cursor
5019 \brief the cursor shape for this widget
5020
5021 The mouse cursor will assume this shape when it's over this
5022 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
5023
5024 An editor widget might use an I-beam cursor:
5025 \snippet code/src_gui_kernel_qwidget.cpp 6
5026
5027 If no cursor has been set, or after a call to unsetCursor(), the
5028 parent's cursor is used.
5029
5030 By default, this property contains a cursor with the Qt::ArrowCursor
5031 shape.
5032
5033 Some underlying window implementations will reset the cursor if it
5034 leaves a widget even if the mouse is grabbed. If you want to have
5035 a cursor set for all widgets, even when outside the window, consider
5036 QGuiApplication::setOverrideCursor().
5037
5038 \sa QGuiApplication::setOverrideCursor()
5039*/
5040
5041#ifndef QT_NO_CURSOR
5042QCursor QWidget::cursor() const
5043{
5044 Q_D(const QWidget);
5045 if (testAttribute(Qt::WA_SetCursor))
5046 return (d->extra && d->extra->curs)
5047 ? *d->extra->curs
5048 : QCursor(Qt::ArrowCursor);
5049 if (isWindow() || !parentWidget())
5050 return QCursor(Qt::ArrowCursor);
5051 return parentWidget()->cursor();
5052}
5053
5054void QWidget::setCursor(const QCursor &cursor)
5055{
5056 Q_D(QWidget);
5057 if (cursor.shape() != Qt::ArrowCursor
5058 || (d->extra && d->extra->curs))
5059 {
5060 d->createExtra();
5061 d->extra->curs = std::make_unique<QCursor>(cursor);
5062 }
5063 setAttribute(Qt::WA_SetCursor);
5064 d->setCursor_sys(cursor);
5065
5066 QEvent event(QEvent::CursorChange);
5067 QCoreApplication::sendEvent(this, &event);
5068}
5069
5070void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5071{
5072 Q_UNUSED(cursor);
5073 Q_Q(QWidget);
5074 qt_qpa_set_cursor(q, false);
5075}
5076
5077void QWidget::unsetCursor()
5078{
5079 Q_D(QWidget);
5080 if (d->extra)
5081 d->extra->curs.reset();
5082 if (!isWindow())
5083 setAttribute(Qt::WA_SetCursor, false);
5084 d->unsetCursor_sys();
5085
5086 QEvent event(QEvent::CursorChange);
5087 QCoreApplication::sendEvent(this, &event);
5088}
5089
5090void QWidgetPrivate::unsetCursor_sys()
5091{
5092 Q_Q(QWidget);
5093 qt_qpa_set_cursor(q, false);
5094}
5095
5096static inline void applyCursor(QWidget *w, const QCursor &c)
5097{
5098 if (QWindow *window = w->windowHandle())
5099 window->setCursor(c);
5100}
5101
5102static inline void unsetCursor(QWidget *w)
5103{
5104 if (QWindow *window = w->windowHandle())
5105 window->unsetCursor();
5106}
5107
5108void qt_qpa_set_cursor(QWidget *w, bool force)
5109{
5110 if (!w->testAttribute(Qt::WA_WState_Created))
5111 return;
5112
5113 static QPointer<QWidget> lastUnderMouse = nullptr;
5114 if (force) {
5115 lastUnderMouse = w;
5116 } else if (lastUnderMouse) {
5117 const WId lastWinId = lastUnderMouse->effectiveWinId();
5118 const WId winId = w->effectiveWinId();
5119 if (lastWinId && lastWinId == winId)
5120 w = lastUnderMouse;
5121 } else if (!w->internalWinId()) {
5122 return; // The mouse is not under this widget, and it's not native, so don't change it.
5123 }
5124
5125 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5126 && !w->testAttribute(Qt::WA_SetCursor))
5127 w = w->parentWidget();
5128
5129 QWidget *nativeParent = w;
5130 if (!w->internalWinId())
5131 nativeParent = w->nativeParentWidget();
5132 if (!nativeParent || !nativeParent->internalWinId())
5133 return;
5134
5135 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
5136 if (w->isEnabled())
5137 applyCursor(nativeParent, w->cursor());
5138 else
5139 // Enforce the windows behavior of clearing the cursor on
5140 // disabled widgets.
5141 unsetCursor(nativeParent);
5142 } else {
5143 unsetCursor(nativeParent);
5144 }
5145}
5146#endif
5147
5148/*!
5149 \enum QWidget::RenderFlag
5150
5151 This enum describes how to render the widget when calling QWidget::render().
5152
5153 \value DrawWindowBackground If you enable this option, the widget's background
5154 is rendered into the target even if autoFillBackground is not set. By default,
5155 this option is enabled.
5156
5157 \value DrawChildren If you enable this option, the widget's children
5158 are rendered recursively into the target. By default, this option is enabled.
5159
5160 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5161 is ignored when rendering into the target. By default, this option is disabled.
5162
5163 \since 4.3
5164*/
5165
5166/*!
5167 \since 4.3
5168
5169 Renders the \a sourceRegion of this widget into the \a target
5170 using \a renderFlags to determine how to render. Rendering
5171 starts at \a targetOffset in the \a target. For example:
5172
5173 \snippet code/src_gui_kernel_qwidget.cpp 7
5174
5175 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5176 the region, i.e. the entire widget.
5177
5178 Ensure that you call QPainter::end() for the \a target device's
5179 active painter (if any) before rendering. For example:
5180
5181 \snippet code/src_gui_kernel_qwidget.cpp 8
5182
5183 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5184 instead.
5185*/
5186void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5187 const QRegion &sourceRegion, RenderFlags renderFlags)
5188{
5189 QPainter p(target);
5190 render(&p, targetOffset, sourceRegion, renderFlags);
5191}
5192
5193/*!
5194 \overload
5195
5196 Renders the widget into the \a painter's QPainter::device().
5197
5198 Transformations and settings applied to the \a painter will be used
5199 when rendering.
5200
5201 \note The \a painter must be active. On \macos the widget will be
5202 rendered into a QPixmap and then drawn by the \a painter.
5203
5204 \sa QPainter::device()
5205*/
5206void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5207 const QRegion &sourceRegion, RenderFlags renderFlags)
5208{
5209 if (Q_UNLIKELY(!painter)) {
5210 qWarning("QWidget::render: Null pointer to painter");
5211 return;
5212 }
5213
5214 if (Q_UNLIKELY(!painter->isActive())) {
5215 qWarning("QWidget::render: Cannot render with an inactive painter");
5216 return;
5217 }
5218
5219 const qreal opacity = painter->opacity();
5220 if (qFuzzyIsNull(opacity))
5221 return; // Fully transparent.
5222
5223 Q_D(QWidget);
5224 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5225 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
5226 : sourceRegion;
5227 if (toBePainted.isEmpty())
5228 return;
5229
5230 if (!d->extra)
5231 d->createExtra();
5232 d->extra->inRenderWithPainter = true;
5233
5234 QPaintEngine *engine = painter->paintEngine();
5235 Q_ASSERT(engine);
5236 QPaintEnginePrivate *enginePriv = engine->d_func();
5237 Q_ASSERT(enginePriv);
5238 QPaintDevice *target = engine->paintDevice();
5239 Q_ASSERT(target);
5240
5241 // Render via a pixmap when dealing with non-opaque painters or printers.
5242 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5243 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
5244 d->extra->inRenderWithPainter = inRenderWithPainter;
5245 return;
5246 }
5247
5248 // Set new shared painter.
5249 QPainter *oldPainter = d->sharedPainter();
5250 d->setSharedPainter(painter);
5251
5252 // Save current system clip, viewport and transform,
5253 const QTransform oldTransform = enginePriv->systemTransform;
5254 const QRegion oldSystemClip = enginePriv->systemClip;
5255 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5256 const QRegion oldSystemViewport = enginePriv->systemViewport;
5257 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5258
5259 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5260 if (painter->hasClipping()) {
5261 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5262 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5263 } else {
5264 enginePriv->setSystemViewport(oldSystemClip);
5265 }
5266 painter->setLayoutDirection(layoutDirection());
5267
5268 d->render(target, targetOffset, toBePainted, renderFlags);
5269
5270 // Restore system clip, viewport and transform.
5271 enginePriv->baseSystemClip = oldBaseClip;
5272 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5273 enginePriv->systemStateChanged();
5274 painter->setLayoutDirection(oldLayoutDirection);
5275
5276 // Restore shared painter.
5277 d->setSharedPainter(oldPainter);
5278
5279 d->extra->inRenderWithPainter = inRenderWithPainter;
5280}
5281
5282static void sendResizeEvents(QWidget *target)
5283{
5284 QResizeEvent e(target->size(), QSize());
5285 QCoreApplication::sendEvent(target, &e);
5286
5287 const QObjectList children = target->children();
5288 for (int i = 0; i < children.size(); ++i) {
5289 if (!children.at(i)->isWidgetType())
5290 continue;
5291 QWidget *child = static_cast<QWidget*>(children.at(i));
5292 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5293 sendResizeEvents(child);
5294 }
5295}
5296
5297/*!
5298 \since 5.0
5299
5300 Renders the widget into a pixmap restricted by the
5301 given \a rectangle. If the widget has any children, then
5302 they are also painted in the appropriate positions.
5303
5304 If a rectangle with an invalid size is specified (the default),
5305 the entire widget is painted.
5306
5307 \sa render(), QPixmap
5308*/
5309QPixmap QWidget::grab(const QRect &rectangle)
5310{
5311 Q_D(QWidget);
5312 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5313 sendResizeEvents(this);
5314
5315 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5316
5317 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5318 QRect r(rectangle);
5319 if (r.width() < 0 || r.height() < 0) {
5320 // For grabbing widgets that haven't been shown yet,
5321 // we trigger the layouting mechanism to determine the widget's size.
5322 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5323 r.setTopLeft(rectangle.topLeft());
5324 }
5325
5326 if (!r.intersects(rect()))
5327 return QPixmap();
5328
5329 const qreal dpr = devicePixelRatio();
5330 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5331 res.setDevicePixelRatio(dpr);
5332 if (!d->isOpaque)
5333 res.fill(Qt::transparent);
5334 d->render(&res, QPoint(), QRegion(r), renderFlags);
5335
5336 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5337 return res;
5338}
5339
5340/*!
5341 \brief The graphicsEffect function returns a pointer to the
5342 widget's graphics effect.
5343
5344 If the widget has no graphics effect, \nullptr is returned.
5345
5346 \since 4.6
5347
5348 \sa setGraphicsEffect()
5349*/
5350#if QT_CONFIG(graphicseffect)
5351QGraphicsEffect *QWidget::graphicsEffect() const
5352{
5353 Q_D(const QWidget);
5354 return d->graphicsEffect;
5355}
5356#endif // QT_CONFIG(graphicseffect)
5357
5358/*!
5359
5360 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5361
5362 Sets \a effect as the widget's effect. If there already is an effect installed
5363 on this widget, QWidget will delete the existing effect before installing
5364 the new \a effect.
5365
5366 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5367 the effect from the widget and install it on this widget.
5368
5369 QWidget takes ownership of \a effect.
5370
5371 \note This function will apply the effect on itself and all its children.
5372
5373 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5374 QOpenGLWidget and QQuickWidget.
5375
5376 \since 4.6
5377
5378 \sa graphicsEffect()
5379*/
5380#if QT_CONFIG(graphicseffect)
5381void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5382{
5383 Q_D(QWidget);
5384 if (d->graphicsEffect == effect)
5385 return;
5386
5387 if (d->graphicsEffect) {
5388 d->invalidateBackingStore(rect());
5389 delete d->graphicsEffect;
5390 d->graphicsEffect = nullptr;
5391 }
5392
5393 if (effect) {
5394 // Set new effect.
5395 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5396 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5397 d->graphicsEffect = effect;
5398 effect->d_func()->setGraphicsEffectSource(source);
5399 update();
5400 }
5401
5402 d->updateIsOpaque();
5403}
5404#endif // QT_CONFIG(graphicseffect)
5405
5406bool QWidgetPrivate::isAboutToShow() const
5407{
5408 if (data.in_show)
5409 return true;
5410
5411 Q_Q(const QWidget);
5412 if (q->isHidden())
5413 return false;
5414
5415 // The widget will be shown if any of its ancestors are about to show.
5416 QWidget *parent = q->parentWidget();
5417 return parent ? parent->d_func()->isAboutToShow() : false;
5418}
5419
5420QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5421{
5422 Q_Q(QWidget);
5423 const bool isVisible = q->isVisible();
5424
5425 // Make sure the widget is laid out correctly.
5426 if (!isVisible && !isAboutToShow()) {
5427 QWidget *topLevel = q->window();
5428 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5429 topLevel->ensurePolished();
5430
5431 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5432 // they're not explicitly hidden.
5433 QWidget *widget = q;
5434 QWidgetList hiddenWidgets;
5435 while (widget) {
5436 if (widget->isHidden()) {
5437 widget->setAttribute(Qt::WA_WState_Hidden, false);
5438 hiddenWidgets.append(widget);
5439 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5440 widget->d_func()->updateGeometry_helper(true);
5441 }
5442 widget = widget->parentWidget();
5443 }
5444
5445 // Activate top-level layout.
5446 if (topLevel->d_func()->layout)
5447 topLevel->d_func()->layout->activate();
5448
5449 // Adjust size if necessary.
5450 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5451 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5452 && !topLevel->testAttribute(Qt::WA_Resized)) {
5453 topLevel->adjustSize();
5454 topLevel->setAttribute(Qt::WA_Resized, false);
5455 }
5456
5457 // Activate child layouts.
5458 topLevel->d_func()->activateChildLayoutsRecursively();
5459
5460 // We're not cheating with WA_WState_Hidden anymore.
5461 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5462 QWidget *widget = hiddenWidgets.at(i);
5463 widget->setAttribute(Qt::WA_WState_Hidden);
5464 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5465 widget->parentWidget()->d_func()->layout->invalidate();
5466 }
5467 } else if (isVisible) {
5468 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5469 }
5470
5471 // Calculate the region to be painted.
5472 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5473 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5474 toBePainted &= extra->mask;
5475 return toBePainted;
5476}
5477
5478void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5479 QWidget::RenderFlags renderFlags)
5480{
5481 Q_ASSERT(painter);
5482 Q_ASSERT(!toBePainted.isEmpty());
5483
5484 Q_Q(QWidget);
5485 const QTransform originalTransform = painter->worldTransform();
5486 const bool useDeviceCoordinates = originalTransform.isScaling();
5487 if (!useDeviceCoordinates) {
5488 // Render via a pixmap.
5489 const QRect rect = toBePainted.boundingRect();
5490 const QSize size = rect.size();
5491 if (size.isNull())
5492 return;
5493
5494 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5495 QPixmap pixmap(size * pixmapDevicePixelRatio);
5496 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5497
5498 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5499 pixmap.fill(Qt::transparent);
5500 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5501
5502 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5503 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5504
5505 painter->drawPixmap(targetOffset, pixmap);
5506
5507 if (restore)
5508 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5509
5510 } else {
5511 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5512 QTransform transform = originalTransform;
5513 transform.translate(targetOffset.x(), targetOffset.y());
5514
5515 QPaintDevice *device = painter->device();
5516 Q_ASSERT(device);
5517
5518 // Calculate device rect.
5519 const QRectF rect(toBePainted.boundingRect());
5520 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5521 deviceRect &= QRect(0, 0, device->width(), device->height());
5522
5523 QPixmap pixmap(deviceRect.size());
5524 pixmap.fill(Qt::transparent);
5525
5526 // Create a pixmap device coordinate painter.
5527 QPainter pixmapPainter(&pixmap);
5528 pixmapPainter.setRenderHints(painter->renderHints());
5529 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5530 pixmapPainter.setTransform(transform);
5531
5532 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5533 pixmapPainter.end();
5534
5535 // And then draw the pixmap.
5536 painter->setTransform(QTransform());
5537 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5538 painter->setTransform(originalTransform);
5539 }
5540}
5541
5542void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5543 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5544{
5545 if (rgn.isEmpty())
5546 return;
5547
5548 Q_Q(QWidget);
5549
5550 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5551 << "into paint device" << pdev << "with" << flags;
5552
5553 const bool asRoot = flags & DrawAsRoot;
5554 bool onScreen = shouldPaintOnScreen();
5555
5556#if QT_CONFIG(graphicseffect)
5557 if (graphicsEffect && graphicsEffect->isEnabled()) {
5558 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5559 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5560 (source->d_func());
5561 if (!sourced->context) {
5562 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5563 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5564 sourced->context = &context;
5565 if (!sharedPainter) {
5566 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), effectRgn.translated(offset));
5567 QPainter p(pdev);
5568 p.translate(offset);
5569 context.painter = &p;
5570 graphicsEffect->draw(&p);
5571 setSystemClip(pdev->paintEngine(), 1, QRegion());
5572 } else {
5573 context.painter = sharedPainter;
5574 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5575 sourced->invalidateCache();
5576 sourced->lastEffectTransform = sharedPainter->worldTransform();
5577 }
5578 sharedPainter->save();
5579 sharedPainter->translate(offset);
5580 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), effectRgn.translated(offset));
5581 graphicsEffect->draw(sharedPainter);
5582 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5583 sharedPainter->restore();
5584 }
5585 sourced->context = nullptr;
5586
5587 if (repaintManager)
5588 repaintManager->markNeedsFlush(q, effectRgn, offset);
5589
5590 return;
5591 }
5592 }
5593#endif // QT_CONFIG(graphicseffect)
5594 flags = flags & ~UseEffectRegionBounds;
5595
5596 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5597 const bool recursive = flags & DrawRecursive;
5598 const bool alsoInvisible = flags & DrawInvisible;
5599
5600 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5601
5602 QRegion toBePainted(rgn);
5603 if (asRoot && !alsoInvisible)
5604 toBePainted &= clipRect(); //(rgn & visibleRegion());
5605 if (!(flags & DontSubtractOpaqueChildren))
5606 subtractOpaqueChildren(toBePainted, q->rect());
5607
5608 if (!toBePainted.isEmpty()) {
5609 if (!onScreen || alsoOnScreen) {
5610 //update the "in paint event" flag
5611 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5612 qWarning("QWidget::repaint: Recursive repaint detected");
5613 q->setAttribute(Qt::WA_WState_InPaintEvent);
5614
5615 //clip away the new area
5616 QPaintEngine *paintEngine = pdev->paintEngine();
5617 if (paintEngine) {
5618 setRedirected(pdev, -offset);
5619
5620 if (sharedPainter)
5621 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5622 else
5623 paintEngine->d_func()->systemRect = q->data->crect;
5624
5625 //paint the background
5626 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5627 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5628 beginBackingStorePainting();
5629 QPainter p(q);
5630 p.setRenderHint(QPainter::SmoothPixmapTransform);
5631 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5632 endBackingStorePainting();
5633 }
5634
5635 if (!sharedPainter)
5636 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5637
5638 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5639 beginBackingStorePainting();
5640 QPainter p(q);
5641 QColor tint = q->palette().window().color();
5642 tint.setAlphaF(.6f);
5643 p.fillRect(toBePainted.boundingRect(), tint);
5644 endBackingStorePainting();
5645 }
5646 }
5647
5648#if 0
5649 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5650 qDebug() << "clipping to" << toBePainted << "location == " << offset
5651 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5652#endif
5653
5654 bool skipPaintEvent = false;
5655 if (renderToTexture) {
5656 // This widget renders into a texture which is composed later. We just need to
5657 // punch a hole in the backingstore, so the texture will be visible.
5658 beginBackingStorePainting();
5659 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5660 QPainter p(q);
5661 p.setCompositionMode(QPainter::CompositionMode_Source);
5662 p.fillRect(q->rect(), Qt::transparent);
5663 } else if (!repaintManager) {
5664 // We are not drawing to a backingstore: fall back to QImage
5665 QImage img = grabFramebuffer();
5666 // grabFramebuffer() always sets the format to RGB32
5667 // regardless of whether it is transparent or not.
5668 if (img.format() == QImage::Format_RGB32)
5669 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5670 QPainter p(q);
5671 p.drawImage(q->rect(), img);
5672 skipPaintEvent = true;
5673 }
5674 endBackingStorePainting();
5675 if (renderToTextureReallyDirty)
5676 renderToTextureReallyDirty = 0;
5677 else
5678 skipPaintEvent = true;
5679 }
5680
5681 if (!skipPaintEvent) {
5682 //actually send the paint event
5683 sendPaintEvent(toBePainted);
5684 }
5685
5686 if (repaintManager)
5687 repaintManager->markNeedsFlush(q, toBePainted, offset);
5688
5689 //restore
5690 if (paintEngine) {
5691 restoreRedirected();
5692 if (!sharedPainter)
5693 paintEngine->d_func()->systemRect = QRect();
5694 else
5695 paintEngine->d_func()->currentClipDevice = nullptr;
5696
5697 setSystemClip(pdev->paintEngine(), 1, QRegion());
5698 }
5699 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5700 if (Q_UNLIKELY(q->paintingActive()))
5701 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5702
5703 if (paintEngine && paintEngine->autoDestruct()) {
5704 delete paintEngine;
5705 }
5706 } else if (q->isWindow()) {
5707 QPaintEngine *engine = pdev->paintEngine();
5708 if (engine) {
5709 QPainter p(pdev);
5710 p.setClipRegion(toBePainted);
5711 const QBrush bg = q->palette().brush(QPalette::Window);
5712 if (bg.style() == Qt::TexturePattern)
5713 p.drawTiledPixmap(q->rect(), bg.texture());
5714 else
5715 p.fillRect(q->rect(), bg);
5716
5717 if (engine->autoDestruct())
5718 delete engine;
5719 }
5720 }
5721 }
5722
5723 if (recursive && !children.isEmpty()) {
5724 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5725 sharedPainter, repaintManager);
5726 }
5727}
5728
5729void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5730{
5731 Q_Q(QWidget);
5732 QPaintEvent e(toBePainted);
5733 QCoreApplication::sendSpontaneousEvent(q, &e);
5734
5735 if (renderToTexture)
5736 resolveSamples();
5737}
5738
5739void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5740 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5741{
5742 if (Q_UNLIKELY(!target)) {
5743 qWarning("QWidget::render: null pointer to paint device");
5744 return;
5745 }
5746
5747 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5748 QRegion paintRegion = !inRenderWithPainter
5749 ? prepareToRender(sourceRegion, renderFlags)
5750 : sourceRegion;
5751 if (paintRegion.isEmpty())
5752 return;
5753
5754 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5755
5756 // Use the target's shared painter if set (typically set when doing
5757 // "other->render(widget);" in the widget's paintEvent.
5758 if (target->devType() == QInternal::Widget) {
5759 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5760 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5761 QPainter *targetPainter = targetPrivate->sharedPainter();
5762 if (targetPainter && targetPainter->isActive())
5763 setSharedPainter(targetPainter);
5764 }
5765 }
5766
5767 // Use the target's redirected device if set and adjust offset and paint
5768 // region accordingly. This is typically the case when people call render
5769 // from the paintEvent.
5770 QPoint offset = targetOffset;
5771 offset -= paintRegion.boundingRect().topLeft();
5772 QPoint redirectionOffset;
5773 QPaintDevice *redirected = nullptr;
5774
5775 if (target->devType() == QInternal::Widget)
5776 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5777
5778 if (redirected) {
5779 target = redirected;
5780 offset -= redirectionOffset;
5781 }
5782
5783 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5784 if (QPaintEngine *targetEngine = target->paintEngine()) {
5785 const QRegion targetSystemClip = targetEngine->systemClip();
5786 if (!targetSystemClip.isEmpty())
5787 paintRegion &= targetSystemClip.translated(-offset);
5788 }
5789 }
5790
5791 // Set backingstore flags.
5792 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5793 if (renderFlags & QWidget::DrawWindowBackground)
5794 flags |= DrawAsRoot;
5795
5796 if (renderFlags & QWidget::DrawChildren)
5797 flags |= DrawRecursive;
5798 else
5799 flags |= DontSubtractOpaqueChildren;
5800
5801 flags |= DontSetCompositionMode;
5802
5803 // Render via backingstore.
5804 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5805
5806 // Restore shared painter.
5807 if (oldSharedPainter)
5808 setSharedPainter(oldSharedPainter);
5809}
5810
5811void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5812 const QPoint &offset, DrawWidgetFlags flags
5813 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5814{
5815 QWidget *w = nullptr;
5816 QRect boundingRect;
5817 bool dirtyBoundingRect = true;
5818 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5819 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5820
5821 do {
5822 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5823 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5824 && !(excludeNativeChildren && x->internalWinId())) {
5825 if (dirtyBoundingRect) {
5826 boundingRect = rgn.boundingRect();
5827 dirtyBoundingRect = false;
5828 }
5829
5830 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5831 w = x;
5832 break;
5833 }
5834 }
5835 --index;
5836 } while (index >= 0);
5837
5838 if (!w)
5839 return;
5840
5841 QWidgetPrivate *wd = w->d_func();
5842 const QPoint widgetPos(w->data->crect.topLeft());
5843 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5844 if (index > 0) {
5845 QRegion wr(rgn);
5846 if (wd->isOpaque)
5847 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5848 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5849 sharedPainter, repaintManager);
5850 }
5851
5852 if (w->updatesEnabled()
5853#if QT_CONFIG(graphicsview)
5854 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5855#endif // QT_CONFIG(graphicsview)
5856 ) {
5857 QRegion wRegion(rgn);
5858 wRegion &= wd->effectiveRectFor(w->data->crect);
5859 wRegion.translate(-widgetPos);
5860 if (hasMask)
5861 wRegion &= wd->extra->mask;
5862 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5863 }
5864}
5865
5866#if QT_CONFIG(graphicseffect)
5867QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5868{
5869 if (system != Qt::DeviceCoordinates)
5870 return m_widget->rect();
5871
5872 if (Q_UNLIKELY(!context)) {
5873 // Device coordinates without context not yet supported.
5874 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5875 return QRectF();
5876 }
5877
5878 return context->painter->worldTransform().mapRect(m_widget->rect());
5879}
5880
5881void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5882{
5883 if (!context || context->painter != painter) {
5884 m_widget->render(painter);
5885 return;
5886 }
5887
5888 // The region saved in the context is neither clipped to the rect
5889 // nor the mask, so we have to clip it here before calling drawWidget.
5890 QRegion toBePainted = context->rgn;
5891 toBePainted &= m_widget->rect();
5892 QWidgetPrivate *wd = qt_widget_private(m_widget);
5893 if (wd->extra && wd->extra->hasMask)
5894 toBePainted &= wd->extra->mask;
5895
5896 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5897 context->sharedPainter, context->repaintManager);
5898}
5899
5900QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5901 QGraphicsEffect::PixmapPadMode mode) const
5902{
5903 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5904 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5905 // Device coordinates without context not yet supported.
5906 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5907 return QPixmap();
5908 }
5909
5910 QPoint pixmapOffset;
5911 QRectF sourceRect = m_widget->rect();
5912
5913 if (deviceCoordinates) {
5914 const QTransform &painterTransform = context->painter->worldTransform();
5915 sourceRect = painterTransform.mapRect(sourceRect);
5916 pixmapOffset = painterTransform.map(pixmapOffset);
5917 }
5918
5919 QRect effectRect;
5920
5921 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5922 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5923 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5924 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5925 else
5926 effectRect = sourceRect.toAlignedRect();
5927
5928 if (offset)
5929 *offset = effectRect.topLeft();
5930
5931 pixmapOffset -= effectRect.topLeft();
5932
5933 qreal dpr(1.0);
5934 if (const auto *paintDevice = context->painter->device())
5935 dpr = paintDevice->devicePixelRatio();
5936 else
5937 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5938 QPixmap pixmap(effectRect.size() * dpr);
5939 pixmap.setDevicePixelRatio(dpr);
5940
5941 pixmap.fill(Qt::transparent);
5942 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5943 return pixmap;
5944}
5945#endif // QT_CONFIG(graphicseffect)
5946
5947#if QT_CONFIG(graphicsview)
5948/*!
5949 \internal
5950
5951 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5952 widget and its ancestors. The search starts at \a origin (inclusive).
5953 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5954 embedded widget was found.
5955*/
5956QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5957{
5958 if (origin) {
5959 const auto &extra = origin->d_func()->extra;
5960 if (extra && extra->proxyWidget)
5961 return extra->proxyWidget;
5962 return nearestGraphicsProxyWidget(origin->parentWidget());
5963 }
5964 return nullptr;
5965}
5966#endif
5967
5968/*!
5969 \property QWidget::locale
5970 \brief the widget's locale
5971 \since 4.3
5972
5973 As long as no special locale has been set, this is either
5974 the parent's locale or (if this widget is a top level widget),
5975 the default locale.
5976
5977 If the widget displays dates or numbers, these should be formatted
5978 using the widget's locale.
5979
5980 \sa QLocale, QLocale::setDefault()
5981*/
5982
5983void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5984{
5985 Q_Q(QWidget);
5986 if (locale == loc && !forceUpdate)
5987 return;
5988
5989 locale = loc;
5990
5991 if (!children.isEmpty()) {
5992 for (int i = 0; i < children.size(); ++i) {
5993 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5994 if (!w)
5995 continue;
5996 if (w->testAttribute(Qt::WA_SetLocale))
5997 continue;
5998 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5999 continue;
6000 w->d_func()->setLocale_helper(loc, forceUpdate);
6001 }
6002 }
6003 QEvent e(QEvent::LocaleChange);
6004 QCoreApplication::sendEvent(q, &e);
6005}
6006
6007void QWidget::setLocale(const QLocale &locale)
6008{
6009 Q_D(QWidget);
6010
6011 setAttribute(Qt::WA_SetLocale);
6012 d->setLocale_helper(locale);
6013}
6014
6015QLocale QWidget::locale() const
6016{
6017 Q_D(const QWidget);
6018
6019 return d->locale;
6020}
6021
6022void QWidgetPrivate::resolveLocale()
6023{
6024 Q_Q(const QWidget);
6025
6026 if (!q->testAttribute(Qt::WA_SetLocale)) {
6027 QWidget *parent = q->parentWidget();
6028 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
6029 ? QLocale() : parent->locale());
6030 }
6031}
6032
6033void QWidget::unsetLocale()
6034{
6035 Q_D(QWidget);
6036 setAttribute(Qt::WA_SetLocale, false);
6037 d->resolveLocale();
6038}
6039
6040/*!
6041 \property QWidget::windowTitle
6042 \brief the window title (caption)
6043
6044 This property only makes sense for top-level widgets, such as
6045 windows and dialogs. If no caption has been set, the title is based of the
6046 \l windowFilePath. If neither of these is set, then the title is
6047 an empty string.
6048
6049 If you use the \l windowModified mechanism, the window title must
6050 contain a "[*]" placeholder, which indicates where the '*' should
6051 appear. Normally, it should appear right after the file name
6052 (e.g., "document1.txt[*] - Text Editor"). If the \l
6053 windowModified property is \c false (the default), the placeholder
6054 is simply removed.
6055
6056 On some desktop platforms (including Windows and Unix), the application name
6057 (from QGuiApplication::applicationDisplayName) is added at the end of the
6058 window title, if set. This is done by the QPA plugin, so it is shown to the
6059 user, but isn't part of the windowTitle string.
6060
6061 \sa windowIcon, windowModified, windowFilePath
6062*/
6063QString QWidget::windowTitle() const
6064{
6065 Q_D(const QWidget);
6066 if (d->extra && d->extra->topextra) {
6067 if (!d->extra->topextra->caption.isEmpty())
6068 return d->extra->topextra->caption;
6069 if (!d->extra->topextra->filePath.isEmpty())
6070 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6071 }
6072 return QString();
6073}
6074
6075/*!
6076 Returns a modified window title with the [*] place holder
6077 replaced according to the rules described in QWidget::setWindowTitle
6078
6079 This function assumes that "[*]" can be quoted by another
6080 "[*]", so it will replace two place holders by one and
6081 a single last one by either "*" or nothing depending on
6082 the modified flag.
6083
6084 \internal
6085*/
6086QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6087{
6088 Q_ASSERT(widget);
6089
6090 QString cap = title;
6091 if (cap.isEmpty())
6092 return cap;
6093
6094 const auto placeHolder = "[*]"_L1;
6095 int index = cap.indexOf(placeHolder);
6096
6097 // here the magic begins
6098 while (index != -1) {
6099 index += placeHolder.size();
6100 int count = 1;
6101 while (cap.indexOf(placeHolder, index) == index) {
6102 ++count;
6103 index += placeHolder.size();
6104 }
6105
6106 if (count%2) { // odd number of [*] -> replace last one
6107 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
6108 if (widget->isWindowModified()
6109 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
6110 cap.replace(lastIndex, 3, QWidget::tr("*"));
6111 else
6112 cap.remove(lastIndex, 3);
6113 }
6114
6115 index = cap.indexOf(placeHolder, index);
6116 }
6117
6118 cap.replace("[*][*]"_L1, placeHolder);
6119
6120 return cap;
6121}
6122
6123void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6124{
6125 Q_Q(QWidget);
6126 if (q->testAttribute(Qt::WA_WState_Created))
6127 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
6128}
6129
6130void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6131{
6132 Q_Q(QWidget);
6133 if (!q->isWindow())
6134 return;
6135
6136 if (QWindow *window = q->windowHandle())
6137 {
6138#if QT_CONFIG(accessibility)
6139 QString oldAccessibleName;
6140 const QAccessibleInterface *accessible = QAccessible::isActive()
6141 ? QAccessible::queryAccessibleInterface(q)
6142 : nullptr;
6143 if (accessible)
6144 oldAccessibleName = accessible->text(QAccessible::Name);
6145#endif
6146
6147 window->setTitle(caption);
6148
6149#if QT_CONFIG(accessibility)
6150 if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
6151 QAccessibleEvent event(q, QAccessible::NameChanged);
6152 QAccessible::updateAccessibility(&event);
6153 }
6154#endif
6155 }
6156}
6157
6158void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6159{
6160 Q_Q(QWidget);
6161 if (q->testAttribute(Qt::WA_WState_Created))
6162 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
6163}
6164
6165void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6166{
6167#if QT_CONFIG(xcb)
6168 Q_Q(QWidget);
6169 // ### The QWidget property is deprecated, but the XCB window function is not.
6170 // It should remain available for the rare application that needs it.
6171 if (QWindow *window = q->windowHandle()) {
6172 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6173 xcbWindow->setWindowIconText(iconText);
6174 }
6175#else
6176 Q_UNUSED(iconText);
6177#endif
6178}
6179
6180/*!
6181 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6182
6183 This signal is emitted when the window's icon text has changed, with the
6184 new \a iconText as an argument.
6185
6186 \since 5.2
6187 \deprecated
6188
6189 This signal is deprecated.
6190*/
6191
6192void QWidget::setWindowIconText(const QString &iconText)
6193{
6194 if (QWidget::windowIconText() == iconText)
6195 return;
6196
6197 Q_D(QWidget);
6198 d->topData()->iconText = iconText;
6199 d->setWindowIconText_helper(iconText);
6200
6201 QEvent e(QEvent::IconTextChange);
6202 QCoreApplication::sendEvent(this, &e);
6203
6204 emit windowIconTextChanged(iconText);
6205}
6206
6207/*!
6208 \fn void QWidget::windowTitleChanged(const QString &title)
6209
6210 This signal is emitted when the window's title has changed, with the
6211 new \a title as an argument.
6212
6213 \since 5.2
6214*/
6215
6216void QWidget::setWindowTitle(const QString &title)
6217{
6218 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6219 return;
6220
6221 Q_D(QWidget);
6222 d->topData()->caption = title;
6223 d->setWindowTitle_helper(title);
6224
6225 QEvent e(QEvent::WindowTitleChange);
6226 QCoreApplication::sendEvent(this, &e);
6227
6228 emit windowTitleChanged(title);
6229}
6230
6231
6232/*!
6233 \property QWidget::windowIcon
6234 \brief the widget's icon
6235
6236 This property only makes sense for windows. If no icon
6237 has been set, windowIcon() returns the application icon
6238 (QApplication::windowIcon()).
6239
6240 \note On \macos, window icons represent the active document,
6241 and will not be displayed unless a file path has also been
6242 set using setWindowFilePath.
6243
6244 \sa windowTitle, setWindowFilePath
6245*/
6246QIcon QWidget::windowIcon() const
6247{
6248 const QWidget *w = this;
6249 while (w) {
6250 const QWidgetPrivate *d = w->d_func();
6251 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6252 return *d->extra->topextra->icon;
6253 w = w->parentWidget();
6254 }
6255 return QApplication::windowIcon();
6256}
6257
6258void QWidgetPrivate::setWindowIcon_helper()
6259{
6260 Q_Q(QWidget);
6261 QEvent e(QEvent::WindowIconChange);
6262
6263 // Do not send the event if the widget is a top level.
6264 // In that case, setWindowIcon_sys does it, and event propagation from
6265 // QWidgetWindow to the top level QWidget ensures that the event reaches
6266 // the top level anyhow
6267 if (!q->windowHandle())
6268 QCoreApplication::sendEvent(q, &e);
6269 for (int i = 0; i < children.size(); ++i) {
6270 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6271 if (w && !w->isWindow())
6272 QCoreApplication::sendEvent(w, &e);
6273 }
6274}
6275
6276/*!
6277 \fn void QWidget::windowIconChanged(const QIcon &icon)
6278
6279 This signal is emitted when the window's icon has changed, with the
6280 new \a icon as an argument.
6281
6282 \since 5.2
6283*/
6284
6285void QWidget::setWindowIcon(const QIcon &icon)
6286{
6287 Q_D(QWidget);
6288
6289 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6290 d->createTLExtra();
6291
6292 if (!d->extra->topextra->icon)
6293 d->extra->topextra->icon = std::make_unique<QIcon>(icon);
6294 else
6295 *d->extra->topextra->icon = icon;
6296
6297 d->setWindowIcon_sys();
6298 d->setWindowIcon_helper();
6299
6300 emit windowIconChanged(icon);
6301}
6302
6303void QWidgetPrivate::setWindowIcon_sys()
6304{
6305 Q_Q(QWidget);
6306 if (QWindow *window = q->windowHandle())
6307 window->setIcon(q->windowIcon());
6308}
6309
6310/*!
6311 \property QWidget::windowIconText
6312 \brief the text to be displayed on the icon of a minimized window
6313
6314 This property only makes sense for windows. If no icon
6315 text has been set, this accessor returns an empty string.
6316 It is only implemented on the X11 platform, and only certain
6317 window managers use this window property.
6318
6319 \deprecated
6320 This property is deprecated.
6321
6322 \sa windowIcon, windowTitle
6323*/
6324
6325QString QWidget::windowIconText() const
6326{
6327 Q_D(const QWidget);
6328 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6329}
6330
6331/*!
6332 \property QWidget::windowFilePath
6333 \since 4.4
6334 \brief the file path associated with a widget
6335
6336 This property only makes sense for windows. It associates a file path with
6337 a window. If you set the file path, but have not set the window title, Qt
6338 sets the window title to the file name of the specified path, obtained using
6339 QFileInfo::fileName().
6340
6341 If the window title is set at any point, then the window title takes precedence and
6342 will be shown instead of the file path string.
6343
6344 Additionally, on \macos, this has an added benefit that it sets the
6345 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6346 for the window, assuming that the file path exists.
6347
6348 If no file path is set, this property contains an empty string.
6349
6350 By default, this property contains an empty string.
6351
6352 \sa windowTitle, windowIcon
6353*/
6354
6355QString QWidget::windowFilePath() const
6356{
6357 Q_D(const QWidget);
6358 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6359}
6360
6361void QWidget::setWindowFilePath(const QString &filePath)
6362{
6363 if (filePath == windowFilePath())
6364 return;
6365
6366 Q_D(QWidget);
6367
6368 d->createTLExtra();
6369 d->extra->topextra->filePath = filePath;
6370 d->setWindowFilePath_helper(filePath);
6371}
6372
6373void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6374{
6375 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6376#ifdef Q_OS_MACOS
6377 setWindowTitle_helper(QFileInfo(filePath).fileName());
6378#else
6379 Q_Q(QWidget);
6380 Q_UNUSED(filePath);
6381 setWindowTitle_helper(q->windowTitle());
6382#endif
6383 }
6384#ifdef Q_OS_MACOS
6385 setWindowFilePath_sys(filePath);
6386#endif
6387}
6388
6389void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6390{
6391 Q_Q(QWidget);
6392 if (!q->isWindow())
6393 return;
6394
6395 if (QWindow *window = q->windowHandle())
6396 window->setFilePath(filePath);
6397}
6398
6399/*!
6400 Returns the window's role, or an empty string.
6401
6402 \sa windowIcon, windowTitle
6403*/
6404
6405QString QWidget::windowRole() const
6406{
6407 Q_D(const QWidget);
6408 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6409}
6410
6411/*!
6412 Sets the window's role to \a role. This only makes sense for
6413 windows on X11.
6414*/
6415void QWidget::setWindowRole(const QString &role)
6416{
6417#if QT_CONFIG(xcb) || QT_CONFIG(wayland)
6418 Q_D(QWidget);
6419 d->createTLExtra();
6420 d->topData()->role = role;
6421#else
6422 Q_UNUSED(role);
6423#endif
6424
6425 if (windowHandle()) {
6426#if QT_CONFIG(xcb)
6427 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6428 xcbWindow->setWindowRole(role);
6429#endif
6430#if QT_CONFIG(wayland)
6431 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(windowHandle()->handle()))
6432 waylandWindow->setSessionRestoreId(role);
6433#endif
6434 }
6435}
6436
6437/*!
6438 \property QWidget::mouseTracking
6439 \brief whether mouse tracking is enabled for the widget
6440
6441 If mouse tracking is disabled (the default), the widget only
6442 receives mouse move events when at least one mouse button is
6443 pressed while the mouse is being moved.
6444
6445 If mouse tracking is enabled, the widget receives mouse move
6446 events even if no buttons are pressed.
6447
6448 \sa mouseMoveEvent()
6449*/
6450
6451/*!
6452 \property QWidget::tabletTracking
6453 \brief whether tablet tracking is enabled for the widget
6454 \since 5.9
6455
6456 If tablet tracking is disabled (the default), the widget only
6457 receives tablet move events when the stylus is in contact with
6458 the tablet, or at least one stylus button is pressed,
6459 while the stylus is being moved.
6460
6461 If tablet tracking is enabled, the widget receives tablet move
6462 events even while hovering in proximity. This is useful for
6463 monitoring position as well as the auxiliary properties such
6464 as rotation and tilt, and providing feedback in the UI.
6465
6466 \sa tabletEvent()
6467*/
6468
6469
6470/*!
6471 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6472 function resets this widget to have no focus proxy.
6473
6474 Some widgets can "have focus", but create a child widget, such as
6475 QLineEdit, to actually handle the focus. In this case, the widget
6476 can set the line edit to be its focus proxy.
6477
6478 setFocusProxy() sets the widget which will actually get focus when
6479 "this widget" gets it. If there is a focus proxy, setFocus() and
6480 hasFocus() operate on the focus proxy. If "this widget" is the focus
6481 widget, then setFocusProxy() moves focus to the new focus proxy.
6482
6483 \sa focusProxy()
6484*/
6485
6486void QWidget::setFocusProxy(QWidget * w)
6487{
6488 Q_D(QWidget);
6489 if (!w && !d->extra)
6490 return;
6491
6492 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6493 if (Q_UNLIKELY(fp == this)) {
6494 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6495 return;
6496 }
6497 }
6498
6499 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6500
6501 d->createExtra();
6502 d->extra->focus_proxy = w;
6503
6504 if (w && isAncestorOf(w)) {
6505 // If the focus proxy is a child of this (so this is a compound widget), then
6506 // we need to make sure that this widget is immediately in front of its own children
6507 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6508 // widgets that are positioned between this compound widget, and its proxy in
6509 // the focus chain.
6510 const QWidget *parentOfW = w->parentWidget();
6511 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6512 QWidget *firstChild = nullptr;
6513 const auto childList = children();
6514 for (QObject *child : childList) {
6515 if ((firstChild = qobject_cast<QWidget *>(child)))
6516 break;
6517 }
6518 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6519 d->insertIntoFocusChainBefore(firstChild);
6520 } else if (w && w->isAncestorOf(this)) {
6521 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6522 // remove it from the chain and insert this into the focus chain after its parent
6523
6524 // is this the case already?
6525 QWidget *parentsNext = w->nextInFocusChain();
6526 if (parentsNext == this) {
6527 // nothing to do.
6528 Q_ASSERT(previousInFocusChain() == w);
6529 } else {
6530 d->QWidgetPrivate::insertIntoFocusChainAfter(w);
6531 }
6532 }
6533
6534 if (moveFocusToProxy)
6535 setFocus(Qt::OtherFocusReason);
6536}
6537
6538
6539/*!
6540 Returns the focus proxy, or \nullptr if there is no focus proxy.
6541
6542 \sa setFocusProxy()
6543*/
6544
6545QWidget *QWidget::focusProxy() const
6546{
6547 Q_D(const QWidget);
6548 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6549}
6550
6551
6552/*!
6553 \property QWidget::focus
6554 \brief whether this widget (or its focus proxy) has the keyboard
6555 input focus
6556
6557 By default, this property is \c false.
6558
6559 \note Obtaining the value of this property for a widget is effectively equivalent
6560 to checking whether QApplication::focusWidget() refers to the widget.
6561
6562 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6563*/
6564bool QWidget::hasFocus() const
6565{
6566 const QWidget* w = this;
6567 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6568 w = w->d_func()->extra->focus_proxy;
6569#if QT_CONFIG(graphicsview)
6570 if (QWidget *window = w->window()) {
6571 const auto &e = window->d_func()->extra;
6572 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6573 return true;
6574 }
6575#endif // QT_CONFIG(graphicsview)
6576 return (QApplication::focusWidget() == w);
6577}
6578
6579/*!
6580 Gives the keyboard input focus to this widget (or its focus
6581 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6582 be passed into any focus event sent from this function, it is used
6583 to give an explanation of what caused the widget to get focus.
6584 If the window is not active, the widget will be given the focus when
6585 the window becomes active.
6586
6587 First, a focus about to change event is sent to the focus widget (if any) to
6588 tell it that it is about to lose the focus. Then focus is changed, a
6589 focus out event is sent to the previous focus item and a focus in event is sent
6590 to the new item to tell it that it just received the focus.
6591 (Nothing happens if the focus in and focus out widgets are the
6592 same.)
6593
6594 \note On embedded platforms, setFocus() will not cause an input panel
6595 to be opened by the input method. If you want this to happen, you
6596 have to send a QEvent::RequestSoftwareInputPanel event to the
6597 widget yourself.
6598
6599 setFocus() gives focus to a widget regardless of its focus policy,
6600 but does not clear any keyboard grab (see grabKeyboard()).
6601
6602 Be aware that if the widget is hidden, it will not accept focus
6603 until it is shown.
6604
6605 \warning If you call setFocus() in a function which may itself be
6606 called from focusOutEvent() or focusInEvent(), you may get an
6607 infinite recursion.
6608
6609 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6610 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6611 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6612*/
6613
6614void QWidget::setFocus(Qt::FocusReason reason)
6615{
6616 if (!isEnabled())
6617 return;
6618
6619 QWidget *f = d_func()->deepestFocusProxy();
6620 if (!f)
6621 f = this;
6622
6623 if (QApplication::focusWidget() == f)
6624 return;
6625
6626#if QT_CONFIG(graphicsview)
6627 QWidget *previousProxyFocus = nullptr;
6628 if (const auto &topData = window()->d_func()->extra) {
6629 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6630 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6631 if (previousProxyFocus && previousProxyFocus->focusProxy())
6632 previousProxyFocus = previousProxyFocus->focusProxy();
6633 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6634 return;
6635 }
6636 }
6637#endif
6638
6639#if QT_CONFIG(graphicsview)
6640 // Update proxy state
6641 if (const auto &topData = window()->d_func()->extra) {
6642 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6643 f->d_func()->updateFocusChild();
6644 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6645 topData->proxyWidget->setFocus(reason);
6646 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6647 }
6648 }
6649#endif
6650
6651 if (f->isActiveWindow()) {
6652 QWidget *prev = QApplicationPrivate::focus_widget;
6653 if (prev) {
6654 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6655 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6656 QGuiApplication::inputMethod()->commit();
6657 }
6658
6659 if (reason != Qt::NoFocusReason) {
6660 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6661 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6662 }
6663 }
6664
6665 f->d_func()->updateFocusChild();
6666
6667 QApplicationPrivate::setFocusWidget(f, reason);
6668#if QT_CONFIG(accessibility)
6669 // menus update the focus manually and this would create bogus events
6670 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6671 {
6672 QAccessibleEvent event(f, QAccessible::Focus);
6673 QAccessible::updateAccessibility(&event);
6674 }
6675#endif
6676#if QT_CONFIG(graphicsview)
6677 if (const auto &topData = window()->d_func()->extra) {
6678 if (topData->proxyWidget) {
6679 if (previousProxyFocus && previousProxyFocus != f) {
6680 // Send event to self
6681 QFocusEvent event(QEvent::FocusOut, reason);
6682 QPointer<QWidget> that = previousProxyFocus;
6683 QCoreApplication::sendEvent(previousProxyFocus, &event);
6684 if (that)
6685 QCoreApplication::sendEvent(that->style(), &event);
6686 }
6687 if (!isHidden()) {
6688#if QT_CONFIG(graphicsview)
6689 // Update proxy state
6690 if (const auto &topData = window()->d_func()->extra)
6691 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6692 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6693#endif
6694 // Send event to self
6695 QFocusEvent event(QEvent::FocusIn, reason);
6696 QPointer<QWidget> that = f;
6697 QCoreApplication::sendEvent(f, &event);
6698 if (that)
6699 QCoreApplication::sendEvent(that->style(), &event);
6700 }
6701 }
6702 }
6703#endif
6704 } else {
6705 f->d_func()->updateFocusChild();
6706 }
6707}
6708
6709
6710/*!\internal
6711 * A focus proxy can have its own focus proxy, which can have its own
6712 * proxy, and so on. This helper function returns the widget that sits
6713 * at the bottom of the proxy chain, and therefore the one that should
6714 * normally get focus if this widget receives a focus request.
6715 */
6716QWidget *QWidgetPrivate::deepestFocusProxy() const
6717{
6718 Q_Q(const QWidget);
6719
6720 QWidget *focusProxy = q->focusProxy();
6721 if (!focusProxy)
6722 return nullptr;
6723
6724 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6725 focusProxy = nextFocusProxy;
6726
6727 return focusProxy;
6728}
6729
6730static inline bool isEmbedded(const QWindow *w)
6731{
6732 const auto platformWindow = w->handle();
6733 return platformWindow && platformWindow->isEmbedded();
6734}
6735
6736void QWidgetPrivate::setFocus_sys()
6737{
6738 Q_Q(QWidget);
6739 // Embedded native widget may have taken the focus; get it back to toplevel
6740 // if that is the case (QTBUG-25852), unless widget is a window container.
6741 if (extra && extra->hasWindowContainer)
6742 return;
6743 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6744 // unless the application is embedded (QTBUG-71991).
6745 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6746 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6747 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6748 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6749 || isEmbedded(nativeWindow))) {
6750 nativeWindow->requestActivate();
6751 }
6752 }
6753}
6754
6755// updates focus_child on parent widgets to point into this widget
6756void QWidgetPrivate::updateFocusChild()
6757{
6758 Q_Q(QWidget);
6759
6760 QWidget *w = q;
6761 if (q->isHidden()) {
6762 while (w && w->isHidden()) {
6763 w->d_func()->focus_child = q;
6764 w = w->isWindow() ? nullptr : w->parentWidget();
6765 }
6766 } else {
6767 while (w) {
6768 w->d_func()->focus_child = q;
6769 w = w->isWindow() ? nullptr : w->parentWidget();
6770 }
6771 }
6772
6773 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6774 if (extra->window)
6775 emit extra->window->focusObjectChanged(q);
6776 }
6777}
6778
6779/*!
6780 \fn void QWidget::setFocus()
6781 \overload
6782
6783 Gives the keyboard input focus to this widget (or its focus
6784 proxy) if this widget or one of its parents is the
6785 \l{isActiveWindow()}{active window}.
6786*/
6787
6788/*!
6789 Takes keyboard input focus from the widget.
6790
6791 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6792 lost the focus.
6793
6794 This widget must enable focus setting to get the keyboard
6795 input focus; that is, it must call setFocusPolicy().
6796
6797 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6798 setFocusPolicy(), QApplication::focusWidget()
6799*/
6800
6801void QWidget::clearFocus()
6802{
6803 if (hasFocus()) {
6804 if (testAttribute(Qt::WA_InputMethodEnabled))
6805 QGuiApplication::inputMethod()->commit();
6806
6807 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6808 QCoreApplication::sendEvent(this, &focusAboutToChange);
6809 }
6810
6811 QTLWExtra *extra = window()->d_func()->maybeTopData();
6812 QObject *originalFocusObject = nullptr;
6813 if (extra && extra->window) {
6814 originalFocusObject = extra->window->focusObject();
6815 // the window's focus object might already be nullptr if we are in the destructor, but we still
6816 // need to update QGuiApplication and input context if we have a focus widget.
6817 if (!originalFocusObject)
6818 originalFocusObject = focusWidget();
6819 }
6820
6821 QWidget *w = this;
6822 while (w) {
6823 // Just like setFocus(), we update (clear) the focus_child of our parents
6824 if (w->d_func()->focus_child == this)
6825 w->d_func()->focus_child = nullptr;
6826 w = w->parentWidget();
6827 }
6828
6829 // We've potentially cleared the focus_child of our parents, so we need
6830 // to report this to the rest of Qt. Note that the focus_child is not the same
6831 // thing as the application's focusWidget, which is why this piece of code is
6832 // not inside a hasFocus() block.
6833 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6834 emit extra->window->focusObjectChanged(extra->window->focusObject());
6835
6836#if QT_CONFIG(graphicsview)
6837 const auto &topData = d_func()->extra;
6838 if (topData && topData->proxyWidget)
6839 topData->proxyWidget->clearFocus();
6840#endif
6841
6842 if (hasFocus()) {
6843 // Update proxy state
6844 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6845#if QT_CONFIG(accessibility)
6846 QAccessibleEvent event(this, QAccessible::Focus);
6847 QAccessible::updateAccessibility(&event);
6848#endif
6849 }
6850}
6851
6852
6853/*!
6854 \fn bool QWidget::focusNextChild()
6855
6856 Finds a new widget to give the keyboard focus to, as appropriate
6857 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6858 false if it can't.
6859
6860 \sa focusPreviousChild()
6861*/
6862
6863/*!
6864 \fn bool QWidget::focusPreviousChild()
6865
6866 Finds a new widget to give the keyboard focus to, as appropriate
6867 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6868 or false if it can't.
6869
6870 \sa focusNextChild()
6871*/
6872
6873/*!
6874 Finds a new widget to give the keyboard focus to, as appropriate
6875 for Tab and Shift+Tab, and returns \c true if it can find a new
6876 widget, or false if it can't.
6877
6878 If \a next is true, this function searches forward, if \a next
6879 is false, it searches backward.
6880
6881 Sometimes, you will want to reimplement this function. For
6882 example, a web browser might reimplement it to move its "current
6883 active link" forward or backward, and call
6884 focusNextPrevChild() only when it reaches the last or
6885 first link on the "page".
6886
6887 Child widgets call focusNextPrevChild() on their parent widgets,
6888 but only the window that contains the child widgets decides where
6889 to redirect focus. By reimplementing this function for an object,
6890 you thus gain control of focus traversal for all child widgets.
6891
6892 \sa focusNextChild(), focusPreviousChild()
6893*/
6894
6895bool QWidget::focusNextPrevChild(bool next)
6896{
6897 QWidget* p = parentWidget();
6898 bool isSubWindow = (windowType() == Qt::SubWindow);
6899 if (!isWindow() && !isSubWindow && p)
6900 return p->focusNextPrevChild(next);
6901#if QT_CONFIG(graphicsview)
6902 Q_D(QWidget);
6903 if (d->extra && d->extra->proxyWidget)
6904 return d->extra->proxyWidget->focusNextPrevChild(next);
6905#endif
6906
6907 bool wrappingOccurred = false;
6908 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6909 &wrappingOccurred);
6910 if (!w) return false;
6911
6912 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6913
6914 /* If we are about to wrap the focus chain, give the platform
6915 * implementation a chance to alter the wrapping behavior. This is
6916 * especially needed when the window is embedded in a window created by
6917 * another process.
6918 */
6919 if (wrappingOccurred) {
6920 QWindow *window = windowHandle();
6921 if (window != nullptr) {
6922 QWindowPrivate *winp = qt_window_private(window);
6923
6924 if (winp->platformWindow != nullptr) {
6925 QFocusEvent event(QEvent::FocusIn, reason);
6926 event.ignore();
6927 winp->platformWindow->windowEvent(&event);
6928 if (event.isAccepted()) return true;
6929 }
6930 }
6931 }
6932
6933 w->setFocus(reason);
6934 return true;
6935}
6936
6937/*!
6938 Returns the last child of this widget that setFocus had been
6939 called on. For top level widgets this is the widget that will get
6940 focus in case this window gets activated
6941
6942 This is not the same as QApplication::focusWidget(), which returns
6943 the focus widget in the currently active window.
6944*/
6945
6946QWidget *QWidget::focusWidget() const
6947{
6948 return const_cast<QWidget *>(d_func()->focus_child);
6949}
6950
6951QObject *QWidgetPrivate::focusObject()
6952{
6953 Q_Q(QWidget);
6954 QWidget *proxy = deepestFocusProxy();
6955 return proxy ? proxy : q;
6956}
6957
6958/*!
6959 Returns the next widget in this widget's focus chain.
6960
6961 \sa previousInFocusChain()
6962*/
6963QWidget *QWidget::nextInFocusChain() const
6964{
6965 Q_D(const QWidget);
6966 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
6967}
6968
6969/*!
6970 \brief The previousInFocusChain function returns the previous
6971 widget in this widget's focus chain.
6972
6973 \sa nextInFocusChain()
6974
6975 \since 4.6
6976*/
6977QWidget *QWidget::previousInFocusChain() const
6978{
6979 Q_D(const QWidget);
6980 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
6981}
6982
6983/*!
6984 \property QWidget::isActiveWindow
6985 \brief whether this widget's window is the active window
6986
6987 The active window is the window that contains the widget that has
6988 keyboard focus (The window may still have focus if it has no
6989 widgets or none of its widgets accepts keyboard focus).
6990
6991 When popup windows are visible, this property is \c true for both the
6992 active window \e and for the popup.
6993
6994 By default, this property is \c false.
6995
6996 \sa activateWindow(), QApplication::activeWindow()
6997*/
6998bool QWidget::isActiveWindow() const
6999{
7000 QWidget *tlw = window();
7001 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
7002 return true;
7003
7004#if QT_CONFIG(graphicsview)
7005 if (const auto &tlwExtra = tlw->d_func()->extra) {
7006 if (isVisible() && tlwExtra->proxyWidget)
7007 return tlwExtra->proxyWidget->isActiveWindow();
7008 }
7009#endif
7010
7011 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
7012 if (tlw->windowType() == Qt::Tool &&
7013 !tlw->isModal() &&
7014 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
7015 return true;
7016 QWidget *w = QApplication::activeWindow();
7017 while(w && tlw->windowType() == Qt::Tool &&
7018 !w->isModal() && w->parentWidget()) {
7019 w = w->parentWidget()->window();
7020 if (w == tlw)
7021 return true;
7022 }
7023 }
7024
7025 // Check for an active window container
7026 if (QWindow *ww = QGuiApplication::focusWindow()) {
7027 while (ww) {
7028 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
7029 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
7030 if (qwc && qwc->topLevelWidget() == tlw)
7031 return true;
7032 ww = ww->parent();
7033 }
7034 }
7035
7036 // Check if platform adaptation thinks the window is active. This is necessary for
7037 // example in case of ActiveQt servers that are embedded into another application.
7038 // Those are separate processes that are not part of the parent application Qt window/widget
7039 // hierarchy, so they need to rely on native methods to determine if they are part of the
7040 // active window.
7041 if (const QWindow *w = tlw->windowHandle()) {
7042 if (w->handle())
7043 return w->handle()->isActive();
7044 }
7045
7046 return false;
7047}
7048
7049/*!
7050 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7051 \overload
7052 \since 6.6
7053
7054 Sets the tab order for the widgets in the \a widgets list by calling
7055 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
7056 pair of widgets.
7057
7058 Instead of setting up each pair manually like this:
7059
7060 \snippet code/src_gui_kernel_qwidget.cpp 9
7061
7062 you can call:
7063
7064 \snippet code/src_gui_kernel_qwidget.cpp 9.list
7065
7066 The call does not create a closed tab focus loop. If there are more widgets
7067 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
7068 of those widgets, not back to \c{a}.
7069
7070 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7071*/
7072
7073/*!
7074 Puts the \a second widget after the \a first widget in the focus order.
7075
7076 It effectively removes the \a second widget from its focus chain and
7077 inserts it after the \a first widget.
7078
7079 Note that since the tab order of the \a second widget is changed, you
7080 should order a chain like this:
7081
7082 \snippet code/src_gui_kernel_qwidget.cpp 9
7083
7084 \e not like this:
7085
7086 \snippet code/src_gui_kernel_qwidget.cpp 10
7087
7088 If \a first or \a second has a focus proxy, setTabOrder()
7089 correctly substitutes the proxy.
7090
7091 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7092 a compound widget. When setting a tab order between one or two compound widgets, the
7093 local tab order inside each will be preserved. This means that if both widgets are
7094 compound widgets, the resulting tab order will be from the last child inside
7095 \a first, to the first child inside \a second.
7096
7097 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7098*/
7099void QWidget::setTabOrder(QWidget* first, QWidget *second)
7100{
7101 if (!first || !second || first == second
7102 || first->focusPolicy() == Qt::NoFocus
7103 || second->focusPolicy() == Qt::NoFocus)
7104 return;
7105
7106 if (Q_UNLIKELY(first->window() != second->window())) {
7107 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7108 return;
7109 }
7110
7111 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7112 {
7113 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7114 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7115 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7116 // 'lastFocusChild' will be set to the target itself.
7117 QWidget *lastFocusChild = target;
7118
7119 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7120 if (!focusProxy) {
7121 // QTBUG-81097: Another case is possible here. We can have a child
7122 // widget, that sets its focusProxy() to the parent (target).
7123 // An example of such widget is a QLineEdit, nested into
7124 // a QAbstractSpinBox. In this case such widget should be considered
7125 // the last focus child.
7126 for (auto *object : target->children()) {
7127 QWidget *w = qobject_cast<QWidget*>(object);
7128 if (w && w->focusProxy() == target) {
7129 lastFocusChild = w;
7130 break;
7131 }
7132 }
7133 } else if (target->isAncestorOf(focusProxy)) {
7134 lastFocusChild = focusProxy;
7135 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7136 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
7137 focusNext = focusNext->nextInFocusChain()) {
7138 if (focusNext == noFurtherThan)
7139 break;
7140 if (focusNext->focusPolicy() != Qt::NoFocus)
7141 lastFocusChild = focusNext;
7142 }
7143 }
7144 return lastFocusChild;
7145 };
7146 // detect inflection in case we have compound widgets
7147 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7148 if (lastFocusChildOfFirst == second)
7149 lastFocusChildOfFirst = first;
7150 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7151 if (lastFocusChildOfSecond == first)
7152 lastFocusChildOfSecond = second;
7153
7154 // Return if only NoFocus widgets are between first and second
7155 QWidget *oldPrev = second->previousInFocusChain();
7156 QWidget *prevWithFocus = oldPrev;
7157 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7158 prevWithFocus = prevWithFocus->previousInFocusChain();
7159 if (prevWithFocus == first)
7160 return;
7161 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
7162 QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
7163}
7164
7165void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7166{
7167 QWidget *prev = nullptr;
7168 for (const auto &widget : widgets) {
7169 if (!prev) {
7170 prev = widget;
7171 } else {
7172 QWidget::setTabOrder(prev, widget);
7173 prev = widget;
7174 }
7175 }
7176}
7177
7178
7179/*!\internal
7180
7181 Moves the relevant subwidgets of this widget from the \a oldtlw's
7182 tab chain to that of the new parent, if there's anything to move and
7183 we're really moving
7184
7185 This function is called from QWidget::reparent() *after* the widget
7186 has been reparented.
7187
7188 \sa reparent()
7189*/
7190
7191void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7192{
7193 Q_Q(QWidget);
7194 if (oldtlw == q->window())
7195 return; // nothing to do
7196
7197 if (focus_child)
7198 focus_child->clearFocus();
7199
7200 reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
7201}
7202
7203/*!
7204 \property QWidget::frameSize
7205 \brief the size of the widget including any window frame
7206
7207 By default, this property contains a value that depends on the user's
7208 platform and screen geometry.
7209*/
7210QSize QWidget::frameSize() const
7211{
7212 Q_D(const QWidget);
7213 if (isWindow() && !(windowType() == Qt::Popup)) {
7214 QRect fs = d->frameStrut();
7215 return QSize(data->crect.width() + fs.left() + fs.right(),
7216 data->crect.height() + fs.top() + fs.bottom());
7217 }
7218 return data->crect.size();
7219}
7220
7221/*! \fn void QWidget::move(int x, int y)
7222
7223 \overload
7224
7225 This corresponds to move(QPoint(\a x, \a y)).
7226*/
7227
7228void QWidget::move(const QPoint &p)
7229{
7230 Q_D(QWidget);
7231 setAttribute(Qt::WA_Moved);
7232 if (testAttribute(Qt::WA_WState_Created)) {
7233 if (isWindow())
7234 d->topData()->posIncludesFrame = false;
7235 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7236 p.y() + geometry().y() - QWidget::y(),
7237 width(), height(), true);
7238 d->setDirtyOpaqueRegion();
7239 } else {
7240 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7241 if (isWindow())
7242 d->topData()->posIncludesFrame = true;
7243 data->crect.moveTopLeft(p); // no frame yet
7244 setAttribute(Qt::WA_PendingMoveEvent);
7245 }
7246
7247 if (d->extra && d->extra->hasWindowContainer)
7248 QWindowContainer::parentWasMoved(this);
7249}
7250
7251// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7252// unknown), that is, crect has a position including the frame.
7253// If we can determine the frame strut, fix that and clear the flag.
7254// FIXME: This does not play well with window states other than
7255// Qt::WindowNoState, as we depend on calling setGeometry() on the
7256// platform window after fixing up the position so that the new
7257// geometry is reflected in the platform window, but when the frame
7258// comes in after the window has been shown (e.g. maximized), we're
7259// not in a position to do that kind of fixup.
7260void QWidgetPrivate::fixPosIncludesFrame()
7261{
7262 Q_Q(QWidget);
7263 if (QTLWExtra *te = maybeTopData()) {
7264 if (te->posIncludesFrame) {
7265 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7266 // example, in QGraphicsProxyWidget).
7267 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7268 te->posIncludesFrame = 0;
7269 } else {
7270 if (q->windowHandle() && q->windowHandle()->handle()) {
7271 updateFrameStrut();
7272 if (!q->data->fstrut_dirty) {
7273 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
7274 te->posIncludesFrame = 0;
7275 }
7276 } // windowHandle()
7277 } // !WA_DontShowOnScreen
7278 } // posIncludesFrame
7279 } // QTLWExtra
7280}
7281
7282/*! \fn void QWidget::resize(int w, int h)
7283 \overload
7284
7285 This corresponds to resize(QSize(\a w, \a h)).
7286*/
7287
7288void QWidget::resize(const QSize &s)
7289{
7290 Q_D(QWidget);
7291 setAttribute(Qt::WA_Resized);
7292 if (testAttribute(Qt::WA_WState_Created)) {
7293 d->fixPosIncludesFrame();
7294 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7295 d->setDirtyOpaqueRegion();
7296 } else {
7297 const auto oldRect = data->crect;
7298 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7299 if (oldRect != data->crect)
7300 setAttribute(Qt::WA_PendingResizeEvent);
7301 }
7302}
7303
7304void QWidget::setGeometry(const QRect &r)
7305{
7306 Q_D(QWidget);
7307 setAttribute(Qt::WA_Resized);
7308 setAttribute(Qt::WA_Moved);
7309 if (isWindow())
7310 d->topData()->posIncludesFrame = 0;
7311 if (testAttribute(Qt::WA_WState_Created)) {
7312 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7313 d->setDirtyOpaqueRegion();
7314 } else {
7315 const auto oldRect = data->crect;
7316 data->crect.setTopLeft(r.topLeft());
7317 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7318 if (oldRect != data->crect) {
7319 setAttribute(Qt::WA_PendingMoveEvent);
7320 setAttribute(Qt::WA_PendingResizeEvent);
7321 }
7322 }
7323
7324 if (d->extra && d->extra->hasWindowContainer)
7325 QWindowContainer::parentWasMoved(this);
7326}
7327
7328void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7329{
7330 Q_Q(QWidget);
7331 if (extra) { // any size restrictions?
7332 w = qMin(w,extra->maxw);
7333 h = qMin(h,extra->maxh);
7334 w = qMax(w,extra->minw);
7335 h = qMax(h,extra->minh);
7336 }
7337
7338 if (q->isWindow() && q->windowHandle()) {
7339 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7340 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7341 x = 0;
7342 y = 0;
7343 w = q->windowHandle()->width();
7344 h = q->windowHandle()->height();
7345 }
7346 }
7347
7348 QPoint oldp = q->geometry().topLeft();
7349 QSize olds = q->size();
7350 QRect r(x, y, w, h);
7351
7352 bool isResize = olds != r.size();
7353 if (!isMove)
7354 isMove = oldp != r.topLeft();
7355
7356
7357 // We only care about stuff that changes the geometry, or may
7358 // cause the window manager to change its state
7359 if (r.size() == olds && oldp == r.topLeft())
7360 return;
7361
7362 if (!data.in_set_window_state) {
7363 q->data->window_state &= ~Qt::WindowMaximized;
7364 q->data->window_state &= ~Qt::WindowFullScreen;
7365 if (q->isWindow())
7366 topData()->normalGeometry = QRect(0, 0, -1, -1);
7367 }
7368
7369 QPoint oldPos = q->pos();
7370 data.crect = r;
7371
7372 bool needsShow = false;
7373
7374 if (q->isWindow() || q->windowHandle()) {
7375 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7376 q->setAttribute(Qt::WA_OutsideWSRange, true);
7377 if (q->isVisible())
7378 hide_sys();
7379 data.crect = QRect(x, y, w, h);
7380 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7381 q->setAttribute(Qt::WA_OutsideWSRange, false);
7382 needsShow = true;
7383 }
7384 }
7385
7386 if (q->isVisible()) {
7387 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7388 if (QWindow *win = q->windowHandle()) {
7389 if (q->isWindow()) {
7390 if (isResize && !isMove)
7391 win->resize(w, h);
7392 else if (isMove && !isResize)
7393 win->setPosition(x, y);
7394 else
7395 win->setGeometry(q->geometry());
7396 } else {
7397 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7398 win->setGeometry(QRect(posInNativeParent,r.size()));
7399 }
7400
7401 if (needsShow)
7402 show_sys();
7403 }
7404
7405 if (!q->isWindow()) {
7406 if (renderToTexture) {
7407 QRegion updateRegion(q->geometry());
7408 updateRegion += QRect(oldPos, olds);
7409 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7410 } else if (isMove && !isResize) {
7411 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7412 } else {
7413 invalidateBackingStore_resizeHelper(oldPos, olds);
7414 }
7415 }
7416 }
7417
7418 if (isMove) {
7419 QMoveEvent e(q->pos(), oldPos);
7420 QCoreApplication::sendEvent(q, &e);
7421 }
7422 if (isResize) {
7423 QResizeEvent e(r.size(), olds);
7424 QCoreApplication::sendEvent(q, &e);
7425 if (q->windowHandle())
7426 q->update();
7427 }
7428 } else { // not visible
7429 if (isMove && q->pos() != oldPos)
7430 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7431 if (isResize)
7432 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7433 }
7434
7435#if QT_CONFIG(accessibility)
7436 if (QAccessible::isActive() && q->isVisible()) {
7437 QAccessibleEvent event(q, QAccessible::LocationChanged);
7438 QAccessible::updateAccessibility(&event);
7439 }
7440#endif
7441}
7442
7443/*!
7444 \since 4.2
7445 Saves the current geometry and state for top-level widgets.
7446
7447 To save the geometry when the window closes, you can
7448 implement a close event like this:
7449
7450 \snippet code/src_gui_kernel_qwidget.cpp 11
7451
7452 See the \l{Window Geometry} documentation for an overview of geometry
7453 issues with windows.
7454
7455 Use QMainWindow::saveState() to save the geometry and the state of
7456 toolbars and dock widgets.
7457
7458 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7459*/
7460QByteArray QWidget::saveGeometry() const
7461{
7462 QByteArray array;
7463 QDataStream stream(&array, QIODevice::WriteOnly);
7464 stream.setVersion(QDataStream::Qt_4_0);
7465 const quint32 magicNumber = 0x1D9D0CB;
7466 // Version history:
7467 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7468 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7469 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7470 quint16 majorVersion = 3;
7471 quint16 minorVersion = 0;
7472 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7473 stream << magicNumber
7474 << majorVersion
7475 << minorVersion
7476 << frameGeometry()
7477 << normalGeometry()
7478 << qint32(screenNumber)
7479 << quint8(windowState() & Qt::WindowMaximized)
7480 << quint8(windowState() & Qt::WindowFullScreen)
7481 << qint32(screen()->geometry().width()) // added in 2.0
7482 << geometry(); // added in 3.0
7483 return array;
7484}
7485
7486/*!
7487 \internal
7488
7489 Check a if \a restoredGeometry fits into \a availableGeometry
7490 This method is used to verify that a widget is restored to a geometry, which
7491 fits into the target screen.
7492
7493 \param frameHeight represents the height of the widget's title bar, which is expected
7494 to be on its top.
7495
7496 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7497 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7498 be full screen.
7499
7500 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7501 \a restoredGeometry will be moved
7502 \list
7503 \li down if its top is off screen
7504 \li up if its bottom is off screen
7505 \li right if its left edge is off screen
7506 \li left if its right edge is off screen
7507 \endlist
7508 */
7509void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7510 int frameHeight)
7511{
7512 // compare with restored geometry's height increased by frameHeight
7513 const int height = restoredGeometry->height() + frameHeight;
7514
7515 // Step 1: Resize if necessary:
7516 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7517 if (availableGeometry.height() <= height)
7518 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7519 if (availableGeometry.width() <= restoredGeometry->width())
7520 restoredGeometry->setWidth(availableGeometry.width() - 2);
7521
7522 // Step 2: Move if necessary:
7523 // Construct a rectangle from restored Geometry adjusted by frameHeight
7524 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7525
7526 // Return if restoredGeometry (including frame) fits into screen
7527 if (availableGeometry.contains(restored))
7528 return;
7529
7530 // (size is correct, but at least one edge is off screen)
7531
7532 // Top out of bounds => move down
7533 if (restored.top() <= availableGeometry.top()) {
7534 restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
7535 } else if (restored.bottom() >= availableGeometry.bottom()) {
7536 // Bottom out of bounds => move up
7537 restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
7538 }
7539
7540 // Left edge out of bounds => move right
7541 if (restored.left() <= availableGeometry.left()) {
7542 restoredGeometry->moveLeft(availableGeometry.left() + 1);
7543 } else if (restored.right() >= availableGeometry.right()) {
7544 // Right edge out of bounds => move left
7545 restoredGeometry->moveRight(availableGeometry.right() - 1);
7546 }
7547}
7548
7549/*!
7550 \since 4.2
7551
7552 Restores the geometry and state of top-level widgets stored in the
7553 byte array \a geometry. Returns \c true on success; otherwise
7554 returns \c false.
7555
7556 If the restored geometry is off-screen, it will be modified to be
7557 inside the available screen geometry.
7558
7559 To restore geometry saved using QSettings, you can use code like
7560 this:
7561
7562 \snippet code/src_gui_kernel_qwidget.cpp 12
7563
7564 See the \l{Window Geometry} documentation for an overview of geometry
7565 issues with windows.
7566
7567 Use QMainWindow::restoreState() to restore the geometry and the
7568 state of toolbars and dock widgets.
7569
7570 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7571*/
7572bool QWidget::restoreGeometry(const QByteArray &geometry)
7573{
7574 if (geometry.size() < 4)
7575 return false;
7576 QDataStream stream(geometry);
7577 stream.setVersion(QDataStream::Qt_4_0);
7578
7579 const quint32 magicNumber = 0x1D9D0CB;
7580 quint32 storedMagicNumber;
7581 stream >> storedMagicNumber;
7582 if (storedMagicNumber != magicNumber)
7583 return false;
7584
7585 const quint16 currentMajorVersion = 3;
7586 quint16 majorVersion = 0;
7587 quint16 minorVersion = 0;
7588
7589 stream >> majorVersion >> minorVersion;
7590
7591 if (majorVersion > currentMajorVersion)
7592 return false;
7593 // (Allow all minor versions.)
7594
7595 QRect restoredFrameGeometry;
7596 QRect restoredGeometry;
7597 QRect restoredNormalGeometry;
7598 qint32 restoredScreenNumber;
7599 quint8 maximized;
7600 quint8 fullScreen;
7601 qint32 restoredScreenWidth = 0;
7602
7603 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7604 >> restoredNormalGeometry
7605 >> restoredScreenNumber
7606 >> maximized
7607 >> fullScreen;
7608
7609 if (majorVersion > 1)
7610 stream >> restoredScreenWidth;
7611 if (majorVersion > 2)
7612 stream >> restoredGeometry;
7613
7614 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7615
7616 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7617 restoredScreenNumber = 0;
7618 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7619 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7620 // Sanity check bailing out when large variations of screen sizes occur due to
7621 // high DPI scaling or different levels of DPI awareness.
7622 if (restoredScreenWidth) {
7623 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7624 if (factor < 0.8 || factor > 1.25)
7625 return false;
7626 } else {
7627 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7628 // unless the size will be adapted by maximized or fullscreen.
7629 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7630 return false;
7631 }
7632
7633 const int frameHeight = QApplication::style()
7634 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7635 : 20;
7636
7637 if (!restoredNormalGeometry.isValid())
7638 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7639 if (!restoredNormalGeometry.isValid()) {
7640 // use the widget's adjustedSize if the sizeHint() doesn't help
7641 restoredNormalGeometry.setSize(restoredNormalGeometry
7642 .size()
7643 .expandedTo(d_func()->adjustedSize()));
7644 }
7645
7646 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7647 : QRect();
7648
7649 // Modify the restored geometry if we are about to restore to coordinates
7650 // that would make the window "lost". This happens if:
7651 // - The restored geometry is completely or partly oustside the available geometry
7652 // - The title bar is outside the available geometry.
7653
7654 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7655 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7656
7657 if (maximized || fullScreen) {
7658 // set geometry before setting the window state to make
7659 // sure the window is maximized to the right screen.
7660 Qt::WindowStates ws = windowState();
7661#ifndef Q_OS_WIN
7662 setGeometry(restoredNormalGeometry);
7663#else
7664 if (ws & Qt::WindowFullScreen) {
7665 // Full screen is not a real window state on Windows.
7666 move(availableGeometry.topLeft());
7667 } else if (ws & Qt::WindowMaximized) {
7668 // Setting a geometry on an already maximized window causes this to be
7669 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7670 // Move the window in normal state if needed.
7671 if (restoredScreen != screen()) {
7672 setWindowState(Qt::WindowNoState);
7673 setGeometry(restoredNormalGeometry);
7674 }
7675 } else {
7676 setGeometry(restoredNormalGeometry);
7677 }
7678#endif // Q_OS_WIN
7679 if (maximized)
7680 ws |= Qt::WindowMaximized;
7681 if (fullScreen)
7682 ws |= Qt::WindowFullScreen;
7683 setWindowState(ws);
7684 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7685 } else {
7686 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7687
7688 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7689 if (majorVersion > 2)
7690 setGeometry(restoredGeometry);
7691 else
7692 setGeometry(restoredNormalGeometry);
7693 }
7694 return true;
7695}
7696
7697/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7698 \overload
7699
7700 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7701*/
7702
7703/*!
7704 Sets the margins around the contents of the widget to have the sizes
7705 \a left, \a top, \a right, and \a bottom. The margins are used by
7706 the layout system, and may be used by subclasses to specify the area
7707 to draw in (e.g. excluding the frame).
7708
7709 Changing the margins will trigger a resizeEvent().
7710
7711 \sa contentsRect(), contentsMargins()
7712*/
7713void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7714{
7715 Q_D(QWidget);
7716 if (left == d->leftmargin && top == d->topmargin
7717 && right == d->rightmargin && bottom == d->bottommargin)
7718 return;
7719 d->leftmargin = left;
7720 d->topmargin = top;
7721 d->rightmargin = right;
7722 d->bottommargin = bottom;
7723
7724 d->updateContentsRect();
7725}
7726
7727/*!
7728 \overload
7729 \since 4.6
7730
7731 \brief The setContentsMargins function sets the margins around the
7732 widget's contents.
7733
7734 Sets the margins around the contents of the widget to have the
7735 sizes determined by \a margins. The margins are
7736 used by the layout system, and may be used by subclasses to
7737 specify the area to draw in (e.g. excluding the frame).
7738
7739 Changing the margins will trigger a resizeEvent().
7740
7741 \sa contentsRect(), contentsMargins()
7742*/
7743void QWidget::setContentsMargins(const QMargins &margins)
7744{
7745 setContentsMargins(margins.left(), margins.top(),
7746 margins.right(), margins.bottom());
7747}
7748
7749void QWidgetPrivate::updateContentsRect()
7750{
7751 Q_Q(QWidget);
7752
7753 if (layout)
7754 layout->update(); //force activate; will do updateGeometry
7755 else
7756 q->updateGeometry();
7757
7758 if (q->isVisible()) {
7759 q->update();
7760 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7761 QCoreApplication::sendEvent(q, &e);
7762 } else {
7763 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7764 }
7765
7766 QEvent e(QEvent::ContentsRectChange);
7767 QCoreApplication::sendEvent(q, &e);
7768}
7769
7770/*!
7771 \since 4.6
7772
7773 \brief The contentsMargins function returns the widget's contents margins.
7774
7775 \sa setContentsMargins(), contentsRect()
7776 */
7777QMargins QWidget::contentsMargins() const
7778{
7779 Q_D(const QWidget);
7780 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7781 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7782 userMargins | d->safeAreaMargins() : userMargins;
7783}
7784
7785/*!
7786 Returns the area inside the widget's margins.
7787
7788 \sa setContentsMargins(), contentsMargins()
7789*/
7790QRect QWidget::contentsRect() const
7791{
7792 return rect() - contentsMargins();
7793}
7794
7795QMargins QWidgetPrivate::safeAreaMargins() const
7796{
7797 Q_Q(const QWidget);
7798
7799#if QT_CONFIG(graphicsview)
7800 // Don't report margins for proxied widgets, as the logic
7801 // below doesn't handle that case (yet).
7802 if (nearestGraphicsProxyWidget(q))
7803 return QMargins();
7804#endif
7805
7806 QWidget *nativeWidget = q->window();
7807 if (!nativeWidget->windowHandle())
7808 return QMargins();
7809
7810 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7811
7812 if (!q->isWindow()) {
7813 // In theory the native parent widget already has a contents rect reflecting
7814 // the safe area of that widget, but we can't be sure that the widget or child
7815 // widgets of that widget have respected the contents rect when setting their
7816 // geometry, so we need to manually compute the safe area.
7817
7818 // Unless the native widget doesn't have any margins, in which case there's
7819 // nothing for us to compute.
7820 if (safeAreaMargins.isNull())
7821 return QMargins();
7822
7823 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7824 // set, and the widget respects the safe area, then we know that the layout has already
7825 // taken care of placing us inside the safe area, by taking the contents rect of its
7826 // parent widget into account.
7827 const QWidget *assumedSafeWidget = nullptr;
7828 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7829 QWidget *parentWidget = w->parentWidget();
7830 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7831 continue; // Layout can't help us
7832
7833 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7834 continue; // Layout not going to help us
7835
7836 QLayout *layout = parentWidget->layout();
7837 if (!layout)
7838 continue;
7839
7840 if (layout->geometry().isNull())
7841 continue; // Layout hasn't been activated yet
7842
7843 if (layout->indexOf(w) < 0)
7844 continue; // Widget is not in layout
7845
7846 assumedSafeWidget = w;
7847 break;
7848 }
7849
7850#if !defined(QT_DEBUG)
7851 if (assumedSafeWidget) {
7852 // We found a layout that we assume will take care of keeping us within the safe area
7853 // For debug builds we still map the safe area using the fallback logic, so that we
7854 // can detect any misbehaving layouts.
7855 return QMargins();
7856 }
7857#endif
7858
7859 // In all other cases we need to map the safe area of the native parent to the widget.
7860 // This depends on the widget being positioned and sized already, which means the initial
7861 // layout will be wrong, but the layout will then adjust itself.
7862 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7863 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7864 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7865 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7866
7867 // Margins should never be negative
7868 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7869 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7870
7871 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7872 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7873 qWarning() << layout << "is laying out" << assumedSafeWidget
7874 << "outside of the contents rect of" << layout->parentWidget();
7875 return QMargins(); // Return empty margin to visually highlight the error
7876 }
7877 }
7878
7879 return safeAreaMargins;
7880}
7881
7882/*!
7883 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7884
7885 This signal is emitted when the widget's \l contextMenuPolicy is
7886 Qt::CustomContextMenu, and the user has requested a context menu on
7887 the widget. The position \a pos is the position of the context menu
7888 event that the widget receives. Normally this is in widget
7889 coordinates. The exception to this rule is QAbstractScrollArea and
7890 its subclasses that map the context menu event to coordinates of the
7891 \l{QAbstractScrollArea::viewport()}{viewport()}.
7892
7893
7894 \sa mapToGlobal(), QMenu, contextMenuPolicy
7895*/
7896
7897
7898/*!
7899 \property QWidget::contextMenuPolicy
7900 \brief how the widget shows a context menu
7901
7902 The default value of this property is Qt::DefaultContextMenu,
7903 which means the contextMenuEvent() handler is called. Other values
7904 are Qt::NoContextMenu, Qt::PreventContextMenu,
7905 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7906 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7907 emitted.
7908
7909 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7910*/
7911
7912Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7913{
7914 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7915}
7916
7917void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7918{
7919 data->context_menu_policy = (uint) policy;
7920}
7921
7922/*!
7923 \property QWidget::focusPolicy
7924 \brief the way the widget accepts keyboard focus
7925
7926 The policy is Qt::TabFocus if the widget accepts keyboard
7927 focus by tabbing, Qt::ClickFocus if the widget accepts
7928 focus by clicking, Qt::StrongFocus if it accepts both, and
7929 Qt::NoFocus (the default) if it does not accept focus at
7930 all.
7931
7932 You must enable keyboard focus for a widget if it processes
7933 keyboard events. This is normally done from the widget's
7934 constructor. For instance, the QLineEdit constructor calls
7935 setFocusPolicy(Qt::StrongFocus).
7936
7937 If the widget has a focus proxy, then the focus policy will
7938 be propagated to it.
7939
7940 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7941*/
7942
7943
7944Qt::FocusPolicy QWidget::focusPolicy() const
7945{
7946 return (Qt::FocusPolicy)data->focus_policy;
7947}
7948
7949void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7950{
7951 data->focus_policy = (uint) policy;
7952 Q_D(QWidget);
7953 if (d->extra && d->extra->focus_proxy)
7954 d->extra->focus_proxy->setFocusPolicy(policy);
7955}
7956
7957/*!
7958 \property QWidget::updatesEnabled
7959 \brief whether updates are enabled
7960
7961 An updates enabled widget receives paint events and has a system
7962 background; a disabled widget does not. This also implies that
7963 calling update() and repaint() has no effect if updates are
7964 disabled.
7965
7966 By default, this property is \c true.
7967
7968 setUpdatesEnabled() is normally used to disable updates for a
7969 short period of time, for instance to avoid screen flicker during
7970 large changes. In Qt, widgets normally do not generate screen
7971 flicker, but on X11 the server might erase regions on the screen
7972 when widgets get hidden before they can be replaced by other
7973 widgets. Disabling updates solves this.
7974
7975 Example:
7976 \snippet code/src_gui_kernel_qwidget.cpp 13
7977
7978 Disabling a widget implicitly disables all its children. Enabling a widget
7979 enables all child widgets \e except top-level widgets or those that
7980 have been explicitly disabled. Re-enabling updates implicitly calls
7981 update() on the widget.
7982
7983 \sa paintEvent()
7984*/
7985void QWidget::setUpdatesEnabled(bool enable)
7986{
7987 Q_D(QWidget);
7988 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7989 d->setUpdatesEnabled_helper(enable);
7990}
7991
7992/*!
7993 Shows the widget and its child widgets.
7994
7995 For child windows, this is equivalent to calling setVisible(true).
7996 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7997 or setVisible(true), depending on the platform's default behavior for the window flags.
7998
7999 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
8000 showNormal(), isVisible(), windowFlags()
8001*/
8002void QWidget::show()
8003{
8004 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
8005
8006 if (!isWindow()) {
8007 setVisible(true);
8008 } else {
8009 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
8010 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
8011 if (defaultState == Qt::WindowFullScreen)
8012 showFullScreen();
8013 else if (defaultState == Qt::WindowMaximized)
8014 showMaximized();
8015 else
8016 setVisible(true);
8017 }
8018}
8019
8020/*! \internal
8021
8022 Makes the widget visible in the isVisible() meaning of the word.
8023 It is only called for toplevels or widgets with visible parents.
8024 */
8025void QWidgetPrivate::show_recursive()
8026{
8027 Q_Q(QWidget);
8028 // polish if necessary
8029
8030 if (!q->testAttribute(Qt::WA_WState_Created))
8031 createRecursively();
8032 q->ensurePolished();
8033
8034 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
8035 q->parentWidget()->d_func()->layout->activate();
8036 // activate our layout before we and our children become visible
8037 if (layout)
8038 layout->activate();
8039
8040 show_helper();
8041}
8042
8043void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
8044{
8045 Q_Q(QWidget);
8046
8047 disableUpdates = disableUpdates && q->updatesEnabled();
8048 if (disableUpdates)
8049 q->setAttribute(Qt::WA_UpdatesDisabled);
8050
8051 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
8052 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
8053 QCoreApplication::sendEvent(q, &e);
8054 q->setAttribute(Qt::WA_PendingMoveEvent, false);
8055 }
8056
8057 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
8058 QResizeEvent e(data.crect.size(), QSize());
8059 QCoreApplication::sendEvent(q, &e);
8060 q->setAttribute(Qt::WA_PendingResizeEvent, false);
8061 }
8062
8063 if (disableUpdates)
8064 q->setAttribute(Qt::WA_UpdatesDisabled, false);
8065
8066 if (!recursive)
8067 return;
8068
8069 for (int i = 0; i < children.size(); ++i) {
8070 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8071 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8072 }
8073}
8074
8075void QWidgetPrivate::activateChildLayoutsRecursively()
8076{
8077 sendPendingMoveAndResizeEvents(false, true);
8078
8079 for (int i = 0; i < children.size(); ++i) {
8080 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8081 if (!child || child->isHidden() || child->isWindow())
8082 continue;
8083
8084 child->ensurePolished();
8085
8086 // Activate child's layout
8087 QWidgetPrivate *childPrivate = child->d_func();
8088 if (childPrivate->layout)
8089 childPrivate->layout->activate();
8090
8091 // Pretend we're visible.
8092 const bool wasVisible = child->isVisible();
8093 if (!wasVisible)
8094 child->setAttribute(Qt::WA_WState_Visible);
8095
8096 // Do the same for all my children.
8097 childPrivate->activateChildLayoutsRecursively();
8098
8099 // We're not cheating anymore.
8100 if (!wasVisible)
8101 child->setAttribute(Qt::WA_WState_Visible, false);
8102 }
8103}
8104
8105void QWidgetPrivate::show_helper()
8106{
8107 Q_Q(QWidget);
8108 data.in_show = true; // qws optimization
8109 // make sure we receive pending move and resize events
8110 sendPendingMoveAndResizeEvents();
8111
8112 // become visible before showing all children
8113 q->setAttribute(Qt::WA_WState_Visible);
8114
8115 // finally show all children recursively
8116 showChildren(false);
8117
8118
8119
8120 const bool isWindow = q->isWindow();
8121#if QT_CONFIG(graphicsview)
8122 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8123#else
8124 bool isEmbedded = false;
8125#endif
8126
8127 // popup handling: new popups and tools need to be raised, and
8128 // existing popups must be closed. Also propagate the current
8129 // windows's KeyboardFocusChange status.
8130 if (isWindow && !isEmbedded) {
8131 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8132 q->raise();
8133 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8134 q->setAttribute(Qt::WA_KeyboardFocusChange);
8135 } else {
8136 while (QApplication::activePopupWidget()) {
8137 if (!QApplication::activePopupWidget()->close())
8138 break;
8139 }
8140 }
8141 }
8142
8143 // Automatic embedding of child windows of widgets already embedded into
8144 // QGraphicsProxyWidget when they are shown the first time.
8145#if QT_CONFIG(graphicsview)
8146 if (isWindow) {
8147 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8148 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8149 if (ancestorProxy) {
8150 isEmbedded = true;
8151 ancestorProxy->d_func()->embedSubWindow(q);
8152 }
8153 }
8154 }
8155#else
8156 Q_UNUSED(isEmbedded);
8157#endif
8158
8159 // send the show event before showing the window
8160 QShowEvent showEvent;
8161 QCoreApplication::sendEvent(q, &showEvent);
8162
8163 show_sys();
8164
8165 if (!isEmbedded && q->windowType() == Qt::Popup)
8166 qApp->d_func()->openPopup(q);
8167
8168#if QT_CONFIG(accessibility)
8169 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8170 QAccessibleEvent event(q, QAccessible::ObjectShow);
8171 QAccessible::updateAccessibility(&event);
8172 }
8173#endif
8174
8175 if (QApplicationPrivate::hidden_focus_widget == q) {
8176 QApplicationPrivate::hidden_focus_widget = nullptr;
8177 q->setFocus(Qt::OtherFocusReason);
8178 }
8179
8180 // Process events when showing a Qt::SplashScreen widget before the event loop
8181 // is spinnning; otherwise it might not show up on particular platforms.
8182 // This makes QSplashScreen behave the same on all platforms.
8183 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8184 QCoreApplication::processEvents();
8185
8186 data.in_show = false; // reset qws optimization
8187}
8188
8189void QWidgetPrivate::show_sys()
8190{
8191 Q_Q(QWidget);
8192
8193 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8194
8195 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8196 invalidateBackingStore(q->rect());
8197 q->setAttribute(Qt::WA_Mapped);
8198 // add our window the modal window list (native dialogs)
8199 if (window && q->isWindow()
8200#if QT_CONFIG(graphicsview)
8201 && (!extra || !extra->proxyWidget)
8202#endif
8203 && q->windowModality() != Qt::NonModal) {
8204 QGuiApplicationPrivate::showModalWindow(window);
8205 }
8206 return;
8207 }
8208
8209 if (renderToTexture && !q->isWindow())
8210 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8211 else
8212 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8213
8214 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8215 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8216 return;
8217 }
8218
8219 if (window) {
8220 if (q->isWindow())
8221 fixPosIncludesFrame();
8222 QRect geomRect = q->geometry();
8223 if (!q->isWindow()) {
8224 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8225 geomRect.moveTopLeft(topLeftOfWindow);
8226 }
8227 const QRect windowRect = window->geometry();
8228 if (windowRect != geomRect) {
8229 if (q->testAttribute(Qt::WA_Moved)
8230 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8231 window->setGeometry(geomRect);
8232 else
8233 window->resize(geomRect.size());
8234 }
8235
8236#ifndef QT_NO_CURSOR
8237 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8238#endif
8239 invalidateBackingStore(q->rect());
8240 window->setNativeWindowVisibility(true);
8241 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8242 if (window->isTopLevel()) {
8243 const QPoint crectTopLeft = q->data->crect.topLeft();
8244 const QPoint windowTopLeft = window->geometry().topLeft();
8245 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8246 q->data->crect.moveTopLeft(windowTopLeft);
8247 }
8248 }
8249}
8250
8251/*!
8252 Hides the widget. This function is equivalent to
8253 setVisible(false).
8254
8255
8256 \note If you are working with QDialog or its subclasses and you invoke
8257 the show() function after this function, the dialog will be displayed in
8258 its original position.
8259
8260 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8261*/
8262void QWidget::hide()
8263{
8264 setVisible(false);
8265}
8266
8267/*!\internal
8268 */
8269void QWidgetPrivate::hide_helper()
8270{
8271 Q_Q(QWidget);
8272
8273 bool isEmbedded = false;
8274#if QT_CONFIG(graphicsview)
8275 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8276#else
8277 Q_UNUSED(isEmbedded);
8278#endif
8279
8280 if (!isEmbedded && (q->windowType() == Qt::Popup))
8281 qApp->d_func()->closePopup(q);
8282
8283 q->setAttribute(Qt::WA_Mapped, false);
8284 hide_sys();
8285
8286 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8287
8288 if (wasVisible) {
8289 q->setAttribute(Qt::WA_WState_Visible, false);
8290
8291 }
8292
8293 QHideEvent hideEvent;
8294 QCoreApplication::sendEvent(q, &hideEvent);
8295 hideChildren(false);
8296
8297 // next bit tries to move the focus if the focus widget is now
8298 // hidden.
8299 if (wasVisible) {
8300 qApp->d_func()->sendSyntheticEnterLeave(q);
8301 QWidget *fw = QApplication::focusWidget();
8302 while (fw && !fw->isWindow()) {
8303 if (fw == q) {
8304 q->focusNextPrevChild(true);
8305 break;
8306 }
8307 fw = fw->parentWidget();
8308 }
8309 }
8310
8311 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8312 repaintManager->removeDirtyWidget(q);
8313
8314#if QT_CONFIG(accessibility)
8315 if (wasVisible) {
8316 QAccessibleEvent event(q, QAccessible::ObjectHide);
8317 QAccessible::updateAccessibility(&event);
8318 }
8319#endif
8320}
8321
8322void QWidgetPrivate::hide_sys()
8323{
8324 Q_Q(QWidget);
8325
8326 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8327
8328 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8329 q->setAttribute(Qt::WA_Mapped, false);
8330 // remove our window from the modal window list (native dialogs)
8331 if (window && q->isWindow()
8332#if QT_CONFIG(graphicsview)
8333 && (!extra || !extra->proxyWidget)
8334#endif
8335 && q->windowModality() != Qt::NonModal) {
8336 QGuiApplicationPrivate::hideModalWindow(window);
8337 }
8338 // do not return here, if window non-zero, we must hide it
8339 }
8340
8341 deactivateWidgetCleanup();
8342
8343 if (!q->isWindow()) {
8344 QWidget *p = q->parentWidget();
8345 if (p &&p->isVisible()) {
8346 if (renderToTexture)
8347 p->d_func()->invalidateBackingStore(q->geometry());
8348 else
8349 invalidateBackingStore(q->rect());
8350 }
8351 } else {
8352 invalidateBackingStore(q->rect());
8353 }
8354
8355 if (window)
8356 window->setNativeWindowVisibility(false);
8357}
8358
8359/*!
8360 \fn bool QWidget::isHidden() const
8361
8362 Returns \c true if the widget is hidden, otherwise returns \c false.
8363
8364 A hidden widget will only become visible when show() is called on
8365 it. It will not be automatically shown when the parent is shown.
8366
8367 To check visibility, use !isVisible() instead (notice the exclamation mark).
8368
8369 isHidden() implies !isVisible(), but a widget can be not visible
8370 and not hidden at the same time. This is the case for widgets that are children of
8371 widgets that are not visible.
8372
8373
8374 Widgets are hidden if:
8375 \list
8376 \li they were created as independent windows,
8377 \li they were created as children of visible widgets,
8378 \li hide() or setVisible(false) was called.
8379 \endlist
8380*/
8381
8382void QWidget::setVisible(bool visible)
8383{
8384 Q_D(QWidget);
8385 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8386 << "with attributes" << WidgetAttributes{this}
8387 << "to" << visible << "via QWidget";
8388
8389 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8390 return;
8391
8392 if (d->dontSetExplicitShowHide) {
8393 d->dontSetExplicitShowHide = false;
8394 } else {
8395 // Remember that setVisible was called explicitly
8396 setAttribute(Qt::WA_WState_ExplicitShowHide);
8397 }
8398
8399 d->setVisible(visible);
8400}
8401
8402// This method is called from QWidgetWindow in response to QWindow::setVisible,
8403// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8404// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8405void QWidgetPrivate::setVisible(bool visible)
8406{
8407 Q_Q(QWidget);
8408 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8409 << "with attributes" << WidgetAttributes{q}
8410 << "to" << visible << "via QWidgetPrivate";
8411
8412 if (visible) { // show
8413 // Designer uses a trick to make grabWidget work without showing
8414 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8415 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8416 q->parentWidget()->window()->d_func()->createRecursively();
8417
8418 //create toplevels but not children of non-visible parents
8419 QWidget *pw = q->parentWidget();
8420 if (!q->testAttribute(Qt::WA_WState_Created)
8421 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8422 q->create();
8423 }
8424
8425 bool wasResized = q->testAttribute(Qt::WA_Resized);
8426 Qt::WindowStates initialWindowState = q->windowState();
8427
8428 // polish if necessary
8429 q->ensurePolished();
8430
8431 // whether we need to inform the parent widget immediately
8432 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8433 // we are no longer hidden
8434 q->setAttribute(Qt::WA_WState_Hidden, false);
8435
8436 if (needUpdateGeometry)
8437 updateGeometry_helper(true);
8438
8439 // activate our layout before we and our children become visible
8440 if (layout)
8441 layout->activate();
8442
8443 if (!q->isWindow()) {
8444 QWidget *parent = q->parentWidget();
8445 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8446 parent->d_func()->layout->activate();
8447 if (parent->isWindow())
8448 break;
8449 parent = parent->parentWidget();
8450 }
8451 if (parent)
8452 parent->d_func()->setDirtyOpaqueRegion();
8453 }
8454
8455 // adjust size if necessary
8456 if (!wasResized
8457 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8458 if (q->isWindow()) {
8459 q->adjustSize();
8460 if (q->windowState() != initialWindowState)
8461 q->setWindowState(initialWindowState);
8462 } else {
8463 q->adjustSize();
8464 }
8465 q->setAttribute(Qt::WA_Resized, false);
8466 }
8467
8468 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8469
8470 if (q->isWindow() || q->parentWidget()->isVisible()) {
8471 show_helper();
8472
8473 qApp->d_func()->sendSyntheticEnterLeave(q);
8474 }
8475
8476 QEvent showToParentEvent(QEvent::ShowToParent);
8477 QCoreApplication::sendEvent(q, &showToParentEvent);
8478 } else { // hide
8479 if (QApplicationPrivate::hidden_focus_widget == q)
8480 QApplicationPrivate::hidden_focus_widget = nullptr;
8481
8482 // hw: The test on getOpaqueRegion() needs to be more intelligent
8483 // currently it doesn't work if the widget is hidden (the region will
8484 // be clipped). The real check should be testing the cached region
8485 // (and dirty flag) directly.
8486 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8487 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8488
8489 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8490 q->setAttribute(Qt::WA_WState_Hidden);
8491 hide_helper();
8492 }
8493
8494 // invalidate layout similar to updateGeometry()
8495 if (!q->isWindow() && q->parentWidget()) {
8496 if (q->parentWidget()->d_func()->layout)
8497 q->parentWidget()->d_func()->layout->invalidate();
8498 else if (q->parentWidget()->isVisible())
8499 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8500 }
8501
8502 QEvent hideToParentEvent(QEvent::HideToParent);
8503 QCoreApplication::sendEvent(q, &hideToParentEvent);
8504 }
8505}
8506
8507/*!
8508 Convenience function, equivalent to setVisible(!\a hidden).
8509*/
8510void QWidget::setHidden(bool hidden)
8511{
8512 setVisible(!hidden);
8513}
8514
8515bool QWidgetPrivate::isExplicitlyHidden() const
8516{
8517 Q_Q(const QWidget);
8518 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8519}
8520
8521void QWidgetPrivate::_q_showIfNotHidden()
8522{
8523 Q_Q(QWidget);
8524 if (!isExplicitlyHidden())
8525 q->setVisible(true);
8526}
8527
8528void QWidgetPrivate::showChildren(bool spontaneous)
8529{
8530 Q_Q(QWidget);
8531 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8532 << "spontaneously" << spontaneous;
8533
8534 QList<QObject*> childList = children;
8535 for (int i = 0; i < childList.size(); ++i) {
8536 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8537 if (!widget)
8538 continue;
8539 qCDebug(lcWidgetShowHide) << "Considering" << widget
8540 << "with attributes" << WidgetAttributes{widget};
8541 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8542 widget->setAttribute(Qt::WA_WState_Hidden, false);
8543 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8544 continue;
8545 if (spontaneous) {
8546 widget->setAttribute(Qt::WA_Mapped);
8547 widget->d_func()->showChildren(true);
8548 QShowEvent e;
8549 QApplication::sendSpontaneousEvent(widget, &e);
8550 } else {
8551 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8552 widget->d_func()->show_recursive();
8553 } else {
8554 // Call QWidget::setVisible() here, so that subclasses
8555 // that (wrongly) override setVisible to do initialization
8556 // will still be notified that they are made visible, but
8557 // do so without triggering ExplicitShowHide.
8558 widget->d_func()->dontSetExplicitShowHide = true;
8559 widget->setVisible(true);
8560 widget->d_func()->dontSetExplicitShowHide = false;
8561 }
8562 }
8563 }
8564}
8565
8566void QWidgetPrivate::hideChildren(bool spontaneous)
8567{
8568 Q_Q(QWidget);
8569 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8570 << "spontaneously" << spontaneous;
8571
8572 QList<QObject*> childList = children;
8573 for (int i = 0; i < childList.size(); ++i) {
8574 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8575 if (!widget)
8576 continue;
8577 qCDebug(lcWidgetShowHide) << "Considering" << widget
8578 << "with attributes" << WidgetAttributes{widget};
8579 if (widget->isWindow() || !widget->isVisible())
8580 continue;
8581
8582 if (spontaneous)
8583 widget->setAttribute(Qt::WA_Mapped, false);
8584 else
8585 widget->setAttribute(Qt::WA_WState_Visible, false);
8586 widget->d_func()->hideChildren(spontaneous);
8587 QHideEvent e;
8588 if (spontaneous) {
8589 QApplication::sendSpontaneousEvent(widget, &e);
8590 } else {
8591 QCoreApplication::sendEvent(widget, &e);
8592 if (widget->internalWinId()
8593 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8594 // hide_sys() on an ancestor won't have any affect on this
8595 // widget, so it needs an explicit hide_sys() of its own
8596 widget->d_func()->hide_sys();
8597 }
8598 }
8599 qApp->d_func()->sendSyntheticEnterLeave(widget);
8600#if QT_CONFIG(accessibility)
8601 if (!spontaneous) {
8602 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8603 QAccessible::updateAccessibility(&event);
8604 }
8605#endif
8606 }
8607
8608 // If the window of this widget is not closed, then the leave event
8609 // will eventually handle the widget under mouse use case.
8610 // Otherwise, we need to explicitly handle it here.
8611 if (QWidget* widgetWindow = q->window();
8612 widgetWindow && widgetWindow->data->is_closing) {
8613 q->setAttribute(Qt::WA_UnderMouse, false);
8614 }
8615}
8616
8617/*!
8618 \internal
8619
8620 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8621 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8622 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8623 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8624 system (i.e. the user clicked the close button in the title bar).
8625
8626 QDialog calls this method directly in its hide() implementation, which might be
8627 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8628 to prevent recursion.
8629
8630 For non-windows, this is called directly by QWidget::close, and \a mode will be
8631 CloseWithEvent.
8632
8633 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8634*/
8635bool QWidgetPrivate::handleClose(CloseMode mode)
8636{
8637 Q_Q(QWidget);
8638 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8639
8640 if (data.is_closing)
8641 return true;
8642
8643 // We might not have initiated the close, so update the state now that we know
8644 data.is_closing = true;
8645
8646 QPointer<QWidget> that = q;
8647
8648 if (data.in_destructor)
8649 mode = CloseNoEvent;
8650
8651 if (mode != CloseNoEvent) {
8652 QCloseEvent e;
8653 if (mode == CloseWithSpontaneousEvent)
8654 QApplication::sendSpontaneousEvent(q, &e);
8655 else
8656 QCoreApplication::sendEvent(q, &e);
8657 if (!that.isNull() && !e.isAccepted()) {
8658 data.is_closing = false;
8659 return false;
8660 }
8661 }
8662
8663 // even for windows, make sure we deliver a hide event and that all children get hidden
8664 if (!that.isNull() && !q->isHidden())
8665 q->hide();
8666
8667 if (!that.isNull()) {
8668 data.is_closing = false;
8669 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8670 q->setAttribute(Qt::WA_DeleteOnClose, false);
8671 q->deleteLater();
8672 }
8673 }
8674 return true;
8675}
8676
8677
8678/*!
8679 Closes this widget. Returns \c true if the widget was closed;
8680 otherwise returns \c false.
8681
8682 First it sends the widget a QCloseEvent. The widget is
8683 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8684 the close event. If it \l{QEvent::ignore()}{ignores}
8685 the event, nothing happens. The default
8686 implementation of QWidget::closeEvent() accepts the close event.
8687
8688 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8689 is also deleted. A close events is delivered to the widget no
8690 matter if the widget is visible or not.
8691
8692 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8693 last visible primary window (i.e. window with no parent) with the
8694 Qt::WA_QuitOnClose attribute set is closed. By default this
8695 attribute is set for all widgets except transient windows such as
8696 splash screens, tool windows, and popup menus.
8697
8698*/
8699
8700bool QWidget::close()
8701{
8702 return d_func()->close();
8703}
8704
8705bool QWidgetPrivate::close()
8706{
8707 // FIXME: We're not setting is_closing here, even though that would
8708 // make sense, as the code below will not end up in handleClose to
8709 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8710 // and we can't assume close is synchronous so we can't reset it here.
8711
8712 // Close native widgets via QWindow::close() in order to run QWindow
8713 // close code. The QWidget-specific close code in handleClose() will
8714 // in this case be called from the Close event handler in QWidgetWindow.
8715 if (QWindow *widgetWindow = windowHandle()) {
8716 if (widgetWindow->isTopLevel())
8717 return widgetWindow->close();
8718 }
8719
8720 return handleClose(QWidgetPrivate::CloseWithEvent);
8721}
8722
8723/*!
8724 \property QWidget::visible
8725 \brief whether the widget is visible
8726
8727 Calling setVisible(true) or show() sets the widget to visible
8728 status if all its parent widgets up to the window are visible. If
8729 an ancestor is not visible, the widget won't become visible until
8730 all its ancestors are shown. If its size or position has changed,
8731 Qt guarantees that a widget gets move and resize events just
8732 before it is shown. If the widget has not been resized yet, Qt
8733 will adjust the widget's size to a useful default using
8734 adjustSize().
8735
8736 Calling setVisible(false) or hide() hides a widget explicitly. An
8737 explicitly hidden widget will never become visible, even if all
8738 its ancestors become visible, unless you show it.
8739
8740 A widget receives show and hide events when its visibility status
8741 changes. Between a hide and a show event, there is no need to
8742 waste CPU cycles preparing or displaying information to the user.
8743 A video application, for example, might simply stop generating new
8744 frames.
8745
8746 A widget that happens to be obscured by other windows on the
8747 screen is considered to be visible. The same applies to iconified
8748 windows and windows that exist on another virtual
8749 desktop (on platforms that support this concept). A widget
8750 receives spontaneous show and hide events when its mapping status
8751 is changed by the window system, e.g. a spontaneous hide event
8752 when the user minimizes the window, and a spontaneous show event
8753 when the window is restored again.
8754
8755 You seldom have to reimplement the setVisible() function. If
8756 you need to change some settings before a widget is shown, use
8757 showEvent() instead. If you need to do some delayed initialization
8758 use the Polish event delivered to the event() function.
8759
8760 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8761 showEvent(), hideEvent()
8762*/
8763
8764
8765/*!
8766 Returns \c true if this widget would become visible if \a ancestor is
8767 shown; otherwise returns \c false.
8768
8769 The true case occurs if neither the widget itself nor any parent
8770 up to but excluding \a ancestor has been explicitly hidden.
8771
8772 This function will still return true if the widget is obscured by
8773 other windows on the screen, but could be physically visible if it
8774 or they were to be moved.
8775
8776 isVisibleTo(0) is identical to isVisible().
8777
8778 \sa show(), hide(), isVisible()
8779*/
8780
8781bool QWidget::isVisibleTo(const QWidget *ancestor) const
8782{
8783 if (!ancestor)
8784 return isVisible();
8785 const QWidget * w = this;
8786 while (!w->isHidden()
8787 && !w->isWindow()
8788 && w->parentWidget()
8789 && w->parentWidget() != ancestor)
8790 w = w->parentWidget();
8791 return !w->isHidden();
8792}
8793
8794
8795/*!
8796 Returns the unobscured region where paint events can occur.
8797
8798 For visible widgets, this is an approximation of the area not
8799 covered by other widgets; otherwise, this is an empty region.
8800
8801 The repaint() function calls this function if necessary, so in
8802 general you do not need to call it.
8803
8804*/
8805QRegion QWidget::visibleRegion() const
8806{
8807 Q_D(const QWidget);
8808
8809 QRect clipRect = d->clipRect();
8810 if (clipRect.isEmpty())
8811 return QRegion();
8812 QRegion r(clipRect);
8813 d->subtractOpaqueChildren(r, clipRect);
8814 d->subtractOpaqueSiblings(r);
8815 return r;
8816}
8817
8818
8819QSize QWidgetPrivate::adjustedSize() const
8820{
8821 Q_Q(const QWidget);
8822
8823 QSize s = q->sizeHint();
8824
8825 if (q->isWindow()) {
8826 Qt::Orientations exp;
8827 if (layout) {
8828 if (layout->hasHeightForWidth())
8829 s.setHeight(layout->totalHeightForWidth(s.width()));
8830 exp = layout->expandingDirections();
8831 } else
8832 {
8833 if (q->sizePolicy().hasHeightForWidth())
8834 s.setHeight(q->heightForWidth(s.width()));
8835 exp = q->sizePolicy().expandingDirections();
8836 }
8837 if (exp & Qt::Horizontal)
8838 s.setWidth(qMax(s.width(), 200));
8839 if (exp & Qt::Vertical)
8840 s.setHeight(qMax(s.height(), 100));
8841
8842 QRect screen;
8843 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8844 screen = screenAtPoint->geometry();
8845 else
8846 screen = QGuiApplication::primaryScreen()->geometry();
8847
8848 s.setWidth(qMin(s.width(), screen.width()*2/3));
8849 s.setHeight(qMin(s.height(), screen.height()*2/3));
8850
8851 if (QTLWExtra *extra = maybeTopData())
8852 extra->sizeAdjusted = true;
8853 }
8854
8855 if (!s.isValid()) {
8856 QRect r = q->childrenRect(); // get children rectangle
8857 if (r.isNull())
8858 return s;
8859 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8860 }
8861
8862 return s;
8863}
8864
8865/*!
8866 Adjusts the size of the widget to fit its contents.
8867
8868 This function uses sizeHint() if it is valid, i.e., the size hint's width
8869 and height are >= 0. Otherwise, it sets the size to the children
8870 rectangle that covers all child widgets (the union of all child widget
8871 rectangles).
8872
8873 For windows, the screen size is also taken into account. If the sizeHint()
8874 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8875 {expanding}, the window will be at least (200, 100). The maximum size of
8876 a window is 2/3 of the screen's width and height.
8877
8878 \sa sizeHint(), childrenRect()
8879*/
8880
8881void QWidget::adjustSize()
8882{
8883 Q_D(QWidget);
8884 ensurePolished();
8885 QSize s = d->adjustedSize();
8886
8887 if (d->layout)
8888 d->layout->activate();
8889
8890 if (s.isValid())
8891 resize(s);
8892}
8893
8894
8895/*!
8896 \property QWidget::sizeHint
8897 \brief the recommended size for the widget
8898
8899 If the value of this property is an invalid size, no size is
8900 recommended.
8901
8902 The default implementation of sizeHint() returns an invalid size
8903 if there is no layout for this widget, and returns the layout's
8904 preferred size otherwise.
8905
8906 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8907 setMinimumSize(), updateGeometry()
8908*/
8909
8910QSize QWidget::sizeHint() const
8911{
8912 Q_D(const QWidget);
8913 if (d->layout)
8914 return d->layout->totalSizeHint();
8915 return QSize(-1, -1);
8916}
8917
8918/*!
8919 \property QWidget::minimumSizeHint
8920 \brief the recommended minimum size for the widget
8921
8922 If the value of this property is an invalid size, no minimum size
8923 is recommended.
8924
8925 The default implementation of minimumSizeHint() returns an invalid
8926 size if there is no layout for this widget, and returns the
8927 layout's minimum size otherwise. Most built-in widgets reimplement
8928 minimumSizeHint().
8929
8930 \l QLayout will never resize a widget to a size smaller than the
8931 minimum size hint unless minimumSize() is set or the size policy is
8932 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8933 size hint will be ignored.
8934
8935 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8936*/
8937QSize QWidget::minimumSizeHint() const
8938{
8939 Q_D(const QWidget);
8940 if (d->layout)
8941 return d->layout->totalMinimumSize();
8942 return QSize(-1, -1);
8943}
8944
8945
8946/*!
8947 \fn QWidget *QWidget::parentWidget() const
8948
8949 Returns the parent of this widget, or \nullptr if it does not have any
8950 parent widget.
8951*/
8952
8953
8954/*!
8955 Returns \c true if this widget is a parent, (or grandparent and so on
8956 to any level), of the given \a child, and both widgets are within
8957 the same window; otherwise returns \c false.
8958*/
8959
8960bool QWidget::isAncestorOf(const QWidget *child) const
8961{
8962 while (child) {
8963 if (child == this)
8964 return true;
8965 if (child->isWindow())
8966 return false;
8967 child = child->parentWidget();
8968 }
8969 return false;
8970}
8971
8972/*****************************************************************************
8973 QWidget event handling
8974 *****************************************************************************/
8975
8976/*!
8977 This is the main event handler; it handles event \a event. You can
8978 reimplement this function in a subclass, but we recommend using
8979 one of the specialized event handlers instead.
8980
8981 Key press and release events are treated differently from other
8982 events. event() checks for Tab and Shift+Tab and tries to move the
8983 focus appropriately. If there is no widget to move the focus to
8984 (or the key press is not Tab or Shift+Tab), event() calls
8985 keyPressEvent().
8986
8987 Mouse and tablet event handling is also slightly special: only
8988 when the widget is \l enabled, event() will call the specialized
8989 handlers such as mousePressEvent(); otherwise it will discard the
8990 event.
8991
8992 This function returns \c true if the event was recognized, otherwise
8993 it returns \c false. If the recognized event was accepted (see \l
8994 QEvent::accepted), any further processing such as event
8995 propagation to the parent widget stops.
8996
8997 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8998 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8999 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
9000 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
9001 QObject::event(), QObject::timerEvent()
9002*/
9003
9004bool QWidget::event(QEvent *event)
9005{
9006 Q_D(QWidget);
9007
9008 // ignore mouse and key events when disabled
9009 if (!isEnabled()) {
9010 switch(event->type()) {
9011 case QEvent::TabletPress:
9012 case QEvent::TabletRelease:
9013 case QEvent::TabletMove:
9014 case QEvent::MouseButtonPress:
9015 case QEvent::MouseButtonRelease:
9016 case QEvent::MouseButtonDblClick:
9017 case QEvent::MouseMove:
9018 case QEvent::TouchBegin:
9019 case QEvent::TouchUpdate:
9020 case QEvent::TouchEnd:
9021 case QEvent::TouchCancel:
9022 case QEvent::ContextMenu:
9023 case QEvent::KeyPress:
9024 case QEvent::KeyRelease:
9025#if QT_CONFIG(wheelevent)
9026 case QEvent::Wheel:
9027#endif
9028 return false;
9029 default:
9030 break;
9031 }
9032 }
9033 switch (event->type()) {
9034 case QEvent::PlatformSurface: {
9035 // Sync up QWidget's view of whether or not the widget has been created
9036 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
9037 case QPlatformSurfaceEvent::SurfaceCreated:
9038 if (!testAttribute(Qt::WA_WState_Created))
9039 create();
9040 break;
9041 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
9042 if (testAttribute(Qt::WA_WState_Created)) {
9043 // Child windows have already been destroyed by QWindow,
9044 // so we skip them here.
9045 destroy(false, false);
9046 }
9047 break;
9048 }
9049 break;
9050 }
9051 case QEvent::MouseMove:
9052 mouseMoveEvent((QMouseEvent*)event);
9053 break;
9054
9055 case QEvent::MouseButtonPress:
9056 mousePressEvent((QMouseEvent*)event);
9057 break;
9058
9059 case QEvent::MouseButtonRelease:
9060 mouseReleaseEvent((QMouseEvent*)event);
9061 break;
9062
9063 case QEvent::MouseButtonDblClick:
9064 mouseDoubleClickEvent((QMouseEvent*)event);
9065 break;
9066#if QT_CONFIG(wheelevent)
9067 case QEvent::Wheel:
9068 wheelEvent((QWheelEvent*)event);
9069 break;
9070#endif
9071#if QT_CONFIG(tabletevent)
9072 case QEvent::TabletMove:
9073 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9074 break;
9075 Q_FALLTHROUGH();
9076 case QEvent::TabletPress:
9077 case QEvent::TabletRelease:
9078 tabletEvent((QTabletEvent*)event);
9079 break;
9080#endif
9081 case QEvent::KeyPress: {
9082 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9083 bool res = false;
9084 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9085 if (k->key() == Qt::Key_Backtab
9086 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9087 res = focusNextPrevChild(false);
9088 else if (k->key() == Qt::Key_Tab)
9089 res = focusNextPrevChild(true);
9090 if (res)
9091 break;
9092 }
9093 keyPressEvent(k);
9094#ifdef QT_KEYPAD_NAVIGATION
9095 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9096 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9097 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9098 if (k->key() == Qt::Key_Up)
9099 res = focusNextPrevChild(false);
9100 else if (k->key() == Qt::Key_Down)
9101 res = focusNextPrevChild(true);
9102 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9103 if (k->key() == Qt::Key_Up)
9104 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9105 else if (k->key() == Qt::Key_Right)
9106 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9107 else if (k->key() == Qt::Key_Down)
9108 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9109 else if (k->key() == Qt::Key_Left)
9110 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9111 }
9112 if (res) {
9113 k->accept();
9114 break;
9115 }
9116 }
9117#endif
9118#if QT_CONFIG(whatsthis)
9119 if (!k->isAccepted()
9120 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9121 && d->whatsThis.size()) {
9122 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9123 k->accept();
9124 }
9125#endif
9126 }
9127 break;
9128
9129 case QEvent::KeyRelease:
9130 keyReleaseEvent((QKeyEvent*)event);
9131 Q_FALLTHROUGH();
9132 case QEvent::ShortcutOverride:
9133 break;
9134
9135 case QEvent::InputMethod:
9136 inputMethodEvent((QInputMethodEvent *) event);
9137 break;
9138
9139 case QEvent::InputMethodQuery: {
9140 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9141 Qt::InputMethodQueries queries = query->queries();
9142 for (uint i = 0; i < 32; ++i) {
9143 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9144 if (q) {
9145 QVariant v = inputMethodQuery(q);
9146 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9147 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9148 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9149 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9150 // will only be set if the widget supports IM _and_ is not read-only. So for
9151 // read-only widgets, not all IM features will be supported when ImEnabled is
9152 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9153 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9154 }
9155 query->setValue(q, v);
9156 }
9157 }
9158 query->accept();
9159 }
9160 break;
9161
9162 case QEvent::PolishRequest:
9163 ensurePolished();
9164 break;
9165
9166 case QEvent::Polish: {
9167 style()->polish(this);
9168 setAttribute(Qt::WA_WState_Polished);
9169 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9170 d->resolveFont();
9171 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9172 d->resolvePalette();
9173 }
9174 break;
9175
9176 case QEvent::ApplicationWindowIconChange:
9177 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9178 d->setWindowIcon_sys();
9179 d->setWindowIcon_helper();
9180 }
9181 break;
9182 case QEvent::FocusIn:
9183 focusInEvent((QFocusEvent*)event);
9184 d->updateWidgetTransform(event);
9185 break;
9186
9187 case QEvent::FocusOut:
9188 focusOutEvent((QFocusEvent*)event);
9189 break;
9190
9191 case QEvent::Enter:
9192#if QT_CONFIG(statustip)
9193 if (d->statusTip.size()) {
9194 QStatusTipEvent tip(d->statusTip);
9195 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9196 }
9197#endif
9198 enterEvent(static_cast<QEnterEvent*>(event));
9199 break;
9200
9201 case QEvent::Leave:
9202#if QT_CONFIG(statustip)
9203 if (d->statusTip.size()) {
9204 QString empty;
9205 QStatusTipEvent tip(empty);
9206 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9207 }
9208#endif
9209 leaveEvent(event);
9210 break;
9211
9212 case QEvent::HoverEnter:
9213 case QEvent::HoverLeave:
9214 update();
9215 break;
9216
9217 case QEvent::Paint:
9218 // At this point the event has to be delivered, regardless
9219 // whether the widget isVisible() or not because it
9220 // already went through the filters
9221 paintEvent((QPaintEvent*)event);
9222 break;
9223
9224 case QEvent::Move:
9225 moveEvent((QMoveEvent*)event);
9226 d->updateWidgetTransform(event);
9227 break;
9228
9229 case QEvent::Resize:
9230 resizeEvent((QResizeEvent*)event);
9231 d->updateWidgetTransform(event);
9232 break;
9233
9234 case QEvent::Close:
9235 closeEvent((QCloseEvent *)event);
9236 break;
9237
9238#ifndef QT_NO_CONTEXTMENU
9239 case QEvent::ContextMenu:
9240 switch (data->context_menu_policy) {
9241 case Qt::PreventContextMenu:
9242 break;
9243 case Qt::DefaultContextMenu:
9244 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9245 break;
9246 case Qt::CustomContextMenu:
9247 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9248 break;
9249#if QT_CONFIG(menu)
9250 case Qt::ActionsContextMenu:
9251 if (d->actions.size()) {
9252 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9253 nullptr, this);
9254 break;
9255 }
9256 Q_FALLTHROUGH();
9257#endif
9258 default:
9259 event->ignore();
9260 break;
9261 }
9262 break;
9263#endif // QT_NO_CONTEXTMENU
9264
9265#if QT_CONFIG(draganddrop)
9266 case QEvent::Drop:
9267 dropEvent((QDropEvent*) event);
9268 break;
9269
9270 case QEvent::DragEnter:
9271 dragEnterEvent((QDragEnterEvent*) event);
9272 break;
9273
9274 case QEvent::DragMove:
9275 dragMoveEvent((QDragMoveEvent*) event);
9276 break;
9277
9278 case QEvent::DragLeave:
9279 dragLeaveEvent((QDragLeaveEvent*) event);
9280 break;
9281#endif
9282
9283 case QEvent::Show:
9284 showEvent((QShowEvent*) event);
9285 break;
9286
9287 case QEvent::Hide:
9288 hideEvent((QHideEvent*) event);
9289 break;
9290
9291 case QEvent::ShowWindowRequest:
9292 if (!isHidden())
9293 d->show_sys();
9294 break;
9295
9296 case QEvent::ApplicationFontChange:
9297 d->resolveFont();
9298 break;
9299 case QEvent::ApplicationPaletteChange:
9300 d->resolvePalette();
9301 break;
9302
9303 case QEvent::ToolBarChange:
9304 case QEvent::ActivationChange:
9305 case QEvent::EnabledChange:
9306 case QEvent::FontChange:
9307 case QEvent::StyleChange:
9308 case QEvent::PaletteChange:
9309 case QEvent::WindowTitleChange:
9310 case QEvent::IconTextChange:
9311 case QEvent::ModifiedChange:
9312 case QEvent::MouseTrackingChange:
9313 case QEvent::TabletTrackingChange:
9314 case QEvent::ParentChange:
9315 case QEvent::LocaleChange:
9316 case QEvent::MacSizeChange:
9317 case QEvent::ContentsRectChange:
9318 case QEvent::ThemeChange:
9319 case QEvent::ReadOnlyChange:
9320 changeEvent(event);
9321 break;
9322
9323 case QEvent::WindowStateChange: {
9324 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9325 if (wasMinimized != isMinimized()) {
9326 QWidget *widget = const_cast<QWidget *>(this);
9327 if (wasMinimized) {
9328 // Always send the spontaneous events here, otherwise it can break the application!
9329 if (!d->childrenShownByExpose) {
9330 // Show widgets only when they are not yet shown by the expose event
9331 d->showChildren(true);
9332 QShowEvent showEvent;
9333 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9334 }
9335 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9336 } else {
9337 QHideEvent hideEvent;
9338 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9339 d->hideChildren(true);
9340 d->childrenHiddenByWState = true;
9341 }
9342 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9343 }
9344 changeEvent(event);
9345 }
9346 break;
9347
9348 case QEvent::WindowActivate:
9349 case QEvent::WindowDeactivate: {
9350 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9351 update();
9352 QList<QObject*> childList = d->children;
9353 for (int i = 0; i < childList.size(); ++i) {
9354 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9355 if (w && w->isVisible() && !w->isWindow())
9356 QCoreApplication::sendEvent(w, event);
9357 }
9358 break; }
9359
9360 case QEvent::LanguageChange:
9361 changeEvent(event);
9362 {
9363 QList<QObject*> childList = d->children;
9364 for (int i = 0; i < childList.size(); ++i) {
9365 QObject *o = childList.at(i);
9366 if (o)
9367 QCoreApplication::sendEvent(o, event);
9368 }
9369 }
9370 update();
9371 break;
9372
9373 case QEvent::ApplicationLayoutDirectionChange:
9374 d->resolveLayoutDirection();
9375 break;
9376
9377 case QEvent::LayoutDirectionChange:
9378 if (d->layout)
9379 d->layout->invalidate();
9380 update();
9381 changeEvent(event);
9382 break;
9383 case QEvent::UpdateRequest:
9384 d->syncBackingStore();
9385 break;
9386 case QEvent::UpdateLater:
9387 update(static_cast<QUpdateLaterEvent*>(event)->region());
9388 break;
9389 case QEvent::StyleAnimationUpdate:
9390 if (isVisible() && !window()->isMinimized()) {
9391 event->accept();
9392 update();
9393 }
9394 break;
9395
9396 case QEvent::WindowBlocked:
9397 case QEvent::WindowUnblocked:
9398 if (!d->children.isEmpty()) {
9399 QWidget *modalWidget = QApplication::activeModalWidget();
9400 for (int i = 0; i < d->children.size(); ++i) {
9401 QObject *o = d->children.at(i);
9402 if (o && o != modalWidget && o->isWidgetType()) {
9403 QWidget *w = static_cast<QWidget *>(o);
9404 // do not forward the event to child windows; QApplication does this for us
9405 if (!w->isWindow())
9406 QCoreApplication::sendEvent(w, event);
9407 }
9408 }
9409 }
9410 break;
9411#if QT_CONFIG(tooltip)
9412 case QEvent::ToolTip:
9413 if (!d->toolTip.isEmpty())
9414 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9415 else
9416 event->ignore();
9417 break;
9418#endif
9419#if QT_CONFIG(whatsthis)
9420 case QEvent::WhatsThis:
9421 if (d->whatsThis.size())
9422 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9423 else
9424 event->ignore();
9425 break;
9426 case QEvent::QueryWhatsThis:
9427 if (d->whatsThis.isEmpty())
9428 event->ignore();
9429 break;
9430#endif
9431 case QEvent::EmbeddingControl:
9432 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9433 data->fstrut_dirty = false;
9434 break;
9435#ifndef QT_NO_ACTION
9436 case QEvent::ActionAdded:
9437 case QEvent::ActionRemoved:
9438 case QEvent::ActionChanged:
9439 actionEvent((QActionEvent*)event);
9440 break;
9441#endif
9442
9443 case QEvent::KeyboardLayoutChange:
9444 {
9445 changeEvent(event);
9446
9447 // inform children of the change
9448 QList<QObject*> childList = d->children;
9449 for (int i = 0; i < childList.size(); ++i) {
9450 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9451 if (w && w->isVisible() && !w->isWindow())
9452 QCoreApplication::sendEvent(w, event);
9453 }
9454 break;
9455 }
9456 case QEvent::TouchBegin:
9457 case QEvent::TouchUpdate:
9458 case QEvent::TouchEnd:
9459 case QEvent::TouchCancel:
9460 {
9461 event->ignore();
9462 break;
9463 }
9464#ifndef QT_NO_GESTURES
9465 case QEvent::Gesture:
9466 event->ignore();
9467 break;
9468#endif
9469 case QEvent::ScreenChangeInternal:
9470 if (const QTLWExtra *te = d->maybeTopData()) {
9471 const QWindow *win = te->window;
9472 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9473 }
9474 break;
9475 case QEvent::DevicePixelRatioChange:
9476 if (d->data.fnt.d->dpi != logicalDpiY())
9477 d->updateFont(d->data.fnt);
9478 d->renderToTextureReallyDirty = 1;
9479 break;
9480 case QEvent::DynamicPropertyChange: {
9481 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9482 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9483 uint value = property(propName.constData()).toUInt();
9484 if (!d->extra)
9485 d->createExtra();
9486 const char axis = propName.at(12);
9487 if (axis == 'X')
9488 d->extra->customDpiX = value;
9489 else if (axis == 'Y')
9490 d->extra->customDpiY = value;
9491 d->updateFont(d->data.fnt);
9492 }
9493 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9494 windowHandle()->setProperty(propName, property(propName));
9495 Q_FALLTHROUGH();
9496 }
9497 default:
9498 return QObject::event(event);
9499 }
9500 return true;
9501}
9502
9503/*!
9504 This event handler can be reimplemented to handle state changes.
9505
9506 The state being changed in this event can be retrieved through the \a event
9507 supplied.
9508
9509 Change events include: QEvent::ToolBarChange,
9510 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9511 QEvent::StyleChange, QEvent::PaletteChange,
9512 QEvent::WindowTitleChange, QEvent::IconTextChange,
9513 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9514 QEvent::ParentChange, QEvent::WindowStateChange,
9515 QEvent::LanguageChange, QEvent::LocaleChange,
9516 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9517
9518*/
9519void QWidget::changeEvent(QEvent * event)
9520{
9521 switch(event->type()) {
9522 case QEvent::EnabledChange: {
9523 update();
9524#if QT_CONFIG(accessibility)
9525 QAccessible::State s;
9526 s.disabled = true;
9527 QAccessibleStateChangeEvent event(this, s);
9528 QAccessible::updateAccessibility(&event);
9529#endif
9530 break;
9531 }
9532
9533 case QEvent::FontChange:
9534 case QEvent::StyleChange: {
9535 Q_D(QWidget);
9536 update();
9537 updateGeometry();
9538 if (d->layout)
9539 d->layout->invalidate();
9540 break;
9541 }
9542
9543 case QEvent::PaletteChange:
9544 update();
9545 break;
9546
9547 case QEvent::ThemeChange:
9548 if (QGuiApplication::desktopSettingsAware()
9549 && qApp && !QCoreApplication::closingDown()) {
9550 if (testAttribute(Qt::WA_WState_Polished))
9551 QApplication::style()->unpolish(this);
9552 if (testAttribute(Qt::WA_WState_Polished))
9553 QApplication::style()->polish(this);
9554 QEvent styleChangedEvent(QEvent::StyleChange);
9555 QCoreApplication::sendEvent(this, &styleChangedEvent);
9556 if (isVisible())
9557 update();
9558 }
9559 break;
9560
9561#ifdef Q_OS_MACOS
9562 case QEvent::MacSizeChange:
9563 updateGeometry();
9564 break;
9565#endif
9566
9567 default:
9568 break;
9569 }
9570}
9571
9572/*!
9573 This event handler, for event \a event, can be reimplemented in a
9574 subclass to receive mouse move events for the widget.
9575
9576 If mouse tracking is switched off, mouse move events only occur if
9577 a mouse button is pressed while the mouse is being moved. If mouse
9578 tracking is switched on, mouse move events occur even if no mouse
9579 button is pressed.
9580
9581 QMouseEvent::position() reports the position of the mouse cursor,
9582 relative to this widget. For press and release events, the
9583 position is usually the same as the position of the last mouse
9584 move event, but it might be different if the user's hand shakes.
9585 This is a feature of the underlying window system, not Qt.
9586
9587 If you want to show a tooltip immediately, while the mouse is
9588 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9589 and show them as a tooltip), you must first enable mouse tracking
9590 as described above. Then, to ensure that the tooltip is updated
9591 immediately, you must call QToolTip::showText() instead of
9592 setToolTip() in your implementation of mouseMoveEvent().
9593
9594 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9595 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9596*/
9597
9598void QWidget::mouseMoveEvent(QMouseEvent *event)
9599{
9600 event->ignore();
9601}
9602
9603/*!
9604 This event handler, for event \a event, can be reimplemented in a
9605 subclass to receive mouse press events for the widget.
9606
9607 If you create new widgets in the mousePressEvent() the
9608 mouseReleaseEvent() may not end up where you expect, depending on
9609 the underlying window system (or X11 window manager), the widgets'
9610 location and maybe more.
9611
9612 The default implementation implements the closing of popup widgets
9613 when you click outside the window. For other widget types it does
9614 nothing.
9615
9616 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9617 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9618*/
9619
9620void QWidget::mousePressEvent(QMouseEvent *event)
9621{
9622 event->ignore();
9623 if ((windowType() == Qt::Popup)) {
9624 event->accept();
9625 QWidget* w;
9626 while ((w = QApplication::activePopupWidget()) && w != this){
9627 w->close();
9628 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9629 w->hide(); // hide at least
9630 }
9631 if (!rect().contains(event->position().toPoint())){
9632 close();
9633 }
9634 }
9635}
9636
9637/*!
9638 This event handler, for event \a event, can be reimplemented in a
9639 subclass to receive mouse release events for the widget.
9640
9641 \sa mousePressEvent(), mouseDoubleClickEvent(),
9642 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9643*/
9644
9645void QWidget::mouseReleaseEvent(QMouseEvent *event)
9646{
9647 event->ignore();
9648}
9649
9650/*!
9651 This event handler, for event \a event, can be reimplemented in a
9652 subclass to receive mouse double click events for the widget.
9653
9654 The default implementation calls mousePressEvent().
9655
9656 \note The widget will also receive mouse press and mouse release
9657 events in addition to the double click event. And if another widget
9658 that overlaps this widget disappears in response to press or
9659 release events, then this widget will only receive the double click
9660 event. It is up to the developer to ensure that the application
9661 interprets these events correctly.
9662
9663 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9664 event(), QMouseEvent
9665*/
9666
9667void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9668{
9669 mousePressEvent(event);
9670}
9671
9672#if QT_CONFIG(wheelevent)
9673/*!
9674 This event handler, for event \a event, can be reimplemented in a
9675 subclass to receive wheel events for the widget.
9676
9677 If you reimplement this handler, it is very important that you
9678 \l{QEvent}{ignore()} the event if you do not handle
9679 it, so that the widget's parent can interpret it.
9680
9681 The default implementation ignores the event.
9682
9683 \sa QEvent::ignore(), QEvent::accept(), event(),
9684 QWheelEvent
9685*/
9686
9687void QWidget::wheelEvent(QWheelEvent *event)
9688{
9689 event->ignore();
9690}
9691#endif // QT_CONFIG(wheelevent)
9692
9693#if QT_CONFIG(tabletevent)
9694/*!
9695 This event handler, for event \a event, can be reimplemented in a
9696 subclass to receive tablet events for the widget.
9697
9698 If you reimplement this handler, it is very important that you
9699 \l{QEvent}{ignore()} the event if you do not handle
9700 it, so that the widget's parent can interpret it.
9701
9702 The default implementation ignores the event.
9703
9704 If tablet tracking is switched off, tablet move events only occur if the
9705 stylus is in contact with the tablet, or at least one stylus button is
9706 pressed, while the stylus is being moved. If tablet tracking is switched on,
9707 tablet move events occur even while the stylus is hovering in proximity of
9708 the tablet, with no buttons pressed.
9709
9710 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9711 QTabletEvent
9712*/
9713
9714void QWidget::tabletEvent(QTabletEvent *event)
9715{
9716 event->ignore();
9717}
9718#endif // QT_CONFIG(tabletevent)
9719
9720/*!
9721 This event handler, for event \a event, can be reimplemented in a
9722 subclass to receive key press events for the widget.
9723
9724 A widget must call setFocusPolicy() to accept focus initially and
9725 have focus in order to receive a key press event.
9726
9727 If you reimplement this handler, it is very important that you
9728 call the base class implementation if you do not act upon the key.
9729
9730 The default implementation closes popup widgets if the user
9731 presses the key sequence for QKeySequence::Cancel (typically the
9732 Escape key). Otherwise the event is ignored, so that the widget's
9733 parent can interpret it.
9734
9735 Note that QKeyEvent starts with isAccepted() == true, so you do not
9736 need to call QKeyEvent::accept() - just do not call the base class
9737 implementation if you act upon the key.
9738
9739 \sa keyReleaseEvent(), setFocusPolicy(),
9740 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9741*/
9742
9743void QWidget::keyPressEvent(QKeyEvent *event)
9744{
9745#ifndef QT_NO_SHORTCUT
9746 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9747 event->accept();
9748 close();
9749 } else
9750#endif
9751 {
9752 event->ignore();
9753 }
9754}
9755
9756/*!
9757 This event handler, for event \a event, can be reimplemented in a
9758 subclass to receive key release events for the widget.
9759
9760 A widget must \l{setFocusPolicy()}{accept focus}
9761 initially and \l{hasFocus()}{have focus} in order to
9762 receive a key release event.
9763
9764 If you reimplement this handler, it is very important that you
9765 call the base class implementation if you do not act upon the key.
9766
9767 The default implementation ignores the event, so that the widget's
9768 parent can interpret it.
9769
9770 Note that QKeyEvent starts with isAccepted() == true, so you do not
9771 need to call QKeyEvent::accept() - just do not call the base class
9772 implementation if you act upon the key.
9773
9774 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9775 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9776*/
9777
9778void QWidget::keyReleaseEvent(QKeyEvent *event)
9779{
9780 event->ignore();
9781}
9782
9783/*!
9784 \fn void QWidget::focusInEvent(QFocusEvent *event)
9785
9786 This event handler can be reimplemented in a subclass to receive
9787 keyboard focus events (focus received) for the widget. The event
9788 is passed in the \a event parameter
9789
9790 A widget normally must setFocusPolicy() to something other than
9791 Qt::NoFocus to receive focus events. (Note that the
9792 application programmer can call setFocus() on any widget, even
9793 those that do not normally accept focus.)
9794
9795 The default implementation updates the widget (except for windows
9796 that do not specify a focusPolicy()).
9797
9798 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9799 keyReleaseEvent(), event(), QFocusEvent
9800*/
9801
9802void QWidget::focusInEvent(QFocusEvent *)
9803{
9804 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9805 update();
9806 }
9807}
9808
9809/*!
9810 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9811
9812 This event handler can be reimplemented in a subclass to receive
9813 keyboard focus events (focus lost) for the widget. The events is
9814 passed in the \a event parameter.
9815
9816 A widget normally must setFocusPolicy() to something other than
9817 Qt::NoFocus to receive focus events. (Note that the
9818 application programmer can call setFocus() on any widget, even
9819 those that do not normally accept focus.)
9820
9821 The default implementation updates the widget (except for windows
9822 that do not specify a focusPolicy()).
9823
9824 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9825 keyReleaseEvent(), event(), QFocusEvent
9826*/
9827
9828void QWidget::focusOutEvent(QFocusEvent *)
9829{
9830 if (focusPolicy() != Qt::NoFocus || !isWindow())
9831 update();
9832
9833#if !defined(QT_PLATFORM_UIKIT)
9834 // FIXME: revisit autoSIP logic, QTBUG-42906
9835 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9836 QGuiApplication::inputMethod()->hide();
9837#endif
9838}
9839
9840/*!
9841 \fn void QWidget::enterEvent(QEnterEvent *event)
9842
9843 This event handler can be reimplemented in a subclass to receive
9844 widget enter events which are passed in the \a event parameter.
9845
9846 An event is sent to the widget when the mouse cursor enters the
9847 widget.
9848
9849 \sa leaveEvent(), mouseMoveEvent(), event()
9850*/
9851
9852void QWidget::enterEvent(QEnterEvent *)
9853{
9854}
9855
9856/*!
9857 \fn void QWidget::leaveEvent(QEvent *event)
9858
9859 This event handler can be reimplemented in a subclass to receive
9860 widget leave events which are passed in the \a event parameter.
9861
9862 A leave event is sent to the widget when the mouse cursor leaves
9863 the widget.
9864
9865 \sa enterEvent(), mouseMoveEvent(), event()
9866*/
9867
9868void QWidget::leaveEvent(QEvent *)
9869{
9870}
9871
9872/*!
9873 \fn void QWidget::paintEvent(QPaintEvent *event)
9874
9875 This event handler can be reimplemented in a subclass to receive paint
9876 events passed in \a event.
9877
9878 A paint event is a request to repaint all or part of a widget. It can
9879 happen for one of the following reasons:
9880
9881 \list
9882 \li repaint() or update() was invoked,
9883 \li the widget was obscured and has now been uncovered, or
9884 \li many other reasons.
9885 \endlist
9886
9887 Many widgets can simply repaint their entire surface when asked to, but
9888 some slow widgets need to optimize by painting only the requested region:
9889 QPaintEvent::region(). This speed optimization does not change the result,
9890 as painting is clipped to that region during event processing. QListView
9891 and QTableView do this, for example.
9892
9893 Qt also tries to speed up painting by merging multiple paint events into
9894 one. When update() is called several times or the window system sends
9895 several paint events, Qt merges these events into one event with a larger
9896 region (see QRegion::united()). The repaint() function does not permit this
9897 optimization, so we suggest using update() whenever possible.
9898
9899 When the paint event occurs, the update region has normally been erased, so
9900 you are painting on the widget's background.
9901
9902 The background can be set using setBackgroundRole() and setPalette().
9903
9904 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9905 is no need to write double-buffering code in paintEvent() to avoid flicker.
9906
9907 \note Generally, you should refrain from calling update() or repaint()
9908 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9909 children inside a paintEvent() results in undefined behavior; the child may
9910 or may not get a paint event.
9911
9912 \warning If you are using a custom paint engine without Qt's backingstore,
9913 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9914 never be called; the backingstore will be used instead.
9915
9916 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9917 {Analog Clock}
9918*/
9919
9920void QWidget::paintEvent(QPaintEvent *)
9921{
9922}
9923
9924
9925/*!
9926 \fn void QWidget::moveEvent(QMoveEvent *event)
9927
9928 This event handler can be reimplemented in a subclass to receive
9929 widget move events which are passed in the \a event parameter.
9930 When the widget receives this event, it is already at the new
9931 position.
9932
9933 The old position is accessible through QMoveEvent::oldPos().
9934
9935 \sa resizeEvent(), event(), move(), QMoveEvent
9936*/
9937
9938void QWidget::moveEvent(QMoveEvent *)
9939{
9940}
9941
9942
9943/*!
9944 This event handler can be reimplemented in a subclass to receive
9945 widget resize events which are passed in the \a event parameter.
9946 When resizeEvent() is called, the widget already has its new
9947 geometry. The old size is accessible through
9948 QResizeEvent::oldSize().
9949
9950 The widget will be erased and receive a paint event immediately
9951 after processing the resize event. No drawing need be (or should
9952 be) done inside this handler.
9953
9954
9955 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9956 {Scribble Example}
9957*/
9958
9959void QWidget::resizeEvent(QResizeEvent * /* event */)
9960{
9961}
9962
9963#ifndef QT_NO_ACTION
9964/*!
9965 \fn void QWidget::actionEvent(QActionEvent *event)
9966
9967 This event handler is called with the given \a event whenever the
9968 widget's actions are changed.
9969
9970 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9971*/
9972void QWidget::actionEvent(QActionEvent *)
9973{
9974
9975}
9976#endif
9977
9978/*!
9979 This event handler is called with the given \a event when Qt receives a window
9980 close request for a top-level widget from the window system.
9981
9982 By default, the event is accepted and the widget is closed. You can reimplement
9983 this function to change the way the widget responds to window close requests.
9984 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9985 on all events.
9986
9987 Main window applications typically use reimplementations of this function to check
9988 whether the user's work has been saved and ask for permission before closing.
9989
9990 \sa event(), hide(), close(), QCloseEvent
9991*/
9992
9993void QWidget::closeEvent(QCloseEvent *event)
9994{
9995 event->accept();
9996}
9997
9998#ifndef QT_NO_CONTEXTMENU
9999/*!
10000 This event handler, for event \a event, can be reimplemented in a
10001 subclass to receive widget context menu events.
10002
10003 The handler is called when the widget's \l contextMenuPolicy is
10004 Qt::DefaultContextMenu.
10005
10006 The default implementation ignores the context event.
10007 See the \l QContextMenuEvent documentation for more details.
10008
10009 \sa event(), QContextMenuEvent, customContextMenuRequested()
10010*/
10011
10012void QWidget::contextMenuEvent(QContextMenuEvent *event)
10013{
10014 event->ignore();
10015}
10016#endif // QT_NO_CONTEXTMENU
10017
10018
10019/*!
10020 This event handler, for event \a event, can be reimplemented in a
10021 subclass to receive Input Method composition events. This handler
10022 is called when the state of the input method changes.
10023
10024 Note that when creating custom text editing widgets, the
10025 Qt::WA_InputMethodEnabled window attribute must be set explicitly
10026 (using the setAttribute() function) in order to receive input
10027 method events.
10028
10029 The default implementation calls event->ignore(), which rejects the
10030 Input Method event. See the \l QInputMethodEvent documentation for more
10031 details.
10032
10033 \sa event(), QInputMethodEvent
10034*/
10035void QWidget::inputMethodEvent(QInputMethodEvent *event)
10036{
10037 event->ignore();
10038}
10039
10040/*!
10041 This method is only relevant for input widgets. It is used by the
10042 input method to query a set of properties of the widget to be
10043 able to support complex input method operations as support for
10044 surrounding text and reconversions.
10045
10046 \a query specifies which property is queried.
10047
10048 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
10049*/
10050QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
10051{
10052 switch(query) {
10053 case Qt::ImCursorRectangle:
10054 return QRect(width()/2, 0, 1, height());
10055 case Qt::ImFont:
10056 return font();
10057 case Qt::ImAnchorPosition:
10058 // Fallback.
10059 return inputMethodQuery(Qt::ImCursorPosition);
10060 case Qt::ImHints:
10061 return (int)inputMethodHints();
10062 case Qt::ImInputItemClipRectangle:
10063 return d_func()->clipRect();
10064 default:
10065 return QVariant();
10066 }
10067}
10068
10069/*!
10070 \property QWidget::inputMethodHints
10071 \brief What input method specific hints the widget has.
10072
10073 This is only relevant for input widgets. It is used by
10074 the input method to retrieve hints as to how the input method
10075 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
10076 is set, the input method may change its visual components to reflect
10077 that only numbers can be entered.
10078
10079 \warning Some widgets require certain flags to work as
10080 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
10081 instead of \c{w->setInputMethodHints(f)}.
10082
10083 \note The flags are only hints, so the particular input method
10084 implementation is free to ignore them. If you want to be
10085 sure that a certain type of characters are entered,
10086 you should also set a QValidator on the widget.
10087
10088 The default value is Qt::ImhNone.
10089
10090 \since 4.6
10091
10092 \sa inputMethodQuery()
10093*/
10094Qt::InputMethodHints QWidget::inputMethodHints() const
10095{
10096#if QT_CONFIG(im)
10097 const QWidgetPrivate *priv = d_func();
10098 while (priv->inheritsInputMethodHints) {
10099 priv = priv->q_func()->parentWidget()->d_func();
10100 Q_ASSERT(priv);
10101 }
10102 return priv->imHints;
10103#else
10104 return Qt::ImhNone;
10105#endif
10106}
10107
10108void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10109{
10110#ifndef QT_NO_IM
10111 Q_D(QWidget);
10112 if (d->imHints == hints)
10113 return;
10114 d->imHints = hints;
10115 if (this == QGuiApplication::focusObject())
10116 QGuiApplication::inputMethod()->update(Qt::ImHints);
10117#else
10118 Q_UNUSED(hints);
10119#endif //QT_NO_IM
10120}
10121
10122
10123#if QT_CONFIG(draganddrop)
10124
10125/*!
10126 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10127
10128 This event handler is called when a drag is in progress and the
10129 mouse enters this widget. The event is passed in the \a event parameter.
10130
10131 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10132 move events}.
10133
10134 See the \l{dnd.html}{Drag-and-drop documentation} for an
10135 overview of how to provide drag-and-drop in your application.
10136
10137 \sa QDrag, QDragEnterEvent
10138*/
10139void QWidget::dragEnterEvent(QDragEnterEvent *)
10140{
10141}
10142
10143/*!
10144 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10145
10146 This event handler is called if a drag is in progress, and when
10147 any of the following conditions occur: the cursor enters this widget,
10148 the cursor moves within this widget, or a modifier key is pressed on
10149 the keyboard while this widget has the focus. The event is passed
10150 in the \a event parameter.
10151
10152 See the \l{dnd.html}{Drag-and-drop documentation} for an
10153 overview of how to provide drag-and-drop in your application.
10154
10155 \sa QDrag, QDragMoveEvent
10156*/
10157void QWidget::dragMoveEvent(QDragMoveEvent *)
10158{
10159}
10160
10161/*!
10162 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10163
10164 This event handler is called when a drag is in progress and the
10165 mouse leaves this widget. The event is passed in the \a event
10166 parameter.
10167
10168 See the \l{dnd.html}{Drag-and-drop documentation} for an
10169 overview of how to provide drag-and-drop in your application.
10170
10171 \sa QDrag, QDragLeaveEvent
10172*/
10173void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10174{
10175}
10176
10177/*!
10178 \fn void QWidget::dropEvent(QDropEvent *event)
10179
10180 This event handler is called when the drag is dropped on this
10181 widget. The event is passed in the \a event parameter.
10182
10183 See the \l{dnd.html}{Drag-and-drop documentation} for an
10184 overview of how to provide drag-and-drop in your application.
10185
10186 \sa QDrag, QDropEvent
10187*/
10188void QWidget::dropEvent(QDropEvent *)
10189{
10190}
10191
10192#endif // QT_CONFIG(draganddrop)
10193
10194/*!
10195 \fn void QWidget::showEvent(QShowEvent *event)
10196
10197 This event handler can be reimplemented in a subclass to receive
10198 widget show events which are passed in the \a event parameter.
10199
10200 Non-spontaneous show events are sent to widgets immediately
10201 before they are shown. The spontaneous show events of windows are
10202 delivered afterwards.
10203
10204 Note: A widget receives spontaneous show and hide events when its
10205 mapping status is changed by the window system, e.g. a spontaneous
10206 hide event when the user minimizes the window, and a spontaneous
10207 show event when the window is restored again. After receiving a
10208 spontaneous hide event, a widget is still considered visible in
10209 the sense of isVisible().
10210
10211 \sa visible, event(), QShowEvent
10212*/
10213void QWidget::showEvent(QShowEvent *)
10214{
10215}
10216
10217/*!
10218 \fn void QWidget::hideEvent(QHideEvent *event)
10219
10220 This event handler can be reimplemented in a subclass to receive
10221 widget hide events. The event is passed in the \a event parameter.
10222
10223 Hide events are sent to widgets immediately after they have been
10224 hidden.
10225
10226 Note: A widget receives spontaneous show and hide events when its
10227 mapping status is changed by the window system, e.g. a spontaneous
10228 hide event when the user minimizes the window, and a spontaneous
10229 show event when the window is restored again. After receiving a
10230 spontaneous hide event, a widget is still considered visible in
10231 the sense of isVisible().
10232
10233 \sa visible, event(), QHideEvent
10234*/
10235void QWidget::hideEvent(QHideEvent *)
10236{
10237}
10238
10239/*!
10240 This special event handler can be reimplemented in a subclass to
10241 receive native platform events identified by \a eventType
10242 which are passed in the \a message parameter.
10243
10244 In your reimplementation of this function, if you want to stop the
10245 event being handled by Qt, return true and set \a result. The \a result
10246 parameter has meaning only on Windows. If you return false, this native
10247 event is passed back to Qt, which translates the event into a Qt event
10248 and sends it to the widget.
10249
10250 \note Events are only delivered to this event handler if the widget
10251 has a native window handle.
10252
10253 \note This function superseedes the event filter functions
10254 x11Event(), winEvent() and macEvent() of Qt 4.
10255
10256 \sa QAbstractNativeEventFilter
10257
10258 \table
10259 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10260 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10261 \row \li macOS \li "NSEvent" \li NSEvent * \li
10262 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10263 \endtable
10264*/
10265
10266bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10267{
10268 Q_UNUSED(eventType);
10269 Q_UNUSED(message);
10270 Q_UNUSED(result);
10271 return false;
10272}
10273
10274/*!
10275 Ensures that the widget and its children have been polished by
10276 QStyle (i.e., have a proper font and palette).
10277
10278 QWidget calls this function after it has been fully constructed
10279 but before it is shown the very first time. You can call this
10280 function if you want to ensure that the widget is polished before
10281 doing an operation, e.g., the correct font size might be needed in
10282 the widget's sizeHint() reimplementation. Note that this function
10283 \e is called from the default implementation of sizeHint().
10284
10285 Polishing is useful for final initialization that must happen after
10286 all constructors (from base classes as well as from subclasses)
10287 have been called.
10288
10289 If you need to change some settings when a widget is polished,
10290 reimplement event() and handle the QEvent::Polish event type.
10291
10292 \b{Note:} The function is declared const so that it can be called from
10293 other const functions (e.g., sizeHint()).
10294
10295 \sa event()
10296*/
10297void QWidget::ensurePolished() const
10298{
10299 Q_D(const QWidget);
10300
10301 const QMetaObject *m = metaObject();
10302 if (m == d->polished)
10303 return;
10304 d->polished = m;
10305
10306 QEvent e(QEvent::Polish);
10307 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10308
10309 // polish children after 'this'
10310 QList<QObject*> children = d->children;
10311 for (int i = 0; i < children.size(); ++i) {
10312 QObject *o = children.at(i);
10313 if (!o->isWidgetType())
10314 continue;
10315 if (QWidget *w = qobject_cast<QWidget *>(o))
10316 w->ensurePolished();
10317 }
10318
10319 if (d->parent && d->sendChildEvents) {
10320 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10321 QCoreApplication::sendEvent(d->parent, &e);
10322 }
10323}
10324
10325/*!
10326 Returns the mask currently set on a widget. If no mask is set the
10327 return value will be an empty region.
10328
10329 \sa setMask(), clearMask(), QRegion::isEmpty()
10330*/
10331QRegion QWidget::mask() const
10332{
10333 Q_D(const QWidget);
10334 return d->extra ? d->extra->mask : QRegion();
10335}
10336
10337/*!
10338 Returns the layout manager that is installed on this widget, or \nullptr
10339 if no layout manager is installed.
10340
10341 The layout manager sets the geometry of the widget's children
10342 that have been added to the layout.
10343
10344 \sa setLayout(), sizePolicy(), {Layout Management}
10345*/
10346QLayout *QWidget::layout() const
10347{
10348 return d_func()->layout;
10349}
10350
10351
10352/*!
10353 \fn void QWidget::setLayout(QLayout *layout)
10354
10355 Sets the layout manager for this widget to \a layout.
10356
10357 If there already is a layout manager installed on this widget,
10358 QWidget won't let you install another. You must first delete the
10359 existing layout manager (returned by layout()) before you can
10360 call setLayout() with the new layout.
10361
10362 If \a layout is the layout manager on a different widget, setLayout()
10363 will reparent the layout and make it the layout manager for this widget.
10364
10365 Example:
10366
10367 \snippet layouts/layouts.cpp 24
10368
10369 An alternative to calling this function is to pass this widget to
10370 the layout's constructor.
10371
10372 The QWidget will take ownership of \a layout.
10373
10374 \sa layout(), {Layout Management}
10375*/
10376
10377void QWidget::setLayout(QLayout *l)
10378{
10379 if (Q_UNLIKELY(!l)) {
10380 qWarning("QWidget::setLayout: Cannot set layout to 0");
10381 return;
10382 }
10383 if (layout()) {
10384 if (Q_UNLIKELY(layout() != l))
10385 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10386 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10387 objectName().toLocal8Bit().data());
10388 return;
10389 }
10390
10391 QObject *oldParent = l->parent();
10392 if (oldParent && oldParent != this) {
10393 if (oldParent->isWidgetType()) {
10394 // Steal the layout off a widget parent. Takes effect when
10395 // morphing laid-out container widgets in Designer.
10396 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10397 oldParentWidget->takeLayout();
10398 } else {
10399 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10400 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10401 objectName().toLocal8Bit().data());
10402 return;
10403 }
10404 }
10405
10406 Q_D(QWidget);
10407 l->d_func()->topLevel = true;
10408 d->layout = l;
10409 if (oldParent != this) {
10410 l->setParent(this);
10411 l->d_func()->reparentChildWidgets(this);
10412 l->invalidate();
10413 }
10414
10415 if (isWindow() && d->maybeTopData())
10416 d->topData()->sizeAdjusted = false;
10417}
10418
10419/*!
10420 \fn QLayout *QWidget::takeLayout()
10421
10422 Remove the layout from the widget.
10423 \since 4.5
10424*/
10425
10426QLayout *QWidget::takeLayout()
10427{
10428 Q_D(QWidget);
10429 QLayout *l = layout();
10430 if (!l)
10431 return nullptr;
10432 d->layout = nullptr;
10433 l->setParent(nullptr);
10434 return l;
10435}
10436
10437/*!
10438 \property QWidget::sizePolicy
10439 \brief the default layout behavior of the widget
10440
10441 If there is a QLayout that manages this widget's children, the
10442 size policy specified by that layout is used. If there is no such
10443 QLayout, the result of this function is used.
10444
10445 The default policy is Preferred/Preferred, which means that the
10446 widget can be freely resized, but prefers to be the size
10447 sizeHint() returns. Button-like widgets set the size policy to
10448 specify that they may stretch horizontally, but are fixed
10449 vertically. The same applies to lineedit controls (such as
10450 QLineEdit, QSpinBox or an editable QComboBox) and other
10451 horizontally orientated widgets (such as QProgressBar).
10452 QToolButton's are normally square, so they allow growth in both
10453 directions. Widgets that support different directions (such as
10454 QSlider, QScrollBar or QHeader) specify stretching in the
10455 respective direction only. Widgets that can provide scroll bars
10456 (usually subclasses of QScrollArea) tend to specify that they can
10457 use additional space, and that they can make do with less than
10458 sizeHint().
10459
10460 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10461*/
10462QSizePolicy QWidget::sizePolicy() const
10463{
10464 Q_D(const QWidget);
10465 return d->size_policy;
10466}
10467
10468void QWidget::setSizePolicy(QSizePolicy policy)
10469{
10470 Q_D(QWidget);
10471 setAttribute(Qt::WA_WState_OwnSizePolicy);
10472 if (policy == d->size_policy)
10473 return;
10474
10475 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10476 d->retainSizeWhenHiddenChanged = 1;
10477
10478 d->size_policy = policy;
10479
10480#if QT_CONFIG(graphicsview)
10481 if (const auto &extra = d->extra) {
10482 if (extra->proxyWidget)
10483 extra->proxyWidget->setSizePolicy(policy);
10484 }
10485#endif
10486
10487 updateGeometry();
10488 d->retainSizeWhenHiddenChanged = 0;
10489
10490 if (isWindow() && d->maybeTopData())
10491 d->topData()->sizeAdjusted = false;
10492}
10493
10494/*!
10495 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10496 \overload
10497
10498 Sets the size policy of the widget to \a horizontal and \a
10499 vertical, with standard stretch and no height-for-width.
10500
10501 \sa QSizePolicy::QSizePolicy()
10502*/
10503
10504/*!
10505 Returns the preferred height for this widget, given the width \a w.
10506
10507 If this widget has a layout, the default implementation returns
10508 the layout's preferred height. if there is no layout, the default
10509 implementation returns -1 indicating that the preferred height
10510 does not depend on the width.
10511*/
10512
10513int QWidget::heightForWidth(int w) const
10514{
10515 if (layout() && layout()->hasHeightForWidth())
10516 return layout()->totalHeightForWidth(w);
10517 return -1;
10518}
10519
10520
10521/*!
10522 \since 5.0
10523
10524 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10525*/
10526bool QWidget::hasHeightForWidth() const
10527{
10528 Q_D(const QWidget);
10529 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10530}
10531
10532/*!
10533 \fn QWidget *QWidget::childAt(int x, int y) const
10534
10535 Returns the visible child widget at the position (\a{x}, \a{y})
10536 in the widget's coordinate system. If there is no visible child
10537 widget at the specified position, the function returns \nullptr.
10538*/
10539
10540/*!
10541 \overload
10542
10543 Returns the visible child widget at point \a p in the widget's own
10544 coordinate system.
10545*/
10546
10547QWidget *QWidget::childAt(const QPoint &p) const
10548{
10549 return d_func()->childAt_helper(QPointF(p), false);
10550}
10551
10552/*!
10553 \overload
10554 \since 6.8
10555
10556 Returns the visible child widget at point \a p in the widget's own
10557 coordinate system.
10558*/
10559
10560QWidget *QWidget::childAt(const QPointF &p) const
10561{
10562 return d_func()->childAt_helper(p, false);
10563}
10564
10565QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10566{
10567 if (children.isEmpty())
10568 return nullptr;
10569
10570 if (!pointInsideRectAndMask(p))
10571 return nullptr;
10572 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10573}
10574
10575QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10576{
10577 for (int i = children.size() - 1; i >= 0; --i) {
10578 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10579 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10580 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10581 continue;
10582 }
10583
10584 // Map the point 'p' from parent coordinates to child coordinates.
10585 QPointF childPoint = p;
10586 childPoint -= child->data->crect.topLeft();
10587
10588 // Check if the point hits the child.
10589 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10590 continue;
10591
10592 // Do the same for the child's descendants.
10593 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10594 return w;
10595
10596 // We have found our target; namely the child at position 'p'.
10597 return child;
10598 }
10599 return nullptr;
10600}
10601
10602void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10603{
10604 Q_Q(QWidget);
10605 if (widgetItem)
10606 widgetItem->invalidateSizeCache();
10607 QWidget *parent;
10608 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10609 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10610
10611 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10612 if (parent->d_func()->layout)
10613 parent->d_func()->layout->invalidate();
10614 else if (parent->isVisible())
10615 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10616 }
10617 }
10618}
10619
10620/*!
10621 Notifies the layout system that this widget has changed and may
10622 need to change geometry.
10623
10624 Call this function if the sizeHint() or sizePolicy() have changed.
10625
10626 For explicitly hidden widgets, updateGeometry() is a no-op. The
10627 layout system will be notified as soon as the widget is shown.
10628*/
10629
10630void QWidget::updateGeometry()
10631{
10632 Q_D(QWidget);
10633 d->updateGeometry_helper(false);
10634}
10635
10636/*! \property QWidget::windowFlags
10637
10638 Window flags are a combination of a type (e.g. Qt::Dialog) and
10639 zero or more hints to the window system (e.g.
10640 Qt::FramelessWindowHint).
10641
10642 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10643 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10644 0) on the desktop. If the widget is a window and becomes a
10645 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10646 relative to its parent widget.
10647
10648 \note This function calls setParent() when changing the flags for
10649 a window, causing the widget to be hidden. You must call show() to make
10650 the widget visible again..
10651
10652 \sa windowType(), setWindowFlag(), {Window Flags Example}
10653*/
10654void QWidget::setWindowFlags(Qt::WindowFlags flags)
10655{
10656 Q_D(QWidget);
10657 d->setWindowFlags(flags);
10658}
10659
10660/*!
10661 \since 5.9
10662
10663 Sets the window flag \a flag on this widget if \a on is true;
10664 otherwise clears the flag.
10665
10666 \note This function calls setParent() when changing the flags for
10667 a window, causing the widget to be hidden. You must call show() to make
10668 the widget visible again.
10669
10670 \sa setWindowFlags(), windowFlags(), windowType()
10671*/
10672void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10673{
10674 Q_D(QWidget);
10675 if (on)
10676 d->setWindowFlags(data->window_flags | flag);
10677 else
10678 d->setWindowFlags(data->window_flags & ~flag);
10679}
10680
10681/*! \internal
10682
10683 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10684*/
10685void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10686{
10687 Q_Q(QWidget);
10688#if QT_DEPRECATED_SINCE(6, 11)
10689 QT_IGNORE_DEPRECATIONS(
10690 if ((flags & Qt::WindowType_Mask) == Qt::WindowType::Desktop) {
10691 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10692 flags.setFlag(Qt::WindowType::Desktop, false);
10693 }
10694 )
10695#endif
10696
10697 if (q->data->window_flags == flags)
10698 return;
10699
10700 if ((q->data->window_flags | flags) & Qt::Window) {
10701 // the old type was a window and/or the new type is a window
10702 QPoint oldPos = q->pos();
10703 bool visible = q->isVisible();
10704 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10705 q->setParent(q->parentWidget(), flags);
10706
10707 // if both types are windows or neither of them are, we restore
10708 // the old position
10709 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10710 q->move(oldPos);
10711 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10712 adjustQuitOnCloseAttribute();
10713 } else {
10714 q->data->window_flags = flags;
10715 }
10716}
10717
10718/*!
10719 Sets the window flags for the widget to \a flags,
10720 \e without telling the window system.
10721
10722 \warning Do not call this function unless you really know what
10723 you're doing.
10724
10725 \sa setWindowFlags()
10726*/
10727void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10728{
10729 data->window_flags = flags;
10730}
10731
10732/*!
10733 \fn Qt::WindowType QWidget::windowType() const
10734
10735 Returns the window type of this widget. This is identical to
10736 windowFlags() & Qt::WindowType_Mask.
10737
10738 \sa windowFlags
10739*/
10740
10741/*!
10742 Sets the parent of the widget to \a parent, and resets the window
10743 flags. The widget is moved to position (0, 0) in its new parent.
10744
10745 If the new parent widget is in a different window, the
10746 reparented widget and its children are appended to the end of the
10747 \l{setFocusPolicy()}{tab chain} of the new parent
10748 widget, in the same internal order as before. If one of the moved
10749 widgets had keyboard focus, setParent() calls clearFocus() for that
10750 widget.
10751
10752 If the new parent widget is in the same window as the
10753 old parent, setting the parent doesn't change the tab order or
10754 keyboard focus.
10755
10756 If the "new" parent widget is the old parent widget, this function
10757 does nothing.
10758
10759 \note The widget becomes invisible as part of changing its parent,
10760 even if it was previously visible. You must call show() to make the
10761 widget visible again.
10762
10763 \warning It is very unlikely that you will ever need this
10764 function. If you have a widget that changes its content
10765 dynamically, it is far easier to use \l QStackedWidget.
10766
10767 \sa setWindowFlags()
10768*/
10769void QWidget::setParent(QWidget *parent)
10770{
10771 if (parent == parentWidget())
10772 return;
10773 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10774}
10775
10776void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10777{
10778 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10779 if (d->renderToTexture) {
10780 QEvent e(eventType);
10781 QCoreApplication::sendEvent(widget, &e);
10782 }
10783
10784 for (int i = 0; i < d->children.size(); ++i) {
10785 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10786 if (w && !w->isWindow())
10787 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10788 }
10789
10790 // Notify QWidgetWindow after we've notified all child QWidgets
10791 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10792 QEvent e(eventType);
10793 QCoreApplication::sendEvent(window, &e);
10794 }
10795}
10796
10797/*!
10798 \overload
10799
10800 This function also takes widget flags, \a f as an argument.
10801*/
10802
10803void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10804{
10805 Q_D(QWidget);
10806 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10807#ifdef QT_DEBUG
10808 const auto checkForParentChildLoops = qScopeGuard([&](){
10809 int depth = 0;
10810 auto p = parentWidget();
10811 while (p) {
10812 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10813 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10814 "this is undefined behavior",
10815 this, metaObject()->className(), qPrintable(objectName()));
10816 }
10817 p = p->parentWidget();
10818 }
10819 });
10820#endif
10821
10822 const bool resized = testAttribute(Qt::WA_Resized);
10823 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10824 QWidget *oldtlw = window();
10825 Q_ASSERT(oldtlw);
10826 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10827
10828 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10829 d->data.fstrut_dirty = true;
10830
10831 bool newParent = (parent != parentWidget());
10832
10833 if (newParent && parent) {
10834 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10835 parent->d_func()->enforceNativeChildren();
10836 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10837 setAttribute(Qt::WA_NativeWindow);
10838 }
10839
10840 if (wasCreated) {
10841 if (!testAttribute(Qt::WA_WState_Hidden)) {
10842 // Hiding the widget will set WA_WState_Hidden as well, which would
10843 // normally require the widget to be explicitly shown again to become
10844 // visible, even as a child widget. But we refine this value later in
10845 // setParent_sys(), applying WA_WState_Hidden based on whether the
10846 // widget is a top level or not.
10847 hide();
10848
10849 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10850 // when we only had QWidget::setVisible(), which is treated as an
10851 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10852 // that allows us to hide a widget without affecting ExplicitShowHide.
10853 // Though it can be argued that ExplicitShowHide should reflect the
10854 // last update of the widget's state, so if we hide the widget as a
10855 // side effect of changing parent, perhaps we _should_ reset it?
10856 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10857 }
10858 if (newParent) {
10859 QEvent e(QEvent::ParentAboutToChange);
10860 QCoreApplication::sendEvent(this, &e);
10861 }
10862 }
10863
10864 // texture-based widgets need a pre-notification when their associated top-level window changes
10865 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10866 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10867 : oldtlw->d_func()->usesRhiFlush;
10868 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10869 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10870
10871 // If we get parented into another window, children will be folded
10872 // into the new parent's focus chain, so clear focus now.
10873 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10874 focusWidget()->clearFocus();
10875
10876 d->setParent_sys(parent, f);
10877
10878 if (d->textureChildSeen && parent) {
10879 // set the textureChildSeen flag up the whole parent chain
10880 QWidgetPrivate::get(parent)->setTextureChildSeen();
10881 }
10882
10883 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10884 if (newParent)
10885 oldPaintManager->removeDirtyWidget(this);
10886 // Move the widget and all its static children from
10887 // the old backing store to the new one.
10888 oldPaintManager->moveStaticWidgets(this);
10889 }
10890
10891 d->reparentFocusWidgets(oldtlw);
10892 setAttribute(Qt::WA_Resized, resized);
10893
10894 const bool useStyleSheetPropagationInWidgetStyles =
10895 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10896
10897 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10898 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10899 // if the parent has a font set or inherited, then propagate the mask to the new child
10900 if (parent) {
10901 const auto pd = parent->d_func();
10902 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10903 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10904 }
10905 d->resolveFont();
10906 d->resolvePalette();
10907 }
10908 d->resolveLayoutDirection();
10909 d->resolveLocale();
10910
10911 // Note: GL widgets under WGL or EGL will always need a ParentChange
10912 // event to handle recreation/rebinding of the GL context, hence the
10913 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10914 // platforms).
10915 if (newParent || !wasCreated
10916#if QT_CONFIG(opengles2)
10917 || (f & Qt::MSWindowsOwnDC)
10918#endif
10919 ) {
10920 // propagate enabled updates enabled state to non-windows
10921 if (!isWindow()) {
10922 if (!testAttribute(Qt::WA_ForceDisabled))
10923 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10924 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10925 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10926 }
10927 d->inheritStyle();
10928
10929 // send and post remaining QObject events
10930 if (parent && d->sendChildEvents) {
10931 QChildEvent e(QEvent::ChildAdded, this);
10932 QCoreApplication::sendEvent(parent, &e);
10933 }
10934
10935 if (parent && d->sendChildEvents && d->polished) {
10936 QChildEvent e(QEvent::ChildPolished, this);
10937 QCoreApplication::sendEvent(parent, &e);
10938 }
10939
10940 QEvent e(QEvent::ParentChange);
10941 QCoreApplication::sendEvent(this, &e);
10942 }
10943
10944 // texture-based widgets need another event when their top-level window
10945 // changes (more precisely, has already changed at this point)
10946 if (oldWidgetUsesRhiFlush && oldtlw != window())
10947 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10948
10949 if (!wasCreated) {
10950 if (isWindow() || parentWidget()->isVisible())
10951 setAttribute(Qt::WA_WState_Hidden, true);
10952 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10953 setAttribute(Qt::WA_WState_Hidden, false);
10954 }
10955
10956 d->updateIsOpaque();
10957
10958#if QT_CONFIG(graphicsview)
10959 // Embed the widget into a proxy if the parent is embedded.
10960 // ### Doesn't handle reparenting out of an embedded widget.
10961 if (oldtlw->graphicsProxyWidget()) {
10962 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10963 ancestorProxy->d_func()->unembedSubWindow(this);
10964 }
10965 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10966 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10967 ancestorProxy->d_func()->embedSubWindow(this);
10968 }
10969#endif
10970
10971 if (d->extra && d->extra->hasWindowContainer)
10972 QWindowContainer::parentWasChanged(this);
10973
10974 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10975 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10976 // Check if the native parent now needs to switch to RHI
10977 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10978 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10979
10980 QPlatformBackingStoreRhiConfig rhiConfig;
10981 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10982
10983 // First evaluate whether the reparented widget uses RHI.
10984 // We do this as a separate step because the performance
10985 // implications of always checking the native parent are
10986 // problematic when it comes to large widget trees.
10987 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10988 // Then check whether the native parent requires RHI
10989 // as a result. It may not, if this widget is a native
10990 // window, and can handle its own RHI flushing.
10991 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10992 // Finally, check whether we need to recreate the
10993 // native parent to enable RHI flushing.
10994 auto *existingWindow = newParentWithWindow->windowHandle();
10995 auto existingSurfaceType = existingWindow->surfaceType();
10996 if (existingSurfaceType != surfaceType) {
10997 qCDebug(lcWidgetPainting)
10998 << "Recreating" << existingWindow
10999 << "with current type" << existingSurfaceType
11000 << "to support" << surfaceType;
11001 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
11002 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
11003 const auto positionBeforeDestroy = newParentWithWindow->pos();
11004 newParentWithWindow->d_func()->recreate();
11005 Q_ASSERT(newParentWithWindow->windowHandle());
11006 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
11007 newParentWithWindow->move(positionBeforeDestroy);
11008 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
11009 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
11010 // If we don't recreate we still need to make sure the native parent
11011 // widget has a RHI config that the reparented widget can use.
11012 backingStore->handle()->createRhi(existingWindow, rhiConfig);
11013 // And that it knows it's now flushing with RHI
11014 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
11015 }
11016 }
11017 }
11018 }
11019
11020#if QT_CONFIG(accessibility)
11021 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
11022 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
11023 QAccessible::updateAccessibility(&qaEvent);
11024 }
11025#endif
11026
11027}
11028
11029void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
11030{
11031 Q_Q(QWidget);
11032
11033 Qt::WindowFlags oldFlags = data.window_flags;
11034 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
11035
11036 QScreen *targetScreen = nullptr;
11037 setWinId(0);
11038
11039 if (!newparent) {
11040 f |= Qt::Window;
11041 if (parent)
11042 targetScreen = q->parentWidget()->window()->screen();
11043 }
11044
11045 const bool destroyWindow = (
11046 // Reparenting top level to child
11047 (oldFlags & Qt::Window) && !(f & Qt::Window)
11048 // And we can dispose of the window
11049 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
11050 );
11051
11052 if (parent != newparent) {
11053 // Update object parent now, so we can resolve new parent window below
11054 QObjectPrivate::setParent_helper(newparent);
11055
11056 if (q->windowHandle())
11057 q->windowHandle()->setFlags(f);
11058
11059 // If the widget itself or any of its children have been created,
11060 // we need to reparent their QWindows as well.
11061 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11062 // But if the widget is about to be destroyed we must skip the
11063 // widget itself, and only reparent children.
11064 if (destroyWindow) {
11065 reparentWidgetWindowChildren(parentWithWindow);
11066 } else {
11067 // During reparentWidgetWindows() we need to know whether the reparented
11068 // QWindow should be a top level (with a transient parent) or not. This
11069 // widget has not updated its window flags yet, so we can't ask the widget
11070 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
11071 // the QWindow flags always reflect Qt::Window, even for child windows. And
11072 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
11073 // which we are in the process of updating. So we propagate the
11074 // new flags of the reparented window here.
11075 reparentWidgetWindows(parentWithWindow, f);
11076 }
11077 }
11078
11079 bool explicitlyHidden = isExplicitlyHidden();
11080
11081 if (destroyWindow) {
11082 if (extra && extra->hasWindowContainer)
11083 QWindowContainer::toplevelAboutToBeDestroyed(q);
11084
11085 // There shouldn't be any QWindow children left, but if there
11086 // are, re-parent them now, before we destroy.
11087 if (!q->windowHandle()->children().isEmpty()) {
11088 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11089 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
11090 for (QObject *child : q->windowHandle()->children()) {
11091 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
11092 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11093 << "before destroying" << this;
11094 childWindow->setParent(newParentWindow);
11095 }
11096 }
11097 }
11098
11099 // We have reparented any child windows of the widget we are
11100 // about to destroy to the new parent window handle, so we can
11101 // safely destroy this widget without destroying sub windows.
11102 q->destroy(true, false);
11103 }
11104
11105 adjustFlags(f, q);
11106 data.window_flags = f;
11107 q->setAttribute(Qt::WA_WState_Created, false);
11108 q->setAttribute(Qt::WA_WState_Visible, false);
11109 q->setAttribute(Qt::WA_WState_Hidden, false);
11110
11111 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11112 q->createWinId();
11113
11114 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11115 q->setAttribute(Qt::WA_WState_Hidden);
11116 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11117
11118 // move the window to the selected screen
11119 if (!newparent && targetScreen) {
11120 // only if it is already created
11121 if (q->testAttribute(Qt::WA_WState_Created))
11122 q->windowHandle()->setScreen(targetScreen);
11123 else
11124 topData()->initialScreen = targetScreen;
11125 }
11126}
11127
11128void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11129{
11130 if (QWindow *window = windowHandle()) {
11131 // Reparent this QWindow, and all QWindow children will follow
11132 if (parentWithWindow) {
11133 if (windowFlags & Qt::Window) {
11134 // Top level windows can only have transient parents,
11135 // and the transient parent must be another top level.
11136 QWidget *topLevel = parentWithWindow->window();
11137 auto *transientParent = topLevel->windowHandle();
11138 Q_ASSERT(transientParent);
11139 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11140 window->setTransientParent(transientParent);
11141 window->setParent(nullptr);
11142 } else {
11143 auto *parentWindow = parentWithWindow->windowHandle();
11144 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11145 window->setTransientParent(nullptr);
11146 window->setParent(parentWindow);
11147 }
11148 } else {
11149 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11150 window->setTransientParent(nullptr);
11151 window->setParent(nullptr);
11152 }
11153 } else {
11154 reparentWidgetWindowChildren(parentWithWindow);
11155 }
11156}
11157
11158void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11159{
11160 for (auto *child : std::as_const(children)) {
11161 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11162 auto *childPrivate = QWidgetPrivate::get(childWidget);
11163 // Child widgets with QWindows should always continue to be child
11164 // windows, so we pass on the child's current window flags here.
11165 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11166 }
11167 }
11168}
11169
11170/*!
11171 Scrolls the widget including its children \a dx pixels to the
11172 right and \a dy downward. Both \a dx and \a dy may be negative.
11173
11174 After scrolling, the widgets will receive paint events for
11175 the areas that need to be repainted. For widgets that Qt knows to
11176 be opaque, this is only the newly exposed parts.
11177 For example, if an opaque widget is scrolled 8 pixels to the left,
11178 only an 8-pixel wide stripe at the right edge needs updating.
11179
11180 Since widgets propagate the contents of their parents by default,
11181 you need to set the \l autoFillBackground property, or use
11182 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11183 a widget opaque.
11184
11185 For widgets that use contents propagation, a scroll will cause an
11186 update of the entire scroll area.
11187
11188 \sa {Transparency and Double Buffering}
11189*/
11190
11191void QWidget::scroll(int dx, int dy)
11192{
11193 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11194 return;
11195 if (dx == 0 && dy == 0)
11196 return;
11197 Q_D(QWidget);
11198#if QT_CONFIG(graphicsview)
11199 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11200 // Graphics View maintains its own dirty region as a list of rects;
11201 // until we can connect item updates directly to the view, we must
11202 // separately add a translated dirty region.
11203 for (const QRect &rect : d->dirty)
11204 proxy->update(rect.translated(dx, dy));
11205 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11206 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11207 return;
11208 }
11209#endif
11210 d->setDirtyOpaqueRegion();
11211 d->scroll_sys(dx, dy);
11212}
11213
11214void QWidgetPrivate::scroll_sys(int dx, int dy)
11215{
11216 Q_Q(QWidget);
11217 scrollChildren(dx, dy);
11218 scrollRect(q->rect(), dx, dy);
11219}
11220
11221/*!
11222 \overload
11223
11224 This version only scrolls \a r and does not move the children of
11225 the widget.
11226
11227 If \a r is empty or invalid, the result is undefined.
11228
11229 \sa QScrollArea
11230*/
11231void QWidget::scroll(int dx, int dy, const QRect &r)
11232{
11233
11234 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11235 return;
11236 if (dx == 0 && dy == 0)
11237 return;
11238 Q_D(QWidget);
11239#if QT_CONFIG(graphicsview)
11240 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11241 // Graphics View maintains its own dirty region as a list of rects;
11242 // until we can connect item updates directly to the view, we must
11243 // separately add a translated dirty region.
11244 if (!d->dirty.isEmpty()) {
11245 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11246 proxy->update(rect);
11247 }
11248 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11249 return;
11250 }
11251#endif
11252 d->scroll_sys(dx, dy, r);
11253}
11254
11255void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11256{
11257 scrollRect(r, dx, dy);
11258}
11259
11260/*!
11261 Repaints the widget directly by calling paintEvent() immediately,
11262 unless updates are disabled or the widget is hidden.
11263
11264 We suggest only using repaint() if you need an immediate repaint,
11265 for example during animation. In most circumstances update()
11266 is better, as it permits Qt to optimize for speed and minimize
11267 flicker.
11268
11269 \warning If you call repaint() in a function which may itself be
11270 called from paintEvent(), you may get infinite recursion. The
11271 update() function never causes recursion.
11272
11273 \sa update(), paintEvent(), setUpdatesEnabled()
11274*/
11275
11276void QWidget::repaint()
11277{
11278 repaint(rect());
11279}
11280
11281/*! \overload
11282
11283 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11284 the widget.
11285
11286 If \a w is negative, it is replaced with \c{width() - x}, and if
11287 \a h is negative, it is replaced width \c{height() - y}.
11288*/
11289void QWidget::repaint(int x, int y, int w, int h)
11290{
11291 if (x > data->crect.width() || y > data->crect.height())
11292 return;
11293
11294 if (w < 0)
11295 w = data->crect.width() - x;
11296 if (h < 0)
11297 h = data->crect.height() - y;
11298
11299 repaint(QRect(x, y, w, h));
11300}
11301
11302/*! \overload
11303
11304 This version repaints a rectangle \a rect inside the widget.
11305*/
11306void QWidget::repaint(const QRect &rect)
11307{
11308 Q_D(QWidget);
11309 d->repaint(rect);
11310}
11311
11312/*!
11313 \overload
11314
11315 This version repaints a region \a rgn inside the widget.
11316*/
11317void QWidget::repaint(const QRegion &rgn)
11318{
11319 Q_D(QWidget);
11320 d->repaint(rgn);
11321}
11322
11323template <typename T>
11324void QWidgetPrivate::repaint(T r)
11325{
11326 Q_Q(QWidget);
11327
11328 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11329 return;
11330
11331 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11332 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11333 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11334}
11335
11336/*!
11337 Updates the widget unless updates are disabled or the widget is
11338 hidden.
11339
11340 This function does not cause an immediate repaint; instead it
11341 schedules a paint event for processing when Qt returns to the main
11342 event loop. This permits Qt to optimize for more speed and less
11343 flicker than a call to repaint() does.
11344
11345 Calling update() several times normally results in just one
11346 paintEvent() call.
11347
11348 Qt normally erases the widget's area before the paintEvent() call.
11349 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11350 responsible for painting all its pixels with an opaque color.
11351
11352 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11353*/
11354void QWidget::update()
11355{
11356 update(rect());
11357}
11358
11359/*! \fn void QWidget::update(int x, int y, int w, int h)
11360 \overload
11361
11362 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11363 the widget.
11364*/
11365
11366/*!
11367 \overload
11368
11369 This version updates a rectangle \a rect inside the widget.
11370*/
11371void QWidget::update(const QRect &rect)
11372{
11373 Q_D(QWidget);
11374 d->update(rect);
11375}
11376
11377/*!
11378 \overload
11379
11380 This version repaints a region \a rgn inside the widget.
11381*/
11382void QWidget::update(const QRegion &rgn)
11383{
11384 Q_D(QWidget);
11385 d->update(rgn);
11386}
11387
11388template <typename T>
11389void QWidgetPrivate::update(T r)
11390{
11391 Q_Q(QWidget);
11392
11393 if (renderToTexture && !q->isVisible()) {
11394 renderToTextureReallyDirty = 1;
11395 return;
11396 }
11397
11398 if (!q->isVisible() || !q->updatesEnabled())
11399 return;
11400
11401 T clipped = r & q->rect();
11402
11403 if (clipped.isEmpty())
11404 return;
11405
11406 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11407 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11408 return;
11409 }
11410
11411 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11412 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11413 tlwExtra->repaintManager->markDirty(clipped, q);
11414}
11415
11416 /*!
11417 \internal
11418
11419 This just sets the corresponding attribute bit to 1 or 0
11420 */
11421static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11422 QWidgetPrivate *d)
11423{
11424 if (attribute < int(8*sizeof(uint))) {
11425 if (on)
11426 data->widget_attributes |= (1<<attribute);
11427 else
11428 data->widget_attributes &= ~(1<<attribute);
11429 } else {
11430 const int x = attribute - 8*sizeof(uint);
11431 const int int_off = x / (8*sizeof(uint));
11432 if (on)
11433 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11434 else
11435 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11436 }
11437}
11438
11439#ifdef Q_OS_MACOS
11440void QWidgetPrivate::macUpdateSizeAttribute()
11441{
11442 Q_Q(QWidget);
11443 QEvent event(QEvent::MacSizeChange);
11444 QCoreApplication::sendEvent(q, &event);
11445 for (int i = 0; i < children.size(); ++i) {
11446 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11447 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11448 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11449 && !w->testAttribute(Qt::WA_MacSmallSize)
11450 && !w->testAttribute(Qt::WA_MacNormalSize))
11451 w->d_func()->macUpdateSizeAttribute();
11452 }
11453 resolveFont();
11454}
11455#endif
11456
11457/*!
11458 Sets the attribute \a attribute on this widget if \a on is true;
11459 otherwise clears the attribute.
11460
11461 \sa testAttribute()
11462*/
11463void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11464{
11465 Q_D(QWidget);
11466
11467 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11468 if (isWindow()) {
11469 auto *topExtra = d->topData();
11470 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11471 }
11472 }
11473
11474 if (testAttribute(attribute) == on)
11475 return;
11476
11477 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11478 "QWidget::setAttribute(WidgetAttribute, bool): "
11479 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11480#ifdef Q_OS_WIN
11481 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11482 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11483 // see ::paintEngine for details
11484 paintEngine();
11485 if (d->noPaintOnScreen)
11486 return;
11487 }
11488#endif
11489
11490 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11491 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11492 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11493 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11494 return;
11495 }
11496
11497 setAttribute_internal(attribute, on, data, d);
11498
11499 switch (attribute) {
11500
11501#if QT_CONFIG(draganddrop)
11502 case Qt::WA_AcceptDrops: {
11503 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11504 setAttribute(Qt::WA_DropSiteRegistered, true);
11505 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11506 setAttribute(Qt::WA_DropSiteRegistered, false);
11507 QEvent e(QEvent::AcceptDropsChange);
11508 QCoreApplication::sendEvent(this, &e);
11509 break;
11510 }
11511 case Qt::WA_DropSiteRegistered: {
11512 for (int i = 0; i < d->children.size(); ++i) {
11513 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11514 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11515 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11516 }
11517 break;
11518 }
11519#endif
11520
11521 case Qt::WA_NoChildEventsForParent:
11522 d->sendChildEvents = !on;
11523 break;
11524 case Qt::WA_NoChildEventsFromChildren:
11525 d->receiveChildEvents = !on;
11526 break;
11527 case Qt::WA_MacNormalSize:
11528 case Qt::WA_MacSmallSize:
11529 case Qt::WA_MacMiniSize:
11530#ifdef Q_OS_MACOS
11531 {
11532 // We can only have one of these set at a time
11533 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11534 Qt::WA_MacMiniSize };
11535 for (int i = 0; i < 3; ++i) {
11536 if (MacSizes[i] != attribute)
11537 setAttribute_internal(MacSizes[i], false, data, d);
11538 }
11539 d->macUpdateSizeAttribute();
11540 }
11541#endif
11542 break;
11543 case Qt::WA_ShowModal:
11544 if (!on) {
11545 // reset modality type to NonModal when clearing WA_ShowModal
11546 data->window_modality = Qt::NonModal;
11547 } else if (data->window_modality == Qt::NonModal) {
11548 // If modality hasn't been set prior to setting WA_ShowModal, use
11549 // ApplicationModal.
11550 data->window_modality = Qt::ApplicationModal;
11551 // Some window managers do not allow us to enter modality after the
11552 // window is visible.The window must be hidden before changing the
11553 // windowModality property and then reshown.
11554 }
11555 if (testAttribute(Qt::WA_WState_Created)) {
11556 // don't call setModal_sys() before create()
11557 d->setModal_sys();
11558 }
11559 break;
11560 case Qt::WA_MouseTracking: {
11561 QEvent e(QEvent::MouseTrackingChange);
11562 QCoreApplication::sendEvent(this, &e);
11563 break; }
11564 case Qt::WA_TabletTracking: {
11565 QEvent e(QEvent::TabletTrackingChange);
11566 QCoreApplication::sendEvent(this, &e);
11567 break; }
11568 case Qt::WA_NativeWindow: {
11569 d->createTLExtra();
11570 if (on)
11571 d->createTLSysExtra();
11572#ifndef QT_NO_IM
11573 QWidget *focusWidget = d->effectiveFocusWidget();
11574 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11575 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11576 QGuiApplication::inputMethod()->commit();
11577 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11578 }
11579 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11580 parentWidget()->d_func()->enforceNativeChildren();
11581 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11582 d->createWinId();
11583 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11584 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11585 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11586 }
11587#endif //QT_NO_IM
11588 break;
11589 }
11590 case Qt::WA_PaintOnScreen:
11591 d->updateIsOpaque();
11592 Q_FALLTHROUGH();
11593 case Qt::WA_OpaquePaintEvent:
11594 d->updateIsOpaque();
11595 break;
11596 case Qt::WA_NoSystemBackground:
11597 d->updateIsOpaque();
11598 Q_FALLTHROUGH();
11599 case Qt::WA_UpdatesDisabled:
11600 d->updateSystemBackground();
11601 break;
11602 case Qt::WA_TransparentForMouseEvents:
11603 break;
11604 case Qt::WA_InputMethodEnabled: {
11605#ifndef QT_NO_IM
11606 if (QGuiApplication::focusObject() == this) {
11607 if (!on)
11608 QGuiApplication::inputMethod()->commit();
11609 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11610 }
11611#endif //QT_NO_IM
11612 break;
11613 }
11614 case Qt::WA_WindowPropagation:
11615 d->resolvePalette();
11616 d->resolveFont();
11617 d->resolveLocale();
11618 break;
11619 case Qt::WA_DontShowOnScreen: {
11620 if (on && isVisible()) {
11621 // Make sure we keep the current state and only hide the widget
11622 // from the desktop. show_sys will only update platform specific
11623 // attributes at this point.
11624 d->hide_sys();
11625 d->show_sys();
11626 }
11627 break;
11628 }
11629
11630 case Qt::WA_X11NetWmWindowTypeDesktop:
11631 case Qt::WA_X11NetWmWindowTypeDock:
11632 case Qt::WA_X11NetWmWindowTypeToolBar:
11633 case Qt::WA_X11NetWmWindowTypeMenu:
11634 case Qt::WA_X11NetWmWindowTypeUtility:
11635 case Qt::WA_X11NetWmWindowTypeSplash:
11636 case Qt::WA_X11NetWmWindowTypeDialog:
11637 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11638 case Qt::WA_X11NetWmWindowTypePopupMenu:
11639 case Qt::WA_X11NetWmWindowTypeToolTip:
11640 case Qt::WA_X11NetWmWindowTypeNotification:
11641 case Qt::WA_X11NetWmWindowTypeCombo:
11642 case Qt::WA_X11NetWmWindowTypeDND:
11643 d->setNetWmWindowTypes();
11644 break;
11645
11646 case Qt::WA_StaticContents:
11647 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11648 if (on)
11649 repaintManager->addStaticWidget(this);
11650 else
11651 repaintManager->removeStaticWidget(this);
11652 }
11653 break;
11654 case Qt::WA_TranslucentBackground:
11655 if (on)
11656 setAttribute(Qt::WA_NoSystemBackground);
11657 d->updateIsTranslucent();
11658
11659 break;
11660 case Qt::WA_AcceptTouchEvents:
11661 break;
11662 default:
11663 break;
11664 }
11665}
11666
11667/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11668
11669 Returns \c true if attribute \a attribute is set on this widget;
11670 otherwise returns \c false.
11671
11672 \sa setAttribute()
11673 */
11674bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11675{
11676 Q_D(const QWidget);
11677 const int x = attribute - 8*sizeof(uint);
11678 const int int_off = x / (8*sizeof(uint));
11679 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11680}
11681
11682/*!
11683 \property QWidget::windowOpacity
11684
11685 \brief The level of opacity for the window.
11686
11687 The valid range of opacity is from 1.0 (completely opaque) to
11688 0.0 (completely transparent).
11689
11690 By default the value of this property is 1.0.
11691
11692 This feature is available on Embedded Linux, \macos, Windows,
11693 and X11 platforms that support the Composite extension.
11694
11695 \note On X11 you need to have a composite manager running,
11696 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11697 supported by the window manager you are using.
11698
11699 \warning Changing this property from opaque to transparent might issue a
11700 paint event that needs to be processed before the window is displayed
11701 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11702 that semi-transparent windows update and resize significantly slower than
11703 opaque windows.
11704
11705 \sa setMask()
11706*/
11707qreal QWidget::windowOpacity() const
11708{
11709 Q_D(const QWidget);
11710 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11711}
11712
11713void QWidget::setWindowOpacity(qreal opacity)
11714{
11715 Q_D(QWidget);
11716 if (!isWindow())
11717 return;
11718
11719 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11720 QTLWExtra *extra = d->topData();
11721 extra->opacity = uint(opacity * 255);
11722 setAttribute(Qt::WA_WState_WindowOpacitySet);
11723 d->setWindowOpacity_sys(opacity);
11724
11725 if (!testAttribute(Qt::WA_WState_Created))
11726 return;
11727
11728#if QT_CONFIG(graphicsview)
11729 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11730 // Avoid invalidating the cache if set.
11731 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11732 proxy->update();
11733 else if (QGraphicsScene *scene = proxy->scene())
11734 scene->update(proxy->sceneBoundingRect());
11735 return;
11736 }
11737#endif
11738}
11739
11740void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11741{
11742 Q_Q(QWidget);
11743 if (q->windowHandle())
11744 q->windowHandle()->setOpacity(level);
11745}
11746
11747/*!
11748 \property QWidget::windowModified
11749 \brief whether the document shown in the window has unsaved changes
11750
11751 A modified window is a window whose content has changed but has
11752 not been saved to disk. This flag will have different effects
11753 varied by the platform. On \macos the close button will have a
11754 modified look; on other platforms, the window title will have an
11755 '*' (asterisk).
11756
11757 The window title must contain a "[*]" placeholder, which
11758 indicates where the '*' should appear. Normally, it should appear
11759 right after the file name (e.g., "document1.txt[*] - Text
11760 Editor"). If the window isn't modified, the placeholder is simply
11761 removed.
11762
11763 Note that if a widget is set as modified, all its ancestors will
11764 also be set as modified. However, if you call \c
11765 {setWindowModified(false)} on a widget, this will not propagate to
11766 its parent because other children of the parent might have been
11767 modified.
11768
11769 \sa windowTitle
11770*/
11771bool QWidget::isWindowModified() const
11772{
11773 return testAttribute(Qt::WA_WindowModified);
11774}
11775
11776void QWidget::setWindowModified(bool mod)
11777{
11778 Q_D(QWidget);
11779 setAttribute(Qt::WA_WindowModified, mod);
11780
11781 d->setWindowModified_helper();
11782
11783 QEvent e(QEvent::ModifiedChange);
11784 QCoreApplication::sendEvent(this, &e);
11785}
11786
11787void QWidgetPrivate::setWindowModified_helper()
11788{
11789 Q_Q(QWidget);
11790 QWindow *window = q->windowHandle();
11791 if (!window)
11792 return;
11793 QPlatformWindow *platformWindow = window->handle();
11794 if (!platformWindow)
11795 return;
11796 bool on = q->testAttribute(Qt::WA_WindowModified);
11797 if (!platformWindow->setWindowModified(on)) {
11798 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11799 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11800 setWindowTitle_helper(q->windowTitle());
11801 setWindowIconText_helper(q->windowIconText());
11802 }
11803}
11804
11805#if QT_CONFIG(tooltip)
11806/*!
11807 \property QWidget::toolTip
11808
11809 \brief the widget's tooltip
11810
11811 Note that by default tooltips are only shown for widgets that are
11812 children of the active window. You can change this behavior by
11813 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11814 not on the widget with the tooltip.
11815
11816 If you want to control a tooltip's behavior, you can intercept the
11817 event() function and catch the QEvent::ToolTip event (e.g., if you
11818 want to customize the area for which the tooltip should be shown).
11819
11820 By default, this property contains an empty string.
11821
11822 \sa QToolTip, statusTip, whatsThis
11823*/
11824void QWidget::setToolTip(const QString &s)
11825{
11826 Q_D(QWidget);
11827 d->toolTip = s;
11828
11829 QEvent event(QEvent::ToolTipChange);
11830 QCoreApplication::sendEvent(this, &event);
11831}
11832
11833QString QWidget::toolTip() const
11834{
11835 Q_D(const QWidget);
11836 return d->toolTip;
11837}
11838
11839/*!
11840 \property QWidget::toolTipDuration
11841 \brief the widget's tooltip duration
11842 \since 5.2
11843
11844 Specifies how long time the tooltip will be displayed, in milliseconds.
11845 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11846
11847 \sa toolTip
11848*/
11849
11850void QWidget::setToolTipDuration(int msec)
11851{
11852 Q_D(QWidget);
11853 d->toolTipDuration = msec;
11854}
11855
11856int QWidget::toolTipDuration() const
11857{
11858 Q_D(const QWidget);
11859 return d->toolTipDuration;
11860}
11861
11862#endif // QT_CONFIG(tooltip)
11863
11864
11865#if QT_CONFIG(statustip)
11866/*!
11867 \property QWidget::statusTip
11868 \brief the widget's status tip
11869
11870 By default, this property contains an empty string.
11871
11872 \sa toolTip, whatsThis
11873*/
11874void QWidget::setStatusTip(const QString &s)
11875{
11876 Q_D(QWidget);
11877 d->statusTip = s;
11878}
11879
11880QString QWidget::statusTip() const
11881{
11882 Q_D(const QWidget);
11883 return d->statusTip;
11884}
11885#endif // QT_CONFIG(statustip)
11886
11887#if QT_CONFIG(whatsthis)
11888/*!
11889 \property QWidget::whatsThis
11890
11891 \brief the widget's What's This help text.
11892
11893 By default, this property contains an empty string.
11894
11895 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11896*/
11897void QWidget::setWhatsThis(const QString &s)
11898{
11899 Q_D(QWidget);
11900 d->whatsThis = s;
11901}
11902
11903QString QWidget::whatsThis() const
11904{
11905 Q_D(const QWidget);
11906 return d->whatsThis;
11907}
11908#endif // QT_CONFIG(whatsthis)
11909
11910#if QT_CONFIG(accessibility)
11911/*!
11912 \property QWidget::accessibleName
11913
11914 \brief the widget's name as seen by assistive technologies
11915
11916 This is the primary name by which assistive technology such as screen readers
11917 announce this widget. For most widgets setting this property is not required.
11918 For example for QPushButton the button's text will be used.
11919
11920 It is important to set this property when the widget does not provide any
11921 text. For example a button that only contains an icon needs to set this
11922 property to work with screen readers.
11923 The name should be short and equivalent to the visual information conveyed
11924 by the widget.
11925
11926 This property has to be \l{Internationalization with Qt}{localized}.
11927
11928 By default, this property contains an empty string.
11929
11930 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11931*/
11932void QWidget::setAccessibleName(const QString &name)
11933{
11934 Q_D(QWidget);
11935 if (d->accessibleName == name)
11936 return;
11937
11938 d->accessibleName = name;
11939 QAccessibleEvent event(this, QAccessible::NameChanged);
11940 QAccessible::updateAccessibility(&event);
11941}
11942
11943QString QWidget::accessibleName() const
11944{
11945 Q_D(const QWidget);
11946 return d->accessibleName;
11947}
11948
11949/*!
11950 \property QWidget::accessibleDescription
11951
11952 \brief the widget's description as seen by assistive technologies
11953
11954 The accessible description of a widget should convey what a widget does.
11955 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11956 the description should give more context, such as \gui{Saves the current document}.
11957
11958 This property has to be \l{Internationalization with Qt}{localized}.
11959
11960 By default, this property contains an empty string and Qt falls back
11961 to using the tool tip to provide this information.
11962
11963 \sa QWidget::accessibleName, QAccessibleInterface::text()
11964*/
11965void QWidget::setAccessibleDescription(const QString &description)
11966{
11967 Q_D(QWidget);
11968 if (d->accessibleDescription == description)
11969 return;
11970
11971 d->accessibleDescription = description;
11972 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11973 QAccessible::updateAccessibility(&event);
11974}
11975
11976QString QWidget::accessibleDescription() const
11977{
11978 Q_D(const QWidget);
11979 return d->accessibleDescription;
11980}
11981
11982/*!
11983 \property QWidget::accessibleIdentifier
11984
11985 \brief the widget's identifier as seen by assistive technologies
11986
11987 If set, the accessible identifier of a widget can be used by assistive
11988 technologies in order to identify a specific widget, e.g. in automated
11989 tests.
11990
11991 \since 6.9
11992*/
11993void QWidget::setAccessibleIdentifier(const QString &identifier)
11994{
11995 Q_D(QWidget);
11996 if (d->accessibleIdentifier == identifier)
11997 return;
11998
11999 d->accessibleIdentifier = identifier;
12000 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
12001 QAccessible::updateAccessibility(&event);
12002}
12003
12004QString QWidget::accessibleIdentifier() const
12005{
12006 Q_D(const QWidget);
12007 return d->accessibleIdentifier;
12008}
12009
12010#endif // QT_CONFIG(accessibility)
12011
12012#ifndef QT_NO_SHORTCUT
12013/*!
12014 Adds a shortcut to Qt's shortcut system that watches for the given
12015 \a key sequence in the given \a context. If the \a context is
12016 Qt::ApplicationShortcut, the shortcut applies to the application as a
12017 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
12018 or to the window itself, Qt::WindowShortcut.
12019
12020 If the same \a key sequence has been grabbed by several widgets,
12021 when the \a key sequence occurs a QEvent::Shortcut event is sent
12022 to all the widgets to which it applies in a non-deterministic
12023 order, but with the ``ambiguous'' flag set to true.
12024
12025 \warning You should not normally need to use this function;
12026 instead create \l{QAction}s with the shortcut key sequences you
12027 require (if you also want equivalent menu options and toolbar
12028 buttons), or create \l{QShortcut}s if you just need key sequences.
12029 Both QAction and QShortcut handle all the event filtering for you,
12030 and provide signals which are triggered when the user triggers the
12031 key sequence, so are much easier to use than this low-level
12032 function.
12033
12034 \sa releaseShortcut(), setShortcutEnabled()
12035*/
12036int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
12037{
12038 Q_ASSERT(qApp);
12039 if (key.isEmpty())
12040 return 0;
12041 setAttribute(Qt::WA_GrabbedShortcut);
12042 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
12043}
12044
12045/*!
12046 Removes the shortcut with the given \a id from Qt's shortcut
12047 system. The widget will no longer receive QEvent::Shortcut events
12048 for the shortcut's key sequence (unless it has other shortcuts
12049 with the same key sequence).
12050
12051 \warning You should not normally need to use this function since
12052 Qt's shortcut system removes shortcuts automatically when their
12053 parent widget is destroyed. It is best to use QAction or
12054 QShortcut to handle shortcuts, since they are easier to use than
12055 this low-level function. Note also that this is an expensive
12056 operation.
12057
12058 \sa grabShortcut(), setShortcutEnabled()
12059*/
12060void QWidget::releaseShortcut(int id)
12061{
12062 Q_ASSERT(qApp);
12063 if (id)
12064 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
12065}
12066
12067/*!
12068 If \a enable is true, the shortcut with the given \a id is
12069 enabled; otherwise the shortcut is disabled.
12070
12071 \warning You should not normally need to use this function since
12072 Qt's shortcut system enables/disables shortcuts automatically as
12073 widgets become hidden/visible and gain or lose focus. It is best
12074 to use QAction or QShortcut to handle shortcuts, since they are
12075 easier to use than this low-level function.
12076
12077 \sa grabShortcut(), releaseShortcut()
12078*/
12079void QWidget::setShortcutEnabled(int id, bool enable)
12080{
12081 Q_ASSERT(qApp);
12082 if (id)
12083 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
12084}
12085
12086/*!
12087 \since 4.2
12088
12089 If \a enable is true, auto repeat of the shortcut with the
12090 given \a id is enabled; otherwise it is disabled.
12091
12092 \sa grabShortcut(), releaseShortcut()
12093*/
12094void QWidget::setShortcutAutoRepeat(int id, bool enable)
12095{
12096 Q_ASSERT(qApp);
12097 if (id)
12098 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12099}
12100#endif // QT_NO_SHORTCUT
12101
12102/*!
12103 Updates the widget's micro focus and informs input methods
12104 that the state specified by \a query has changed.
12105*/
12106void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12107{
12108 if (this == QGuiApplication::focusObject())
12109 QGuiApplication::inputMethod()->update(query);
12110}
12111
12112/*!
12113 Raises this widget to the top of the parent widget's stack.
12114
12115 After this call the widget will be visually in front of any
12116 overlapping sibling widgets.
12117
12118 \note When using activateWindow(), you can call this function to
12119 ensure that the window is stacked on top.
12120
12121 \sa lower(), stackUnder()
12122*/
12123
12124void QWidget::raise()
12125{
12126 Q_D(QWidget);
12127 if (!isWindow()) {
12128 QWidget *p = parentWidget();
12129 const int parentChildCount = p->d_func()->children.size();
12130 if (parentChildCount < 2)
12131 return;
12132 const int from = p->d_func()->children.indexOf(this);
12133 Q_ASSERT(from >= 0);
12134 // Do nothing if the widget is already in correct stacking order _and_ created.
12135 if (from != parentChildCount -1)
12136 p->d_func()->children.move(from, parentChildCount - 1);
12137 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12138 create();
12139 else if (from == parentChildCount - 1)
12140 return;
12141
12142 QRegion region(rect());
12143 d->subtractOpaqueSiblings(region);
12144 d->invalidateBackingStore(region);
12145 }
12146 if (testAttribute(Qt::WA_WState_Created))
12147 d->raise_sys();
12148
12149 if (d->extra && d->extra->hasWindowContainer)
12150 QWindowContainer::parentWasRaised(this);
12151
12152 QEvent e(QEvent::ZOrderChange);
12153 QCoreApplication::sendEvent(this, &e);
12154}
12155
12156void QWidgetPrivate::raise_sys()
12157{
12158 Q_Q(QWidget);
12159 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12160 q->windowHandle()->raise();
12161 } else if (renderToTexture) {
12162 if (QWidget *p = q->parentWidget()) {
12163 setDirtyOpaqueRegion();
12164 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12165 }
12166 }
12167}
12168
12169/*!
12170 Lowers the widget to the bottom of the parent widget's stack.
12171
12172 After this call the widget will be visually behind (and therefore
12173 obscured by) any overlapping sibling widgets.
12174
12175 \sa raise(), stackUnder()
12176*/
12177
12178void QWidget::lower()
12179{
12180 Q_D(QWidget);
12181 if (!isWindow()) {
12182 QWidget *p = parentWidget();
12183 const int parentChildCount = p->d_func()->children.size();
12184 if (parentChildCount < 2)
12185 return;
12186 const int from = p->d_func()->children.indexOf(this);
12187 Q_ASSERT(from >= 0);
12188 // Do nothing if the widget is already in correct stacking order _and_ created.
12189 if (from != 0)
12190 p->d_func()->children.move(from, 0);
12191 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12192 create();
12193 else if (from == 0)
12194 return;
12195 }
12196 if (testAttribute(Qt::WA_WState_Created))
12197 d->lower_sys();
12198
12199 if (d->extra && d->extra->hasWindowContainer)
12200 QWindowContainer::parentWasLowered(this);
12201
12202 QEvent e(QEvent::ZOrderChange);
12203 QCoreApplication::sendEvent(this, &e);
12204}
12205
12206void QWidgetPrivate::lower_sys()
12207{
12208 Q_Q(QWidget);
12209 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12210 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12211 q->windowHandle()->lower();
12212 } else if (QWidget *p = q->parentWidget()) {
12213 setDirtyOpaqueRegion();
12214 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12215 }
12216}
12217
12218/*!
12219 Places the widget under \a w in the parent widget's stack.
12220
12221 To make this work, the widget itself and \a w must be siblings.
12222
12223 \sa raise(), lower()
12224*/
12225void QWidget::stackUnder(QWidget* w)
12226{
12227 Q_D(QWidget);
12228 QWidget *p = parentWidget();
12229 if (!w || isWindow() || p != w->parentWidget() || this == w)
12230 return;
12231 if (p) {
12232 int from = p->d_func()->children.indexOf(this);
12233 int to = p->d_func()->children.indexOf(w);
12234 Q_ASSERT(from >= 0);
12235 Q_ASSERT(to >= 0);
12236 if (from < to)
12237 --to;
12238 // Do nothing if the widget is already in correct stacking order _and_ created.
12239 if (from != to)
12240 p->d_func()->children.move(from, to);
12241 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12242 create();
12243 else if (from == to)
12244 return;
12245 }
12246 if (testAttribute(Qt::WA_WState_Created))
12247 d->stackUnder_sys(w);
12248
12249 QEvent e(QEvent::ZOrderChange);
12250 QCoreApplication::sendEvent(this, &e);
12251}
12252
12253void QWidgetPrivate::stackUnder_sys(QWidget*)
12254{
12255 Q_Q(QWidget);
12256 if (QWidget *p = q->parentWidget()) {
12257 setDirtyOpaqueRegion();
12258 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12259 }
12260}
12261
12262/*!
12263 \fn bool QWidget::isTopLevel() const
12264 \deprecated
12265
12266 Use isWindow() instead.
12267*/
12268
12269/*!
12270 \fn bool QWidget::isRightToLeft() const
12271 \internal
12272*/
12273
12274/*!
12275 \fn bool QWidget::isLeftToRight() const
12276 \internal
12277*/
12278
12279/*!
12280 \macro QWIDGETSIZE_MAX
12281 \relates QWidget
12282
12283 Defines the maximum size for a QWidget object.
12284
12285 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12286 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12287
12288 \sa QWidget::setMaximumSize()
12289*/
12290
12291/*!
12292 \fn QWidget::setupUi(QWidget *widget)
12293
12294 Sets up the user interface for the specified \a widget.
12295
12296 \note This function is available with widgets that derive from user
12297 interface descriptions created using \l{uic}.
12298
12299 \sa {Using a Designer UI File in Your Application}
12300*/
12301
12302QRect QWidgetPrivate::frameStrut() const
12303{
12304 Q_Q(const QWidget);
12305 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12306 // x2 = x1 + w - 1, so w/h = 1
12307 return QRect(0, 0, 1, 1);
12308 }
12309
12310 if (data.fstrut_dirty
12311 // ### Fix properly for 4.3
12312 && q->isVisible()
12313 && q->testAttribute(Qt::WA_WState_Created))
12314 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12315
12316 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12317}
12318
12319void QWidgetPrivate::updateFrameStrut()
12320{
12321 Q_Q(QWidget);
12322 if (q->data->fstrut_dirty) {
12323 if (QTLWExtra *te = maybeTopData()) {
12324 if (te->window && te->window->handle()) {
12325 const QMargins margins = te->window->frameMargins();
12326 if (!margins.isNull()) {
12327 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12328 q->data->fstrut_dirty = false;
12329 }
12330 }
12331 }
12332 }
12333}
12334
12335#ifdef QT_KEYPAD_NAVIGATION
12336/*!
12337 \internal
12338
12339 Changes the focus from the current focusWidget to a widget in
12340 the \a direction.
12341
12342 Returns \c true, if there was a widget in that direction
12343*/
12344bool QWidgetPrivate::navigateToDirection(Direction direction)
12345{
12346 QWidget *targetWidget = widgetInNavigationDirection(direction);
12347 if (targetWidget)
12348 targetWidget->setFocus();
12349 return (targetWidget != 0);
12350}
12351
12352/*!
12353 \internal
12354
12355 Searches for a widget that is positioned in the \a direction, starting
12356 from the current focusWidget.
12357
12358 Returns the pointer to a found widget or \nullptr, if there was no widget
12359 in that direction.
12360*/
12361QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12362{
12363 const QWidget *sourceWidget = QApplication::focusWidget();
12364 if (!sourceWidget)
12365 return nullptr;
12366 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12367 const int sourceX =
12368 (direction == DirectionNorth || direction == DirectionSouth) ?
12369 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12370 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12371 const int sourceY =
12372 (direction == DirectionEast || direction == DirectionWest) ?
12373 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12374 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12375 const QPoint sourcePoint(sourceX, sourceY);
12376 const QPoint sourceCenter = sourceRect.center();
12377 const QWidget *sourceWindow = sourceWidget->window();
12378
12379 QWidget *targetWidget = nullptr;
12380 int shortestDistance = INT_MAX;
12381
12382 const auto targetCandidates = QApplication::allWidgets();
12383 for (QWidget *targetCandidate : targetCandidates) {
12384
12385 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12386
12387 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12388 // but the owner of the proxy cannot.
12389 // Additionally, empty widgets should be ignored.
12390 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12391 continue;
12392
12393 // Only navigate to a target widget that...
12394 if ( targetCandidate != sourceWidget
12395 // ...takes the focus,
12396 && targetCandidate->focusPolicy() & Qt::TabFocus
12397 // ...is above if DirectionNorth,
12398 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12399 // ...is on the right if DirectionEast,
12400 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12401 // ...is below if DirectionSouth,
12402 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12403 // ...is on the left if DirectionWest,
12404 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12405 // ...is enabled,
12406 && targetCandidate->isEnabled()
12407 // ...is visible,
12408 && targetCandidate->isVisible()
12409 // ...is in the same window,
12410 && targetCandidate->window() == sourceWindow) {
12411 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12412 const QRect &targetCandidateRect) {
12413 int dx = 0;
12414 int dy = 0;
12415 if (p.x() < r.left())
12416 dx = r.left() - p.x();
12417 else if (p.x() > r.right())
12418 dx = p.x() - r.right();
12419 if (p.y() < r.top())
12420 dy = r.top() - p.y();
12421 else if (p.y() > r.bottom())
12422 dy = p.y() - r.bottom();
12423 return dx + dy;
12424 }();
12425 if (targetCandidateDistance < shortestDistance) {
12426 shortestDistance = targetCandidateDistance;
12427 targetWidget = targetCandidate;
12428 }
12429 }
12430 }
12431 return targetWidget;
12432}
12433
12434/*!
12435 \internal
12436
12437 Tells us if it there is currently a reachable widget by keypad navigation in
12438 a certain \a orientation.
12439 If no navigation is possible, occurring key events in that \a orientation may
12440 be used to interact with the value in the focused widget, even though it
12441 currently has not the editFocus.
12442
12443 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12444*/
12445bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12446{
12447 return orientation == Qt::Horizontal?
12448 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12449 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12450 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12451 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12452}
12453/*!
12454 \internal
12455
12456 Checks, if the \a widget is inside a QTabWidget. If is is inside
12457 one, left/right key events will be used to switch between tabs in keypad
12458 navigation. If there is no QTabWidget, the horizontal key events can be used
12459to
12460 interact with the value in the focused widget, even though it currently has
12461 not the editFocus.
12462
12463 \sa QWidget::hasEditFocus()
12464*/
12465bool QWidgetPrivate::inTabWidget(QWidget *widget)
12466{
12467 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12468 if (qobject_cast<const QTabWidget*>(tabWidget))
12469 return true;
12470 return false;
12471}
12472#endif
12473
12474/*!
12475 \since 5.0
12476 \internal
12477
12478 Sets the backing store to be the \a store specified.
12479 The QWidget will take ownership of the \a store.
12480*/
12481void QWidget::setBackingStore(QBackingStore *store)
12482{
12483 // ### createWinId() ??
12484
12485 if (!isWindow())
12486 return;
12487
12488 Q_D(QWidget);
12489
12490 QTLWExtra *topData = d->topData();
12491 if (topData->backingStore == store)
12492 return;
12493
12494 QBackingStore *oldStore = topData->backingStore;
12495 delete topData->backingStore;
12496 topData->backingStore = store;
12497
12498 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12499 if (!repaintManager)
12500 return;
12501
12502 if (isWindow()) {
12503 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12504 delete repaintManager->backingStore();
12505 repaintManager->setBackingStore(store);
12506 }
12507}
12508
12509/*!
12510 \since 5.0
12511
12512 Returns the QBackingStore this widget will be drawn into.
12513*/
12514QBackingStore *QWidget::backingStore() const
12515{
12516 Q_D(const QWidget);
12517 QTLWExtra *extra = d->maybeTopData();
12518 if (extra && extra->backingStore)
12519 return extra->backingStore;
12520
12521 if (!isWindow())
12522 return window()->backingStore();
12523
12524 return nullptr;
12525}
12526
12527void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12528{
12529 if (left)
12530 *left = (int)leftLayoutItemMargin;
12531 if (top)
12532 *top = (int)topLayoutItemMargin;
12533 if (right)
12534 *right = (int)rightLayoutItemMargin;
12535 if (bottom)
12536 *bottom = (int)bottomLayoutItemMargin;
12537}
12538
12539void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12540{
12541 if (leftLayoutItemMargin == left
12542 && topLayoutItemMargin == top
12543 && rightLayoutItemMargin == right
12544 && bottomLayoutItemMargin == bottom)
12545 return;
12546
12547 Q_Q(QWidget);
12548 leftLayoutItemMargin = (signed char)left;
12549 topLayoutItemMargin = (signed char)top;
12550 rightLayoutItemMargin = (signed char)right;
12551 bottomLayoutItemMargin = (signed char)bottom;
12552 q->updateGeometry();
12553}
12554
12555void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12556{
12557 Q_Q(QWidget);
12558 QStyleOption myOpt;
12559 if (!opt) {
12560 myOpt.initFrom(q);
12561 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12562 opt = &myOpt;
12563 }
12564
12565 QRect liRect = q->style()->subElementRect(element, opt, q);
12566 if (liRect.isValid()) {
12567 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12568 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12569 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12570 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12571 } else {
12572 leftLayoutItemMargin = 0;
12573 topLayoutItemMargin = 0;
12574 rightLayoutItemMargin = 0;
12575 bottomLayoutItemMargin = 0;
12576 }
12577}
12578// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12579void QWidgetPrivate::adjustQuitOnCloseAttribute()
12580{
12581 Q_Q(QWidget);
12582
12583 if (!q->parentWidget()) {
12584 Qt::WindowType type = q->windowType();
12585 if (type == Qt::Widget || type == Qt::SubWindow)
12586 type = Qt::Window;
12587 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12588 q->setAttribute(Qt::WA_QuitOnClose, false);
12589 }
12590}
12591
12592void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12593{
12594 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12595 if (!wd->textureChildSeen)
12596 return;
12597 if (end)
12598 wd->endCompose();
12599 else
12600 wd->beginCompose();
12601 for (int i = 0; i < wd->children.size(); ++i) {
12602 w = qobject_cast<QWidget *>(wd->children.at(i));
12603 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12604 sendComposeStatus(w, end);
12605 }
12606}
12607
12608Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12609{
12610 return widget->data;
12611}
12612
12613Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12614{
12615 return widget->d_func();
12616}
12617
12618
12619#if QT_CONFIG(graphicsview)
12620/*!
12621 \since 4.5
12622
12623 Returns the proxy widget for the corresponding embedded widget in a graphics
12624 view; otherwise returns \nullptr.
12625
12626 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12627 QGraphicsScene::addWidget()
12628 */
12629QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12630{
12631 Q_D(const QWidget);
12632 if (d->extra) {
12633 return d->extra->proxyWidget;
12634 }
12635 return nullptr;
12636}
12637#endif
12638
12639#ifndef QT_NO_GESTURES
12640/*!
12641 Subscribes the widget to a given \a gesture with specific \a flags.
12642
12643 \sa ungrabGesture(), QGestureEvent
12644 \since 4.6
12645*/
12646void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12647{
12648 Q_D(QWidget);
12649 d->gestureContext.insert(gesture, flags);
12650 (void)QGestureManager::instance(); // create a gesture manager
12651}
12652
12653/*!
12654 Unsubscribes the widget from a given \a gesture type
12655
12656 \sa grabGesture(), QGestureEvent
12657 \since 4.6
12658*/
12659void QWidget::ungrabGesture(Qt::GestureType gesture)
12660{
12661 // if you modify this function, check the inlined version in ~QWidget, too
12662 Q_D(QWidget);
12663 if (d->gestureContext.remove(gesture)) {
12664 if (QGestureManager *manager = QGestureManager::instance())
12665 manager->cleanupCachedGestures(this, gesture);
12666 }
12667}
12668#endif // QT_NO_GESTURES
12669
12670/*!
12671 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12672
12673 Frees up window system resources. Destroys the widget window if \a
12674 destroyWindow is true.
12675
12676 destroy() calls itself recursively for all the child widgets,
12677 passing \a destroySubWindows for the \a destroyWindow parameter.
12678 To have more control over destruction of subwidgets, destroy
12679 subwidgets selectively first.
12680
12681 This function is usually called from the QWidget destructor.
12682*/
12683void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12684{
12685 Q_D(QWidget);
12686
12687 d->aboutToDestroy();
12688 if (!isWindow() && parentWidget())
12689 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12690 d->deactivateWidgetCleanup();
12691
12692 if ((windowType() == Qt::Popup) && qApp)
12693 qApp->d_func()->closePopup(this);
12694
12695 if (this == qApp->activeWindow())
12696 QApplicationPrivate::setActiveWindow(nullptr);
12697 if (QWidget::mouseGrabber() == this)
12698 releaseMouse();
12699 if (QWidget::keyboardGrabber() == this)
12700 releaseKeyboard();
12701
12702 setAttribute(Qt::WA_WState_Created, false);
12703
12704 if (destroySubWindows) {
12705 QObjectList childList(children());
12706 for (int i = 0; i < childList.size(); i++) {
12707 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12708 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12709 if (widget->windowHandle()) {
12710 widget->destroy();
12711 }
12712 }
12713 }
12714 }
12715 if (destroyWindow) {
12716 d->deleteTLSysExtra();
12717 } else {
12718 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12719 d->hide_sys();
12720 }
12721 }
12722
12723 d->setWinId(0);
12724}
12725
12726/*!
12727 \fn QPaintEngine *QWidget::paintEngine() const
12728
12729 Returns the widget's paint engine.
12730
12731 Note that this function should not be called explicitly by the
12732 user, since it's meant for reimplementation purposes only. The
12733 function is called by Qt internally, and the default
12734 implementation may not always return a valid pointer.
12735*/
12736QPaintEngine *QWidget::paintEngine() const
12737{
12738 qWarning("QWidget::paintEngine: Should no longer be called");
12739
12740#ifdef Q_OS_WIN
12741 // We set this bit which is checked in setAttribute for
12742 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12743 //
12744 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12745 // Windows which would mean suddenly their widgets stop working.
12746 //
12747 // 2. Users set paint on screen and subclass paintEngine() to
12748 // return 0, in which case we have a "hole" in the backingstore
12749 // allowing use of GDI or DirectX directly.
12750 //
12751 // 1 is WRONG, but to minimize silent failures, we have set this
12752 // bit to ignore the setAttribute call. 2. needs to be
12753 // supported because its our only means of embedding native
12754 // graphics stuff.
12755 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12756#endif
12757
12758 return nullptr; //##### @@@
12759}
12760
12761// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12762static inline bool canMapPosition(QWindow *window)
12763{
12764 return window->handle() && !qt_window_private(window)->resizeEventPending;
12765}
12766
12767#if QT_CONFIG(graphicsview)
12768static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12769{
12770 QGraphicsProxyWidget *result = nullptr;
12771 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12772 if (d->extra)
12773 result = d->extra->proxyWidget;
12774 return result;
12775}
12776#endif // QT_CONFIG(graphicsview)
12777
12779 QTransform transform;
12780 QWindow *window;
12781};
12782
12784{
12786 result.window = nullptr;
12787 for ( ; w ; w = w->parentWidget()) {
12788#if QT_CONFIG(graphicsview)
12789 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12790 if (const QGraphicsScene *scene = qgpw->scene()) {
12791 const QList <QGraphicsView *> views = scene->views();
12792 if (!views.isEmpty()) {
12793 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12794 result.transform *= viewP->mapToViewTransform(qgpw);
12795 w = views.first()->viewport();
12796 }
12797 }
12798 }
12799#endif // QT_CONFIG(graphicsview)
12800 QWindow *window = w->windowHandle();
12801 if (window && canMapPosition(window)) {
12802 result.window = window;
12803 break;
12804 }
12805
12806 const auto &geometry = w->geometry();
12807 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12808 if (w->isWindow())
12809 break;
12810 }
12811 return result;
12812}
12813
12814/*!
12815 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12816
12817 Translates the widget coordinate \a pos to global screen
12818 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12819 the global coordinates of the top-left pixel of the widget.
12820
12821 \sa mapFromGlobal(), mapTo(), mapToParent()
12822 \since 6.0
12823*/
12824QPointF QWidget::mapToGlobal(const QPointF &pos) const
12825{
12826 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12827 const QPointF g = t.transform.map(pos);
12828 return t.window ? t.window->mapToGlobal(g) : g;
12829}
12830
12831/*!
12832 \overload
12833*/
12834QPoint QWidget::mapToGlobal(const QPoint &pos) const
12835{
12836 return mapToGlobal(QPointF(pos)).toPoint();
12837}
12838
12839/*!
12840 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12841
12842 Translates the global screen coordinate \a pos to widget
12843 coordinates.
12844
12845 \sa mapToGlobal(), mapFrom(), mapFromParent()
12846 \since 6.0
12847*/
12848QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12849{
12850 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12851 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12852 return t.transform.inverted().map(windowLocal);
12853}
12854
12855/*!
12856 \overload
12857*/
12858QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12859{
12860 return mapFromGlobal(QPointF(pos)).toPoint();
12861}
12862
12864static bool mouseGrabWithCursor = false;
12865static QWidget *keyboardGrb = nullptr;
12866
12867static inline QWindow *grabberWindow(const QWidget *w)
12868{
12869 QWindow *window = w->windowHandle();
12870 if (!window)
12871 if (const QWidget *nativeParent = w->nativeParentWidget())
12872 window = nativeParent->windowHandle();
12873 return window;
12874}
12875
12876#ifndef QT_NO_CURSOR
12877static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12878#else
12879static void grabMouseForWidget(QWidget *widget)
12880#endif
12881{
12882 if (qt_mouseGrb)
12883 qt_mouseGrb->releaseMouse();
12884
12885 mouseGrabWithCursor = false;
12886 if (QWindow *window = grabberWindow(widget)) {
12887#ifndef QT_NO_CURSOR
12888 if (cursor) {
12889 mouseGrabWithCursor = true;
12890 QGuiApplication::setOverrideCursor(*cursor);
12891 }
12892#endif // !QT_NO_CURSOR
12893 window->setMouseGrabEnabled(true);
12894 }
12895
12896 qt_mouseGrb = widget;
12897}
12898
12900{
12901 if (qt_mouseGrb == widget) {
12902 if (QWindow *window = grabberWindow(widget)) {
12903#ifndef QT_NO_CURSOR
12904 if (mouseGrabWithCursor) {
12905 QGuiApplication::restoreOverrideCursor();
12906 mouseGrabWithCursor = false;
12907 }
12908#endif // !QT_NO_CURSOR
12909 window->setMouseGrabEnabled(false);
12910 }
12911 }
12912 qt_mouseGrb = nullptr;
12913}
12914
12915/*!
12916 \fn void QWidget::grabMouse()
12917
12918 Grabs the mouse input.
12919
12920 This widget receives all mouse events until releaseMouse() is
12921 called; other widgets get no mouse events at all. Keyboard
12922 events are not affected. Use grabKeyboard() if you want to grab
12923 that.
12924
12925 \warning Bugs in mouse-grabbing applications very often lock the
12926 terminal. Use this function with extreme caution, and consider
12927 using the \c -nograb command line option while debugging.
12928
12929 It is seldom necessary to grab the mouse when using Qt, as
12930 Qt grabs and releases it sensibly. In particular, Qt grabs the
12931 mouse when a mouse button is pressed and keeps it until the last
12932 button is released.
12933
12934 \note Only visible widgets can grab mouse input. If isVisible()
12935 returns \c false for a widget, that widget cannot call grabMouse().
12936
12937 \note On Windows, grabMouse() only works when the mouse is inside a window
12938 owned by the process.
12939 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12940
12941 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12942*/
12943void QWidget::grabMouse()
12944{
12945 grabMouseForWidget(this);
12946}
12947
12948/*!
12949 \fn void QWidget::grabMouse(const QCursor &cursor)
12950 \overload grabMouse()
12951
12952 Grabs the mouse input and changes the cursor shape.
12953
12954 The cursor will assume shape \a cursor (for as long as the mouse
12955 focus is grabbed) and this widget will be the only one to receive
12956 mouse events until releaseMouse() is called().
12957
12958 \warning Grabbing the mouse might lock the terminal.
12959
12960 \note See the note in QWidget::grabMouse().
12961
12962 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12963*/
12964#ifndef QT_NO_CURSOR
12965void QWidget::grabMouse(const QCursor &cursor)
12966{
12967 grabMouseForWidget(this, &cursor);
12968}
12969#endif
12970
12971bool QWidgetPrivate::stealMouseGrab(bool grab)
12972{
12973 // This is like a combination of grab/releaseMouse() but with error checking
12974 // and it has no effect on the result of mouseGrabber().
12975 Q_Q(QWidget);
12976 QWindow *window = grabberWindow(q);
12977 return window ? window->setMouseGrabEnabled(grab) : false;
12978}
12979
12980/*!
12981 \fn void QWidget::releaseMouse()
12982
12983 Releases the mouse grab.
12984
12985 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12986*/
12987void QWidget::releaseMouse()
12988{
12989 releaseMouseGrabOfWidget(this);
12990}
12991
12992/*!
12993 \fn void QWidget::grabKeyboard()
12994
12995 Grabs the keyboard input.
12996
12997 This widget receives all keyboard events until releaseKeyboard()
12998 is called; other widgets get no keyboard events at all. Mouse
12999 events are not affected. Use grabMouse() if you want to grab that.
13000
13001 The focus widget is not affected, except that it doesn't receive
13002 any keyboard events. setFocus() moves the focus as usual, but the
13003 new focus widget receives keyboard events only after
13004 releaseKeyboard() is called.
13005
13006 If a different widget is currently grabbing keyboard input, that
13007 widget's grab is released first.
13008
13009 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
13010*/
13011void QWidget::grabKeyboard()
13012{
13013 if (keyboardGrb)
13014 keyboardGrb->releaseKeyboard();
13015 if (QWindow *window = grabberWindow(this))
13016 window->setKeyboardGrabEnabled(true);
13017 keyboardGrb = this;
13018}
13019
13020bool QWidgetPrivate::stealKeyboardGrab(bool grab)
13021{
13022 // This is like a combination of grab/releaseKeyboard() but with error
13023 // checking and it has no effect on the result of keyboardGrabber().
13024 Q_Q(QWidget);
13025 QWindow *window = grabberWindow(q);
13026 return window ? window->setKeyboardGrabEnabled(grab) : false;
13027}
13028
13029/*!
13030 \fn void QWidget::releaseKeyboard()
13031
13032 Releases the keyboard grab.
13033
13034 \sa grabKeyboard(), grabMouse(), releaseMouse()
13035*/
13036void QWidget::releaseKeyboard()
13037{
13038 if (keyboardGrb == this) {
13039 if (QWindow *window = grabberWindow(this))
13040 window->setKeyboardGrabEnabled(false);
13041 keyboardGrb = nullptr;
13042 }
13043}
13044
13045/*!
13046 \fn QWidget *QWidget::mouseGrabber()
13047
13048 Returns the widget that is currently grabbing the mouse input.
13049
13050 If no widget in this application is currently grabbing the mouse,
13051 \nullptr is returned.
13052
13053 \sa grabMouse(), keyboardGrabber()
13054*/
13055QWidget *QWidget::mouseGrabber()
13056{
13057 return qt_mouseGrb;
13058}
13059
13060/*!
13061 \fn QWidget *QWidget::keyboardGrabber()
13062
13063 Returns the widget that is currently grabbing the keyboard input.
13064
13065 If no widget in this application is currently grabbing the
13066 keyboard, \nullptr is returned.
13067
13068 \sa grabMouse(), mouseGrabber()
13069*/
13070QWidget *QWidget::keyboardGrabber()
13071{
13072 return keyboardGrb;
13073}
13074
13075/*!
13076 \fn void QWidget::activateWindow()
13077
13078 Sets the top-level widget containing this widget to be the active
13079 window.
13080
13081 An active window is a visible top-level window that has the
13082 keyboard input focus.
13083
13084 This function performs the same operation as clicking the mouse on
13085 the title bar of a top-level window. On X11, the result depends on
13086 the Window Manager. If you want to ensure that the window is
13087 stacked on top as well you should also call raise(). Note that the
13088 window must be visible, otherwise activateWindow() has no effect.
13089
13090 On Windows, if you are calling this when the application is not
13091 currently the active one then it will not make it the active
13092 window. It will change the color of the taskbar entry to indicate
13093 that the window has changed in some way. This is because Microsoft
13094 does not allow an application to interrupt what the user is currently
13095 doing in another application.
13096
13097 \sa isActiveWindow(), window(), show()
13098*/
13099void QWidget::activateWindow()
13100{
13101 QWindow *const wnd = window()->windowHandle();
13102
13103 if (wnd)
13104 wnd->requestActivate();
13105}
13106
13107/*!
13108
13109 Internal implementation of the virtual QPaintDevice::metric()
13110 function.
13111
13112 \a m is the metric to get.
13113*/
13114int QWidget::metric(PaintDeviceMetric m) const
13115{
13116 QScreen *screen = this->screen();
13117
13118 if (!screen) {
13119 if (m == PdmDpiX || m == PdmDpiY)
13120 return 72;
13121 return QPaintDevice::metric(m);
13122 }
13123
13124 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
13125
13126 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
13127 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
13128 QWindow *window = this->window()->windowHandle();
13129 if (window)
13130 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
13131 return screen->devicePixelRatio();
13132 };
13133
13134 switch (m) {
13135 case PdmWidth:
13136 return data->crect.width();
13137 case PdmWidthMM:
13138 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
13139 case PdmHeight:
13140 return data->crect.height();
13141 case PdmHeightMM:
13142 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13143 case PdmDepth:
13144 return screen->depth();
13145 case PdmDpiX:
13146 for (const QWidget *p = this; p; p = p->parentWidget()) {
13147 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13148 return p->d_func()->extra->customDpiX;
13149 }
13150 return qRound(screen->logicalDotsPerInchX());
13151 case PdmDpiY:
13152 for (const QWidget *p = this; p; p = p->parentWidget()) {
13153 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13154 return p->d_func()->extra->customDpiY;
13155 }
13156 return qRound(screen->logicalDotsPerInchY());
13157 case PdmPhysicalDpiX:
13158 return qRound(screen->physicalDotsPerInchX());
13159 case PdmPhysicalDpiY:
13160 return qRound(screen->physicalDotsPerInchY());
13161 case PdmDevicePixelRatio:
13162 return resolveDevicePixelRatio();
13163 case PdmDevicePixelRatioScaled:
13164 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13165 case PdmDevicePixelRatioF_EncodedA:
13166 Q_FALLTHROUGH();
13167 case PdmDevicePixelRatioF_EncodedB:
13168 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
13169 default:
13170 break;
13171 }
13172 return QPaintDevice::metric(m);
13173}
13174
13175/*!
13176 Initializes the \a painter pen, background and font to the same as
13177 the given widget's. This function is called automatically when the
13178 painter is opened on a QWidget.
13179*/
13180void QWidget::initPainter(QPainter *painter) const
13181{
13182 const QPalette &pal = palette();
13183 QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
13184
13185 painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
13186 painterPrivate->state->bgBrush = pal.brush(backgroundRole());
13187 QFont f(font(), this);
13188 painterPrivate->state->deviceFont = f;
13189 painterPrivate->state->font = f;
13190
13191 painterPrivate->setEngineDirtyFlags({
13192 QPaintEngine::DirtyPen,
13193 QPaintEngine::DirtyBrush,
13194 QPaintEngine::DirtyFont,
13195 });
13196
13197 if (painterPrivate->extended)
13198 painterPrivate->extended->penChanged();
13199}
13200
13201/*!
13202 \internal
13203
13204 Do PaintDevice rendering with the specified \a offset.
13205*/
13206QPaintDevice *QWidget::redirected(QPoint *offset) const
13207{
13208 return d_func()->redirected(offset);
13209}
13210
13211/*!
13212 \internal
13213
13214 A painter that is shared among other instances of QPainter.
13215*/
13216QPainter *QWidget::sharedPainter() const
13217{
13218 // Someone sent a paint event directly to the widget
13219 if (!d_func()->redirectDev)
13220 return nullptr;
13221
13222 QPainter *sp = d_func()->sharedPainter();
13223 if (!sp || !sp->isActive())
13224 return nullptr;
13225
13226 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13227 return nullptr;
13228
13229 return sp;
13230}
13231
13232/*!
13233 \fn void QWidget::setMask(const QRegion &region)
13234 \overload
13235
13236 Causes only the parts of the widget which overlap \a region to be
13237 visible. If the region includes pixels outside the rect() of the
13238 widget, window system controls in that area may or may not be
13239 visible, depending on the platform.
13240
13241 Since QRegion allows arbitrarily complex regions to be created, widget
13242 masks can be made to suit the most unconventionally-shaped windows, and
13243 even allow widgets to be displayed with holes in them. Note that this
13244 effect can be slow if the region is particularly complex.
13245
13246 Widget masks are used to hint to the window system that the application
13247 does not want mouse events for areas outside the mask. On most systems,
13248 they also result in coarse visual clipping. To get smooth window edges, use
13249 translucent background and anti-aliased painting instead, as shown in the
13250 \l{Translucent Background} example.
13251
13252 \sa windowOpacity
13253*/
13254void QWidget::setMask(const QRegion &newMask)
13255{
13256 Q_D(QWidget);
13257
13258 d->createExtra();
13259 if (newMask == d->extra->mask)
13260 return;
13261
13262#ifndef QT_NO_BACKINGSTORE
13263 const QRegion oldMask(d->extra->mask);
13264#endif
13265
13266 d->extra->mask = newMask;
13267 d->extra->hasMask = !newMask.isEmpty();
13268
13269 if (!testAttribute(Qt::WA_WState_Created))
13270 return;
13271
13272 d->setMask_sys(newMask);
13273
13274#ifndef QT_NO_BACKINGSTORE
13275 if (!isVisible())
13276 return;
13277
13278 if (!d->extra->hasMask) {
13279 // Mask was cleared; update newly exposed area.
13280 QRegion expose(rect());
13281 expose -= oldMask;
13282 if (!expose.isEmpty()) {
13283 d->setDirtyOpaqueRegion();
13284 update(expose);
13285 }
13286 return;
13287 }
13288
13289 if (!isWindow()) {
13290 // Update newly exposed area on the parent widget.
13291 QRegion parentExpose(rect());
13292 parentExpose -= newMask;
13293 if (!parentExpose.isEmpty()) {
13294 d->setDirtyOpaqueRegion();
13295 parentExpose.translate(data->crect.topLeft());
13296 parentWidget()->update(parentExpose);
13297 }
13298
13299 // Update newly exposed area on this widget
13300 if (!oldMask.isEmpty())
13301 update(newMask - oldMask);
13302 }
13303#endif
13304}
13305
13306void QWidgetPrivate::setMask_sys(const QRegion &region)
13307{
13308 Q_Q(QWidget);
13309 if (QWindow *window = q->windowHandle())
13310 window->setMask(region);
13311}
13312
13313/*!
13314 \fn void QWidget::setMask(const QBitmap &bitmap)
13315
13316 Causes only the pixels of the widget for which \a bitmap has a
13317 corresponding 1 bit to be visible. If the region includes pixels
13318 outside the rect() of the widget, window system controls in that
13319 area may or may not be visible, depending on the platform.
13320
13321 Note that this effect can be slow if the region is particularly
13322 complex.
13323
13324 The following code shows how an image with an alpha channel can be
13325 used to generate a mask for a widget:
13326
13327 \snippet widget-mask/main.cpp 0
13328
13329 The label shown by this code is masked using the image it contains,
13330 giving the appearance that an irregularly-shaped image is being drawn
13331 directly onto the screen.
13332
13333 Masked widgets receive mouse events only on their visible
13334 portions.
13335
13336 \sa clearMask(), windowOpacity()
13337*/
13338void QWidget::setMask(const QBitmap &bitmap)
13339{
13340 setMask(QRegion(bitmap));
13341}
13342
13343/*!
13344 \fn void QWidget::clearMask()
13345
13346 Removes any mask set by setMask().
13347
13348 \sa setMask()
13349*/
13350void QWidget::clearMask()
13351{
13352 Q_D(QWidget);
13353 if (!d->extra || !d->extra->hasMask)
13354 return;
13355 setMask(QRegion());
13356}
13357
13358void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13359{
13360 Q_ASSERT(widgetAsObject->isWidgetType());
13361 Q_ASSERT(!newParent || newParent->isWidgetType());
13362 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13363 widget->setParent(static_cast<QWidget*>(newParent));
13364}
13365
13366std::string QWidgetPrivate::flagsForDumping() const
13367{
13368 Q_Q(const QWidget);
13369 std::string flags = QObjectPrivate::flagsForDumping();
13370 if (QApplication::focusWidget() == q)
13371 flags += 'F';
13372 if (q->isVisible()) {
13373 std::stringstream s;
13374 s << '<'
13375 << q->width() << 'x' << q->height()
13376 << std::showpos << q->x() << q->y()
13377 << '>';
13378 flags += s.str();
13379 } else {
13380 flags += 'I';
13381 }
13382 return flags;
13383}
13384
13385void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13386{
13387#if QT_CONFIG(xcb)
13388 Q_Q(QWidget);
13389
13390 if (!q->windowHandle())
13391 return;
13392
13393 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13394 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13395 wmWindowType |= QXcbWindow::Desktop;
13396 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13397 wmWindowType |= QXcbWindow::Dock;
13398 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13399 wmWindowType |= QXcbWindow::Toolbar;
13400 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13401 wmWindowType |= QXcbWindow::Menu;
13402 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13403 wmWindowType |= QXcbWindow::Utility;
13404 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13405 wmWindowType |= QXcbWindow::Splash;
13406 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13407 wmWindowType |= QXcbWindow::Dialog;
13408 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13409 wmWindowType |= QXcbWindow::DropDownMenu;
13410 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13411 wmWindowType |= QXcbWindow::PopupMenu;
13412 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13413 wmWindowType |= QXcbWindow::Tooltip;
13414 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13415 wmWindowType |= QXcbWindow::Notification;
13416 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13417 wmWindowType |= QXcbWindow::Combo;
13418 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13419 wmWindowType |= QXcbWindow::Dnd;
13420
13421 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13422 return;
13423
13424 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13425 xcbWindow->setWindowType(wmWindowType);
13426#else
13427 Q_UNUSED(skipIfMissing);
13428#endif
13429}
13430
13431/*!
13432 \internal
13433 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13434 Return false otherwise.
13435 */
13436bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13437{
13438 Q_Q(const QWidget);
13439 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13440 for (const auto *child : children) {
13441 if (child->focusPolicy() == policy && child->isEnabled()
13442 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13443 return true;
13444 }
13445 }
13446 return false;
13447}
13448
13449#ifndef QT_NO_DEBUG_STREAM
13450
13451namespace {
13452QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13453{
13454 const QDebugStateSaver saver(debug);
13455 debug.nospace();
13456 debug << '[';
13457 if (const QWidget *widget = attributes.widget) {
13458 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13459 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13460 int count = 0;
13461 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13462 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13463 if (count++)
13464 debug << ',';
13465 debug << me.valueToKey(a);
13466 }
13467 }
13468 }
13469 debug << ']';
13470 return debug;
13471}
13472}
13473
13474QDebug operator<<(QDebug debug, const QWidget *widget)
13475{
13476 const QDebugStateSaver saver(debug);
13477 debug.nospace();
13478 if (widget) {
13479 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13480 if (!widget->objectName().isEmpty())
13481 debug << ", name=" << widget->objectName();
13482 if (debug.verbosity() > 2) {
13483 const QRect geometry = widget->geometry();
13484 const QRect frameGeometry = widget->frameGeometry();
13485 if (widget->isVisible())
13486 debug << ", visible";
13487 if (!widget->isEnabled())
13488 debug << ", disabled";
13489 debug << ", states=" << widget->windowState()
13490 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13491 debug << ", attributes=" << WidgetAttributes{widget};
13492 if (widget->isWindow())
13493 debug << ", window";
13494 debug << ", " << geometry.width() << 'x' << geometry.height()
13495 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13496 if (frameGeometry != geometry) {
13497 const QMargins margins(geometry.x() - frameGeometry.x(),
13498 geometry.y() - frameGeometry.y(),
13499 frameGeometry.right() - geometry.right(),
13500 frameGeometry.bottom() - geometry.bottom());
13501 debug << ", margins=" << margins;
13502 }
13503 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13504 if (const WId wid = widget->internalWinId())
13505 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13506 }
13507 debug << ')';
13508 } else {
13509 debug << "QWidget(0x0)";
13510 }
13511 return debug;
13512}
13513#endif // !QT_NO_DEBUG_STREAM
13514
13515
13516// *************************** Focus abstraction ************************************
13517
13518#define FOCUS_NEXT(w) w->d_func()->focus_next
13519#define FOCUS_PREV(w) w->d_func()->focus_prev
13520
13521/*!
13522 \internal
13523 \return next or previous element in the focus chain, depending on
13524 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13525 */
13526QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13527{
13528 Q_Q(const QWidget);
13529 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13530}
13531
13532/*!
13533 \internal
13534 Removes a widget from the focus chain, respecting the flags set in \param rules.
13535 \list
13536 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13537 in the focus chain, depending on \param direction.
13538 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13539 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13540 \endlist
13541 \return \c true if the widget has been removed, otherwise \c false.
13542 */
13543bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13544{
13545 Q_Q(QWidget);
13546 if (!isFocusChainConsistent()) {
13547#ifdef QT_DEBUG
13548 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13549 qFatal() << q << "has inconsistent focus chain.";
13550#endif
13551 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13552 return false;
13553 }
13554
13555 if (!isInFocusChain()) {
13556 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13557 return false;
13558 }
13559
13560 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13561 q->focusNextPrevChild(direction == FocusDirection::Next);
13562
13565 initFocusChain();
13566 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13567 return true;
13568}
13569
13570/*!
13571 \internal
13572 Initialises the focus chain by making the widget point to itself.
13573 */
13574void QWidgetPrivate::initFocusChain()
13575{
13576 Q_Q(QWidget);
13577 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13578 FOCUS_PREV(q) = q;
13579 FOCUS_NEXT(q) = q;
13580}
13581
13582/*!
13583 \internal
13584 Reads QWidget children, which are not part of a focus chain yet.
13585 Inserts them into the focus chain before or after the widget,
13586 depending on \param direction and in the order of their creation.
13587 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13588 */
13589void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13590{
13591 Q_Q(QWidget);
13592
13593 // separate the focus chain into new (children of myself) and old (the rest)
13594 QWidget *firstOld = nullptr;
13595 QWidget *lastOld = nullptr; // last in the old list
13596 QWidget *lastNew = q; // last in the new list
13597 bool prevWasNew = true;
13598 QWidget *widget = nextPrevElementInFocusChain(direction);
13599
13600 // For efficiency, do not maintain the list invariant inside the loop.
13601 // Append items to the relevant list, and we optimize by not changing pointers,
13602 // when subsequent items are going into the same list.
13603 while (widget != q) {
13604 bool currentIsNew = q->isAncestorOf(widget);
13605 if (currentIsNew) {
13606 if (!prevWasNew) {
13607 // previous was old => append to new list
13608 FOCUS_NEXT(lastNew) = widget;
13609 FOCUS_PREV(widget) = lastNew;
13610 }
13611 lastNew = widget;
13612 } else {
13613 if (prevWasNew) {
13614 // prev was new => append to old list, if it exists
13615 if (lastOld) {
13616 FOCUS_NEXT(lastOld) = widget;
13617 FOCUS_PREV(widget) = lastOld;
13618 } else {
13619 // start the old list
13620 firstOld = widget;
13621 }
13622 }
13623 lastOld = widget;
13624 }
13625 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13626 prevWasNew = currentIsNew;
13627 }
13628
13629 // repair old list:
13630 if (firstOld) {
13631 FOCUS_NEXT(lastOld) = firstOld;
13632 FOCUS_PREV(firstOld) = lastOld;
13633 }
13634
13635 if (!q->isWindow()) {
13636 QWidget *topLevel = q->window();
13637 // insert new chain into toplevel's chain
13638 QWidget *prev = FOCUS_PREV(topLevel);
13639 FOCUS_PREV(topLevel) = lastNew;
13640 FOCUS_NEXT(prev) = q;
13641 FOCUS_PREV(q) = prev;
13642 FOCUS_NEXT(lastNew) = topLevel;
13643 } else {
13644 // repair new list
13645 FOCUS_NEXT(lastNew) = q;
13646 FOCUS_PREV(q) = lastNew;
13647 }
13648}
13649
13650/*!
13651 \internal
13652 Inserts a widget into the focus chain before or after \param position, depending on
13653 \param direction.
13654 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13655 */
13656bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13657{
13658 Q_Q(QWidget);
13659 Q_ASSERT(position);
13660 QWidget *next = FOCUS_NEXT(q);
13661 QWidget *previous = FOCUS_PREV(q);
13662
13663 switch (direction) {
13664 case FocusDirection::Next:
13665 if (previous == position) {
13666 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13667 return false;
13668 }
13669
13670 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13671
13672 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13673 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13674 FOCUS_NEXT(position) = q;
13675 FOCUS_PREV(q) = position;
13676 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13677 break;
13678
13679 case FocusDirection::Previous:
13680 if (next == position) {
13681 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13682 return false;
13683 }
13684
13685 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13686
13687 FOCUS_PREV(q) = FOCUS_PREV(position);
13688 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13689 FOCUS_PREV(position) = q;
13690 FOCUS_NEXT(q) = position;
13691 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13692 break;
13693 }
13694
13695 Q_ASSERT(isFocusChainConsistent());
13696 return true;
13697}
13698
13699/*!
13700 \internal
13701 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13702 before or after \param position, depending on \param direction.
13703 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13704 \note
13705 \param toBeInserted must be a consistent focus chain.
13706 */
13707bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13708 FocusDirection direction, QWidget *position)
13709{
13710 if (toBeInserted.isEmpty()) {
13711 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13712 return false;
13713 }
13714
13715 Q_ASSERT_X(!toBeInserted.contains(position),
13716 Q_FUNC_INFO,
13717 "Coding error: toBeInserted contains position");
13718
13719 QWidget *first = toBeInserted.constFirst();
13720 QWidget *last = toBeInserted.constLast();
13721
13722 // Call QWidget override to log accordingly
13723 if (toBeInserted.count() == 1)
13724 return first->d_func()->insertIntoFocusChain(direction, position);
13725
13726 Q_ASSERT(first != last);
13727 switch (direction) {
13728 case FocusDirection::Previous:
13729 if (FOCUS_PREV(position) == last) {
13730 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13731 << position;
13732 return false;
13733 }
13734 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13735 FOCUS_PREV(first) = FOCUS_PREV(position);
13736 FOCUS_NEXT(last) = position;
13737 FOCUS_PREV(position) = last;
13738 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13739 break;
13740 case FocusDirection::Next:
13741 if (FOCUS_PREV(position) == last) {
13742 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13743 << position;
13744 return false;
13745 }
13746 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13747 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13748 FOCUS_PREV(first) = position;
13749 FOCUS_NEXT(position) = first;
13750 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13751 break;
13752 }
13753
13754 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13755 return true;
13756}
13757
13758/*!
13759 \internal
13760 \return a QWidgetList, representing the part of the focus chain,
13761 starting with \param from and ending with \param to, in \param direction.
13762 */
13763QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13764{
13765 QWidgetList path({from});
13766 if (from == to)
13767 return path;
13768
13769 QWidget *current = from;
13770 do {
13771 switch (direction) {
13772 case QWidgetPrivate::FocusDirection::Previous:
13773 current = current->previousInFocusChain();
13774 break;
13775 case QWidgetPrivate::FocusDirection::Next:
13776 current = current->nextInFocusChain();
13777 break;
13778 }
13779 if (path.contains(current))
13780 return QWidgetList();
13781 path << current;
13782 } while (current != to);
13783
13784 return path;
13785}
13786
13787/*!
13788 \internal
13789 Removes the part from the focus chain starting with \param from and ending with \param to,
13790 in \param direction.
13791 \return removed part as a QWidgetList.
13792 */
13793QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13794 QWidget *to,
13795 FocusDirection direction)
13796{
13797 // Check if there is a path from->to in direction
13798 const QWidgetList path = focusPath(from, to , direction);
13799 if (path.isEmpty()) {
13800 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13801 return QWidgetList();
13802 }
13803
13804 QWidget *first = path.constFirst();
13805 QWidget *last = path.constLast();
13806 if (first == last) {
13807 first->d_func()->removeFromFocusChain();
13808 return QWidgetList({first});
13809 }
13810
13811 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13812 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13813 FOCUS_PREV(first) = last;
13814 FOCUS_NEXT(last) = first;
13815 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13816 return path;
13817}
13818
13819/*!
13820 \internal
13821 \return The last focus child of the widget, traversing the focus chain no further than
13822 \param noFurtherThan.
13823 */
13824QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13825{
13826 Q_Q(QWidget);
13827 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13828 // that determines the last focus child for a widget, taking proxies and compound widgets into
13829 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13830 // to a child), 'lastFocusChild' will be set to the target itself.
13831 QWidget *lastFocusChild = q;
13832
13833 QWidget *focusProxy = deepestFocusProxy();
13834 if (!focusProxy) {
13835 // QTBUG-81097: Another case is possible here. We can have a child
13836 // widget, that sets its focusProxy() to the parent (target).
13837 // An example of such widget is a QLineEdit, nested into
13838 // a QAbstractSpinBox. In this case such widget should be considered
13839 // the last focus child.
13840 for (auto *object : std::as_const(q->children())) {
13841 QWidget *w = qobject_cast<QWidget *>(object);
13842 if (w && w->focusProxy() == q) {
13843 lastFocusChild = w;
13844 break;
13845 }
13846 }
13847 } else if (q->isAncestorOf(focusProxy)) {
13848 lastFocusChild = focusProxy;
13849 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13850 focusNext != focusProxy && q->isAncestorOf(focusNext)
13851 && focusNext->window() == focusProxy->window();
13852 focusNext = focusNext->nextInFocusChain()) {
13853 if (focusNext == noFurtherThan)
13854 break;
13855 if (focusNext->focusPolicy() != Qt::NoFocus)
13856 lastFocusChild = focusNext;
13857 }
13858 }
13859 return lastFocusChild;
13860};
13861
13862/*!
13863 \internal
13864 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13865 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13866 are pointing to the widget itself.
13867
13868 \note
13869 This method doesn't check the consistency of the focus chain.
13870 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13871 isInFocusChain() will return \c true for all of those widgets, even if they represent
13872 an inconsistent focus chain.
13873 */
13874bool QWidgetPrivate::isInFocusChain() const
13875{
13876 Q_Q(const QWidget);
13877 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13878}
13879
13880/*!
13881 \internal
13882 A focus chain is consistent, when it is circular: Following the chain in either direction
13883 has to return to the beginning. This is why a newly constructed widget points to itself,
13884 when the focus chain has been initialized. A newly constructed widget is considered to have
13885 a consistent focus chain, while not being part of a focus chain.
13886
13887 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13888 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13889 It returns \c false, if one of the following is detected:
13890 \list
13891 \li nullptr found in a previous/next pointer.
13892 \li broken chain: widget A is B's previous, but B isn't A's next.
13893 \li chain isn't closed: starting at A doesn't lead back to A.
13894 \endlist
13895 It return \c true, if none of the above is observed.
13896
13897 \note
13898 The focus chain is checked only in forward direction.
13899 This is sufficient, because the check for a broken chain asserts consistent paths
13900 in both directions.
13901 */
13902bool QWidgetPrivate::isFocusChainConsistent() const
13903{
13904 Q_Q(const QWidget);
13905 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13906 if (skip)
13907 return true;
13908
13909 if (!isInFocusChain())
13910 return true;
13911
13912 const QWidget *position = q;
13913
13914 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13915 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13916 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13917 << "Previous pointing to" << FOCUS_PREV(position)
13918 << "Next pointing to" << FOCUS_NEXT(position);
13919 return false;
13920 }
13921 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13922 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13923 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13924 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13925 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13926 return false;
13927 }
13928 position = FOCUS_NEXT(position);
13929 if (position == q)
13930 return true;
13931
13932 }
13933
13934 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13935 return false;
13936}
13937
13938#undef FOCUS_NEXT
13939#undef FOCUS_PREV
13940
13941
13942QT_END_NAMESPACE
13943
13944#include "moc_qwidget.cpp"
13945#include "moc_qwidget_p.cpp"
friend class QWidgetPrivate
friend class QWidget
Definition qpainter.h:432
\inmodule QtWidgets
Definition qwidget_p.h:184
void qt_qpa_set_cursor(QWidget *w, bool force)
Definition qwidget.cpp:5108
#define qApp
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static bool canMapPosition(QWindow *window)
static void unsetCursor(QWidget *w)
Definition qwidget.cpp:5102
void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
Definition qwidget.cpp:1267
QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
Returns a modified window title with the [*] place holder replaced according to the rules described i...
Definition qwidget.cpp:6086
static void sendResizeEvents(QWidget *target)
Definition qwidget.cpp:5282
static void applyCursor(QWidget *w, const QCursor &c)
Definition qwidget.cpp:5096
#define FOCUS_PREV(w)
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6730
static void releaseMouseGrabOfWidget(QWidget *widget)
#define FOCUS_NEXT(w)
static void grabMouseForWidget(QWidget *widget, const QCursor *cursor=nullptr)
QWidget * qt_button_down
Definition qwidget.cpp:2371
static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data, QWidgetPrivate *d)
void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
static bool qRectIntersects(const QRect &r1, const QRect &r2)
Definition qwidget.cpp:101
bool qt_sendSpontaneousEvent(QObject *, QEvent *)
QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1136
static QWidget * keyboardGrb
QWidget * qt_mouseGrb
static bool mouseGrabWithCursor
static QWindow * grabberWindow(const QWidget *w)
static void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
Definition qwidget.cpp:2290
static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1110
#define QWIDGETSIZE_MAX
Definition qwidget.h:922
static void cleanup(QWidget *that, QWidgetPrivate *d)
Definition qwidget.cpp:821