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/private/qhighdpiscaling_p.h>
48#include <QtGui/qinputmethod.h>
49
50#if QT_CONFIG(graphicseffect)
51#include <private/qgraphicseffect_p.h>
52#endif
53#include <qbackingstore.h>
54#include <private/qwidgetrepaintmanager_p.h>
55#include <private/qpaintengine_raster_p.h>
56
57#include "qwidget_p.h"
58#include <QtGui/private/qwindow_p.h>
59#if QT_CONFIG(action)
60# include "QtGui/private/qaction_p.h"
61#endif
62#include "qlayout_p.h"
63#if QT_CONFIG(graphicsview)
64#include "QtWidgets/qgraphicsproxywidget.h"
65#include "QtWidgets/qgraphicsscene.h"
66#include "private/qgraphicsproxywidget_p.h"
67#include "private/qgraphicsview_p.h"
68#endif
69#include "QtWidgets/qabstractscrollarea.h"
70#include "private/qabstractscrollarea_p.h"
71#include "private/qevent_p.h"
72
73#include "private/qgesturemanager_p.h"
74
75#ifdef QT_KEYPAD_NAVIGATION
76#if QT_CONFIG(tabwidget)
77#include "qtabwidget.h" // Needed in inTabWidget()
78#endif
79#endif // QT_KEYPAD_NAVIGATION
80
82
83#include <sstream>
84
85QT_BEGIN_NAMESPACE
86
87using namespace QNativeInterface::Private;
88using namespace Qt::StringLiterals;
89
90Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
91Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
92Q_STATIC_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
93Q_STATIC_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
94
95#ifndef QT_NO_DEBUG_STREAM
96namespace {
97 struct WidgetAttributes { const QWidget *widget; };
98 QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
99}
100#endif
101
102static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
103{
104 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
105 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
106}
107
108extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
109
110static void setAttribute_internal(Qt::WidgetAttribute attribute,
111 bool on, QWidgetData *data, QWidgetPrivate *d);
112
113QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
114 : QObjectPrivate(version)
115 , focus_next(nullptr)
116 , focus_prev(nullptr)
117 , focus_child(nullptr)
118 , layout(nullptr)
119 , needsFlush(nullptr)
120 , redirectDev(nullptr)
121 , widgetItem(nullptr)
122 , extraPaintEngine(nullptr)
123 , polished(nullptr)
124 , graphicsEffect(nullptr)
125#if !defined(QT_NO_IM)
126 , imHints(Qt::ImhNone)
127#endif
128#if QT_CONFIG(tooltip)
129 , toolTipDuration(-1)
130#endif
131 , directFontResolveMask(0)
132 , inheritedFontResolveMask(0)
133 , directPaletteResolveMask(0)
134 , inheritedPaletteResolveMask(0)
135 , leftmargin(0)
136 , topmargin(0)
137 , rightmargin(0)
138 , bottommargin(0)
139 , leftLayoutItemMargin(0)
140 , topLayoutItemMargin(0)
141 , rightLayoutItemMargin(0)
142 , bottomLayoutItemMargin(0)
143 , hd(nullptr)
144 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
145 , fg_role(QPalette::NoRole)
146 , bg_role(QPalette::NoRole)
147 , dirtyOpaqueChildren(1)
148 , isOpaque(0)
149 , retainSizeWhenHiddenChanged(0)
150 , inDirtyList(0)
151 , isScrolled(0)
152 , isMoved(0)
153 , usesDoubleBufferedGLContext(0)
154 , mustHaveWindowHandle(0)
155 , renderToTexture(0)
156 , textureChildSeen(0)
157#ifndef QT_NO_IM
158 , inheritsInputMethodHints(0)
159#endif
160 , renderToTextureReallyDirty(1)
161 , usesRhiFlush(0)
162 , childrenHiddenByWState(0)
163 , childrenShownByExpose(0)
164 , dontSetExplicitShowHide(0)
165 , inheritStyleRecursionGuard(0)
166#if defined(Q_OS_WIN)
167 , noPaintOnScreen(0)
168#endif
169{
170 if (Q_UNLIKELY(!qApp)) {
171 qFatal("QWidget: Must construct a QApplication before a QWidget");
172 return;
173 }
174
175 willBeWidget = true; // used in QObject's ctor
176 memset(high_attributes, 0, sizeof(high_attributes));
177
178#ifdef QWIDGET_EXTRA_DEBUG
179 static int count = 0;
180 qDebug() << "widgets" << ++count;
181#endif
182}
183
184
185QWidgetPrivate::~QWidgetPrivate()
186{
187 if (widgetItem)
188 widgetItem->wid = nullptr;
189
190 if (extra)
191 deleteExtra();
192}
193
194/*!
195 \internal
196*/
197void QWidgetPrivate::scrollChildren(int dx, int dy)
198{
199 Q_Q(QWidget);
200 if (q->children().size() > 0) { // scroll children
201 QPoint pd(dx, dy);
202 QObjectList childObjects = q->children();
203 for (int i = 0; i < childObjects.size(); ++i) { // move all children
204 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
205 if (w && !w->isWindow()) {
206 QPoint oldp = w->pos();
207 QRect r(w->pos() + pd, w->size());
208 w->data->crect = r;
209 if (w->testAttribute(Qt::WA_WState_Created))
210 w->d_func()->setWSGeometry();
211 w->d_func()->setDirtyOpaqueRegion();
212 QMoveEvent e(r.topLeft(), oldp);
213 QCoreApplication::sendEvent(w, &e);
214 }
215 }
216 }
217}
218
219void QWidgetPrivate::setWSGeometry()
220{
221 Q_Q(QWidget);
222 if (QWindow *window = q->windowHandle())
223 window->setGeometry(data.crect);
224}
225
226void QWidgetPrivate::updateWidgetTransform(QEvent *event)
227{
228 Q_Q(QWidget);
229 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
230 QTransform t;
231 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
232 t.translate(p.x(), p.y());
233 QGuiApplication::inputMethod()->setInputItemTransform(t);
234 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
235 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
236 }
237}
238
239#ifdef QT_KEYPAD_NAVIGATION
240QPointer<QWidget> QWidgetPrivate::editingWidget;
241
242/*!
243 Returns \c true if this widget currently has edit focus; otherwise false.
244
245 This feature is only available in Qt for Embedded Linux.
246
247 \sa setEditFocus(), QApplication::navigationMode()
248*/
249bool QWidget::hasEditFocus() const
250{
251 const QWidget* w = this;
252 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
253 w = w->d_func()->extra->focus_proxy;
254 return QWidgetPrivate::editingWidget == w;
255}
256
257/*!
258 \fn void QWidget::setEditFocus(bool enable)
259
260 If \a enable is true, make this widget have edit focus, in which
261 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
262 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
263 change focus.
264
265 This feature is only available in Qt for Embedded Linux.
266
267 \sa hasEditFocus(), QApplication::navigationMode()
268*/
269void QWidget::setEditFocus(bool on)
270{
271 QWidget *f = this;
272 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
273 f = f->d_func()->extra->focus_proxy;
274
275 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
276 QWidgetPrivate::editingWidget->setEditFocus(false);
277
278 if (on && !f->hasFocus())
279 f->setFocus();
280
281 if ((!on && !QWidgetPrivate::editingWidget)
282 || (on && QWidgetPrivate::editingWidget == f)) {
283 return;
284 }
285
286 if (!on && QWidgetPrivate::editingWidget == f) {
287 QWidgetPrivate::editingWidget = 0;
288 QEvent event(QEvent::LeaveEditFocus);
289 QCoreApplication::sendEvent(f, &event);
290 QCoreApplication::sendEvent(f->style(), &event);
291 } else if (on) {
292 QWidgetPrivate::editingWidget = f;
293 QEvent event(QEvent::EnterEditFocus);
294 QCoreApplication::sendEvent(f, &event);
295 QCoreApplication::sendEvent(f->style(), &event);
296 }
297}
298#endif
299
300/*!
301 \property QWidget::autoFillBackground
302 \brief whether the widget background is filled automatically
303 \since 4.1
304
305 If enabled, this property will cause Qt to fill the background of the
306 widget before invoking the paint event. The color used is defined by the
307 QPalette::Window color role from the widget's \l{QPalette}{palette}.
308
309 In addition, Windows are always filled with QPalette::Window, unless the
310 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
311
312 This property cannot be turned off (i.e., set to false) if a widget's
313 parent has a static gradient for its background.
314
315 \warning Use this property with caution in conjunction with
316 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
317 background or a border-image, this property is automatically disabled.
318
319 By default, this property is \c false.
320
321 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
322 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
323*/
324bool QWidget::autoFillBackground() const
325{
326 Q_D(const QWidget);
327 return d->extra && d->extra->autoFillBackground;
328}
329
330void QWidget::setAutoFillBackground(bool enabled)
331{
332 Q_D(QWidget);
333 if (!d->extra)
334 d->createExtra();
335 if (d->extra->autoFillBackground == enabled)
336 return;
337
338 d->extra->autoFillBackground = enabled;
339 d->updateIsOpaque();
340 update();
341 d->updateIsOpaque();
342}
343
344/*!
345 \class QWidget
346 \brief The QWidget class is the base class of all user interface objects.
347
348 \ingroup basicwidgets
349 \inmodule QtWidgets
350
351 The widget is the atom of the user interface: it receives mouse, keyboard
352 and other events from the window system, and paints a representation of
353 itself on the screen. Every widget is rectangular, and they are sorted in a
354 Z-order. A widget is clipped by its parent and by the widgets in front of
355 it.
356
357 A widget that is not embedded in a parent widget is called a window.
358 Usually, windows have a frame and a title bar, although it is also possible
359 to create windows without such decoration using suitable
360 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
361 subclasses of QDialog are the most common window types.
362
363 Every widget's constructor accepts one or two standard arguments:
364
365 \list 1
366 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
367 If it is \nullptr (the default), the new widget will be a window.
368 If not, it will be a child of \e parent, and be constrained by
369 \e parent's geometry (unless you specify Qt::Window as window flag).
370 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
371 the default is suitable for most widgets, but to get, for
372 example, a window without a window system frame, you must use
373 special flags.
374 \endlist
375
376 QWidget has many member functions, but some of them have little direct
377 functionality; for example, QWidget has a font property, but never uses
378 this itself. There are many subclasses that provide real functionality,
379 such as QLabel, QPushButton, QListWidget, and QTabWidget.
380
381
382 \section1 Top-Level and Child Widgets
383
384 A widget without a parent widget is always an independent window (top-level
385 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
386 title bar and icon, respectively.
387
388 Non-window widgets are child widgets, displayed within their parent
389 widgets. Most widgets in Qt are mainly useful as child widgets. For
390 example, it is possible to display a button as a top-level window, but most
391 people prefer to put their buttons inside other widgets, such as QDialog.
392
393 \image parent-child-widgets.png
394 {Appointment widget with labeled child widgets}
395 \caption A parent widget containing various child widgets.
396
397 The diagram above shows a QGroupBox widget being used to hold various child
398 widgets in a layout provided by QGridLayout. The QLabel child widgets have
399 been outlined to indicate their full sizes.
400
401 If you want to use a QWidget to hold child widgets, you will usually want to
402 add a layout to the parent QWidget. See \l{Layout Management} for more
403 information.
404
405
406 \section1 Composite Widgets
407
408 When a widget is used as a container to group a number of child widgets, it
409 is known as a composite widget. These can be created by constructing a
410 widget with the required visual properties - a QFrame, for example - and
411 adding child widgets to it, usually managed by a layout.
412
413 Composite widgets can also be created by subclassing a standard widget,
414 such as QWidget or QFrame, and adding the necessary layout and child
415 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
416 {examples provided with Qt} use this approach, and it is also covered in
417 the Qt \l{Widgets Tutorial}.
418
419
420 \section1 Custom Widgets and Painting
421
422 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
423 display custom content that is composed using a series of painting
424 operations with an instance of the QPainter class. This approach contrasts
425 with the canvas-style approach used by the \l{Graphics View}
426 {Graphics View Framework} where items are added to a scene by the
427 application and are rendered by the framework itself.
428
429 Each widget performs all painting operations from within its paintEvent()
430 function. This is called whenever the widget needs to be redrawn, either
431 because of some external change or when requested by the application.
432
433 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
434 can handle paint events.
435
436
437 \section1 Size Hints and Size Policies
438
439 When implementing a new widget, it is almost always useful to reimplement
440 sizeHint() to provide a reasonable default size for the widget and to set
441 the correct size policy with setSizePolicy().
442
443 By default, composite widgets that do not provide a size hint will be
444 sized according to the space requirements of their child widgets.
445
446 The size policy lets you supply good default behavior for the layout
447 management system, so that other widgets can contain and manage yours
448 easily. The default size policy indicates that the size hint represents
449 the preferred size of the widget, and this is often good enough for many
450 widgets.
451
452 \note The size of top-level widgets are constrained to 2/3 of the desktop's
453 height and width. You can resize() the widget manually if these bounds are
454 inadequate.
455
456
457 \section1 Events
458
459 Widgets respond to events that are typically caused by user actions. Qt
460 delivers events to widgets by calling specific event handler functions with
461 instances of QEvent subclasses containing information about each event.
462
463 If your widget only contains child widgets, you probably don't need to
464 implement any event handlers. If you want to detect a mouse click in a
465 child widget, call the child's underMouse() function inside the widget's
466 mousePressEvent().
467
468 The \l{widgets/scribble}{Scribble example} implements a wider set of
469 events to handle mouse movement, button presses, and window resizing.
470
471 You will need to supply the behavior and content for your own widgets, but
472 here is a brief overview of the events that are relevant to QWidget,
473 starting with the most common ones:
474
475 \list
476 \li paintEvent() is called whenever the widget needs to be repainted.
477 Every widget displaying custom content must implement it. Painting
478 using a QPainter can only take place in a paintEvent() or a
479 function called by a paintEvent().
480 \li resizeEvent() is called when the widget has been resized.
481 \li mousePressEvent() is called when a mouse button is pressed while
482 the mouse cursor is inside the widget, or when the widget has
483 grabbed the mouse using grabMouse(). Pressing the mouse without
484 releasing it is effectively the same as calling grabMouse().
485 \li mouseReleaseEvent() is called when a mouse button is released. A
486 widget receives mouse release events when it has received the
487 corresponding mouse press event. This means that if the user
488 presses the mouse inside \e your widget, then drags the mouse
489 somewhere else before releasing the mouse button, \e your widget
490 receives the release event. There is one exception: if a popup menu
491 appears while the mouse button is held down, this popup immediately
492 steals the mouse events.
493 \li mouseDoubleClickEvent() is called when the user double-clicks in
494 the widget. If the user double-clicks, the widget receives a mouse
495 press event, a mouse release event, (a mouse click event,) a second
496 mouse press, this event and finally a second mouse release event.
497 (Some mouse move events may also be
498 received if the mouse is not held steady during this operation.) It
499 is \e{not possible} to distinguish a click from a double-click
500 until the second click arrives. (This is one reason why most GUI
501 books recommend that double-clicks be an extension of
502 single-clicks, rather than trigger a different action.)
503 \endlist
504
505 Widgets that accept keyboard input need to reimplement a few more event
506 handlers:
507
508 \list
509 \li keyPressEvent() is called whenever a key is pressed, and again when
510 a key has been held down long enough for it to auto-repeat. The
511 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
512 they are not used by the focus-change mechanisms. To force those
513 keys to be processed by your widget, you must reimplement
514 QWidget::event().
515 \li focusInEvent() is called when the widget gains keyboard focus
516 (assuming you have called setFocusPolicy()). Well-behaved widgets
517 indicate that they own the keyboard focus in a clear but discreet
518 way.
519 \li focusOutEvent() is called when the widget loses keyboard focus.
520 \endlist
521
522 You may be required to also reimplement some of the less common event
523 handlers:
524
525 \list
526 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
527 button is held down. This can be useful during drag and drop
528 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
529 you get mouse move events even when no buttons are held down.
530 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
531 \li keyReleaseEvent() is called whenever a key is released and while it
532 is held down (if the key is auto-repeating). In that case, the
533 widget will receive a pair of key release and key press event for
534 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
535 to the widget if they are not used by the focus-change mechanisms.
536 To force those keys to be processed by your widget, you must
537 reimplement QWidget::event().
538 \li wheelEvent() is called whenever the user turns the mouse wheel
539 while the widget has the focus.
540 \li enterEvent() is called when the mouse enters the widget's screen
541 space. (This excludes screen space owned by any of the widget's
542 children.)
543 \li leaveEvent() is called when the mouse leaves the widget's screen
544 space. If the mouse enters a child widget, it will not cause a
545 leaveEvent().
546 \li moveEvent() is called when the widget has been moved relative to
547 its parent.
548 \li closeEvent() is called when the user closes the widget (or when
549 close() is called).
550 \endlist
551
552 There are also some rather obscure events described in the documentation
553 for QEvent::Type. To handle these events, you need to reimplement event()
554 directly.
555
556 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
557 (to move the keyboard focus), and passes on most of the other events to
558 one of the more specialized handlers above.
559
560 Events and the mechanism used to deliver them are covered in
561 \l{The Event System}.
562
563 \section1 Groups of Functions and Properties
564
565 \table
566 \header \li Context \li Functions and Properties
568 \row \li Window functions \li
569 show(),
570 hide(),
571 raise(),
572 lower(),
573 close().
574
575 \row \li Top-level windows \li
576 \l windowModified, \l windowTitle, \l windowIcon,
577 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
578 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
579 showNormal().
580
581 \row \li Window contents \li
582 update(),
583 repaint(),
584 scroll().
585
586 \row \li Geometry \li
587 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
588 \l sizePolicy, sizeHint(), minimumSizeHint(),
589 updateGeometry(), layout(),
590 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
591 adjustSize(),
592 mapFromGlobal(), mapToGlobal(),
593 mapFromParent(), mapToParent(),
594 \l maximumSize, \l minimumSize, \l sizeIncrement,
595 \l baseSize, setFixedSize()
596
597 \row \li Mode \li
598 \l visible, isVisibleTo(),
599 \l enabled, isEnabledTo(),
600 \l modal,
601 isWindow(),
602 \l mouseTracking,
603 \l updatesEnabled,
604 visibleRegion().
605
606 \row \li Look and feel \li
607 style(),
608 setStyle(),
609 \l styleSheet,
610 \l cursor,
611 \l font,
612 \l palette,
613 backgroundRole(), setBackgroundRole(),
614 fontInfo(), fontMetrics().
615
616 \row \li Keyboard focus functions \li
617 \l focus, \l focusPolicy,
618 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
619 focusNextChild(), focusPreviousChild().
620
621 \row \li Mouse and keyboard grabbing \li
622 grabMouse(), releaseMouse(),
623 grabKeyboard(), releaseKeyboard(),
624 mouseGrabber(), keyboardGrabber().
625
626 \row \li Event handlers \li
627 event(),
628 mousePressEvent(),
629 mouseReleaseEvent(),
630 mouseDoubleClickEvent(),
631 mouseMoveEvent(),
632 keyPressEvent(),
633 keyReleaseEvent(),
634 focusInEvent(),
635 focusOutEvent(),
636 wheelEvent(),
637 enterEvent(),
638 leaveEvent(),
639 paintEvent(),
640 moveEvent(),
641 resizeEvent(),
642 closeEvent(),
643 dragEnterEvent(),
644 dragMoveEvent(),
645 dragLeaveEvent(),
646 dropEvent(),
647 childEvent(),
648 showEvent(),
649 hideEvent(),
650 customEvent().
651 changeEvent(),
652
653 \row \li System functions \li
654 parentWidget(), window(), setParent(), winId(),
655 find(), metric().
656
657 \row \li Context menu \li
658 contextMenuPolicy, contextMenuEvent(),
659 customContextMenuRequested(), actions()
660
661 \row \li Interactive help \li
662 setToolTip(), setWhatsThis()
663
664 \endtable
665
666
667 \section1 Widget Style Sheets
668
669 In addition to the standard widget styles for each platform, widgets can
670 also be styled according to rules specified in a \l{styleSheet}
671 {style sheet}. This feature enables you to customize the appearance of
672 specific widgets to provide visual cues to users about their purpose. For
673 example, a button could be styled in a particular way to indicate that it
674 performs a destructive action.
675
676 The use of widget style sheets is described in more detail in the
677 \l{Qt Style Sheets} document.
678
679
680 \section1 Transparency and Double Buffering
681
682 QWidget automatically double-buffers its painting, so there
683 is no need to write double-buffering code in paintEvent() to avoid
684 flicker.
685
686 The contents of parent widgets are propagated by
687 default to each of their children as long as Qt::WA_PaintOnScreen is not
688 set. Custom widgets can be written to take advantage of this feature by
689 updating irregular regions (to create non-rectangular child widgets), or
690 painting with colors that have less than full alpha component. The
691 following diagram shows how attributes and properties of a custom widget
692 can be fine-tuned to achieve different effects.
693
694 \image propagation-custom.png
695 {Three pixmaps of a house with different background properties:
696 transparent, filled with white, and uninitialized}
697
698 In the above diagram, a semi-transparent rectangular child widget with an
699 area removed is constructed and added to a parent widget (a QLabel showing
700 a pixmap). Then, different properties and widget attributes are set to
701 achieve different effects:
702
703 \list
704 \li The left widget has no additional properties or widget attributes
705 set. This default state suits most custom widgets that have
706 transparency, are irregularly-shaped, or do not paint over their
707 entire area with an opaque brush.
708 \li The center widget has the \l autoFillBackground property set. This
709 property is used with custom widgets that rely on the widget to
710 supply a default background, and do not paint over their entire
711 area with an opaque brush.
712 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
713 set. This indicates that the widget will paint over its entire area
714 with opaque colors. The widget's area will initially be
715 \e{uninitialized}, represented in the diagram with a red diagonal
716 grid pattern that shines through the overpainted area.
717 \endlist
718
719 To rapidly update custom widgets with simple background colors, such as
720 real-time plotting or graphing widgets, it is better to define a suitable
721 background color (using setBackgroundRole() with the
722 QPalette::Window role), set the \l autoFillBackground property, and only
723 implement the necessary drawing functionality in the widget's paintEvent().
724
725 To rapidly update custom widgets that constantly paint over their entire
726 areas with opaque content, for example, video streaming widgets, it is
727 better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
728 overhead associated with repainting the widget's background.
729
730 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
731 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
732 attribute takes precedence. Depending on your requirements, you should
733 choose either one of them.
734
735 The contents of parent widgets are also propagated to standard Qt widgets.
736 This can lead to some unexpected results if the parent widget is decorated
737 in a non-standard way, as shown in the diagram below.
738
739 \image propagation-standard.png
740 {One widget has a transparent background
741 and the other widget has a filled background}
742
743 The scope for customizing the painting behavior of standard Qt widgets,
744 without resorting to subclassing, is slightly less than that possible for
745 custom widgets. Usually, the desired appearance of a standard widget can be
746 achieved by setting its \l autoFillBackground property.
747
748
749 \section1 Creating Translucent Windows
750
751 You can create windows with translucent regions on window systems that
752 support compositing.
753
754 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
755 attribute with setAttribute() and ensure that its background is painted with
756 non-opaque colors in the regions you want to be partially transparent.
757
758 Platform notes:
759
760 \list
761 \li X11: This feature relies on the use of an X server that supports ARGB visuals
762 and a compositing window manager.
763 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
764 for the translucency to work.
765 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
766 for the translucency to work.
767 \endlist
768
769
770 \section1 Native Widgets vs Alien Widgets
771
772 Alien widgets are widgets unknown to the windowing system. They do not have
773 a native window handle associated with them. This feature significantly
774 speeds up widget painting, resizing, and removes flicker.
775
776 Should you require the old behavior with native windows, choose one of the
777 following options:
778
779 \list 1
780 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
781 \li Set the Qt::AA_NativeWindows attribute on your application. All
782 widgets will be native widgets.
783 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
784 and all its ancestors will become native (unless
785 Qt::WA_DontCreateNativeAncestors is set).
786 \li Call QWidget::winId to enforce a native window (this implies 3).
787 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
788 (this implies 3).
789 \endlist
790
791 \sa QEvent, QPainter, QGridLayout, QBoxLayout
792
793*/
794
795QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
796QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
797
798
799/*****************************************************************************
800 QWidget member functions
801 *****************************************************************************/
802
803/*
804 Widget state flags:
805 \list
806 \li Qt::WA_WState_Created The widget has a valid winId().
807 \li Qt::WA_WState_Visible The widget is currently visible.
808 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
809 become visible unless you call show() on it. Qt::WA_WState_Hidden
810 implies !Qt::WA_WState_Visible.
811 \li Qt::WA_WState_CompressKeys Compress keyboard events.
812 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
813 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
814 \li Qt::WA_WState_Reparented The widget has been reparented.
815 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
816 \endlist
817*/
818
820{
821 /* this cleans up when the constructor throws an exception */
822 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
823 {
824#ifdef QT_NO_EXCEPTIONS
825 Q_UNUSED(that);
826 Q_UNUSED(d);
827#else
828 QWidgetPrivate::allWidgets->remove(that);
829 d->removeFromFocusChain();
830#endif
831 }
832};
833
834/*!
835 Constructs a widget which is a child of \a parent, with widget
836 flags set to \a f.
837
838 If \a parent is \nullptr, the new widget becomes a window. If
839 \a parent is another widget, this widget becomes a child window
840 inside \a parent. The new widget is deleted when its \a parent is
841 deleted.
842
843 The widget flags argument, \a f, is normally 0, but it can be set
844 to customize the frame of a window (i.e. \a parent must be
845 \nullptr). To customize the frame, use a value composed
846 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
847
848 If you add a child widget to an already visible widget you must
849 explicitly show the child to make it visible.
850
851 Note that the X11 version of Qt may not be able to deliver all
852 combinations of style flags on all systems. This is because on
853 X11, Qt can only ask the window manager, and the window manager
854 can override the application's settings. On Windows, Qt can set
855 whatever flags you want.
856
857 \sa windowFlags
858*/
859QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
860 : QWidget(*new QWidgetPrivate, parent, f)
861{
862}
863
864
865/*! \internal
866*/
867QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
868 : QObject(dd, nullptr), QPaintDevice()
869 , data(&dd.data)
870{
871 Q_D(QWidget);
872 QT_TRY {
873 d->init(parent, f);
874 } QT_CATCH(...) {
875 QWidgetExceptionCleaner::cleanup(this, d_func());
876 QT_RETHROW;
877 }
878}
879
880/*!
881 \internal
882*/
883int QWidget::devType() const
884{
885 return QInternal::Widget;
886}
887
888
889//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
890void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
891{
892 bool customize = (flags & (Qt::CustomizeWindowHint
893 | Qt::FramelessWindowHint
894 | Qt::WindowTitleHint
895 | Qt::WindowSystemMenuHint
896 | Qt::WindowMinimizeButtonHint
897 | Qt::WindowMaximizeButtonHint
898 | Qt::WindowCloseButtonHint
899 | Qt::WindowContextHelpButtonHint));
900
901 uint type = (flags & Qt::WindowType_Mask);
902
903 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
904 type = Qt::Window;
905 flags |= Qt::Window;
906 }
907
908 if (flags & Qt::CustomizeWindowHint) {
909 // modify window flags to make them consistent.
910 // Only enable this on non-Mac platforms. Since the old way of doing this would
911 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
912 // we can't just add this in.
913 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
914# ifdef Q_OS_WIN
915 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
916# endif
917 ) {
918 flags |= Qt::WindowSystemMenuHint;
919 flags |= Qt::WindowTitleHint;
920 flags &= ~Qt::FramelessWindowHint;
921 }
922 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
923 // if any of the window hints that affect the titlebar are set
924 // and the window is supposed to have frame, we add a titlebar
925 // and system menu by default.
926 flags |= Qt::WindowSystemMenuHint;
927 flags |= Qt::WindowTitleHint;
928 }
929 if (!customize) { // don't modify window flags if the user explicitly set them.
930 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
931 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
932 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
933 }
934 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
935 flags |= Qt::WindowTransparentForInput;
936}
937
938void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
939{
940 Q_Q(QWidget);
941 isWidget = true;
942 wasWidget = true;
943
944#if QT_DEPRECATED_SINCE(6, 11)
945 QT_IGNORE_DEPRECATIONS(
946 Q_ASSERT_X(!f.testFlag(Qt::WindowType::Desktop), Q_FUNC_INFO, "Qt::WindowType::Desktop is not allowed.");
947 if (f.testFlag(Qt::WindowType::Desktop))
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 win->setTransientParent(nativeParent->window()->windowHandle());
1352 win->setParent(nullptr);
1353 } else {
1354 win->setTransientParent(nullptr);
1355 win->setParent(nativeParent->windowHandle());
1356 }
1357 }
1358 }
1359
1360 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1361 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1362
1363 win->create();
1364 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1365 if (QPlatformWindow *platformWindow = win->handle())
1366 platformWindow->setFrameStrutEventsEnabled(true);
1367
1368 data.window_flags = win->flags();
1369
1370#if QT_CONFIG(xcb)
1371 if (!topData()->role.isNull()) {
1372 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1373 xcbWindow->setWindowRole(topData()->role);
1374 }
1375#endif
1376#if QT_CONFIG(wayland)
1377 if (!topData()->role.isNull()) {
1378 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(win->handle()))
1379 waylandWindow->setSessionRestoreId(topData()->role);
1380 }
1381#endif
1382
1383 QBackingStore *store = q->backingStore();
1384 usesRhiFlush = false;
1385
1386 if (!store && q->isWindow())
1387 q->setBackingStore(new QBackingStore(win));
1388
1389 QPlatformBackingStoreRhiConfig rhiConfig;
1390 usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr);
1391 if (usesRhiFlush && q->backingStore()) {
1392 // Trigger creation of support infrastructure up front,
1393 // now that we have a specific RHI configuration.
1394 q->backingStore()->handle()->createRhi(win, rhiConfig);
1395 }
1396
1397 setWindowModified_helper();
1398
1399 if (win->handle()) {
1400 WId id = win->winId();
1401 // See the QPlatformWindow::winId() documentation
1402 Q_ASSERT(id != WId(0));
1403 setWinId(id);
1404 }
1405 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1406
1407 // Check children and create windows for them if necessary
1408 q_createNativeChildrenAndSetParent(q);
1409
1410 if (extra && !extra->mask.isEmpty())
1411 setMask_sys(extra->mask);
1412
1413 if (data.crect.width() == 0 || data.crect.height() == 0) {
1414 q->setAttribute(Qt::WA_OutsideWSRange, true);
1415 } else {
1416 q->setAttribute(Qt::WA_OutsideWSRange, false);
1417 if (q->isVisible()) {
1418 // If widget is already shown, set window visible, too
1419 win->setNativeWindowVisibility(true);
1420 }
1421 }
1422}
1423
1424#ifdef Q_OS_WIN
1425static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1426#endif
1427
1428void QWidgetPrivate::createTLSysExtra()
1429{
1430 Q_Q(QWidget);
1431 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1432 extra->topextra->window = new QWidgetWindow(q);
1433 if (extra->minw || extra->minh)
1434 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1435 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1436 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1437 if (extra->topextra->opacity != 255 && q->isWindow())
1438 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1439
1440#if QT_CONFIG(tooltip)
1441 const bool isTipLabel = qobject_cast<const QTipLabel *>(q) != nullptr;
1442#endif
1443 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1444#ifdef Q_OS_WIN
1445 // Pass on native parent handle for Widget embedded into Active X.
1446 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1447 if (activeXNativeParentHandle.isValid())
1448 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1449 if (isTipLabel || isAlphaWidget)
1450 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1451#endif
1452 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1453 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1454
1455 updateIsTranslucent();
1456 }
1457
1458}
1459
1460/*!
1461 Destroys the widget.
1462
1463 All this widget's children are deleted first. The application
1464 exits if this widget is the main widget.
1465*/
1466
1467QWidget::~QWidget()
1468{
1469 Q_D(QWidget);
1470 d->data.in_destructor = true;
1471
1472#if QT_CONFIG(accessibility)
1473 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive())
1474 QAccessibleCache::instance()->sendObjectDestroyedEvent(this);
1475#endif
1476
1477#if defined (QT_CHECK_STATE)
1478 if (Q_UNLIKELY(paintingActive()))
1479 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1480#endif
1481
1482#ifndef QT_NO_GESTURES
1483 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1484 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1485 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1486 manager->cleanupCachedGestures(this, *it);
1487 }
1488 d->gestureContext.clear();
1489#endif
1490
1491#ifndef QT_NO_ACTION
1492 // remove all actions from this widget
1493 for (auto action : std::as_const(d->actions)) {
1494 QActionPrivate *apriv = action->d_func();
1495 apriv->associatedObjects.removeAll(this);
1496 }
1497 d->actions.clear();
1498#endif
1499
1500#ifndef QT_NO_SHORTCUT
1501 // Remove all shortcuts grabbed by this
1502 // widget, unless application is closing
1503 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1504 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1505#endif
1506
1507 // delete layout while we still are a valid widget
1508 delete d->layout;
1509 d->layout = nullptr;
1510
1511 // Remove this from focus list
1512 d->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1513
1514 QT_TRY {
1515#if QT_CONFIG(graphicsview)
1516 const QWidget* w = this;
1517 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1518 w = w->d_func()->extra->focus_proxy;
1519 QWidget *window = w->window();
1520 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1521 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1522#endif
1523 clearFocus();
1524 } QT_CATCH(...) {
1525 // swallow this problem because we are in a destructor
1526 }
1527
1528 d->setDirtyOpaqueRegion();
1529
1530 if (isWindow() && isVisible() && internalWinId()) {
1531 QT_TRY {
1532 d->close();
1533 } QT_CATCH(...) {
1534 // if we're out of memory, at least hide the window.
1535 QT_TRY {
1536 hide();
1537 } QT_CATCH(...) {
1538 // and if that also doesn't work, then give up
1539 }
1540 }
1541 } else if (isVisible()) {
1542 qApp->d_func()->sendSyntheticEnterLeave(this);
1543 }
1544
1545 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1546 repaintManager->removeDirtyWidget(this);
1547 if (testAttribute(Qt::WA_StaticContents))
1548 repaintManager->removeStaticWidget(this);
1549 }
1550
1551 delete d->needsFlush;
1552 d->needsFlush = nullptr;
1553
1554 // The next 20 lines are duplicated from QObject, but required here
1555 // since QWidget deletes is children itself
1556 bool blocked = d->blockSig;
1557 d->blockSig = 0; // unblock signals so we always emit destroyed()
1558
1559 if (d->isSignalConnected(0)) {
1560 QT_TRY {
1561 emit destroyed(this);
1562 } QT_CATCH(...) {
1563 // all the signal/slots connections are still in place - if we don't
1564 // quit now, we will crash pretty soon.
1565 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1566 QT_RETHROW;
1567 }
1568 }
1569
1570 if (d->declarativeData) {
1571 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1572 if (QAbstractDeclarativeData::destroyed)
1573 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1574 d->declarativeData = nullptr; // don't activate again in ~QObject
1575 d->wasDeleted = false;
1576 }
1577
1578 d->blockSig = blocked;
1579
1580 if (!d->children.isEmpty())
1581 d->deleteChildren();
1582
1583 QCoreApplication::removePostedEvents(this);
1584
1585 QT_TRY {
1586 destroy(); // platform-dependent cleanup
1587 } QT_CATCH(...) {
1588 // if this fails we can't do anything about it but at least we are not allowed to throw.
1589 }
1590 --QWidgetPrivate::instanceCounter;
1591
1592 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1593 QWidgetPrivate::allWidgets->remove(this);
1594
1595 QT_TRY {
1596 QEvent e(QEvent::Destroy);
1597 QCoreApplication::sendEvent(this, &e);
1598 } QT_CATCH(const std::exception&) {
1599 // if this fails we can't do anything about it but at least we are not allowed to throw.
1600 }
1601
1602#if QT_CONFIG(graphicseffect)
1603 delete d->graphicsEffect;
1604#endif
1605 d->deleteExtra();
1606
1607 d->isWidget = false;
1608}
1609
1610int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1611int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1612
1613void QWidgetPrivate::setWinId(WId id) // set widget identifier
1614{
1615 Q_Q(QWidget);
1616 if (mapper && data.winid) {
1617 mapper->remove(data.winid);
1618 }
1619
1620 const WId oldWinId = data.winid;
1621
1622 data.winid = id;
1623 if (mapper && id) {
1624 mapper->insert(data.winid, q);
1625 }
1626
1627 if (oldWinId != id) {
1628 QEvent e(QEvent::WinIdChange);
1629 QCoreApplication::sendEvent(q, &e);
1630 }
1631}
1632
1633void QWidgetPrivate::createTLExtra()
1634{
1635 if (!extra)
1636 createExtra();
1637 if (!extra->topextra) {
1638 extra->topextra = std::make_unique<QTLWExtra>();
1639 QTLWExtra* x = extra->topextra.get();
1640 x->backingStore = nullptr;
1641 x->sharedPainter = nullptr;
1642 x->incw = x->inch = 0;
1643 x->basew = x->baseh = 0;
1644 x->frameStrut.setCoords(0, 0, 0, 0);
1645 x->normalGeometry = QRect(0,0,-1,-1);
1646 x->savedFlags = { };
1647 x->opacity = 255;
1648 x->posIncludesFrame = 0;
1649 x->sizeAdjusted = false;
1650 x->embedded = 0;
1651 x->explicitContentsMarginsRespectsSafeArea = 0;
1652 x->window = nullptr;
1653 x->initialScreen = nullptr;
1654
1655#ifdef QWIDGET_EXTRA_DEBUG
1656 static int count = 0;
1657 qDebug() << "tlextra" << ++count;
1658#endif
1659 }
1660}
1661
1662/*!
1663 \internal
1664 Creates the widget extra data.
1665*/
1666
1667void QWidgetPrivate::createExtra()
1668{
1669 if (!extra) { // if not exists
1670 extra = std::make_unique<QWExtra>();
1671 extra->glContext = nullptr;
1672#if QT_CONFIG(graphicsview)
1673 extra->proxyWidget = nullptr;
1674#endif
1675 extra->minw = 0;
1676 extra->minh = 0;
1677 extra->maxw = QWIDGETSIZE_MAX;
1678 extra->maxh = QWIDGETSIZE_MAX;
1679 extra->customDpiX = 0;
1680 extra->customDpiY = 0;
1681 extra->explicitMinSize = 0;
1682 extra->explicitMaxSize = 0;
1683 extra->autoFillBackground = 0;
1684 extra->nativeChildrenForced = 0;
1685 extra->inRenderWithPainter = 0;
1686 extra->hasWindowContainer = false;
1687 extra->hasMask = 0;
1688 createSysExtra();
1689#ifdef QWIDGET_EXTRA_DEBUG
1690 static int count = 0;
1691 qDebug() << "extra" << ++count;
1692#endif
1693 }
1694}
1695
1696void QWidgetPrivate::createSysExtra()
1697{
1698}
1699
1700/*!
1701 \internal
1702 Deletes the widget extra data.
1703*/
1704
1705void QWidgetPrivate::deleteExtra()
1706{
1707 if (extra) { // if exists
1708 deleteSysExtra();
1709#if QT_CONFIG(style_stylesheet)
1710 // dereference the stylesheet style
1711 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1712 proxy->deref();
1713#endif
1714 if (extra->topextra)
1715 deleteTLSysExtra();
1716
1717 // extra->xic destroyed in QWidget::destroy()
1718 extra.reset();
1719 }
1720}
1721
1722void QWidgetPrivate::deleteSysExtra()
1723{
1724}
1725
1726void QWidgetPrivate::deleteTLSysExtra()
1727{
1728 Q_Q(QWidget);
1729 if (extra && extra->topextra) {
1730 if (extra->hasWindowContainer)
1731 QWindowContainer::toplevelAboutToBeDestroyed(q);
1732
1733 delete extra->topextra->window;
1734 extra->topextra->window = nullptr;
1735 }
1736}
1737
1738/*
1739 Returns \c region of widgets above this which overlap with
1740 \a rect, which is in parent's coordinate system (same as crect).
1741*/
1742
1743QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1744{
1745 Q_Q(const QWidget);
1746
1747 const QWidget *w = q;
1748 QRect r = rect;
1749 QPoint p;
1750 QRegion region;
1751 while (w) {
1752 if (w->isWindow())
1753 break;
1754 QWidgetPrivate *pd = w->parentWidget()->d_func();
1755 bool above = false;
1756 for (int i = 0; i < pd->children.size(); ++i) {
1757 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1758 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1759 continue;
1760 if (!above) {
1761 above = (sibling == w);
1762 continue;
1763 }
1764
1765 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1766 if (qRectIntersects(siblingRect, r)) {
1767 const auto &siblingExtra = sibling->d_func()->extra;
1768 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1769 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1770 continue;
1771 }
1772 region += siblingRect.translated(-p);
1773 if (breakAfterFirst)
1774 break;
1775 }
1776 }
1777 w = w->parentWidget();
1778 r.translate(pd->data.crect.topLeft());
1779 p += pd->data.crect.topLeft();
1780 }
1781 return region;
1782}
1783
1784void QWidgetPrivate::syncBackingStore()
1785{
1786 if (shouldPaintOnScreen()) {
1787 paintOnScreen(dirty);
1788 dirty = QRegion();
1789 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1790 repaintManager->sync();
1791 }
1792}
1793
1794void QWidgetPrivate::syncBackingStore(const QRegion &region)
1795{
1796 if (shouldPaintOnScreen())
1797 paintOnScreen(region);
1798 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1799 repaintManager->sync(q_func(), region);
1800 }
1801}
1802
1803void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1804{
1805 if (data.in_destructor)
1806 return;
1807
1808 if (shouldDiscardSyncRequest())
1809 return;
1810
1811 Q_Q(QWidget);
1812 if (q->testAttribute(Qt::WA_StaticContents)) {
1813 if (!extra)
1814 createExtra();
1815 extra->staticContentsSize = data.crect.size();
1816 }
1817
1818 QPaintEngine *engine = q->paintEngine();
1819
1820 // QGLWidget does not support partial updates if:
1821 // 1) The context is double buffered
1822 // 2) The context is single buffered and auto-fill background is enabled.
1823 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1824 || engine->type() == QPaintEngine::OpenGL2))
1825 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1826 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1827
1828 toBePainted &= clipRect();
1829 clipToEffectiveMask(toBePainted);
1830 if (toBePainted.isEmpty())
1831 return; // Nothing to repaint.
1832
1833 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1834
1835 if (Q_UNLIKELY(q->paintingActive()))
1836 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1837}
1838
1839void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1840{
1841 Q_Q(QWidget);
1842
1843 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1844 return; // nothing we can do
1845
1846 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1847 return; // nothing to do
1848
1849 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1850 if (enable)
1851 q->update();
1852
1853 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1854 for (int i = 0; i < children.size(); ++i) {
1855 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1856 if (w && !w->isWindow() && !w->testAttribute(attribute))
1857 w->d_func()->setUpdatesEnabled_helper(enable);
1858 }
1859}
1860
1861/*!
1862 \internal
1863
1864 Propagate this widget's palette to all children, except style sheet
1865 widgets, and windows that don't enable window propagation (palettes don't
1866 normally propagate to windows).
1867*/
1868void QWidgetPrivate::propagatePaletteChange()
1869{
1870 Q_Q(QWidget);
1871 // Propagate a new inherited mask to all children.
1872#if QT_CONFIG(graphicsview)
1873 if (!q->parentWidget() && extra && extra->proxyWidget) {
1874 QGraphicsProxyWidget *p = extra->proxyWidget;
1875 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1876 } else
1877#endif // QT_CONFIG(graphicsview)
1878 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1879 inheritedPaletteResolveMask = 0;
1880 }
1881
1882 directPaletteResolveMask = data.pal.resolveMask();
1883 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1884
1885 const bool useStyleSheetPropagationInWidgetStyles =
1886 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1887
1888 QEvent pc(QEvent::PaletteChange);
1889 QCoreApplication::sendEvent(q, &pc);
1890 for (int i = 0; i < children.size(); ++i) {
1891 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1892 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1893 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1894 QWidgetPrivate *wd = w->d_func();
1895 wd->inheritedPaletteResolveMask = mask;
1896 wd->resolvePalette();
1897 }
1898 }
1899}
1900
1901/*
1902 Returns the widget's clipping rectangle.
1903*/
1904QRect QWidgetPrivate::clipRect() const
1905{
1906 Q_Q(const QWidget);
1907 const QWidget * w = q;
1908 if (!w->isVisible())
1909 return QRect();
1910 QRect r = effectiveRectFor(q->rect());
1911 int ox = 0;
1912 int oy = 0;
1913 while (w
1914 && w->isVisible()
1915 && !w->isWindow()
1916 && w->parentWidget()) {
1917 ox -= w->x();
1918 oy -= w->y();
1919 w = w->parentWidget();
1920 r &= QRect(ox, oy, w->width(), w->height());
1921 }
1922 return r;
1923}
1924
1925/*
1926 Returns the widget's clipping region (without siblings).
1927*/
1928QRegion QWidgetPrivate::clipRegion() const
1929{
1930 Q_Q(const QWidget);
1931 if (!q->isVisible())
1932 return QRegion();
1933 QRegion r(q->rect());
1934 const QWidget * w = q;
1935 const QWidget *ignoreUpTo;
1936 int ox = 0;
1937 int oy = 0;
1938 while (w
1939 && w->isVisible()
1940 && !w->isWindow()
1941 && w->parentWidget()) {
1942 ox -= w->x();
1943 oy -= w->y();
1944 ignoreUpTo = w;
1945 w = w->parentWidget();
1946 r &= QRegion(ox, oy, w->width(), w->height());
1947
1948 int i = 0;
1949 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1950 ;
1951 for ( ; i < w->d_func()->children.size(); ++i) {
1952 if (QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1953 if (sibling->isVisible() && !sibling->isWindow()) {
1954 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1955 sibling->width(), sibling->height());
1956 if (qRectIntersects(siblingRect, q->rect()))
1957 r -= QRegion(siblingRect);
1958 }
1959 }
1960 }
1961 }
1962 return r;
1963}
1964
1965void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1966{
1967// Transform the system clip region from device-independent pixels to device pixels
1968 QTransform scaleTransform;
1969 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1970
1971 paintEngine->d_func()->baseSystemClip = region;
1972 paintEngine->d_func()->setSystemTransform(scaleTransform);
1973
1974}
1975
1976#if QT_CONFIG(graphicseffect)
1977void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1978{
1979 Q_Q(QWidget);
1980 QWidget *w = q;
1981 do {
1982 if (w->graphicsEffect()) {
1983 QWidgetEffectSourcePrivate *sourced =
1984 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1985 if (!sourced->updateDueToGraphicsEffect)
1986 w->graphicsEffect()->source()->d_func()->invalidateCache();
1987 }
1988 w = w->parentWidget();
1989 } while (w);
1990}
1991#endif // QT_CONFIG(graphicseffect)
1992
1993void QWidgetPrivate::setDirtyOpaqueRegion()
1994{
1995 Q_Q(QWidget);
1996
1997 dirtyOpaqueChildren = true;
1998
1999#if QT_CONFIG(graphicseffect)
2000 invalidateGraphicsEffectsRecursively();
2001#endif // QT_CONFIG(graphicseffect)
2002
2003 if (q->isWindow())
2004 return;
2005
2006 QWidget *parent = q->parentWidget();
2007 if (!parent)
2008 return;
2009
2010 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2011 QWidgetPrivate *pd = parent->d_func();
2012 if (!pd->dirtyOpaqueChildren)
2013 pd->setDirtyOpaqueRegion();
2014}
2015
2016const QRegion &QWidgetPrivate::getOpaqueChildren() const
2017{
2018 if (!dirtyOpaqueChildren)
2019 return opaqueChildren;
2020
2021 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2022 that->opaqueChildren = QRegion();
2023
2024 for (int i = 0; i < children.size(); ++i) {
2025 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2026 if (!child || !child->isVisible() || child->isWindow())
2027 continue;
2028
2029 const QPoint offset = child->geometry().topLeft();
2030 QWidgetPrivate *childd = child->d_func();
2031 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2032 if (childd->extra && childd->extra->hasMask)
2033 r &= childd->extra->mask;
2034 if (r.isEmpty())
2035 continue;
2036 r.translate(offset);
2037 that->opaqueChildren += r;
2038 }
2039
2040 that->opaqueChildren &= q_func()->rect();
2041 that->dirtyOpaqueChildren = false;
2042
2043 return that->opaqueChildren;
2044}
2045
2046void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2047{
2048 if (children.isEmpty() || clipRect.isEmpty())
2049 return;
2050
2051 const QRegion &r = getOpaqueChildren();
2052 if (!r.isEmpty())
2053 source -= (r & clipRect);
2054}
2055
2056//subtract any relatives that are higher up than me --- this is too expensive !!!
2057void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2058 bool alsoNonOpaque) const
2059{
2060 Q_Q(const QWidget);
2061 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2062 if (disableSubtractOpaqueSiblings || q->isWindow())
2063 return;
2064
2065 QRect clipBoundingRect;
2066 bool dirtyClipBoundingRect = true;
2067
2068 QRegion parentClip;
2069 bool dirtyParentClip = true;
2070
2071 QPoint parentOffset = data.crect.topLeft();
2072
2073 const QWidget *w = q;
2074
2075 while (w) {
2076 if (w->isWindow())
2077 break;
2078 QWidgetPrivate *pd = w->parentWidget()->d_func();
2079 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2080 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2081 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2082 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2083 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2084 continue;
2085
2086 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2087 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2088 continue;
2089
2090 if (dirtyClipBoundingRect) {
2091 clipBoundingRect = sourceRegion.boundingRect();
2092 dirtyClipBoundingRect = false;
2093 }
2094
2095 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2096 continue;
2097
2098 if (dirtyParentClip) {
2099 parentClip = sourceRegion.translated(parentOffset);
2100 dirtyParentClip = false;
2101 }
2102
2103 const QPoint siblingPos(sibling->data->crect.topLeft());
2104 const QRect siblingClipRect(sibling->d_func()->clipRect());
2105 QRegion siblingDirty(parentClip);
2106 siblingDirty &= (siblingClipRect.translated(siblingPos));
2107 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2108 && !sibling->d_func()->graphicsEffect;
2109 if (hasMask)
2110 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2111 if (siblingDirty.isEmpty())
2112 continue;
2113
2114 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2115 if (hasMask) {
2116 siblingDirty.translate(-parentOffset);
2117 sourceRegion -= siblingDirty;
2118 } else {
2119 sourceRegion -= siblingGeometry.translated(-parentOffset);
2120 }
2121 } else {
2122 if (hasDirtySiblingsAbove)
2123 *hasDirtySiblingsAbove = true;
2124 if (sibling->d_func()->children.isEmpty())
2125 continue;
2126 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2127 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2128 sourceRegion -= opaqueSiblingChildren;
2129 }
2130 if (sourceRegion.isEmpty())
2131 return;
2132
2133 dirtyClipBoundingRect = true;
2134 dirtyParentClip = true;
2135 }
2136
2137 w = w->parentWidget();
2138 parentOffset += pd->data.crect.topLeft();
2139 dirtyParentClip = true;
2140 }
2141}
2142
2143void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2144{
2145 Q_Q(const QWidget);
2146
2147 const QWidget *w = q;
2148 QPoint offset;
2149
2150#if QT_CONFIG(graphicseffect)
2151 if (graphicsEffect && !w->isWindow()) {
2152 w = q->parentWidget();
2153 offset -= data.crect.topLeft();
2154 }
2155#endif // QT_CONFIG(graphicseffect)
2156
2157 while (w) {
2158 const QWidgetPrivate *wd = w->d_func();
2159 if (wd->extra && wd->extra->hasMask)
2160 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2161 if (w->isWindow())
2162 return;
2163 offset -= wd->data.crect.topLeft();
2164 w = w->parentWidget();
2165 }
2166}
2167
2168bool QWidgetPrivate::shouldPaintOnScreen() const
2169{
2170#if defined(QT_NO_BACKINGSTORE)
2171 return true;
2172#else
2173 Q_Q(const QWidget);
2174 if (q->testAttribute(Qt::WA_PaintOnScreen)
2175 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2176 return true;
2177 }
2178
2179 return false;
2180#endif
2181}
2182
2183void QWidgetPrivate::updateIsOpaque()
2184{
2185 // hw: todo: only needed if opacity actually changed
2186 setDirtyOpaqueRegion();
2187
2188#if QT_CONFIG(graphicseffect)
2189 if (graphicsEffect) {
2190 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2191 setOpaque(false);
2192 return;
2193 }
2194#endif // QT_CONFIG(graphicseffect)
2195
2196 Q_Q(QWidget);
2197 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2198 setOpaque(true);
2199 return;
2200 }
2201
2202 const QPalette &pal = q->palette();
2203
2204 if (q->autoFillBackground()) {
2205 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2206 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2207 setOpaque(true);
2208 return;
2209 }
2210 }
2211
2212 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2213 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2214 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2215 setOpaque(true);
2216 return;
2217 }
2218 }
2219 setOpaque(false);
2220}
2221
2222void QWidgetPrivate::setOpaque(bool opaque)
2223{
2224 if (isOpaque != opaque) {
2225 isOpaque = opaque;
2226 updateIsTranslucent();
2227 }
2228}
2229
2230void QWidgetPrivate::updateIsTranslucent()
2231{
2232 Q_Q(QWidget);
2233 if (QWindow *window = q->windowHandle()) {
2234 QSurfaceFormat format = window->format();
2235 const int oldAlpha = format.alphaBufferSize();
2236 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
2237 if (oldAlpha != newAlpha) {
2238 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2239 //
2240 // If that is not the case, then the setFormat() is not just futile
2241 // but downright dangerous. Futile because the format matters only
2242 // when creating the native window, no point in changing it
2243 // afterwards. Dangerous because a QOpenGLContext or something else
2244 // may eventually query the QWindow's format(), in order to ensure
2245 // compatibility (in terms of native concepts such as pixel format,
2246 // EGLConfig, etc.), and if we change it here, then the returned
2247 // format does not describe reality anymore. (reality being the
2248 // settings with which the native resource was created).
2249 //
2250 // Whereas if one does a destroy()-create() then this all here
2251 // won't matter because the format is updated in
2252 // QWidgetPrivate::create() again.
2253 //
2254 if (!window->handle()) {
2255 format.setAlphaBufferSize(newAlpha);
2256 window->setFormat(format);
2257 }
2258 }
2259 }
2260}
2261
2262static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2263{
2264 Q_ASSERT(painter);
2265
2266 if (brush.style() == Qt::TexturePattern) {
2267 const QRect rect(rgn.boundingRect());
2268 painter->setClipRegion(rgn);
2269 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2270 } else if (brush.gradient()
2271 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2272 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2273 painter->save();
2274 painter->setClipRegion(rgn);
2275 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2276 painter->restore();
2277 } else {
2278 for (const QRect &rect : rgn)
2279 painter->fillRect(rect, brush);
2280 }
2281}
2282
2283bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2284{
2285#if QT_CONFIG(scrollarea)
2286 Q_Q(const QWidget);
2287 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2288 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2289 return false;
2290 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2291 if (scrollArea && scrollArea->viewport() == q) {
2292 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2293 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2294 painter->setBrushOrigin(-priv->contentsOffset());
2295 }
2296#endif // QT_CONFIG(scrollarea)
2297 return true;
2298}
2299
2300void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2301{
2302 Q_Q(const QWidget);
2303
2304 bool brushOriginSet = false;
2305 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2306
2307 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2308 const QBrush bg = q->palette().brush(QPalette::Window);
2309 if (!brushOriginSet)
2310 brushOriginSet = updateBrushOrigin(painter, bg);
2311 if (!(flags & DontSetCompositionMode)) {
2312 //copy alpha straight in
2313 QPainter::CompositionMode oldMode = painter->compositionMode();
2314 painter->setCompositionMode(QPainter::CompositionMode_Source);
2315 fillRegion(painter, rgn, bg);
2316 painter->setCompositionMode(oldMode);
2317 } else {
2318 fillRegion(painter, rgn, bg);
2319 }
2320 }
2321
2322 if (q->autoFillBackground()) {
2323 if (!brushOriginSet)
2324 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2325 fillRegion(painter, rgn, autoFillBrush);
2326 }
2327
2328 if (q->testAttribute(Qt::WA_StyledBackground)) {
2329 painter->setClipRegion(rgn);
2330 QStyleOption opt;
2331 opt.initFrom(q);
2332 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2333 }
2334}
2335
2336/*
2337 \internal
2338 This function is called when a widget is hidden or destroyed.
2339 It resets some application global pointers that should only refer active,
2340 visible widgets.
2341*/
2342
2344
2345void QWidgetPrivate::deactivateWidgetCleanup()
2346{
2347 Q_Q(QWidget);
2348 // If this was the active application window, reset it
2349 if (QApplication::activeWindow() == q)
2350 QApplicationPrivate::setActiveWindow(nullptr);
2351 // If the is the active mouse press widget, reset it
2352 if (q == qt_button_down)
2353 qt_button_down = nullptr;
2354}
2355
2356
2357/*!
2358 Returns a pointer to the widget with window identifier/handle \a
2359 id.
2360
2361 The window identifier type depends on the underlying window
2362 system, see \c qwindowdefs.h for the actual definition. If there
2363 is no widget with this identifier, \nullptr is returned.
2364*/
2365
2366QWidget *QWidget::find(WId id)
2367{
2368 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2369}
2370
2371
2372
2373/*!
2374 \fn WId QWidget::internalWinId() const
2375 \internal
2376 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2377
2378*/
2379
2380/*!
2381 \fn WId QWidget::winId() const
2382
2383 Returns the window system identifier of the widget.
2384
2385 Portable in principle, but if you use it you are probably about to
2386 do something non-portable. Be careful.
2387
2388 If a widget is non-native (alien) and winId() is invoked on it, that widget
2389 will be provided a native handle.
2390
2391 This value may change at run-time. An event with type QEvent::WinIdChange
2392 will be sent to the widget following a change in window system identifier.
2393
2394 \sa find()
2395*/
2396WId QWidget::winId() const
2397{
2398 if (!data->in_destructor
2399 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2400 {
2401 QWidget *that = const_cast<QWidget*>(this);
2402 that->setAttribute(Qt::WA_NativeWindow);
2403 that->d_func()->createWinId();
2404 return that->data->winid;
2405 }
2406 return data->winid;
2407}
2408
2409void QWidgetPrivate::createWinId()
2410{
2411 Q_Q(QWidget);
2412
2413 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2414 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2415 if (!q->isWindow()) {
2416 QWidget *parent = q->parentWidget();
2417 QWidgetPrivate *pd = parent->d_func();
2418 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2419 parent->setAttribute(Qt::WA_NativeWindow);
2420 if (!parent->internalWinId()) {
2421 pd->createWinId();
2422 }
2423
2424 for (int i = 0; i < pd->children.size(); ++i) {
2425 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2426 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2427 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2428 w->create();
2429 }
2430 }
2431 } else {
2432 q->create();
2433 }
2434 }
2435}
2436
2437/*!
2438\internal
2439Ensures that the widget is set on the screen point is on. This is handy getting a correct
2440size hint before a resize in e.g QMenu and QToolTip.
2441Returns if the screen was changed.
2442*/
2443
2444bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2445{
2446 Q_Q(QWidget);
2447 if (!q->isWindow())
2448 return false;
2449 // Find the screen for pos and make the widget understand it is on that screen.
2450 return setScreen(QGuiApplication::screenAt(pos));
2451}
2452
2453/*!
2454\internal
2455Ensures that the widget's QWindow is set to be on the given \a screen.
2456Returns true if the screen was changed.
2457*/
2458
2459bool QWidgetPrivate::setScreen(QScreen *screen)
2460{
2461 Q_Q(QWidget);
2462 if (!screen || !q->isWindow())
2463 return false;
2464 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2465 if (currentScreen != screen) {
2466 topData()->initialScreen = screen;
2467 if (windowHandle())
2468 windowHandle()->setScreen(screen);
2469 return true;
2470 }
2471 return false;
2472}
2473
2474/*!
2475\internal
2476Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2477
2478*/
2479
2480void QWidget::createWinId()
2481{
2482 Q_D(QWidget);
2483 d->createWinId();
2484}
2485
2486/*!
2487 \since 4.4
2488
2489 Returns the effective window system identifier of the widget, i.e. the
2490 native parent's window system identifier.
2491
2492 If the widget is native, this function returns the native widget ID.
2493 Otherwise, the window ID of the first native parent widget, i.e., the
2494 top-level widget that contains this widget, is returned.
2495
2496 \note We recommend that you do not store this value as it is likely to
2497 change at run-time.
2498
2499 \sa nativeParentWidget()
2500*/
2501WId QWidget::effectiveWinId() const
2502{
2503 const WId id = internalWinId();
2504 if (id || !testAttribute(Qt::WA_WState_Created))
2505 return id;
2506 if (const QWidget *realParent = nativeParentWidget())
2507 return realParent->internalWinId();
2508 return 0;
2509}
2510
2511/*!
2512 If this is a native widget, return the associated QWindow.
2513 Otherwise return null.
2514
2515 Native widgets include toplevel widgets, QGLWidget, and child widgets
2516 on which winId() was called.
2517
2518 \since 5.0
2519
2520 \sa winId(), screen()
2521*/
2522QWindow *QWidget::windowHandle() const
2523{
2524 Q_D(const QWidget);
2525 return d->windowHandle();
2526}
2527
2528/*!
2529 Returns the screen the widget is on.
2530
2531 \since 5.14
2532
2533 \sa windowHandle()
2534*/
2535QScreen *QWidget::screen() const
2536{
2537 Q_D(const QWidget);
2538 if (auto associatedScreen = d->associatedScreen())
2539 return associatedScreen;
2540 if (auto topLevel = window()) {
2541 if (auto topData = qt_widget_private(topLevel)->topData()) {
2542 if (topData->initialScreen)
2543 return topData->initialScreen;
2544 }
2545 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2546 return screenByPos;
2547 }
2548 return QGuiApplication::primaryScreen();
2549}
2550
2551/*!
2552 Sets the screen on which the widget should be shown to \a screen.
2553
2554 Setting the screen only makes sense for windows. If necessary, the widget's
2555 window will get recreated on \a screen.
2556
2557 \note If the screen is part of a virtual desktop of multiple screens,
2558 the window will not move automatically to \a screen. To place the
2559 window relative to the screen, use the screen's topLeft() position.
2560
2561 \sa QWindow::setScreen()
2562*/
2563void QWidget::setScreen(QScreen *screen)
2564{
2565 Q_D(QWidget);
2566 d->setScreen(screen);
2567}
2568
2569#if QT_CONFIG(style_stylesheet)
2570
2571/*!
2572 \property QWidget::styleSheet
2573 \brief the widget's style sheet
2574 \since 4.2
2575
2576 The style sheet contains a textual description of customizations to the
2577 widget's style, as described in the \l{Qt Style Sheets} document.
2578
2579 Since Qt 4.5, Qt style sheets fully supports \macos.
2580
2581 \warning Qt style sheets are currently not supported for custom QStyle
2582 subclasses. We plan to address this in some future release.
2583
2584 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2585*/
2586QString QWidget::styleSheet() const
2587{
2588 Q_D(const QWidget);
2589 if (!d->extra)
2590 return QString();
2591 return d->extra->styleSheet;
2592}
2593
2594void QWidget::setStyleSheet(const QString& styleSheet)
2595{
2596 Q_D(QWidget);
2597 if (data->in_destructor)
2598 return;
2599 d->createExtra();
2600
2601 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2602 d->extra->styleSheet = styleSheet;
2603 if (styleSheet.isEmpty()) { // stylesheet removed
2604 if (!proxy)
2605 return;
2606
2607 d->inheritStyle();
2608 return;
2609 }
2610
2611 if (proxy) { // style sheet update
2612 bool repolish = d->polished;
2613 if (!repolish) {
2614 const auto childWidgets = findChildren<QWidget*>();
2615 for (auto child : childWidgets) {
2616 repolish = child->d_func()->polished;
2617 if (repolish)
2618 break;
2619 }
2620 }
2621 if (repolish)
2622 proxy->repolish(this);
2623 return;
2624 }
2625
2626 if (testAttribute(Qt::WA_SetStyle)) {
2627 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2628 } else {
2629 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2630 }
2631}
2632
2633#endif // QT_NO_STYLE_STYLESHEET
2634
2635/*!
2636 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2637*/
2638
2639QStyle *QWidget::style() const
2640{
2641 Q_D(const QWidget);
2642
2643 if (d->extra && d->extra->style)
2644 return d->extra->style;
2645 return QApplication::style();
2646}
2647
2648/*!
2649 Sets the widget's GUI style to \a style. The ownership of the style
2650 object is not transferred.
2651
2652 If no style is set, the widget uses the application's style,
2653 QApplication::style() instead.
2654
2655 Setting a widget's style has no effect on existing or future child
2656 widgets.
2657
2658 \warning This function is particularly useful for demonstration
2659 purposes, where you want to show Qt's styling capabilities. Real
2660 applications should avoid it and use one consistent GUI style
2661 instead.
2662
2663 \warning Qt style sheets are currently not supported for custom QStyle
2664 subclasses. We plan to address this in some future release.
2665
2666 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2667*/
2668
2669void QWidget::setStyle(QStyle *style)
2670{
2671 Q_D(QWidget);
2672 setAttribute(Qt::WA_SetStyle, style != nullptr);
2673 d->createExtra();
2674#if QT_CONFIG(style_stylesheet)
2675 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2676 //if for some reason someone try to set a QStyleSheetStyle, ref it
2677 //(this may happen for example in QButtonDialogBox which propagates its style)
2678 styleSheetStyle->ref();
2679 d->setStyle_helper(style, false);
2680 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2681 // if we have an application stylesheet or have a proxy already, propagate
2682 d->setStyle_helper(new QStyleSheetStyle(style), true);
2683 } else
2684#endif
2685 d->setStyle_helper(style, false);
2686}
2687
2688void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2689{
2690 Q_Q(QWidget);
2691 QStyle *oldStyle = q->style();
2692
2693 createExtra();
2694
2695#if QT_CONFIG(style_stylesheet)
2696 QPointer<QStyle> origStyle = extra->style;
2697#endif
2698 extra->style = newStyle;
2699
2700 // repolish
2701 if (polished) {
2702 oldStyle->unpolish(q);
2703 q->style()->polish(q);
2704 }
2705
2706 if (propagate) {
2707 // We copy the list because the order may be modified
2708 const QObjectList childrenList = children;
2709 for (int i = 0; i < childrenList.size(); ++i) {
2710 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2711 if (c)
2712 c->d_func()->inheritStyle();
2713 }
2714 }
2715
2716#if QT_CONFIG(style_stylesheet)
2717 if (!qt_styleSheet(newStyle)) {
2718 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2719 cssStyle->clearWidgetFont(q);
2720 }
2721 }
2722#endif
2723
2724 QEvent e(QEvent::StyleChange);
2725 QCoreApplication::sendEvent(q, &e);
2726
2727#if QT_CONFIG(style_stylesheet)
2728 // dereference the old stylesheet style
2729 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2730 proxy->deref();
2731#endif
2732}
2733
2734// Inherits style from the current parent and propagates it as necessary
2735void QWidgetPrivate::inheritStyle()
2736{
2737#if QT_CONFIG(style_stylesheet)
2738 Q_Q(QWidget);
2739
2740 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2741
2742 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2743
2744 if (!q->styleSheet().isEmpty()) {
2745 Q_ASSERT(proxy);
2746 proxy->repolish(q);
2747 return;
2748 }
2749 if (inheritStyleRecursionGuard)
2750 return;
2751 inheritStyleRecursionGuard = true;
2752 const auto resetGuard = qScopeGuard([&]() {
2753 inheritStyleRecursionGuard = false;
2754 });
2755
2756 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2757 QWidget *parent = q->parentWidget();
2758 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2759 // If we have stylesheet on app or parent has stylesheet style, we need
2760 // to be running a proxy
2761 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2762 QStyle *newStyle = parentStyle;
2763 if (q->testAttribute(Qt::WA_SetStyle) && qt_styleSheet(origStyle) == nullptr)
2764 newStyle = new QStyleSheetStyle(origStyle);
2765 else if (auto *styleSheetStyle = qt_styleSheet(origStyle))
2766 newStyle = styleSheetStyle;
2767 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2768 newProxy->ref();
2769
2770 setStyle_helper(newStyle, true);
2771 return;
2772 }
2773
2774 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2775 // we just need our original style back
2776 if (origStyle == extraStyle) // is it any different?
2777 return;
2778
2779 // We could have inherited the proxy from our parent (which has a custom style)
2780 // In such a case we need to start following the application style (i.e revert
2781 // the propagation behavior of QStyleSheetStyle)
2782 if (!q->testAttribute(Qt::WA_SetStyle))
2783 origStyle = nullptr;
2784
2785 setStyle_helper(origStyle, true);
2786#endif // QT_NO_STYLE_STYLESHEET
2787}
2788
2789
2790/*!
2791 \fn bool QWidget::isWindow() const
2792
2793 Returns \c true if the widget is an independent window, otherwise
2794 returns \c false.
2795
2796 A window is a widget that isn't visually the child of any other
2797 widget and that usually has a frame and a
2798 \l{QWidget::setWindowTitle()}{window title}.
2799
2800 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2801 It will then be grouped with its parent and deleted when the
2802 parent is deleted, minimized when the parent is minimized etc. If
2803 supported by the window manager, it will also have a common
2804 taskbar entry with its parent.
2805
2806 QDialog and QMainWindow widgets are by default windows, even if a
2807 parent widget is specified in the constructor. This behavior is
2808 specified by the Qt::Window flag.
2809
2810 \sa window(), isModal(), parentWidget()
2811*/
2812
2813/*!
2814 \property QWidget::modal
2815 \brief whether the widget is a modal widget
2816
2817 This property only makes sense for windows. A modal widget
2818 prevents widgets in all other windows from getting any input.
2819
2820 By default, this property is \c false.
2821
2822 \sa isWindow(), windowModality, QDialog
2823*/
2824
2825/*!
2826 \property QWidget::windowModality
2827 \brief which windows are blocked by the modal widget
2828 \since 4.1
2829
2830 This property only makes sense for windows. A modal widget
2831 prevents widgets in other windows from getting input. The value of
2832 this property controls which windows are blocked when the widget
2833 is visible. Changing this property while the window is visible has
2834 no effect; you must hide() the widget first, then show() it again.
2835
2836 By default, this property is Qt::NonModal.
2837
2838 \sa isWindow(), QWidget::modal, QDialog
2839*/
2840
2841Qt::WindowModality QWidget::windowModality() const
2842{
2843 return static_cast<Qt::WindowModality>(data->window_modality);
2844}
2845
2846void QWidget::setWindowModality(Qt::WindowModality windowModality)
2847{
2848 data->window_modality = windowModality;
2849 // setModal_sys() will be called by setAttribute()
2850 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2851 setAttribute(Qt::WA_SetWindowModality, true);
2852}
2853
2854void QWidgetPrivate::setModal_sys()
2855{
2856 Q_Q(QWidget);
2857 if (q->windowHandle())
2858 q->windowHandle()->setModality(q->windowModality());
2859}
2860
2861/*!
2862 \fn bool QWidget::underMouse() const
2863
2864 Returns \c true if the widget is under the mouse cursor; otherwise
2865 returns \c false.
2866
2867 This value is not updated properly during drag and drop
2868 operations.
2869
2870 \sa enterEvent(), leaveEvent()
2871*/
2872
2873/*!
2874 \property QWidget::minimized
2875 \brief whether this widget is minimized (iconified)
2876
2877 This property is only relevant for windows.
2878
2879 By default, this property is \c false.
2880
2881 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2882*/
2883bool QWidget::isMinimized() const
2884{ return data->window_state & Qt::WindowMinimized; }
2885
2886/*!
2887 Shows the widget minimized, as an icon.
2888
2889 Calling this function only affects \l{isWindow()}{windows}.
2890
2891 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2892 isMinimized()
2893*/
2894void QWidget::showMinimized()
2895{
2896 bool isMin = isMinimized();
2897 if (isMin && isVisible())
2898 return;
2899
2900 ensurePolished();
2901
2902 if (!isMin)
2903 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2904 setVisible(true);
2905}
2906
2907/*!
2908 \property QWidget::maximized
2909 \brief whether this widget is maximized
2910
2911 This property is only relevant for windows.
2912
2913 \note Due to limitations on some window systems, this does not always
2914 report the expected results (e.g., if the user on X11 maximizes the
2915 window via the window manager, Qt has no way of distinguishing this
2916 from any other resize). This is expected to improve as window manager
2917 protocols evolve.
2918
2919 By default, this property is \c false.
2920
2921 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2922*/
2923bool QWidget::isMaximized() const
2924{ return data->window_state & Qt::WindowMaximized; }
2925
2926
2927
2928/*!
2929 Returns the current window state. The window state is a OR'ed
2930 combination of Qt::WindowState: Qt::WindowMinimized,
2931 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2932
2933 \sa Qt::WindowState, setWindowState()
2934 */
2935Qt::WindowStates QWidget::windowState() const
2936{
2937 return Qt::WindowStates(data->window_state);
2938}
2939
2940/*!\internal
2941
2942 The function sets the window state on child widgets similar to
2943 setWindowState(). The difference is that the window state changed
2944 event has the isOverride() flag set. It exists mainly to keep
2945 QWorkspace working.
2946 */
2947void QWidget::overrideWindowState(Qt::WindowStates newstate)
2948{
2949 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2950 data->window_state = newstate;
2951 QCoreApplication::sendEvent(this, &e);
2952}
2953
2954/*!
2955 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2956
2957 Sets the window state to \a windowState. The window state is a OR'ed
2958 combination of Qt::WindowState: Qt::WindowMinimized,
2959 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2960
2961 If the window is not visible (i.e. isVisible() returns \c false), the
2962 window state will take effect when show() is called. For visible
2963 windows, the change is immediate. For example, to toggle between
2964 full-screen and normal mode, use the following code:
2965
2966 \snippet code/src_gui_kernel_qwidget.cpp 0
2967
2968 To restore and activate a minimized window (while
2969 preserving its maximized and/or full-screen state), use the following:
2970
2971 \snippet code/src_gui_kernel_qwidget.cpp 1
2972
2973 Calling this function will hide the widget. You must call show() to make
2974 the widget visible again.
2975
2976 \note On some window systems Qt::WindowActive is not immediate, and may be
2977 ignored in certain cases.
2978
2979 When the window state changes, the widget receives a changeEvent()
2980 of type QEvent::WindowStateChange.
2981
2982 \sa Qt::WindowState, windowState()
2983*/
2984void QWidget::setWindowState(Qt::WindowStates newstate)
2985{
2986 Q_D(QWidget);
2987 Qt::WindowStates oldstate = windowState();
2988 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2989 newstate.setFlag(Qt::WindowActive, false);
2990 if (oldstate == newstate)
2991 return;
2992 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2993 create();
2994
2995 data->window_state = newstate;
2996 data->in_set_window_state = 1;
2997 if (isWindow()) {
2998 // Ensure the initial size is valid, since we store it as normalGeometry below.
2999 if (!testAttribute(Qt::WA_Resized) && !isVisible())
3000 adjustSize();
3001
3002 d->createTLExtra();
3003 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3004 d->topData()->normalGeometry = geometry();
3005
3006 Q_ASSERT(windowHandle());
3007 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3008 }
3009 data->in_set_window_state = 0;
3010
3011 if (newstate & Qt::WindowActive)
3012 activateWindow();
3013
3014 QWindowStateChangeEvent e(oldstate);
3015 QCoreApplication::sendEvent(this, &e);
3016}
3017
3018/*!
3019 \property QWidget::fullScreen
3020 \brief whether the widget is shown in full screen mode
3021
3022 A widget in full screen mode occupies the whole screen area and does not
3023 display window decorations, such as a title bar.
3024
3025 By default, this property is \c false.
3026
3027 \sa windowState(), minimized, maximized
3028*/
3029bool QWidget::isFullScreen() const
3030{ return data->window_state & Qt::WindowFullScreen; }
3031
3032/*!
3033 Shows the widget in full-screen mode.
3034
3035 Calling this function only affects \l{isWindow()}{windows}.
3036
3037 To return from full-screen mode, call showNormal() or close().
3038
3039 \note Full-screen mode works fine under Windows, but has certain
3040 problems under X. These problems are due to limitations of the
3041 ICCCM protocol that specifies the communication between X11
3042 clients and the window manager. ICCCM simply does not understand
3043 the concept of non-decorated full-screen windows. Therefore, the
3044 best you can do is to request a borderless window and place and
3045 resize it to fill the entire screen. Depending on the window
3046 manager, this may or may not work. The borderless window is
3047 requested using MOTIF hints, which are at least partially
3048 supported by virtually all modern window managers.
3049
3050 An alternative would be to bypass the window manager entirely and
3051 create a window with the Qt::X11BypassWindowManagerHint flag. This
3052 has other severe problems though, like broken keyboard focus
3053 and very strange effects on desktop changes or when the user raises
3054 other windows.
3055
3056 X11 window managers that follow modern post-ICCCM specifications
3057 support full-screen mode properly.
3058
3059 On macOS, showing a window full screen puts the entire application in
3060 full-screen mode, providing it with a dedicated desktop. Showing another
3061 window while the application runs in full-screen mode might automatically
3062 make that window full screen as well. To prevent that, exit full-screen
3063 mode by calling showNormal() or by close() on the full screen window
3064 before showing another window.
3065
3066 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3067*/
3068void QWidget::showFullScreen()
3069{
3070 ensurePolished();
3071
3072 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3073 | Qt::WindowFullScreen);
3074 setVisible(true);
3075#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3076 // activating it here before libscreen activates it causes problems
3077 activateWindow();
3078#endif
3079}
3080
3081/*!
3082 Shows the widget maximized.
3083
3084 Calling this function only affects \l{isWindow()}{windows}.
3085
3086 On X11, this function may not work properly with certain window
3087 managers. See the \l{Window Geometry} documentation for an explanation.
3088
3089 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3090*/
3091void QWidget::showMaximized()
3092{
3093 ensurePolished();
3094
3095 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3096 | Qt::WindowMaximized);
3097 setVisible(true);
3098}
3099
3100/*!
3101 Restores the widget after it has been maximized or minimized.
3102
3103 Calling this function only affects \l{isWindow()}{windows}.
3104
3105 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3106*/
3107void QWidget::showNormal()
3108{
3109 ensurePolished();
3110
3111 setWindowState(windowState() & ~(Qt::WindowMinimized
3112 | Qt::WindowMaximized
3113 | Qt::WindowFullScreen));
3114 setVisible(true);
3115}
3116
3117/*!
3118 Returns \c true if this widget would become enabled if \a ancestor is
3119 enabled; otherwise returns \c false.
3120
3121
3122
3123 This is the case if neither the widget itself nor every parent up
3124 to but excluding \a ancestor has been explicitly disabled.
3125
3126 isEnabledTo(0) returns false if this widget or any if its ancestors
3127 was explicitly disabled.
3128
3129 The word ancestor here means a parent widget within the same window.
3130
3131 Therefore isEnabledTo(0) stops at this widget's window, unlike
3132 isEnabled() which also takes parent windows into considerations.
3133
3134 \sa setEnabled(), enabled
3135*/
3136
3137bool QWidget::isEnabledTo(const QWidget *ancestor) const
3138{
3139 const QWidget * w = this;
3140 while (!w->testAttribute(Qt::WA_ForceDisabled)
3141 && !w->isWindow()
3142 && w->parentWidget()
3143 && w->parentWidget() != ancestor)
3144 w = w->parentWidget();
3145 return !w->testAttribute(Qt::WA_ForceDisabled);
3146}
3147
3148#ifndef QT_NO_ACTION
3149/*!
3150 Appends the action \a action to this widget's list of actions.
3151
3152 All QWidgets have a list of \l{QAction}s. However, they can be
3153 represented graphically in many different ways. The default use of
3154 the QAction list (as returned by actions()) is to create a context
3155 QMenu.
3156
3157 A QWidget should only have one of each action and adding an action
3158 it already has will not cause the same action to be in the widget twice.
3159
3160 The ownership of \a action is not transferred to this QWidget.
3161
3162 \sa removeAction(), insertAction(), actions(), QMenu
3163*/
3164void QWidget::addAction(QAction *action)
3165{
3166 insertAction(nullptr, action);
3167}
3168
3169/*!
3170 Appends the actions \a actions to this widget's list of actions.
3171
3172 \sa removeAction(), QMenu, addAction()
3173*/
3174void QWidget::addActions(const QList<QAction *> &actions)
3175{
3176 for(int i = 0; i < actions.size(); i++)
3177 insertAction(nullptr, actions.at(i));
3178}
3179
3180/*!
3181 Inserts the action \a action to this widget's list of actions,
3182 before the action \a before. It appends the action if \a before is \nullptr or
3183 \a before is not a valid action for this widget.
3184
3185 A QWidget should only have one of each action.
3186
3187 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3188*/
3189void QWidget::insertAction(QAction *before, QAction *action)
3190{
3191 if (Q_UNLIKELY(!action)) {
3192 qWarning("QWidget::insertAction: Attempt to insert null action");
3193 return;
3194 }
3195
3196 Q_D(QWidget);
3197 if (d->actions.contains(action))
3198 removeAction(action);
3199
3200 int pos = d->actions.indexOf(before);
3201 if (pos < 0) {
3202 before = nullptr;
3203 pos = d->actions.size();
3204 }
3205 d->actions.insert(pos, action);
3206
3207 QActionPrivate *apriv = action->d_func();
3208 apriv->associatedObjects.append(this);
3209
3210 QActionEvent e(QEvent::ActionAdded, action, before);
3211 QCoreApplication::sendEvent(this, &e);
3212}
3213
3214/*!
3215 Inserts the actions \a actions to this widget's list of actions,
3216 before the action \a before. It appends the action if \a before is \nullptr or
3217 \a before is not a valid action for this widget.
3218
3219 A QWidget can have at most one of each action.
3220
3221 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3222*/
3223void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3224{
3225 for(int i = 0; i < actions.size(); ++i)
3226 insertAction(before, actions.at(i));
3227}
3228
3229/*!
3230 Removes the action \a action from this widget's list of actions.
3231 \sa insertAction(), actions(), insertAction()
3232*/
3233void QWidget::removeAction(QAction *action)
3234{
3235 if (!action)
3236 return;
3237
3238 Q_D(QWidget);
3239
3240 QActionPrivate *apriv = action->d_func();
3241 apriv->associatedObjects.removeAll(this);
3242
3243 if (d->actions.removeAll(action)) {
3244 QActionEvent e(QEvent::ActionRemoved, action);
3245 QCoreApplication::sendEvent(this, &e);
3246 }
3247}
3248
3249/*!
3250 Returns the (possibly empty) list of this widget's actions.
3251
3252 \sa contextMenuPolicy, insertAction(), removeAction()
3253*/
3254QList<QAction*> QWidget::actions() const
3255{
3256 Q_D(const QWidget);
3257 return d->actions;
3258}
3259
3260/*!
3261 \fn QAction *QWidget::addAction(const QString &text);
3262 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3263 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3264 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3265
3266 \since 6.3
3267
3268 These convenience functions create a new action with text \a text,
3269 icon \a icon and shortcut \a shortcut, if any.
3270
3271 The functions add the newly created action to the widget's
3272 list of actions, and return it.
3273
3274 QWidget takes ownership of the returned QAction.
3275*/
3276QAction *QWidget::addAction(const QString &text)
3277{
3278 QAction *ret = new QAction(text, this);
3279 addAction(ret);
3280 return ret;
3281}
3282
3283QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3284{
3285 QAction *ret = new QAction(icon, text, this);
3286 addAction(ret);
3287 return ret;
3288}
3289
3290#if QT_CONFIG(shortcut)
3291QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3292{
3293 QAction *ret = addAction(text);
3294 ret->setShortcut(shortcut);
3295 return ret;
3296}
3297
3298QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3299{
3300 QAction *ret = addAction(icon, text);
3301 ret->setShortcut(shortcut);
3302 return ret;
3303}
3304#endif
3305
3306/*!
3307 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3308 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3309 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3310 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3311
3312 \overload
3313 \since 6.3
3314
3315 This convenience function creates a new action with the text \a
3316 text, icon \a icon, and shortcut \a shortcut, if any.
3317
3318 The action's \l{QAction::triggered()}{triggered()} signal is connected
3319 to the \a receiver's \a member slot. The function adds the newly created
3320 action to the widget's list of actions and returns it.
3321
3322 QWidget takes ownership of the returned QAction.
3323*/
3324QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3325 Qt::ConnectionType type)
3326{
3327 QAction *action = addAction(text);
3328 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3329 return action;
3330}
3331
3332QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3333 const QObject *receiver, const char* member,
3334 Qt::ConnectionType type)
3335{
3336 QAction *action = addAction(icon, text);
3337 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3338 return action;
3339}
3340
3341#if QT_CONFIG(shortcut)
3342QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3343 const QObject *receiver, const char* member,
3344 Qt::ConnectionType type)
3345{
3346 QAction *action = addAction(text, receiver, member, type);
3347 action->setShortcut(shortcut);
3348 return action;
3349}
3350
3351QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3352 const QObject *receiver, const char* member,
3353 Qt::ConnectionType type)
3354{
3355 QAction *action = addAction(icon, text, receiver, member, type);
3356 action->setShortcut(shortcut);
3357 return action;
3358}
3359#endif // QT_CONFIG(shortcut)
3360
3361/*!
3362 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3363 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3364 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3365 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3366
3367 \since 6.3
3368 \overload
3369
3370 These convenience functions create a new action with the text \a text,
3371 icon \a icon, and shortcut \a shortcut, if any.
3372
3373 The action's \l{QAction::triggered()}{triggered()} signal is connected
3374 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3375 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3376
3377 The function adds the newly created action to the widget's list of
3378 actions and returns it.
3379
3380 QWidget takes ownership of the returned QAction.
3381*/
3382#endif // QT_NO_ACTION
3383
3384/*!
3385 \property QWidget::enabled
3386 \brief whether the widget is enabled
3387
3388 In general an enabled widget handles keyboard and mouse events; a disabled
3389 widget does not. An exception is made with \l{QAbstractButton}.
3390
3391 Some widgets display themselves differently when they are
3392 disabled. For example a button might draw its label grayed out. If
3393 your widget needs to know when it becomes enabled or disabled, you
3394 can use the changeEvent() with type QEvent::EnabledChange.
3395
3396 Disabling a widget implicitly disables all its children. Enabling
3397 respectively enables all child widgets unless they have been
3398 explicitly disabled. It it not possible to explicitly enable a child
3399 widget which is not a window while its parent widget remains disabled.
3400
3401 By default, this property is \c true.
3402
3403 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3404*/
3405void QWidget::setEnabled(bool enable)
3406{
3407 Q_D(QWidget);
3408
3409#if QT_CONFIG(accessibility)
3410 const bool wasEnabled = !testAttribute(Qt::WA_ForceDisabled);
3411#endif
3412
3413 setAttribute(Qt::WA_ForceDisabled, !enable);
3414 d->setEnabled_helper(enable);
3415
3416#if QT_CONFIG(accessibility)
3417 // A widget is enabled if it's parent and itself is enabled.
3418 // We do not send state changed events recursively. It is up
3419 // to the receiver of the events to check children if required.
3420 if (QAccessible::isActive() && wasEnabled != enable) {
3421 QAccessible::State states;
3422 states.disabled = 1;
3423 QAccessibleStateChangeEvent scEvent(this, states);
3424 QAccessible::updateAccessibility(&scEvent);
3425 }
3426#endif
3427}
3428
3429void QWidgetPrivate::setEnabled_helper(bool enable)
3430{
3431 Q_Q(QWidget);
3432
3433 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3434 return; // nothing we can do
3435
3436 if (enable != q->testAttribute(Qt::WA_Disabled))
3437 return; // nothing to do
3438
3439 q->setAttribute(Qt::WA_Disabled, !enable);
3440 updateSystemBackground();
3441
3442 if (!enable && q->window()->focusWidget() == q) {
3443 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3444 if (!parentIsEnabled || !q->focusNextChild())
3445 q->clearFocus();
3446 }
3447
3448 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3449 for (int i = 0; i < children.size(); ++i) {
3450 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3451 if (w && !w->testAttribute(attribute))
3452 w->d_func()->setEnabled_helper(enable);
3453 }
3454#ifndef QT_NO_CURSOR
3455 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3456 // enforce the windows behavior of clearing the cursor on
3457 // disabled widgets
3458 qt_qpa_set_cursor(q, false);
3459 }
3460#endif
3461#ifndef QT_NO_IM
3462 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3463 QWidget *focusWidget = effectiveFocusWidget();
3464
3465 if (enable) {
3466 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3467 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3468 } else {
3469 QGuiApplication::inputMethod()->commit();
3470 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3471 }
3472 }
3473#endif //QT_NO_IM
3474 QEvent e(QEvent::EnabledChange);
3475 QCoreApplication::sendEvent(q, &e);
3476}
3477
3478/*!
3479 \property QWidget::acceptDrops
3480 \brief whether drop events are enabled for this widget
3481
3482 Setting this property to true announces to the system that this
3483 widget \e may be able to accept drop events.
3484
3485 \warning Do not modify this property in a drag and drop event handler.
3486
3487 By default, this property is \c false.
3488
3489 \sa {Drag and Drop in Qt}{Drag and Drop}
3490*/
3491bool QWidget::acceptDrops() const
3492{
3493 return testAttribute(Qt::WA_AcceptDrops);
3494}
3495
3496void QWidget::setAcceptDrops(bool on)
3497{
3498 setAttribute(Qt::WA_AcceptDrops, on);
3499
3500}
3501
3502/*!
3503 Disables widget input events if \a disable is true; otherwise
3504 enables input events.
3505
3506 See the \l enabled documentation for more information.
3507
3508 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3509*/
3510void QWidget::setDisabled(bool disable)
3511{
3512 setEnabled(!disable);
3513}
3514
3515/*!
3516 \property QWidget::frameGeometry
3517 \brief geometry of the widget relative to its parent including any
3518 window frame
3519
3520 See the \l{Window Geometry} documentation for an overview of geometry
3521 issues with windows.
3522
3523 By default, this property contains a value that depends on the user's
3524 platform and screen geometry.
3525
3526 \sa geometry(), x(), y(), pos()
3527*/
3528QRect QWidget::frameGeometry() const
3529{
3530 Q_D(const QWidget);
3531 if (isWindow() && ! (windowType() == Qt::Popup)) {
3532 QRect fs = d->frameStrut();
3533 return QRect(data->crect.x() - fs.left(),
3534 data->crect.y() - fs.top(),
3535 data->crect.width() + fs.left() + fs.right(),
3536 data->crect.height() + fs.top() + fs.bottom());
3537 }
3538 return data->crect;
3539}
3540
3541/*!
3542 \property QWidget::x
3543
3544 \brief the x coordinate of the widget relative to its parent including
3545 any window frame
3546
3547 See the \l{Window Geometry} documentation for an overview of geometry
3548 issues with windows.
3549
3550 By default, this property has a value of 0.
3551
3552 \sa frameGeometry, y, pos
3553*/
3554int QWidget::x() const
3555{
3556 Q_D(const QWidget);
3557 if (isWindow() && ! (windowType() == Qt::Popup))
3558 return data->crect.x() - d->frameStrut().left();
3559 return data->crect.x();
3560}
3561
3562/*!
3563 \property QWidget::y
3564 \brief the y coordinate of the widget relative to its parent and
3565 including any window frame
3566
3567 See the \l{Window Geometry} documentation for an overview of geometry
3568 issues with windows.
3569
3570 By default, this property has a value of 0.
3571
3572 \sa frameGeometry, x, pos
3573*/
3574int QWidget::y() const
3575{
3576 Q_D(const QWidget);
3577 if (isWindow() && ! (windowType() == Qt::Popup))
3578 return data->crect.y() - d->frameStrut().top();
3579 return data->crect.y();
3580}
3581
3582/*!
3583 \property QWidget::pos
3584 \brief the position of the widget within its parent widget
3585
3586 If the widget is a window, the position is that of the widget on
3587 the desktop, including its frame.
3588
3589 When changing the position, the widget, if visible, receives a
3590 move event (moveEvent()) immediately. If the widget is not
3591 currently visible, it is guaranteed to receive an event before it
3592 is shown.
3593
3594 By default, this property contains a position that refers to the
3595 origin.
3596
3597 \warning Calling move() or setGeometry() inside moveEvent() can
3598 lead to infinite recursion.
3599
3600 See the \l{Window Geometry} documentation for an overview of geometry
3601 issues with windows.
3602
3603 \note Not all windowing systems support setting or querying top level window positions.
3604 On such a system, programmatically moving windows may not have any effect, and artificial
3605 values may be returned for the current positions, such as \c QPoint(0, 0).
3606
3607 \sa frameGeometry, size, x(), y()
3608*/
3609QPoint QWidget::pos() const
3610{
3611 Q_D(const QWidget);
3612 QPoint result = data->crect.topLeft();
3613 if (isWindow() && ! (windowType() == Qt::Popup))
3614 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3615 result -= d->frameStrut().topLeft();
3616 return result;
3617}
3618
3619/*!
3620 \property QWidget::geometry
3621 \brief the geometry of the widget relative to its parent and
3622 excluding the window frame
3623
3624 When changing the geometry, the widget, if visible, receives a
3625 move event (moveEvent()) and/or a resize event (resizeEvent())
3626 immediately. If the widget is not currently visible, it is
3627 guaranteed to receive appropriate events before it is shown.
3628
3629 The size component is adjusted if it lies outside the range
3630 defined by minimumSize() and maximumSize().
3631
3632 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3633 can lead to infinite recursion.
3634
3635 See the \l{Window Geometry} documentation for an overview of geometry
3636 issues with windows.
3637
3638 By default, this property contains a value that depends on the user's
3639 platform and screen geometry.
3640
3641 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3642 resizeEvent(), minimumSize(), maximumSize()
3643*/
3644
3645/*!
3646 \property QWidget::size
3647 \brief the size of the widget excluding any window frame
3648
3649 If the widget is visible when it is being resized, it receives a resize event
3650 (resizeEvent()) immediately. If the widget is not currently
3651 visible, it is guaranteed to receive an event before it is shown.
3652
3653 The size is adjusted if it lies outside the range defined by
3654 minimumSize() and maximumSize().
3655
3656 By default, this property contains a value that depends on the user's
3657 platform and screen geometry.
3658
3659 \warning Calling resize() or setGeometry() inside resizeEvent() can
3660 lead to infinite recursion.
3661
3662 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3663 appear on screen. This also applies to windows.
3664
3665 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3666*/
3667
3668/*!
3669 \property QWidget::width
3670 \brief the width of the widget excluding any window frame
3671
3672 See the \l{Window Geometry} documentation for an overview of geometry
3673 issues with windows.
3674
3675 \note Do not use this function to find the width of a screen on
3676 a multi-screen desktop. See QScreen for details.
3677
3678 By default, this property contains a value that depends on the user's
3679 platform and screen geometry.
3680
3681 \sa geometry, height, size
3682*/
3683
3684/*!
3685 \property QWidget::height
3686 \brief the height of the widget excluding any window frame
3687
3688 See the \l{Window Geometry} documentation for an overview of geometry
3689 issues with windows.
3690
3691 By default, this property contains a value that depends on the user's
3692 platform and \l{QScreen::geometry}{screen geometry}.
3693
3694 \sa geometry, width, size
3695*/
3696
3697/*!
3698 \property QWidget::rect
3699 \brief the internal geometry of the widget excluding any window
3700 frame
3701
3702 The rect property equals QRect(0, 0, width(), height()).
3703
3704 See the \l{Window Geometry} documentation for an overview of geometry
3705 issues with windows.
3706
3707 By default, this property contains a value that depends on the user's
3708 platform and screen geometry.
3709
3710 \sa size
3711*/
3712
3713/*!
3714 \property QWidget::normalGeometry
3715
3716 \brief the geometry of the widget as it will appear when shown as
3717 a normal (not maximized or full screen) top-level widget
3718
3719 If the widget is already in this state the normal geometry will
3720 reflect the widget's current geometry().
3721
3722 For child widgets this property always holds an empty rectangle.
3723
3724 By default, this property contains an empty rectangle.
3725
3726 \sa QWidget::windowState(), QWidget::geometry
3727*/
3728QRect QWidget::normalGeometry() const
3729{
3730 Q_D(const QWidget);
3731 if (!isWindow())
3732 return QRect();
3733
3734 if (!isMaximized() && !isFullScreen())
3735 return geometry();
3736
3737 return d->topData()->normalGeometry;
3738}
3739
3740
3741/*!
3742 \property QWidget::childrenRect
3743 \brief the bounding rectangle of the widget's children
3744
3745 Hidden children are excluded.
3746
3747 By default, for a widget with no children, this property contains a
3748 rectangle with zero width and height located at the origin.
3749
3750 \sa childrenRegion(), geometry()
3751*/
3752
3753QRect QWidget::childrenRect() const
3754{
3755 Q_D(const QWidget);
3756 QRect r(0, 0, 0, 0);
3757 for (int i = 0; i < d->children.size(); ++i) {
3758 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3759 if (w && !w->isWindow() && !w->isHidden())
3760 r |= w->geometry();
3761 }
3762 return r;
3763}
3764
3765/*!
3766 \property QWidget::childrenRegion
3767 \brief the combined region occupied by the widget's children
3768
3769 Hidden children are excluded.
3770
3771 By default, for a widget with no children, this property contains an
3772 empty region.
3773
3774 \sa childrenRect(), geometry(), mask()
3775*/
3776
3777QRegion QWidget::childrenRegion() const
3778{
3779 Q_D(const QWidget);
3780 QRegion r;
3781 for (int i = 0; i < d->children.size(); ++i) {
3782 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3783 if (w && !w->isWindow() && !w->isHidden()) {
3784 QRegion mask = w->mask();
3785 if (mask.isEmpty())
3786 r |= w->geometry();
3787 else
3788 r |= mask.translated(w->pos());
3789 }
3790 }
3791 return r;
3792}
3793
3794
3795/*!
3796 \property QWidget::minimumSize
3797 \brief the widget's minimum size
3798
3799 The widget cannot be resized to a smaller size than the minimum
3800 widget size. The widget's size is forced to the minimum size if
3801 the current size is smaller.
3802
3803 The minimum size set by this function will override the minimum size
3804 defined by QLayout. To unset the minimum size, use a
3805 value of \c{QSize(0, 0)}.
3806
3807 By default, this property contains a size with zero width and height.
3808
3809 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3810*/
3811
3812QSize QWidget::minimumSize() const
3813{
3814 Q_D(const QWidget);
3815 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3816}
3817
3818/*!
3819 \property QWidget::maximumSize
3820 \brief the widget's maximum size in pixels
3821
3822 The widget cannot be resized to a larger size than the maximum
3823 widget size.
3824
3825 By default, this property contains a size in which both width and height
3826 have values of 16777215.
3827
3828 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3829 of widgets.
3830
3831 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3832*/
3833
3834QSize QWidget::maximumSize() const
3835{
3836 Q_D(const QWidget);
3837 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3839}
3840
3841
3842/*!
3843 \property QWidget::minimumWidth
3844 \brief the widget's minimum width in pixels
3845
3846 This property corresponds to the width held by the \l minimumSize property.
3847
3848 By default, this property has a value of 0.
3849
3850 \sa minimumSize, minimumHeight
3851*/
3852
3853/*!
3854 \property QWidget::minimumHeight
3855 \brief the widget's minimum height in pixels
3856
3857 This property corresponds to the height held by the \l minimumSize property.
3858
3859 By default, this property has a value of 0.
3860
3861 \sa minimumSize, minimumWidth
3862*/
3863
3864/*!
3865 \property QWidget::maximumWidth
3866 \brief the widget's maximum width in pixels
3867
3868 This property corresponds to the width held by the \l maximumSize property.
3869
3870 By default, this property contains a value of 16777215.
3871
3872 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3873 of widgets.
3874
3875 \sa maximumSize, maximumHeight
3876*/
3877
3878/*!
3879 \property QWidget::maximumHeight
3880 \brief the widget's maximum height in pixels
3881
3882 This property corresponds to the height held by the \l maximumSize property.
3883
3884 By default, this property contains a value of 16777215.
3885
3886 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3887 of widgets.
3888
3889 \sa maximumSize, maximumWidth
3890*/
3891
3892/*!
3893 \property QWidget::sizeIncrement
3894 \brief the size increment of the widget
3895
3896 When the user resizes the window, the size will move in steps of
3897 sizeIncrement().width() pixels horizontally and
3898 sizeIncrement.height() pixels vertically, with baseSize() as the
3899 basis. Preferred widget sizes are for non-negative integers \e i
3900 and \e j:
3901 \snippet code/src_gui_kernel_qwidget.cpp 2
3902
3903 Note that while you can set the size increment for all widgets, it
3904 only affects windows.
3905
3906 By default, this property contains a size with zero width and height.
3907
3908 \warning The size increment has no effect under Windows, and may
3909 be disregarded by the window manager on X11.
3910
3911 \sa size, minimumSize, maximumSize
3912*/
3913QSize QWidget::sizeIncrement() const
3914{
3915 Q_D(const QWidget);
3916 return (d->extra && d->extra->topextra)
3917 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3918 : QSize(0, 0);
3919}
3920
3921/*!
3922 \property QWidget::baseSize
3923 \brief the base size of the widget
3924
3925 The base size is used to calculate a proper widget size if the
3926 widget defines sizeIncrement().
3927
3928 By default, for a newly-created widget, this property contains a size with
3929 zero width and height.
3930
3931 \sa setSizeIncrement()
3932*/
3933
3934QSize QWidget::baseSize() const
3935{
3936 Q_D(const QWidget);
3937 return (d->extra && d->extra->topextra)
3938 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3939 : QSize(0, 0);
3940}
3941
3942bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3943{
3944 Q_Q(QWidget);
3945
3946 int mw = minw, mh = minh;
3947 if (mw == QWIDGETSIZE_MAX)
3948 mw = 0;
3949 if (mh == QWIDGETSIZE_MAX)
3950 mh = 0;
3951 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3952 qWarning("QWidget::setMinimumSize: (%s/%s) "
3953 "The largest allowed size is (%d,%d)",
3954 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3956 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3957 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3958 }
3959 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3960 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3961 "are not possible",
3962 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3963 minw = mw = qMax(minw, 0);
3964 minh = mh = qMax(minh, 0);
3965 }
3966 createExtra();
3967 if (extra->minw == mw && extra->minh == mh)
3968 return false;
3969 extra->minw = mw;
3970 extra->minh = mh;
3971 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3972 return true;
3973}
3974
3975void QWidgetPrivate::setConstraints_sys()
3976{
3977 Q_Q(QWidget);
3978 if (extra && q->windowHandle()) {
3979 QWindow *win = q->windowHandle();
3980 QWindowPrivate *winp = qt_window_private(win);
3981
3982 winp->minimumSize = QSize(extra->minw, extra->minh);
3983 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3984
3985 if (extra->topextra) {
3986 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3987 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3988 }
3989
3990 if (winp->platformWindow) {
3991 fixPosIncludesFrame();
3992 winp->platformWindow->propagateSizeHints();
3993 }
3994 }
3995}
3996
3997/*!
3998 \overload
3999
4000 This function corresponds to setMinimumSize(QSize(minw, minh)).
4001 Sets the minimum width to \a minw and the minimum height to \a
4002 minh.
4003*/
4004
4005void QWidget::setMinimumSize(int minw, int minh)
4006{
4007 Q_D(QWidget);
4008 if (!d->setMinimumSize_helper(minw, minh))
4009 return;
4010
4011 if (isWindow())
4012 d->setConstraints_sys();
4013 if (minw > width() || minh > height()) {
4014 bool resized = testAttribute(Qt::WA_Resized);
4015 bool maximized = isMaximized();
4016 resize(qMax(minw,width()), qMax(minh,height()));
4017 setAttribute(Qt::WA_Resized, resized); //not a user resize
4018 if (maximized)
4019 data->window_state = data->window_state | Qt::WindowMaximized;
4020 }
4021#if QT_CONFIG(graphicsview)
4022 if (d->extra) {
4023 if (d->extra->proxyWidget)
4024 d->extra->proxyWidget->setMinimumSize(minw, minh);
4025 }
4026#endif
4027 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4028}
4029
4030bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
4031{
4032 Q_Q(QWidget);
4033 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
4034 qWarning("QWidget::setMaximumSize: (%s/%s) "
4035 "The largest allowed size is (%d,%d)",
4036 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4038 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4039 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4040 }
4041 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4042 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4043 "are not possible",
4044 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4045 maxw = qMax(maxw, 0);
4046 maxh = qMax(maxh, 0);
4047 }
4048 createExtra();
4049 if (extra->maxw == maxw && extra->maxh == maxh)
4050 return false;
4051 extra->maxw = maxw;
4052 extra->maxh = maxh;
4053 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4054 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4055 return true;
4056}
4057
4058/*!
4059 \overload
4060
4061 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4062 maxh)). Sets the maximum width to \a maxw and the maximum height
4063 to \a maxh.
4064*/
4065void QWidget::setMaximumSize(int maxw, int maxh)
4066{
4067 Q_D(QWidget);
4068 if (!d->setMaximumSize_helper(maxw, maxh))
4069 return;
4070
4071 if (isWindow())
4072 d->setConstraints_sys();
4073 if (maxw < width() || maxh < height()) {
4074 bool resized = testAttribute(Qt::WA_Resized);
4075 resize(qMin(maxw,width()), qMin(maxh,height()));
4076 setAttribute(Qt::WA_Resized, resized); //not a user resize
4077 }
4078
4079#if QT_CONFIG(graphicsview)
4080 if (d->extra) {
4081 if (d->extra->proxyWidget)
4082 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4083 }
4084#endif
4085
4086 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4087}
4088
4089/*!
4090 \overload
4091
4092 Sets the x (width) size increment to \a w and the y (height) size
4093 increment to \a h.
4094*/
4095void QWidget::setSizeIncrement(int w, int h)
4096{
4097 Q_D(QWidget);
4098 d->createTLExtra();
4099 QTLWExtra* x = d->topData();
4100 if (x->incw == w && x->inch == h)
4101 return;
4102 x->incw = w;
4103 x->inch = h;
4104 if (isWindow())
4105 d->setConstraints_sys();
4106}
4107
4108/*!
4109 \overload
4110
4111 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4112 the widgets base size to width \a basew and height \a baseh.
4113*/
4114void QWidget::setBaseSize(int basew, int baseh)
4115{
4116 Q_D(QWidget);
4117 d->createTLExtra();
4118 QTLWExtra* x = d->topData();
4119 if (x->basew == basew && x->baseh == baseh)
4120 return;
4121 x->basew = basew;
4122 x->baseh = baseh;
4123 if (isWindow())
4124 d->setConstraints_sys();
4125}
4126
4127/*!
4128 Sets both the minimum and maximum sizes of the widget to \a s,
4129 thereby preventing it from ever growing or shrinking.
4130
4131 This will override the default size constraints set by QLayout.
4132
4133 To remove constraints, set the size to QWIDGETSIZE_MAX.
4134
4135 Alternatively, if you want the widget to have a
4136 fixed size based on its contents, you can call
4137 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4138
4139 \sa maximumSize, minimumSize
4140*/
4141
4142void QWidget::setFixedSize(const QSize & s)
4143{
4144 setFixedSize(s.width(), s.height());
4145}
4146
4147
4148/*!
4149 \fn void QWidget::setFixedSize(int w, int h)
4150 \overload
4151
4152 Sets the width of the widget to \a w and the height to \a h.
4153*/
4154
4155void QWidget::setFixedSize(int w, int h)
4156{
4157 Q_D(QWidget);
4158 bool minSizeSet = d->setMinimumSize_helper(w, h);
4159 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4160 if (!minSizeSet && !maxSizeSet)
4161 return;
4162
4163 if (isWindow())
4164 d->setConstraints_sys();
4165 else
4166 d->updateGeometry_helper(true);
4167
4168 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4169 resize(w, h);
4170}
4171
4172void QWidget::setMinimumWidth(int w)
4173{
4174 Q_D(QWidget);
4175 d->createExtra();
4176 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4177 setMinimumSize(w, minimumSize().height());
4178 d->extra->explicitMinSize = expl;
4179}
4180
4181void QWidget::setMinimumHeight(int h)
4182{
4183 Q_D(QWidget);
4184 d->createExtra();
4185 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4186 setMinimumSize(minimumSize().width(), h);
4187 d->extra->explicitMinSize = expl;
4188}
4189
4190void QWidget::setMaximumWidth(int w)
4191{
4192 Q_D(QWidget);
4193 d->createExtra();
4194 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4195 setMaximumSize(w, maximumSize().height());
4196 d->extra->explicitMaxSize = expl;
4197}
4198
4199void QWidget::setMaximumHeight(int h)
4200{
4201 Q_D(QWidget);
4202 d->createExtra();
4203 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4204 setMaximumSize(maximumSize().width(), h);
4205 d->extra->explicitMaxSize = expl;
4206}
4207
4208/*!
4209 Sets both the minimum and maximum width of the widget to \a w
4210 without changing the heights. Provided for convenience.
4211
4212 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4213*/
4214
4215void QWidget::setFixedWidth(int w)
4216{
4217 Q_D(QWidget);
4218 d->createExtra();
4219 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4220 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4221 setMinimumSize(w, minimumSize().height());
4222 setMaximumSize(w, maximumSize().height());
4223 d->extra->explicitMinSize = explMin;
4224 d->extra->explicitMaxSize = explMax;
4225}
4226
4227
4228/*!
4229 Sets both the minimum and maximum heights of the widget to \a h
4230 without changing the widths. Provided for convenience.
4231
4232 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4233*/
4234
4235void QWidget::setFixedHeight(int h)
4236{
4237 Q_D(QWidget);
4238 d->createExtra();
4239 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4240 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4241 setMinimumSize(minimumSize().width(), h);
4242 setMaximumSize(maximumSize().width(), h);
4243 d->extra->explicitMinSize = explMin;
4244 d->extra->explicitMaxSize = explMax;
4245}
4246
4247
4248/*!
4249 Translates the widget coordinate \a pos to the coordinate system
4250 of \a parent. The \a parent must not be \nullptr and must be a parent
4251 of the calling widget.
4252
4253 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4254 \since 6.0
4255*/
4256
4257QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4258{
4259 QPointF p = pos;
4260 if (parent) {
4261 const QWidget * w = this;
4262 while (w != parent) {
4263 p = w->mapToParent(p);
4264 w = w->parentWidget();
4265 if (!w) {
4266 qWarning("QWidget::mapTo(): parent must be in parent hierarchy");
4267 break;
4268 }
4269 }
4270 }
4271 return p;
4272}
4273
4274/*!
4275 \overload
4276*/
4277QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4278{
4279 return mapTo(parent, QPointF(pos)).toPoint();
4280}
4281
4282/*!
4283 Translates the widget coordinate \a pos from the coordinate system
4284 of \a parent to this widget's coordinate system. The \a parent
4285 must not be \nullptr and must be a parent of the calling widget.
4286
4287 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4288 \since 6.0
4289*/
4290
4291QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4292{
4293 QPointF p(pos);
4294 if (parent) {
4295 const QWidget * w = this;
4296 while (w != parent) {
4297 p = w->mapFromParent(p);
4298 w = w->parentWidget();
4299 if (!w) {
4300 qWarning("QWidget::mapFrom(): parent must be in parent hierarchy");
4301 break;
4302 }
4303 }
4304 }
4305 return p;
4306}
4307
4308/*!
4309 \overload
4310*/
4311QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4312{
4313 return mapFrom(parent, QPointF(pos)).toPoint();
4314}
4315
4316/*!
4317 Translates the widget coordinate \a pos to a coordinate in the
4318 parent widget.
4319
4320 Same as mapToGlobal() if the widget has no parent.
4321
4322 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4323 \since 6.0
4324*/
4325
4326QPointF QWidget::mapToParent(const QPointF &pos) const
4327{
4328 return pos + QPointF(data->crect.topLeft());
4329}
4330
4331/*!
4332 \overload
4333*/
4334QPoint QWidget::mapToParent(const QPoint &pos) const
4335{
4336 return pos + data->crect.topLeft();
4337}
4338
4339/*!
4340 Translates the parent widget coordinate \a pos to widget
4341 coordinates.
4342
4343 Same as mapFromGlobal() if the widget has no parent.
4344
4345 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4346 \since 6.0
4347*/
4348
4349QPointF QWidget::mapFromParent(const QPointF &pos) const
4350{
4351 return pos - QPointF(data->crect.topLeft());
4352}
4353
4354/*!
4355 \overload
4356*/
4357QPoint QWidget::mapFromParent(const QPoint &pos) const
4358{
4359 return pos - data->crect.topLeft();
4360}
4361
4362
4363/*!
4364 Returns the window for this widget, i.e. the next ancestor widget
4365 that has (or could have) a window-system frame.
4366
4367 If the widget is a window, the widget itself is returned.
4368
4369 Typical usage is changing the window title:
4370
4371 \snippet code/src_gui_kernel_qwidget.cpp 3
4372
4373 \sa isWindow()
4374*/
4375
4376QWidget *QWidget::window() const
4377{
4378 QWidget *w = const_cast<QWidget *>(this);
4379 QWidget *p = w->parentWidget();
4380 while (!w->isWindow() && p) {
4381 w = p;
4382 p = p->parentWidget();
4383 }
4384 return w;
4385}
4386
4387/*!
4388 \since 4.4
4389
4390 Returns the native parent for this widget, i.e. the next ancestor widget
4391 that has a system identifier, or \nullptr if it does not have any native
4392 parent.
4393
4394 \sa effectiveWinId()
4395*/
4396QWidget *QWidget::nativeParentWidget() const
4397{
4398 QWidget *parent = parentWidget();
4399 while (parent && !parent->internalWinId())
4400 parent = parent->parentWidget();
4401 return parent;
4402}
4403
4404/*! \fn QWidget *QWidget::topLevelWidget() const
4405 \deprecated
4406
4407 Use window() instead.
4408*/
4409
4410
4411
4412/*!
4413 Returns the background role of the widget.
4414
4415 The background role defines the brush from the widget's \l palette that
4416 is used to render the background.
4417
4418 If no explicit background role is set, the widget inherits its parent
4419 widget's background role.
4420
4421 \sa setBackgroundRole(), foregroundRole()
4422 */
4423QPalette::ColorRole QWidget::backgroundRole() const
4424{
4425
4426 const QWidget *w = this;
4427 do {
4428 QPalette::ColorRole role = w->d_func()->bg_role;
4429 if (role != QPalette::NoRole)
4430 return role;
4431 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4432 break;
4433 w = w->parentWidget();
4434 } while (w);
4435 return QPalette::Window;
4436}
4437
4438/*!
4439 Sets the background role of the widget to \a role.
4440
4441 The background role defines the brush from the widget's \l palette that
4442 is used to render the background.
4443
4444 If \a role is QPalette::NoRole, then the widget inherits its
4445 parent's background role.
4446
4447 Note that styles are free to choose any color from the palette.
4448 You can modify the palette or set a style sheet if you don't
4449 achieve the result you want with setBackgroundRole().
4450
4451 \sa backgroundRole(), foregroundRole()
4452 */
4453
4454void QWidget::setBackgroundRole(QPalette::ColorRole role)
4455{
4456 Q_D(QWidget);
4457 d->bg_role = role;
4458 d->updateSystemBackground();
4459 d->propagatePaletteChange();
4460 d->updateIsOpaque();
4461}
4462
4463/*!
4464 Returns the foreground role.
4465
4466 The foreground role defines the color from the widget's \l palette that
4467 is used to draw the foreground.
4468
4469 If no explicit foreground role is set, the function returns a role
4470 that contrasts with the background role.
4471
4472 \sa setForegroundRole(), backgroundRole()
4473 */
4474QPalette::ColorRole QWidget::foregroundRole() const
4475{
4476 Q_D(const QWidget);
4477 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4478 if (rl != QPalette::NoRole)
4479 return rl;
4480 QPalette::ColorRole role = QPalette::WindowText;
4481 switch (backgroundRole()) {
4482 case QPalette::Button:
4483 role = QPalette::ButtonText;
4484 break;
4485 case QPalette::Base:
4486 role = QPalette::Text;
4487 break;
4488 case QPalette::Dark:
4489 case QPalette::Shadow:
4490 role = QPalette::Light;
4491 break;
4492 case QPalette::Highlight:
4493 role = QPalette::HighlightedText;
4494 break;
4495 case QPalette::ToolTipBase:
4496 role = QPalette::ToolTipText;
4497 break;
4498 default:
4499 ;
4500 }
4501 return role;
4502}
4503
4504/*!
4505 Sets the foreground role of the widget to \a role.
4506
4507 The foreground role defines the color from the widget's \l palette that
4508 is used to draw the foreground.
4509
4510 If \a role is QPalette::NoRole, the widget uses a foreground role
4511 that contrasts with the background role.
4512
4513 Note that styles are free to choose any color from the palette.
4514 You can modify the palette or set a style sheet if you don't
4515 achieve the result you want with setForegroundRole().
4516
4517 \sa foregroundRole(), backgroundRole()
4518 */
4519void QWidget::setForegroundRole(QPalette::ColorRole role)
4520{
4521 Q_D(QWidget);
4522 d->fg_role = role;
4523 d->updateSystemBackground();
4524 d->propagatePaletteChange();
4525}
4526
4527/*!
4528 \property QWidget::palette
4529 \brief the widget's palette
4530
4531 This property describes the widget's palette. The palette is used by the
4532 widget's style when rendering standard components, and is available as a
4533 means to ensure that custom widgets can maintain consistency with the
4534 native platform's look and feel. It's common that different platforms, or
4535 different styles, have different palettes.
4536
4537 When you assign a new palette to a widget, the color roles from this
4538 palette are combined with the widget's default palette to form the
4539 widget's final palette. The palette entry for the widget's background role
4540 is used to fill the widget's background (see QWidget::autoFillBackground),
4541 and the foreground role initializes QPainter's pen.
4542
4543 The default depends on the system environment. QApplication maintains a
4544 system/theme palette which serves as a default for all widgets. There may
4545 also be special palette defaults for certain types of widgets (e.g., on
4546 Windows Vista, all classes that derive from QMenuBar have a special
4547 default palette). You can also define default palettes for widgets
4548 yourself by passing a custom palette and the name of a widget to
4549 QApplication::setPalette(). Finally, the style always has the option of
4550 polishing the palette as it's assigned (see QStyle::polish()).
4551
4552 QWidget propagates explicit palette roles from parent to child. If you
4553 assign a brush or color to a specific role on a palette and assign that
4554 palette to a widget, that role will propagate to all the widget's
4555 children, overriding any system defaults for that role. Note that palettes
4556 by default don't propagate to windows (see isWindow()) unless the
4557 Qt::WA_WindowPropagation attribute is enabled.
4558
4559 QWidget's palette propagation is similar to its font propagation.
4560
4561 The current style, which is used to render the content of all standard Qt
4562 widgets, is free to choose colors and brushes from the widget palette, or,
4563 in some cases, to ignore the palette (partially, or completely). In
4564 particular, certain styles like GTK style, Mac style, and Windows Vista
4565 style, depend on third party APIs to render the content of widgets,
4566 and these styles typically do not follow the palette. Because of this,
4567 assigning roles to a widget's palette is not guaranteed to change the
4568 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4569
4570 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4571 When using style sheets, the palette of a widget can be customized using
4572 the "color", "background-color", "selection-color",
4573 "selection-background-color" and "alternate-background-color".
4574
4575 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4576*/
4577const QPalette &QWidget::palette() const
4578{
4579 if (!isEnabled()) {
4580 data->pal.setCurrentColorGroup(QPalette::Disabled);
4581 } else if ((!isVisible() || isActiveWindow())
4582#if defined(Q_OS_WIN)
4583 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4584#endif
4585 ) {
4586 data->pal.setCurrentColorGroup(QPalette::Active);
4587 } else {
4588 data->pal.setCurrentColorGroup(QPalette::Inactive);
4589 }
4590 return data->pal;
4591}
4592
4593void QWidget::setPalette(const QPalette &palette)
4594{
4595 Q_D(QWidget);
4596 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4597
4598 // Determine which palette is inherited from this widget's ancestors and
4599 // QApplication::palette, resolve this against \a palette (attributes from
4600 // the inherited palette are copied over this widget's palette). Then
4601 // propagate this palette to this widget's children.
4602 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4603 QPalette resolvedPalette = palette.resolve(naturalPalette);
4604 d->setPalette_helper(resolvedPalette);
4605}
4606
4607/*!
4608 \internal
4609
4610 Returns the palette that the widget \a w inherits from its ancestors and
4611 QApplication::palette. \a inheritedMask is the combination of the widget's
4612 ancestors palette request masks (i.e., which attributes from the parent
4613 widget's palette are implicitly imposed on this widget by the user). Note
4614 that this font does not take into account the palette set on \a w itself.
4615*/
4616QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4617{
4618 Q_Q(const QWidget);
4619
4620 const bool useStyleSheetPropagationInWidgetStyles =
4621 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4622
4623 QPalette naturalPalette = QApplication::palette(q);
4624 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4625 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4626#if QT_CONFIG(graphicsview)
4627 || (extra && extra->proxyWidget)
4628#endif // QT_CONFIG(graphicsview)
4629 )) {
4630 if (QWidget *p = q->parentWidget()) {
4631 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4632 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4633 QPalette inheritedPalette = p->palette();
4634 inheritedPalette.setResolveMask(inheritedMask);
4635 naturalPalette = inheritedPalette.resolve(naturalPalette);
4636 } else {
4637 naturalPalette = p->palette();
4638 }
4639 }
4640 }
4641#if QT_CONFIG(graphicsview)
4642 else if (extra && extra->proxyWidget) {
4643 QPalette inheritedPalette = extra->proxyWidget->palette();
4644 inheritedPalette.setResolveMask(inheritedMask);
4645 naturalPalette = inheritedPalette.resolve(naturalPalette);
4646 }
4647#endif // QT_CONFIG(graphicsview)
4648 }
4649 naturalPalette.setResolveMask(0);
4650 return naturalPalette;
4651}
4652/*!
4653 \internal
4654
4655 Determine which palette is inherited from this widget's ancestors and
4656 QApplication::palette, resolve this against this widget's palette
4657 (attributes from the inherited palette are copied over this widget's
4658 palette). Then propagate this palette to this widget's children.
4659*/
4660void QWidgetPrivate::resolvePalette()
4661{
4662 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4663 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4664 setPalette_helper(resolvedPalette);
4665}
4666
4667void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4668{
4669 Q_Q(QWidget);
4670 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4671 return;
4672 data.pal = palette;
4673 updateSystemBackground();
4674 propagatePaletteChange();
4675 updateIsOpaque();
4676 q->update();
4677 updateIsOpaque();
4678}
4679
4680void QWidgetPrivate::updateSystemBackground()
4681{
4682}
4683
4684/*!
4685 \property QWidget::font
4686 \brief the font currently set for the widget
4687
4688 This property describes the widget's requested font. The font is used by
4689 the widget's style when rendering standard components, and is available as
4690 a means to ensure that custom widgets can maintain consistency with the
4691 native platform's look and feel. It's common that different platforms, or
4692 different styles, define different fonts for an application.
4693
4694 When you assign a new font to a widget, the properties from this font are
4695 combined with the widget's default font to form the widget's final
4696 font. You can call fontInfo() to get a copy of the widget's final
4697 font. The final font is also used to initialize QPainter's font.
4698
4699 The default depends on the system environment. QApplication maintains a
4700 system/theme font which serves as a default for all widgets. There may
4701 also be special font defaults for certain types of widgets. You can also
4702 define default fonts for widgets yourself by passing a custom font and the
4703 name of a widget to QApplication::setFont(). Finally, the font is matched
4704 against Qt's font database to find the best match.
4705
4706 QWidget propagates explicit font properties from parent to child. If you
4707 change a specific property on a font and assign that font to a widget,
4708 that property will propagate to all the widget's children, overriding any
4709 system defaults for that property. Note that fonts by default don't
4710 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4711 attribute is enabled.
4712
4713 QWidget's font propagation is similar to its palette propagation.
4714
4715 The current style, which is used to render the content of all standard Qt
4716 widgets, is free to choose to use the widget font, or in some cases, to
4717 ignore it (partially, or completely). In particular, certain styles like
4718 GTK style, Mac style, and Windows Vista style, apply special
4719 modifications to the widget font to match the platform's native look and
4720 feel. Because of this, assigning properties to a widget's font is not
4721 guaranteed to change the appearance of the widget. Instead, you may choose
4722 to apply a \l styleSheet.
4723
4724 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4725 style sheets will take precedence if the settings conflict.
4726
4727 \sa fontInfo(), fontMetrics()
4728*/
4729
4730void QWidget::setFont(const QFont &font)
4731{
4732 Q_D(QWidget);
4733
4734#if QT_CONFIG(style_stylesheet)
4735 const QStyleSheetStyle* style;
4736 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4737 style->saveWidgetFont(this, font);
4738#endif
4739
4740 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4741
4742 // Determine which font is inherited from this widget's ancestors and
4743 // QApplication::font, resolve this against \a font (attributes from the
4744 // inherited font are copied over). Then propagate this font to this
4745 // widget's children.
4746 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4747 QFont resolvedFont = font.resolve(naturalFont);
4748 d->setFont_helper(resolvedFont);
4749}
4750
4751/*
4752 \internal
4753
4754 Returns the font that the widget \a w inherits from its ancestors and
4755 QApplication::font. \a inheritedMask is the combination of the widget's
4756 ancestors font request masks (i.e., which attributes from the parent
4757 widget's font are implicitly imposed on this widget by the user). Note
4758 that this font does not take into account the font set on \a w itself.
4759
4760 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4761 is applied, fonts are not propagated anymore
4762*/
4763QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4764{
4765 Q_Q(const QWidget);
4766
4767 const bool useStyleSheetPropagationInWidgetStyles =
4768 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4769
4770 QFont naturalFont = QApplication::font(q);
4771 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4772 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4773#if QT_CONFIG(graphicsview)
4774 || (extra && extra->proxyWidget)
4775#endif // QT_CONFIG(graphicsview)
4776 )) {
4777 if (QWidget *p = q->parentWidget()) {
4778 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4779 if (!naturalFont.isCopyOf(QApplication::font())) {
4780 if (inheritedMask != 0) {
4781 QFont inheritedFont = p->font();
4782 inheritedFont.setResolveMask(inheritedMask);
4783 naturalFont = inheritedFont.resolve(naturalFont);
4784 } // else nothing to do (naturalFont = naturalFont)
4785 } else {
4786 naturalFont = p->font();
4787 }
4788 }
4789 }
4790#if QT_CONFIG(graphicsview)
4791 else if (extra && extra->proxyWidget) {
4792 if (inheritedMask != 0) {
4793 QFont inheritedFont = extra->proxyWidget->font();
4794 inheritedFont.setResolveMask(inheritedMask);
4795 naturalFont = inheritedFont.resolve(naturalFont);
4796 } // else nothing to do (naturalFont = naturalFont)
4797 }
4798#endif // QT_CONFIG(graphicsview)
4799 }
4800 naturalFont.setResolveMask(0);
4801 return naturalFont;
4802}
4803
4804/*!
4805 \internal
4806
4807 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4808*/
4809QFont QWidgetPrivate::localFont() const
4810{
4811 QFont localfont = data.fnt;
4812 localfont.setResolveMask(directFontResolveMask);
4813 return localfont;
4814}
4815
4816/*!
4817 \internal
4818
4819 Determine which font is implicitly imposed on this widget by its ancestors
4820 and QApplication::font, resolve this against its own font (attributes from
4821 the implicit font are copied over). Then propagate this font to this
4822 widget's children.
4823*/
4824void QWidgetPrivate::resolveFont()
4825{
4826 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4827 QFont resolvedFont = localFont().resolve(naturalFont);
4828 setFont_helper(resolvedFont);
4829}
4830
4831/*!
4832 \internal
4833
4834 Assign \a font to this widget, and propagate it to all children, except
4835 style sheet widgets (handled differently) and windows that don't enable
4836 window propagation. \a implicitMask is the union of all ancestor widgets'
4837 font request masks, and determines which attributes from this widget's
4838 font should propagate.
4839*/
4840void QWidgetPrivate::updateFont(const QFont &font)
4841{
4842 Q_Q(QWidget);
4843#if QT_CONFIG(style_stylesheet)
4844 const QStyleSheetStyle* cssStyle;
4845 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4846 const bool useStyleSheetPropagationInWidgetStyles =
4847 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4848#endif
4849
4850 data.fnt = QFont(font, q);
4851
4852 // Combine new mask with natural mask and propagate to children.
4853#if QT_CONFIG(graphicsview)
4854 if (!q->parentWidget() && extra && extra->proxyWidget) {
4855 QGraphicsProxyWidget *p = extra->proxyWidget;
4856 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4857 } else
4858#endif // QT_CONFIG(graphicsview)
4859 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4860 inheritedFontResolveMask = 0;
4861 }
4862 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4863 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4864 // isn't all weak information, but save the original mask to be able to let new changes on the
4865 // parent widget font propagate correctly.
4866 directFontResolveMask = data.fnt.resolveMask();
4867 data.fnt.setResolveMask(newMask);
4868
4869 for (int i = 0; i < children.size(); ++i) {
4870 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4871 if (w) {
4872 if (0) {
4873#if QT_CONFIG(style_stylesheet)
4874 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4875 // Style sheets follow a different font propagation scheme.
4876 if (cssStyle)
4877 cssStyle->updateStyleSheetFont(w);
4878#endif
4879 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4880 // Propagate font changes.
4881 QWidgetPrivate *wd = w->d_func();
4882 wd->inheritedFontResolveMask = newMask;
4883 wd->resolveFont();
4884 }
4885 }
4886 }
4887
4888#if QT_CONFIG(style_stylesheet)
4889 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4890 cssStyle->updateStyleSheetFont(q);
4891 }
4892#endif
4893
4894 QEvent e(QEvent::FontChange);
4895 QCoreApplication::sendEvent(q, &e);
4896}
4897
4898void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4899{
4900 Q_Q(QWidget);
4901
4902 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4903 return;
4904 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4905 if (!children.isEmpty()) {
4906 for (int i = 0; i < children.size(); ++i) {
4907 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4908 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4909 w->d_func()->setLayoutDirection_helper(direction);
4910 }
4911 }
4912 QEvent e(QEvent::LayoutDirectionChange);
4913 QCoreApplication::sendEvent(q, &e);
4914}
4915
4916void QWidgetPrivate::resolveLayoutDirection()
4917{
4918 Q_Q(const QWidget);
4919 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4920 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4921}
4922
4923/*!
4924 \property QWidget::layoutDirection
4925
4926 \brief the layout direction for this widget.
4927
4928 \note This method no longer affects text layout direction since Qt 4.7.
4929
4930 By default, this property is set to Qt::LeftToRight.
4931
4932 When the layout direction is set on a widget, it will propagate to
4933 the widget's children, but not to a child that is a window and not
4934 to a child for which setLayoutDirection() has been explicitly
4935 called. Also, child widgets added \e after setLayoutDirection()
4936 has been called for the parent do not inherit the parent's layout
4937 direction.
4938
4939
4940 \sa QApplication::layoutDirection
4941*/
4942void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4943{
4944 Q_D(QWidget);
4945
4946 if (direction == Qt::LayoutDirectionAuto) {
4947 unsetLayoutDirection();
4948 return;
4949 }
4950
4951 setAttribute(Qt::WA_SetLayoutDirection);
4952 d->setLayoutDirection_helper(direction);
4953}
4954
4955Qt::LayoutDirection QWidget::layoutDirection() const
4956{
4957 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4958}
4959
4960void QWidget::unsetLayoutDirection()
4961{
4962 Q_D(QWidget);
4963 setAttribute(Qt::WA_SetLayoutDirection, false);
4964 d->resolveLayoutDirection();
4965}
4966
4967/*!
4968 \fn QFontMetrics QWidget::fontMetrics() const
4969
4970 Returns the font metrics for the widget's current font.
4971 Equivalent to \c QFontMetrics(widget->font()).
4972
4973 \sa font(), fontInfo(), setFont()
4974*/
4975
4976/*!
4977 \fn QFontInfo QWidget::fontInfo() const
4978
4979 Returns the font info for the widget's current font.
4980 Equivalent to \c QFontInfo(widget->font()).
4981
4982 \sa font(), fontMetrics(), setFont()
4983*/
4984
4985
4986/*!
4987 \property QWidget::cursor
4988 \brief the cursor shape for this widget
4989
4990 The mouse cursor will assume this shape when it's over this
4991 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4992
4993 An editor widget might use an I-beam cursor:
4994 \snippet code/src_gui_kernel_qwidget.cpp 6
4995
4996 If no cursor has been set, or after a call to unsetCursor(), the
4997 parent's cursor is used.
4998
4999 By default, this property contains a cursor with the Qt::ArrowCursor
5000 shape.
5001
5002 Some underlying window implementations will reset the cursor if it
5003 leaves a widget even if the mouse is grabbed. If you want to have
5004 a cursor set for all widgets, even when outside the window, consider
5005 QGuiApplication::setOverrideCursor().
5006
5007 \sa QGuiApplication::setOverrideCursor()
5008*/
5009
5010#ifndef QT_NO_CURSOR
5011QCursor QWidget::cursor() const
5012{
5013 Q_D(const QWidget);
5014 if (testAttribute(Qt::WA_SetCursor))
5015 return (d->extra && d->extra->curs)
5016 ? *d->extra->curs
5017 : QCursor(Qt::ArrowCursor);
5018 if (isWindow() || !parentWidget())
5019 return QCursor(Qt::ArrowCursor);
5020 return parentWidget()->cursor();
5021}
5022
5023void QWidget::setCursor(const QCursor &cursor)
5024{
5025 Q_D(QWidget);
5026 if (cursor.shape() != Qt::ArrowCursor
5027 || (d->extra && d->extra->curs))
5028 {
5029 d->createExtra();
5030 d->extra->curs = std::make_unique<QCursor>(cursor);
5031 }
5032 setAttribute(Qt::WA_SetCursor);
5033 d->setCursor_sys(cursor);
5034
5035 QEvent event(QEvent::CursorChange);
5036 QCoreApplication::sendEvent(this, &event);
5037}
5038
5039void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5040{
5041 Q_UNUSED(cursor);
5042 Q_Q(QWidget);
5043 qt_qpa_set_cursor(q, false);
5044}
5045
5046void QWidget::unsetCursor()
5047{
5048 Q_D(QWidget);
5049 if (d->extra)
5050 d->extra->curs.reset();
5051 if (!isWindow())
5052 setAttribute(Qt::WA_SetCursor, false);
5053 d->unsetCursor_sys();
5054
5055 QEvent event(QEvent::CursorChange);
5056 QCoreApplication::sendEvent(this, &event);
5057}
5058
5059void QWidgetPrivate::unsetCursor_sys()
5060{
5061 Q_Q(QWidget);
5062 qt_qpa_set_cursor(q, false);
5063}
5064
5065static inline void applyCursor(QWidget *w, const QCursor &c)
5066{
5067 if (QWindow *window = w->windowHandle())
5068 window->setCursor(c);
5069}
5070
5071static inline void unsetCursor(QWidget *w)
5072{
5073 if (QWindow *window = w->windowHandle())
5074 window->unsetCursor();
5075}
5076
5077void qt_qpa_set_cursor(QWidget *w, bool force)
5078{
5079 if (!w->testAttribute(Qt::WA_WState_Created))
5080 return;
5081
5082 static QPointer<QWidget> lastUnderMouse = nullptr;
5083 if (force) {
5084 lastUnderMouse = w;
5085 } else if (lastUnderMouse) {
5086 const WId lastWinId = lastUnderMouse->effectiveWinId();
5087 const WId winId = w->effectiveWinId();
5088 if (lastWinId && lastWinId == winId)
5089 w = lastUnderMouse;
5090 } else if (!w->internalWinId()) {
5091 return; // The mouse is not under this widget, and it's not native, so don't change it.
5092 }
5093
5094 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5095 && !w->testAttribute(Qt::WA_SetCursor))
5096 w = w->parentWidget();
5097
5098 QWidget *nativeParent = w;
5099 if (!w->internalWinId())
5100 nativeParent = w->nativeParentWidget();
5101 if (!nativeParent || !nativeParent->internalWinId())
5102 return;
5103
5104 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
5105 if (w->isEnabled())
5106 applyCursor(nativeParent, w->cursor());
5107 else
5108 // Enforce the windows behavior of clearing the cursor on
5109 // disabled widgets.
5110 unsetCursor(nativeParent);
5111 } else {
5112 unsetCursor(nativeParent);
5113 }
5114}
5115#endif
5116
5117/*!
5118 \enum QWidget::RenderFlag
5119
5120 This enum describes how to render the widget when calling QWidget::render().
5121
5122 \value DrawWindowBackground If you enable this option, the widget's background
5123 is rendered into the target even if autoFillBackground is not set. By default,
5124 this option is enabled.
5125
5126 \value DrawChildren If you enable this option, the widget's children
5127 are rendered recursively into the target. By default, this option is enabled.
5128
5129 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5130 is ignored when rendering into the target. By default, this option is disabled.
5131
5132 \since 4.3
5133*/
5134
5135/*!
5136 \since 4.3
5137
5138 Renders the \a sourceRegion of this widget into the \a target
5139 using \a renderFlags to determine how to render. Rendering
5140 starts at \a targetOffset in the \a target. For example:
5141
5142 \snippet code/src_gui_kernel_qwidget.cpp 7
5143
5144 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5145 the region, i.e. the entire widget.
5146
5147 Ensure that you call QPainter::end() for the \a target device's
5148 active painter (if any) before rendering. For example:
5149
5150 \snippet code/src_gui_kernel_qwidget.cpp 8
5151
5152 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5153 instead.
5154*/
5155void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5156 const QRegion &sourceRegion, RenderFlags renderFlags)
5157{
5158 QPainter p(target);
5159 render(&p, targetOffset, sourceRegion, renderFlags);
5160}
5161
5162/*!
5163 \overload
5164
5165 Renders the widget into the \a painter's QPainter::device().
5166
5167 Transformations and settings applied to the \a painter will be used
5168 when rendering.
5169
5170 \note The \a painter must be active. On \macos the widget will be
5171 rendered into a QPixmap and then drawn by the \a painter.
5172
5173 \sa QPainter::device()
5174*/
5175void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5176 const QRegion &sourceRegion, RenderFlags renderFlags)
5177{
5178 if (Q_UNLIKELY(!painter)) {
5179 qWarning("QWidget::render: Null pointer to painter");
5180 return;
5181 }
5182
5183 if (Q_UNLIKELY(!painter->isActive())) {
5184 qWarning("QWidget::render: Cannot render with an inactive painter");
5185 return;
5186 }
5187
5188 const qreal opacity = painter->opacity();
5189 if (qFuzzyIsNull(opacity))
5190 return; // Fully transparent.
5191
5192 Q_D(QWidget);
5193 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5194 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
5195 : sourceRegion;
5196 if (toBePainted.isEmpty())
5197 return;
5198
5199 if (!d->extra)
5200 d->createExtra();
5201 d->extra->inRenderWithPainter = true;
5202
5203 QPaintEngine *engine = painter->paintEngine();
5204 Q_ASSERT(engine);
5205 QPaintEnginePrivate *enginePriv = engine->d_func();
5206 Q_ASSERT(enginePriv);
5207 QPaintDevice *target = engine->paintDevice();
5208 Q_ASSERT(target);
5209
5210 // Render via a pixmap when dealing with non-opaque painters or printers.
5211 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5212 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
5213 d->extra->inRenderWithPainter = inRenderWithPainter;
5214 return;
5215 }
5216
5217 // Set new shared painter.
5218 QPainter *oldPainter = d->sharedPainter();
5219 d->setSharedPainter(painter);
5220
5221 // Save current system clip, viewport and transform,
5222 const QTransform oldTransform = enginePriv->systemTransform;
5223 const QRegion oldSystemClip = enginePriv->systemClip;
5224 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5225 const QRegion oldSystemViewport = enginePriv->systemViewport;
5226 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5227
5228 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5229 if (painter->hasClipping()) {
5230 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5231 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5232 } else {
5233 enginePriv->setSystemViewport(oldSystemClip);
5234 }
5235 painter->setLayoutDirection(layoutDirection());
5236
5237 d->render(target, targetOffset, toBePainted, renderFlags);
5238
5239 // Restore system clip, viewport and transform.
5240 enginePriv->baseSystemClip = oldBaseClip;
5241 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5242 enginePriv->systemStateChanged();
5243 painter->setLayoutDirection(oldLayoutDirection);
5244
5245 // Restore shared painter.
5246 d->setSharedPainter(oldPainter);
5247
5248 d->extra->inRenderWithPainter = inRenderWithPainter;
5249}
5250
5251static void sendResizeEvents(QWidget *target)
5252{
5253 QResizeEvent e(target->size(), QSize());
5254 QCoreApplication::sendEvent(target, &e);
5255
5256 const QObjectList children = target->children();
5257 for (int i = 0; i < children.size(); ++i) {
5258 if (!children.at(i)->isWidgetType())
5259 continue;
5260 QWidget *child = static_cast<QWidget*>(children.at(i));
5261 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5262 sendResizeEvents(child);
5263 }
5264}
5265
5266/*!
5267 \since 5.0
5268
5269 Renders the widget into a pixmap restricted by the
5270 given \a rectangle. If the widget has any children, then
5271 they are also painted in the appropriate positions.
5272
5273 If a rectangle with an invalid size is specified (the default),
5274 the entire widget is painted.
5275
5276 \sa render(), QPixmap
5277*/
5278QPixmap QWidget::grab(const QRect &rectangle)
5279{
5280 Q_D(QWidget);
5281 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5282 sendResizeEvents(this);
5283
5284 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5285
5286 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5287 QRect r(rectangle);
5288 if (r.width() < 0 || r.height() < 0) {
5289 // For grabbing widgets that haven't been shown yet,
5290 // we trigger the layouting mechanism to determine the widget's size.
5291 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5292 r.setTopLeft(rectangle.topLeft());
5293 }
5294
5295 if (!r.intersects(rect()))
5296 return QPixmap();
5297
5298 const qreal dpr = devicePixelRatio();
5299 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5300 res.setDevicePixelRatio(dpr);
5301 if (!d->isOpaque)
5302 res.fill(Qt::transparent);
5303 d->render(&res, QPoint(), QRegion(r), renderFlags);
5304
5305 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5306 return res;
5307}
5308
5309/*!
5310 \brief The graphicsEffect function returns a pointer to the
5311 widget's graphics effect.
5312
5313 If the widget has no graphics effect, \nullptr is returned.
5314
5315 \since 4.6
5316
5317 \sa setGraphicsEffect()
5318*/
5319#if QT_CONFIG(graphicseffect)
5320QGraphicsEffect *QWidget::graphicsEffect() const
5321{
5322 Q_D(const QWidget);
5323 return d->graphicsEffect;
5324}
5325#endif // QT_CONFIG(graphicseffect)
5326
5327/*!
5328
5329 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5330
5331 Sets \a effect as the widget's effect. If there already is an effect installed
5332 on this widget, QWidget will delete the existing effect before installing
5333 the new \a effect.
5334
5335 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5336 the effect from the widget and install it on this widget.
5337
5338 QWidget takes ownership of \a effect.
5339
5340 \note This function will apply the effect on itself and all its children.
5341
5342 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5343 QOpenGLWidget and QQuickWidget.
5344
5345 \since 4.6
5346
5347 \sa graphicsEffect()
5348*/
5349#if QT_CONFIG(graphicseffect)
5350void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5351{
5352 Q_D(QWidget);
5353 if (d->graphicsEffect == effect)
5354 return;
5355
5356 if (d->graphicsEffect) {
5357 d->invalidateBackingStore(rect());
5358 delete d->graphicsEffect;
5359 d->graphicsEffect = nullptr;
5360 }
5361
5362 if (effect) {
5363 // Set new effect.
5364 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5365 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5366 d->graphicsEffect = effect;
5367 effect->d_func()->setGraphicsEffectSource(source);
5368 update();
5369 }
5370
5371 d->updateIsOpaque();
5372}
5373#endif // QT_CONFIG(graphicseffect)
5374
5375bool QWidgetPrivate::isAboutToShow() const
5376{
5377 if (data.in_show)
5378 return true;
5379
5380 Q_Q(const QWidget);
5381 if (q->isHidden())
5382 return false;
5383
5384 // The widget will be shown if any of its ancestors are about to show.
5385 QWidget *parent = q->parentWidget();
5386 return parent ? parent->d_func()->isAboutToShow() : false;
5387}
5388
5389QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5390{
5391 Q_Q(QWidget);
5392 const bool isVisible = q->isVisible();
5393
5394 // Make sure the widget is laid out correctly.
5395 if (!isVisible && !isAboutToShow()) {
5396 QWidget *topLevel = q->window();
5397 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5398 topLevel->ensurePolished();
5399
5400 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5401 // they're not explicitly hidden.
5402 QWidget *widget = q;
5403 QWidgetList hiddenWidgets;
5404 while (widget) {
5405 if (widget->isHidden()) {
5406 widget->setAttribute(Qt::WA_WState_Hidden, false);
5407 hiddenWidgets.append(widget);
5408 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5409 widget->d_func()->updateGeometry_helper(true);
5410 }
5411 widget = widget->parentWidget();
5412 }
5413
5414 // Activate top-level layout.
5415 if (topLevel->d_func()->layout)
5416 topLevel->d_func()->layout->activate();
5417
5418 // Adjust size if necessary.
5419 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5420 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5421 && !topLevel->testAttribute(Qt::WA_Resized)) {
5422 topLevel->adjustSize();
5423 topLevel->setAttribute(Qt::WA_Resized, false);
5424 }
5425
5426 // Activate child layouts.
5427 topLevel->d_func()->activateChildLayoutsRecursively();
5428
5429 // We're not cheating with WA_WState_Hidden anymore.
5430 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5431 QWidget *widget = hiddenWidgets.at(i);
5432 widget->setAttribute(Qt::WA_WState_Hidden);
5433 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5434 widget->parentWidget()->d_func()->layout->invalidate();
5435 }
5436 } else if (isVisible) {
5437 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5438 }
5439
5440 // Calculate the region to be painted.
5441 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5442 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5443 toBePainted &= extra->mask;
5444 return toBePainted;
5445}
5446
5447void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5448 QWidget::RenderFlags renderFlags)
5449{
5450 Q_ASSERT(painter);
5451 Q_ASSERT(!toBePainted.isEmpty());
5452
5453 Q_Q(QWidget);
5454 const QTransform originalTransform = painter->worldTransform();
5455 const bool useDeviceCoordinates = originalTransform.isScaling();
5456 if (!useDeviceCoordinates) {
5457 // Render via a pixmap.
5458 const QRect rect = toBePainted.boundingRect();
5459 const QSize size = rect.size();
5460 if (size.isNull())
5461 return;
5462
5463 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5464 QPixmap pixmap(size * pixmapDevicePixelRatio);
5465 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5466
5467 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5468 pixmap.fill(Qt::transparent);
5469 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5470
5471 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5472 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5473
5474 painter->drawPixmap(targetOffset, pixmap);
5475
5476 if (restore)
5477 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5478
5479 } else {
5480 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5481 QTransform transform = originalTransform;
5482 transform.translate(targetOffset.x(), targetOffset.y());
5483
5484 QPaintDevice *device = painter->device();
5485 Q_ASSERT(device);
5486
5487 // Calculate device rect.
5488 const QRectF rect(toBePainted.boundingRect());
5489 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5490 deviceRect &= QRect(0, 0, device->width(), device->height());
5491
5492 QPixmap pixmap(deviceRect.size());
5493 pixmap.fill(Qt::transparent);
5494
5495 // Create a pixmap device coordinate painter.
5496 QPainter pixmapPainter(&pixmap);
5497 pixmapPainter.setRenderHints(painter->renderHints());
5498 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5499 pixmapPainter.setTransform(transform);
5500
5501 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5502 pixmapPainter.end();
5503
5504 // And then draw the pixmap.
5505 painter->setTransform(QTransform());
5506 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5507 painter->setTransform(originalTransform);
5508 }
5509}
5510
5511void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5512 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5513{
5514 if (rgn.isEmpty())
5515 return;
5516
5517 Q_Q(QWidget);
5518
5519 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5520 << "into paint device" << pdev << "with" << flags;
5521
5522 const bool asRoot = flags & DrawAsRoot;
5523 bool onScreen = shouldPaintOnScreen();
5524
5525#if QT_CONFIG(graphicseffect)
5526 if (graphicsEffect && graphicsEffect->isEnabled()) {
5527 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5528 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5529 (source->d_func());
5530 if (!sourced->context) {
5531 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5532 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5533 sourced->context = &context;
5534 if (!sharedPainter) {
5535 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), effectRgn.translated(offset));
5536 QPainter p(pdev);
5537 p.translate(offset);
5538 context.painter = &p;
5539 graphicsEffect->draw(&p);
5540 setSystemClip(pdev->paintEngine(), 1, QRegion());
5541 } else {
5542 context.painter = sharedPainter;
5543 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5544 sourced->invalidateCache();
5545 sourced->lastEffectTransform = sharedPainter->worldTransform();
5546 }
5547 sharedPainter->save();
5548 sharedPainter->translate(offset);
5549 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), effectRgn.translated(offset));
5550 graphicsEffect->draw(sharedPainter);
5551 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5552 sharedPainter->restore();
5553 }
5554 sourced->context = nullptr;
5555
5556 if (repaintManager)
5557 repaintManager->markNeedsFlush(q, effectRgn, offset);
5558
5559 return;
5560 }
5561 }
5562#endif // QT_CONFIG(graphicseffect)
5563 flags = flags & ~UseEffectRegionBounds;
5564
5565 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5566 const bool recursive = flags & DrawRecursive;
5567 const bool alsoInvisible = flags & DrawInvisible;
5568
5569 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5570
5571 QRegion toBePainted(rgn);
5572 if (asRoot && !alsoInvisible)
5573 toBePainted &= clipRect(); //(rgn & visibleRegion());
5574 if (!(flags & DontSubtractOpaqueChildren))
5575 subtractOpaqueChildren(toBePainted, q->rect());
5576
5577 if (!toBePainted.isEmpty()) {
5578 if (!onScreen || alsoOnScreen) {
5579 //update the "in paint event" flag
5580 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5581 qWarning("QWidget::repaint: Recursive repaint detected");
5582 q->setAttribute(Qt::WA_WState_InPaintEvent);
5583
5584 //clip away the new area
5585 QPaintEngine *paintEngine = pdev->paintEngine();
5586 if (paintEngine) {
5587 setRedirected(pdev, -offset);
5588
5589 if (sharedPainter)
5590 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5591 else
5592 paintEngine->d_func()->systemRect = q->data->crect;
5593
5594 //paint the background
5595 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5596 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5597 beginBackingStorePainting();
5598 QPainter p(q);
5599 p.setRenderHint(QPainter::SmoothPixmapTransform);
5600 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5601 endBackingStorePainting();
5602 }
5603
5604 if (!sharedPainter)
5605 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5606
5607 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5608 beginBackingStorePainting();
5609 QPainter p(q);
5610 QColor tint = q->palette().window().color();
5611 tint.setAlphaF(.6f);
5612 p.fillRect(toBePainted.boundingRect(), tint);
5613 endBackingStorePainting();
5614 }
5615 }
5616
5617#if 0
5618 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5619 qDebug() << "clipping to" << toBePainted << "location == " << offset
5620 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5621#endif
5622
5623 bool skipPaintEvent = false;
5624 if (renderToTexture) {
5625 // This widget renders into a texture which is composed later. We just need to
5626 // punch a hole in the backingstore, so the texture will be visible.
5627 beginBackingStorePainting();
5628 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5629 QPainter p(q);
5630 p.setCompositionMode(QPainter::CompositionMode_Source);
5631 p.fillRect(q->rect(), Qt::transparent);
5632 } else if (!repaintManager) {
5633 // We are not drawing to a backingstore: fall back to QImage
5634 QImage img = grabFramebuffer();
5635 // grabFramebuffer() always sets the format to RGB32
5636 // regardless of whether it is transparent or not.
5637 if (img.format() == QImage::Format_RGB32)
5638 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5639 QPainter p(q);
5640 p.drawImage(q->rect(), img);
5641 skipPaintEvent = true;
5642 }
5643 endBackingStorePainting();
5644 if (renderToTextureReallyDirty)
5645 renderToTextureReallyDirty = 0;
5646 else
5647 skipPaintEvent = true;
5648 }
5649
5650 if (!skipPaintEvent) {
5651 //actually send the paint event
5652 sendPaintEvent(toBePainted);
5653 }
5654
5655 if (repaintManager)
5656 repaintManager->markNeedsFlush(q, toBePainted, offset);
5657
5658 //restore
5659 if (paintEngine) {
5660 restoreRedirected();
5661 if (!sharedPainter)
5662 paintEngine->d_func()->systemRect = QRect();
5663 else
5664 paintEngine->d_func()->currentClipDevice = nullptr;
5665
5666 setSystemClip(pdev->paintEngine(), 1, QRegion());
5667 }
5668 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5669 if (Q_UNLIKELY(q->paintingActive()))
5670 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5671
5672 if (paintEngine && paintEngine->autoDestruct()) {
5673 delete paintEngine;
5674 }
5675 } else if (q->isWindow()) {
5676 QPaintEngine *engine = pdev->paintEngine();
5677 if (engine) {
5678 QPainter p(pdev);
5679 p.setClipRegion(toBePainted);
5680 const QBrush bg = q->palette().brush(QPalette::Window);
5681 if (bg.style() == Qt::TexturePattern)
5682 p.drawTiledPixmap(q->rect(), bg.texture());
5683 else
5684 p.fillRect(q->rect(), bg);
5685
5686 if (engine->autoDestruct())
5687 delete engine;
5688 }
5689 }
5690 }
5691
5692 if (recursive && !children.isEmpty()) {
5693 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5694 sharedPainter, repaintManager);
5695 }
5696}
5697
5698void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5699{
5700 Q_Q(QWidget);
5701 QPaintEvent e(toBePainted);
5702 QCoreApplication::sendSpontaneousEvent(q, &e);
5703
5704 if (renderToTexture)
5705 resolveSamples();
5706}
5707
5708void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5709 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5710{
5711 if (Q_UNLIKELY(!target)) {
5712 qWarning("QWidget::render: null pointer to paint device");
5713 return;
5714 }
5715
5716 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5717 QRegion paintRegion = !inRenderWithPainter
5718 ? prepareToRender(sourceRegion, renderFlags)
5719 : sourceRegion;
5720 if (paintRegion.isEmpty())
5721 return;
5722
5723 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5724
5725 // Use the target's shared painter if set (typically set when doing
5726 // "other->render(widget);" in the widget's paintEvent.
5727 if (target->devType() == QInternal::Widget) {
5728 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5729 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5730 QPainter *targetPainter = targetPrivate->sharedPainter();
5731 if (targetPainter && targetPainter->isActive())
5732 setSharedPainter(targetPainter);
5733 }
5734 }
5735
5736 // Use the target's redirected device if set and adjust offset and paint
5737 // region accordingly. This is typically the case when people call render
5738 // from the paintEvent.
5739 QPoint offset = targetOffset;
5740 offset -= paintRegion.boundingRect().topLeft();
5741 QPoint redirectionOffset;
5742 QPaintDevice *redirected = nullptr;
5743
5744 if (target->devType() == QInternal::Widget)
5745 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5746
5747 if (redirected) {
5748 target = redirected;
5749 offset -= redirectionOffset;
5750 }
5751
5752 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5753 if (QPaintEngine *targetEngine = target->paintEngine()) {
5754 const QRegion targetSystemClip = targetEngine->systemClip();
5755 if (!targetSystemClip.isEmpty())
5756 paintRegion &= targetSystemClip.translated(-offset);
5757 }
5758 }
5759
5760 // Set backingstore flags.
5761 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5762 if (renderFlags & QWidget::DrawWindowBackground)
5763 flags |= DrawAsRoot;
5764
5765 if (renderFlags & QWidget::DrawChildren)
5766 flags |= DrawRecursive;
5767 else
5768 flags |= DontSubtractOpaqueChildren;
5769
5770 flags |= DontSetCompositionMode;
5771
5772 // Render via backingstore.
5773 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5774
5775 // Restore shared painter.
5776 if (oldSharedPainter)
5777 setSharedPainter(oldSharedPainter);
5778}
5779
5780void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5781 const QPoint &offset, DrawWidgetFlags flags
5782 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5783{
5784 QWidget *w = nullptr;
5785 QRect boundingRect;
5786 bool dirtyBoundingRect = true;
5787 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5788 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5789
5790 do {
5791 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5792 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5793 && !(excludeNativeChildren && x->internalWinId())) {
5794 if (dirtyBoundingRect) {
5795 boundingRect = rgn.boundingRect();
5796 dirtyBoundingRect = false;
5797 }
5798
5799 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5800 w = x;
5801 break;
5802 }
5803 }
5804 --index;
5805 } while (index >= 0);
5806
5807 if (!w)
5808 return;
5809
5810 QWidgetPrivate *wd = w->d_func();
5811 const QPoint widgetPos(w->data->crect.topLeft());
5812 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5813 if (index > 0) {
5814 QRegion wr(rgn);
5815 if (wd->isOpaque)
5816 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5817 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5818 sharedPainter, repaintManager);
5819 }
5820
5821 if (w->updatesEnabled()
5822#if QT_CONFIG(graphicsview)
5823 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5824#endif // QT_CONFIG(graphicsview)
5825 ) {
5826 QRegion wRegion(rgn);
5827 wRegion &= wd->effectiveRectFor(w->data->crect);
5828 wRegion.translate(-widgetPos);
5829 if (hasMask)
5830 wRegion &= wd->extra->mask;
5831 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5832 }
5833}
5834
5835#if QT_CONFIG(graphicseffect)
5836QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5837{
5838 if (system != Qt::DeviceCoordinates)
5839 return m_widget->rect();
5840
5841 if (Q_UNLIKELY(!context)) {
5842 // Device coordinates without context not yet supported.
5843 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5844 return QRectF();
5845 }
5846
5847 return context->painter->worldTransform().mapRect(m_widget->rect());
5848}
5849
5850void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5851{
5852 if (!context || context->painter != painter) {
5853 m_widget->render(painter);
5854 return;
5855 }
5856
5857 // The region saved in the context is neither clipped to the rect
5858 // nor the mask, so we have to clip it here before calling drawWidget.
5859 QRegion toBePainted = context->rgn;
5860 toBePainted &= m_widget->rect();
5861 QWidgetPrivate *wd = qt_widget_private(m_widget);
5862 if (wd->extra && wd->extra->hasMask)
5863 toBePainted &= wd->extra->mask;
5864
5865 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5866 context->sharedPainter, context->repaintManager);
5867}
5868
5869QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5870 QGraphicsEffect::PixmapPadMode mode) const
5871{
5872 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5873 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5874 // Device coordinates without context not yet supported.
5875 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5876 return QPixmap();
5877 }
5878
5879 QPoint pixmapOffset;
5880 QRectF sourceRect = m_widget->rect();
5881
5882 if (deviceCoordinates) {
5883 const QTransform &painterTransform = context->painter->worldTransform();
5884 sourceRect = painterTransform.mapRect(sourceRect);
5885 pixmapOffset = painterTransform.map(pixmapOffset);
5886 }
5887
5888 QRect effectRect;
5889
5890 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5891 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5892 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5893 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5894 else
5895 effectRect = sourceRect.toAlignedRect();
5896
5897 if (offset)
5898 *offset = effectRect.topLeft();
5899
5900 pixmapOffset -= effectRect.topLeft();
5901
5902 qreal dpr(1.0);
5903 if (const auto *paintDevice = context->painter->device())
5904 dpr = paintDevice->devicePixelRatio();
5905 else
5906 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5907 QPixmap pixmap(effectRect.size() * dpr);
5908 pixmap.setDevicePixelRatio(dpr);
5909
5910 pixmap.fill(Qt::transparent);
5911 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5912 return pixmap;
5913}
5914#endif // QT_CONFIG(graphicseffect)
5915
5916#if QT_CONFIG(graphicsview)
5917/*!
5918 \internal
5919
5920 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5921 widget and its ancestors. The search starts at \a origin (inclusive).
5922 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5923 embedded widget was found.
5924*/
5925QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5926{
5927 if (origin) {
5928 const auto &extra = origin->d_func()->extra;
5929 if (extra && extra->proxyWidget)
5930 return extra->proxyWidget;
5931 return nearestGraphicsProxyWidget(origin->parentWidget());
5932 }
5933 return nullptr;
5934}
5935#endif
5936
5937/*!
5938 \property QWidget::locale
5939 \brief the widget's locale
5940 \since 4.3
5941
5942 As long as no special locale has been set, this is either
5943 the parent's locale or (if this widget is a top level widget),
5944 the default locale.
5945
5946 If the widget displays dates or numbers, these should be formatted
5947 using the widget's locale.
5948
5949 \sa QLocale, QLocale::setDefault()
5950*/
5951
5952void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5953{
5954 Q_Q(QWidget);
5955 if (locale == loc && !forceUpdate)
5956 return;
5957
5958 locale = loc;
5959
5960 if (!children.isEmpty()) {
5961 for (int i = 0; i < children.size(); ++i) {
5962 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5963 if (!w)
5964 continue;
5965 if (w->testAttribute(Qt::WA_SetLocale))
5966 continue;
5967 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5968 continue;
5969 w->d_func()->setLocale_helper(loc, forceUpdate);
5970 }
5971 }
5972 QEvent e(QEvent::LocaleChange);
5973 QCoreApplication::sendEvent(q, &e);
5974}
5975
5976void QWidget::setLocale(const QLocale &locale)
5977{
5978 Q_D(QWidget);
5979
5980 setAttribute(Qt::WA_SetLocale);
5981 d->setLocale_helper(locale);
5982}
5983
5984QLocale QWidget::locale() const
5985{
5986 Q_D(const QWidget);
5987
5988 return d->locale;
5989}
5990
5991void QWidgetPrivate::resolveLocale()
5992{
5993 Q_Q(const QWidget);
5994
5995 if (!q->testAttribute(Qt::WA_SetLocale)) {
5996 QWidget *parent = q->parentWidget();
5997 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5998 ? QLocale() : parent->locale());
5999 }
6000}
6001
6002void QWidget::unsetLocale()
6003{
6004 Q_D(QWidget);
6005 setAttribute(Qt::WA_SetLocale, false);
6006 d->resolveLocale();
6007}
6008
6009/*!
6010 \property QWidget::windowTitle
6011 \brief the window title (caption)
6012
6013 This property only makes sense for top-level widgets, such as
6014 windows and dialogs. If no caption has been set, the title is based of the
6015 \l windowFilePath. If neither of these is set, then the title is
6016 an empty string.
6017
6018 If you use the \l windowModified mechanism, the window title must
6019 contain a "[*]" placeholder, which indicates where the '*' should
6020 appear. Normally, it should appear right after the file name
6021 (e.g., "document1.txt[*] - Text Editor"). If the \l
6022 windowModified property is \c false (the default), the placeholder
6023 is simply removed.
6024
6025 On some desktop platforms (including Windows and Unix), the application name
6026 (from QGuiApplication::applicationDisplayName) is added at the end of the
6027 window title, if set. This is done by the QPA plugin, so it is shown to the
6028 user, but isn't part of the windowTitle string.
6029
6030 \sa windowIcon, windowModified, windowFilePath
6031*/
6032QString QWidget::windowTitle() const
6033{
6034 Q_D(const QWidget);
6035 if (d->extra && d->extra->topextra) {
6036 if (!d->extra->topextra->caption.isEmpty())
6037 return d->extra->topextra->caption;
6038 if (!d->extra->topextra->filePath.isEmpty())
6039 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6040 }
6041 return QString();
6042}
6043
6044/*!
6045 Returns a modified window title with the [*] place holder
6046 replaced according to the rules described in QWidget::setWindowTitle
6047
6048 This function assumes that "[*]" can be quoted by another
6049 "[*]", so it will replace two place holders by one and
6050 a single last one by either "*" or nothing depending on
6051 the modified flag.
6052
6053 \internal
6054*/
6055QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6056{
6057 Q_ASSERT(widget);
6058
6059 QString cap = title;
6060 if (cap.isEmpty())
6061 return cap;
6062
6063 const auto placeHolder = "[*]"_L1;
6064 int index = cap.indexOf(placeHolder);
6065
6066 // here the magic begins
6067 while (index != -1) {
6068 index += placeHolder.size();
6069 int count = 1;
6070 while (cap.indexOf(placeHolder, index) == index) {
6071 ++count;
6072 index += placeHolder.size();
6073 }
6074
6075 if (count%2) { // odd number of [*] -> replace last one
6076 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
6077 if (widget->isWindowModified()
6078 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
6079 cap.replace(lastIndex, 3, QWidget::tr("*"));
6080 else
6081 cap.remove(lastIndex, 3);
6082 }
6083
6084 index = cap.indexOf(placeHolder, index);
6085 }
6086
6087 cap.replace("[*][*]"_L1, placeHolder);
6088
6089 return cap;
6090}
6091
6092void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6093{
6094 Q_Q(QWidget);
6095 if (q->testAttribute(Qt::WA_WState_Created))
6096 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
6097}
6098
6099void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6100{
6101 Q_Q(QWidget);
6102 if (!q->isWindow())
6103 return;
6104
6105 if (QWindow *window = q->windowHandle())
6106 {
6107#if QT_CONFIG(accessibility)
6108 QString oldAccessibleName;
6109 const QAccessibleInterface *accessible = QAccessible::isActive()
6110 ? QAccessible::queryAccessibleInterface(q)
6111 : nullptr;
6112 if (accessible)
6113 oldAccessibleName = accessible->text(QAccessible::Name);
6114#endif
6115
6116 window->setTitle(caption);
6117
6118#if QT_CONFIG(accessibility)
6119 if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
6120 QAccessibleEvent event(q, QAccessible::NameChanged);
6121 QAccessible::updateAccessibility(&event);
6122 }
6123#endif
6124 }
6125}
6126
6127void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6128{
6129 Q_Q(QWidget);
6130 if (q->testAttribute(Qt::WA_WState_Created))
6131 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
6132}
6133
6134void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6135{
6136#if QT_CONFIG(xcb)
6137 Q_Q(QWidget);
6138 // ### The QWidget property is deprecated, but the XCB window function is not.
6139 // It should remain available for the rare application that needs it.
6140 if (QWindow *window = q->windowHandle()) {
6141 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6142 xcbWindow->setWindowIconText(iconText);
6143 }
6144#else
6145 Q_UNUSED(iconText);
6146#endif
6147}
6148
6149/*!
6150 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6151
6152 This signal is emitted when the window's icon text has changed, with the
6153 new \a iconText as an argument.
6154
6155 \since 5.2
6156 \deprecated
6157
6158 This signal is deprecated.
6159*/
6160
6161void QWidget::setWindowIconText(const QString &iconText)
6162{
6163 if (QWidget::windowIconText() == iconText)
6164 return;
6165
6166 Q_D(QWidget);
6167 d->topData()->iconText = iconText;
6168 d->setWindowIconText_helper(iconText);
6169
6170 QEvent e(QEvent::IconTextChange);
6171 QCoreApplication::sendEvent(this, &e);
6172
6173 emit windowIconTextChanged(iconText);
6174}
6175
6176/*!
6177 \fn void QWidget::windowTitleChanged(const QString &title)
6178
6179 This signal is emitted when the window's title has changed, with the
6180 new \a title as an argument.
6181
6182 \since 5.2
6183*/
6184
6185void QWidget::setWindowTitle(const QString &title)
6186{
6187 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6188 return;
6189
6190 Q_D(QWidget);
6191 d->topData()->caption = title;
6192 d->setWindowTitle_helper(title);
6193
6194 QEvent e(QEvent::WindowTitleChange);
6195 QCoreApplication::sendEvent(this, &e);
6196
6197 emit windowTitleChanged(title);
6198}
6199
6200
6201/*!
6202 \property QWidget::windowIcon
6203 \brief the widget's icon
6204
6205 This property only makes sense for windows. If no icon
6206 has been set, windowIcon() returns the application icon
6207 (QApplication::windowIcon()).
6208
6209 \note On \macos, window icons represent the active document,
6210 and will not be displayed unless a file path has also been
6211 set using setWindowFilePath.
6212
6213 \sa windowTitle, setWindowFilePath
6214*/
6215QIcon QWidget::windowIcon() const
6216{
6217 const QWidget *w = this;
6218 while (w) {
6219 const QWidgetPrivate *d = w->d_func();
6220 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6221 return *d->extra->topextra->icon;
6222 w = w->parentWidget();
6223 }
6224 return QApplication::windowIcon();
6225}
6226
6227void QWidgetPrivate::setWindowIcon_helper()
6228{
6229 Q_Q(QWidget);
6230 QEvent e(QEvent::WindowIconChange);
6231
6232 // Do not send the event if the widget is a top level.
6233 // In that case, setWindowIcon_sys does it, and event propagation from
6234 // QWidgetWindow to the top level QWidget ensures that the event reaches
6235 // the top level anyhow
6236 if (!q->windowHandle())
6237 QCoreApplication::sendEvent(q, &e);
6238 for (int i = 0; i < children.size(); ++i) {
6239 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6240 if (w && !w->isWindow())
6241 QCoreApplication::sendEvent(w, &e);
6242 }
6243}
6244
6245/*!
6246 \fn void QWidget::windowIconChanged(const QIcon &icon)
6247
6248 This signal is emitted when the window's icon has changed, with the
6249 new \a icon as an argument.
6250
6251 \since 5.2
6252*/
6253
6254void QWidget::setWindowIcon(const QIcon &icon)
6255{
6256 Q_D(QWidget);
6257
6258 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6259 d->createTLExtra();
6260
6261 if (!d->extra->topextra->icon)
6262 d->extra->topextra->icon = std::make_unique<QIcon>(icon);
6263 else
6264 *d->extra->topextra->icon = icon;
6265
6266 d->setWindowIcon_sys();
6267 d->setWindowIcon_helper();
6268
6269 emit windowIconChanged(icon);
6270}
6271
6272void QWidgetPrivate::setWindowIcon_sys()
6273{
6274 Q_Q(QWidget);
6275 if (QWindow *window = q->windowHandle())
6276 window->setIcon(q->windowIcon());
6277}
6278
6279/*!
6280 \property QWidget::windowIconText
6281 \brief the text to be displayed on the icon of a minimized window
6282
6283 This property only makes sense for windows. If no icon
6284 text has been set, this accessor returns an empty string.
6285 It is only implemented on the X11 platform, and only certain
6286 window managers use this window property.
6287
6288 \deprecated
6289 This property is deprecated.
6290
6291 \sa windowIcon, windowTitle
6292*/
6293
6294QString QWidget::windowIconText() const
6295{
6296 Q_D(const QWidget);
6297 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6298}
6299
6300/*!
6301 \property QWidget::windowFilePath
6302 \since 4.4
6303 \brief the file path associated with a widget
6304
6305 This property only makes sense for windows. It associates a file path with
6306 a window. If you set the file path, but have not set the window title, Qt
6307 sets the window title to the file name of the specified path, obtained using
6308 QFileInfo::fileName().
6309
6310 If the window title is set at any point, then the window title takes precedence and
6311 will be shown instead of the file path string.
6312
6313 Additionally, on \macos, this has an added benefit that it sets the
6314 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6315 for the window, assuming that the file path exists.
6316
6317 If no file path is set, this property contains an empty string.
6318
6319 By default, this property contains an empty string.
6320
6321 \sa windowTitle, windowIcon
6322*/
6323
6324QString QWidget::windowFilePath() const
6325{
6326 Q_D(const QWidget);
6327 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6328}
6329
6330void QWidget::setWindowFilePath(const QString &filePath)
6331{
6332 if (filePath == windowFilePath())
6333 return;
6334
6335 Q_D(QWidget);
6336
6337 d->createTLExtra();
6338 d->extra->topextra->filePath = filePath;
6339 d->setWindowFilePath_helper(filePath);
6340}
6341
6342void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6343{
6344 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6345#ifdef Q_OS_MAC
6346 setWindowTitle_helper(QFileInfo(filePath).fileName());
6347#else
6348 Q_Q(QWidget);
6349 Q_UNUSED(filePath);
6350 setWindowTitle_helper(q->windowTitle());
6351#endif
6352 }
6353#ifdef Q_OS_MAC
6354 setWindowFilePath_sys(filePath);
6355#endif
6356}
6357
6358void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6359{
6360 Q_Q(QWidget);
6361 if (!q->isWindow())
6362 return;
6363
6364 if (QWindow *window = q->windowHandle())
6365 window->setFilePath(filePath);
6366}
6367
6368/*!
6369 Returns the window's role, or an empty string.
6370
6371 \sa windowIcon, windowTitle
6372*/
6373
6374QString QWidget::windowRole() const
6375{
6376 Q_D(const QWidget);
6377 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6378}
6379
6380/*!
6381 Sets the window's role to \a role. This only makes sense for
6382 windows on X11.
6383*/
6384void QWidget::setWindowRole(const QString &role)
6385{
6386#if QT_CONFIG(xcb) || QT_CONFIG(wayland)
6387 Q_D(QWidget);
6388 d->createTLExtra();
6389 d->topData()->role = role;
6390#else
6391 Q_UNUSED(role);
6392#endif
6393
6394 if (windowHandle()) {
6395#if QT_CONFIG(xcb)
6396 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6397 xcbWindow->setWindowRole(role);
6398#endif
6399#if QT_CONFIG(wayland)
6400 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(windowHandle()->handle()))
6401 waylandWindow->setSessionRestoreId(role);
6402#endif
6403 }
6404}
6405
6406/*!
6407 \property QWidget::mouseTracking
6408 \brief whether mouse tracking is enabled for the widget
6409
6410 If mouse tracking is disabled (the default), the widget only
6411 receives mouse move events when at least one mouse button is
6412 pressed while the mouse is being moved.
6413
6414 If mouse tracking is enabled, the widget receives mouse move
6415 events even if no buttons are pressed.
6416
6417 \sa mouseMoveEvent()
6418*/
6419
6420/*!
6421 \property QWidget::tabletTracking
6422 \brief whether tablet tracking is enabled for the widget
6423 \since 5.9
6424
6425 If tablet tracking is disabled (the default), the widget only
6426 receives tablet move events when the stylus is in contact with
6427 the tablet, or at least one stylus button is pressed,
6428 while the stylus is being moved.
6429
6430 If tablet tracking is enabled, the widget receives tablet move
6431 events even while hovering in proximity. This is useful for
6432 monitoring position as well as the auxiliary properties such
6433 as rotation and tilt, and providing feedback in the UI.
6434
6435 \sa tabletEvent()
6436*/
6437
6438
6439/*!
6440 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6441 function resets this widget to have no focus proxy.
6442
6443 Some widgets can "have focus", but create a child widget, such as
6444 QLineEdit, to actually handle the focus. In this case, the widget
6445 can set the line edit to be its focus proxy.
6446
6447 setFocusProxy() sets the widget which will actually get focus when
6448 "this widget" gets it. If there is a focus proxy, setFocus() and
6449 hasFocus() operate on the focus proxy. If "this widget" is the focus
6450 widget, then setFocusProxy() moves focus to the new focus proxy.
6451
6452 \sa focusProxy()
6453*/
6454
6455void QWidget::setFocusProxy(QWidget * w)
6456{
6457 Q_D(QWidget);
6458 if (!w && !d->extra)
6459 return;
6460
6461 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6462 if (Q_UNLIKELY(fp == this)) {
6463 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6464 return;
6465 }
6466 }
6467
6468 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6469
6470 d->createExtra();
6471 d->extra->focus_proxy = w;
6472
6473 if (w && isAncestorOf(w)) {
6474 // If the focus proxy is a child of this (so this is a compound widget), then
6475 // we need to make sure that this widget is immediately in front of its own children
6476 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6477 // widgets that are positioned between this compound widget, and its proxy in
6478 // the focus chain.
6479 const QWidget *parentOfW = w->parentWidget();
6480 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6481 QWidget *firstChild = nullptr;
6482 const auto childList = children();
6483 for (QObject *child : childList) {
6484 if ((firstChild = qobject_cast<QWidget *>(child)))
6485 break;
6486 }
6487 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6488 d->insertIntoFocusChainBefore(firstChild);
6489 } else if (w && w->isAncestorOf(this)) {
6490 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6491 // remove it from the chain and insert this into the focus chain after its parent
6492
6493 // is this the case already?
6494 QWidget *parentsNext = w->nextInFocusChain();
6495 if (parentsNext == this) {
6496 // nothing to do.
6497 Q_ASSERT(previousInFocusChain() == w);
6498 } else {
6499 d->QWidgetPrivate::insertIntoFocusChainAfter(w);
6500 }
6501 }
6502
6503 if (moveFocusToProxy)
6504 setFocus(Qt::OtherFocusReason);
6505}
6506
6507
6508/*!
6509 Returns the focus proxy, or \nullptr if there is no focus proxy.
6510
6511 \sa setFocusProxy()
6512*/
6513
6514QWidget *QWidget::focusProxy() const
6515{
6516 Q_D(const QWidget);
6517 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6518}
6519
6520
6521/*!
6522 \property QWidget::focus
6523 \brief whether this widget (or its focus proxy) has the keyboard
6524 input focus
6525
6526 By default, this property is \c false.
6527
6528 \note Obtaining the value of this property for a widget is effectively equivalent
6529 to checking whether QApplication::focusWidget() refers to the widget.
6530
6531 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6532*/
6533bool QWidget::hasFocus() const
6534{
6535 const QWidget* w = this;
6536 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6537 w = w->d_func()->extra->focus_proxy;
6538#if QT_CONFIG(graphicsview)
6539 if (QWidget *window = w->window()) {
6540 const auto &e = window->d_func()->extra;
6541 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6542 return true;
6543 }
6544#endif // QT_CONFIG(graphicsview)
6545 return (QApplication::focusWidget() == w);
6546}
6547
6548/*!
6549 Gives the keyboard input focus to this widget (or its focus
6550 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6551 be passed into any focus event sent from this function, it is used
6552 to give an explanation of what caused the widget to get focus.
6553 If the window is not active, the widget will be given the focus when
6554 the window becomes active.
6555
6556 First, a focus about to change event is sent to the focus widget (if any) to
6557 tell it that it is about to lose the focus. Then focus is changed, a
6558 focus out event is sent to the previous focus item and a focus in event is sent
6559 to the new item to tell it that it just received the focus.
6560 (Nothing happens if the focus in and focus out widgets are the
6561 same.)
6562
6563 \note On embedded platforms, setFocus() will not cause an input panel
6564 to be opened by the input method. If you want this to happen, you
6565 have to send a QEvent::RequestSoftwareInputPanel event to the
6566 widget yourself.
6567
6568 setFocus() gives focus to a widget regardless of its focus policy,
6569 but does not clear any keyboard grab (see grabKeyboard()).
6570
6571 Be aware that if the widget is hidden, it will not accept focus
6572 until it is shown.
6573
6574 \warning If you call setFocus() in a function which may itself be
6575 called from focusOutEvent() or focusInEvent(), you may get an
6576 infinite recursion.
6577
6578 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6579 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6580 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6581*/
6582
6583void QWidget::setFocus(Qt::FocusReason reason)
6584{
6585 if (!isEnabled())
6586 return;
6587
6588 QWidget *f = d_func()->deepestFocusProxy();
6589 if (!f)
6590 f = this;
6591
6592 if (QApplication::focusWidget() == f)
6593 return;
6594
6595#if QT_CONFIG(graphicsview)
6596 QWidget *previousProxyFocus = nullptr;
6597 if (const auto &topData = window()->d_func()->extra) {
6598 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6599 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6600 if (previousProxyFocus && previousProxyFocus->focusProxy())
6601 previousProxyFocus = previousProxyFocus->focusProxy();
6602 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6603 return;
6604 }
6605 }
6606#endif
6607
6608#if QT_CONFIG(graphicsview)
6609 // Update proxy state
6610 if (const auto &topData = window()->d_func()->extra) {
6611 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6612 f->d_func()->updateFocusChild();
6613 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6614 topData->proxyWidget->setFocus(reason);
6615 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6616 }
6617 }
6618#endif
6619
6620 if (f->isActiveWindow()) {
6621 QWidget *prev = QApplicationPrivate::focus_widget;
6622 if (prev) {
6623 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6624 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6625 QGuiApplication::inputMethod()->commit();
6626 }
6627
6628 if (reason != Qt::NoFocusReason) {
6629 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6630 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6631 }
6632 }
6633
6634 f->d_func()->updateFocusChild();
6635
6636 QApplicationPrivate::setFocusWidget(f, reason);
6637#if QT_CONFIG(accessibility)
6638 // menus update the focus manually and this would create bogus events
6639 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6640 {
6641 QAccessibleEvent event(f, QAccessible::Focus);
6642 QAccessible::updateAccessibility(&event);
6643 }
6644#endif
6645#if QT_CONFIG(graphicsview)
6646 if (const auto &topData = window()->d_func()->extra) {
6647 if (topData->proxyWidget) {
6648 if (previousProxyFocus && previousProxyFocus != f) {
6649 // Send event to self
6650 QFocusEvent event(QEvent::FocusOut, reason);
6651 QPointer<QWidget> that = previousProxyFocus;
6652 QCoreApplication::sendEvent(previousProxyFocus, &event);
6653 if (that)
6654 QCoreApplication::sendEvent(that->style(), &event);
6655 }
6656 if (!isHidden()) {
6657#if QT_CONFIG(graphicsview)
6658 // Update proxy state
6659 if (const auto &topData = window()->d_func()->extra)
6660 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6661 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6662#endif
6663 // Send event to self
6664 QFocusEvent event(QEvent::FocusIn, reason);
6665 QPointer<QWidget> that = f;
6666 QCoreApplication::sendEvent(f, &event);
6667 if (that)
6668 QCoreApplication::sendEvent(that->style(), &event);
6669 }
6670 }
6671 }
6672#endif
6673 } else {
6674 f->d_func()->updateFocusChild();
6675 }
6676}
6677
6678
6679/*!\internal
6680 * A focus proxy can have its own focus proxy, which can have its own
6681 * proxy, and so on. This helper function returns the widget that sits
6682 * at the bottom of the proxy chain, and therefore the one that should
6683 * normally get focus if this widget receives a focus request.
6684 */
6685QWidget *QWidgetPrivate::deepestFocusProxy() const
6686{
6687 Q_Q(const QWidget);
6688
6689 QWidget *focusProxy = q->focusProxy();
6690 if (!focusProxy)
6691 return nullptr;
6692
6693 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6694 focusProxy = nextFocusProxy;
6695
6696 return focusProxy;
6697}
6698
6699static inline bool isEmbedded(const QWindow *w)
6700{
6701 const auto platformWindow = w->handle();
6702 return platformWindow && platformWindow->isEmbedded();
6703}
6704
6705void QWidgetPrivate::setFocus_sys()
6706{
6707 Q_Q(QWidget);
6708 // Embedded native widget may have taken the focus; get it back to toplevel
6709 // if that is the case (QTBUG-25852), unless widget is a window container.
6710 if (extra && extra->hasWindowContainer)
6711 return;
6712 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6713 // unless the application is embedded (QTBUG-71991).
6714 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6715 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6716 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6717 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6718 || isEmbedded(nativeWindow))) {
6719 nativeWindow->requestActivate();
6720 }
6721 }
6722}
6723
6724// updates focus_child on parent widgets to point into this widget
6725void QWidgetPrivate::updateFocusChild()
6726{
6727 Q_Q(QWidget);
6728
6729 QWidget *w = q;
6730 if (q->isHidden()) {
6731 while (w && w->isHidden()) {
6732 w->d_func()->focus_child = q;
6733 w = w->isWindow() ? nullptr : w->parentWidget();
6734 }
6735 } else {
6736 while (w) {
6737 w->d_func()->focus_child = q;
6738 w = w->isWindow() ? nullptr : w->parentWidget();
6739 }
6740 }
6741
6742 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6743 if (extra->window)
6744 emit extra->window->focusObjectChanged(q);
6745 }
6746}
6747
6748/*!
6749 \fn void QWidget::setFocus()
6750 \overload
6751
6752 Gives the keyboard input focus to this widget (or its focus
6753 proxy) if this widget or one of its parents is the
6754 \l{isActiveWindow()}{active window}.
6755*/
6756
6757/*!
6758 Takes keyboard input focus from the widget.
6759
6760 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6761 lost the focus.
6762
6763 This widget must enable focus setting to get the keyboard
6764 input focus; that is, it must call setFocusPolicy().
6765
6766 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6767 setFocusPolicy(), QApplication::focusWidget()
6768*/
6769
6770void QWidget::clearFocus()
6771{
6772 if (hasFocus()) {
6773 if (testAttribute(Qt::WA_InputMethodEnabled))
6774 QGuiApplication::inputMethod()->commit();
6775
6776 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6777 QCoreApplication::sendEvent(this, &focusAboutToChange);
6778 }
6779
6780 QTLWExtra *extra = window()->d_func()->maybeTopData();
6781 QObject *originalFocusObject = nullptr;
6782 if (extra && extra->window) {
6783 originalFocusObject = extra->window->focusObject();
6784 // the window's focus object might already be nullptr if we are in the destructor, but we still
6785 // need to update QGuiApplication and input context if we have a focus widget.
6786 if (!originalFocusObject)
6787 originalFocusObject = focusWidget();
6788 }
6789
6790 QWidget *w = this;
6791 while (w) {
6792 // Just like setFocus(), we update (clear) the focus_child of our parents
6793 if (w->d_func()->focus_child == this)
6794 w->d_func()->focus_child = nullptr;
6795 w = w->parentWidget();
6796 }
6797
6798 // We've potentially cleared the focus_child of our parents, so we need
6799 // to report this to the rest of Qt. Note that the focus_child is not the same
6800 // thing as the application's focusWidget, which is why this piece of code is
6801 // not inside a hasFocus() block.
6802 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6803 emit extra->window->focusObjectChanged(extra->window->focusObject());
6804
6805#if QT_CONFIG(graphicsview)
6806 const auto &topData = d_func()->extra;
6807 if (topData && topData->proxyWidget)
6808 topData->proxyWidget->clearFocus();
6809#endif
6810
6811 if (hasFocus()) {
6812 // Update proxy state
6813 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6814#if QT_CONFIG(accessibility)
6815 QAccessibleEvent event(this, QAccessible::Focus);
6816 QAccessible::updateAccessibility(&event);
6817#endif
6818 }
6819}
6820
6821
6822/*!
6823 \fn bool QWidget::focusNextChild()
6824
6825 Finds a new widget to give the keyboard focus to, as appropriate
6826 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6827 false if it can't.
6828
6829 \sa focusPreviousChild()
6830*/
6831
6832/*!
6833 \fn bool QWidget::focusPreviousChild()
6834
6835 Finds a new widget to give the keyboard focus to, as appropriate
6836 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6837 or false if it can't.
6838
6839 \sa focusNextChild()
6840*/
6841
6842/*!
6843 Finds a new widget to give the keyboard focus to, as appropriate
6844 for Tab and Shift+Tab, and returns \c true if it can find a new
6845 widget, or false if it can't.
6846
6847 If \a next is true, this function searches forward, if \a next
6848 is false, it searches backward.
6849
6850 Sometimes, you will want to reimplement this function. For
6851 example, a web browser might reimplement it to move its "current
6852 active link" forward or backward, and call
6853 focusNextPrevChild() only when it reaches the last or
6854 first link on the "page".
6855
6856 Child widgets call focusNextPrevChild() on their parent widgets,
6857 but only the window that contains the child widgets decides where
6858 to redirect focus. By reimplementing this function for an object,
6859 you thus gain control of focus traversal for all child widgets.
6860
6861 \sa focusNextChild(), focusPreviousChild()
6862*/
6863
6864bool QWidget::focusNextPrevChild(bool next)
6865{
6866 QWidget* p = parentWidget();
6867 bool isSubWindow = (windowType() == Qt::SubWindow);
6868 if (!isWindow() && !isSubWindow && p)
6869 return p->focusNextPrevChild(next);
6870#if QT_CONFIG(graphicsview)
6871 Q_D(QWidget);
6872 if (d->extra && d->extra->proxyWidget)
6873 return d->extra->proxyWidget->focusNextPrevChild(next);
6874#endif
6875
6876 bool wrappingOccurred = false;
6877 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6878 &wrappingOccurred);
6879 if (!w) return false;
6880
6881 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6882
6883 /* If we are about to wrap the focus chain, give the platform
6884 * implementation a chance to alter the wrapping behavior. This is
6885 * especially needed when the window is embedded in a window created by
6886 * another process.
6887 */
6888 if (wrappingOccurred) {
6889 QWindow *window = windowHandle();
6890 if (window != nullptr) {
6891 QWindowPrivate *winp = qt_window_private(window);
6892
6893 if (winp->platformWindow != nullptr) {
6894 QFocusEvent event(QEvent::FocusIn, reason);
6895 event.ignore();
6896 winp->platformWindow->windowEvent(&event);
6897 if (event.isAccepted()) return true;
6898 }
6899 }
6900 }
6901
6902 w->setFocus(reason);
6903 return true;
6904}
6905
6906/*!
6907 Returns the last child of this widget that setFocus had been
6908 called on. For top level widgets this is the widget that will get
6909 focus in case this window gets activated
6910
6911 This is not the same as QApplication::focusWidget(), which returns
6912 the focus widget in the currently active window.
6913*/
6914
6915QWidget *QWidget::focusWidget() const
6916{
6917 return const_cast<QWidget *>(d_func()->focus_child);
6918}
6919
6920QObject *QWidgetPrivate::focusObject()
6921{
6922 Q_Q(QWidget);
6923 QWidget *proxy = deepestFocusProxy();
6924 return proxy ? proxy : q;
6925}
6926
6927/*!
6928 Returns the next widget in this widget's focus chain.
6929
6930 \sa previousInFocusChain()
6931*/
6932QWidget *QWidget::nextInFocusChain() const
6933{
6934 Q_D(const QWidget);
6935 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
6936}
6937
6938/*!
6939 \brief The previousInFocusChain function returns the previous
6940 widget in this widget's focus chain.
6941
6942 \sa nextInFocusChain()
6943
6944 \since 4.6
6945*/
6946QWidget *QWidget::previousInFocusChain() const
6947{
6948 Q_D(const QWidget);
6949 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
6950}
6951
6952/*!
6953 \property QWidget::isActiveWindow
6954 \brief whether this widget's window is the active window
6955
6956 The active window is the window that contains the widget that has
6957 keyboard focus (The window may still have focus if it has no
6958 widgets or none of its widgets accepts keyboard focus).
6959
6960 When popup windows are visible, this property is \c true for both the
6961 active window \e and for the popup.
6962
6963 By default, this property is \c false.
6964
6965 \sa activateWindow(), QApplication::activeWindow()
6966*/
6967bool QWidget::isActiveWindow() const
6968{
6969 QWidget *tlw = window();
6970 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6971 return true;
6972
6973#if QT_CONFIG(graphicsview)
6974 if (const auto &tlwExtra = tlw->d_func()->extra) {
6975 if (isVisible() && tlwExtra->proxyWidget)
6976 return tlwExtra->proxyWidget->isActiveWindow();
6977 }
6978#endif
6979
6980 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6981 if (tlw->windowType() == Qt::Tool &&
6982 !tlw->isModal() &&
6983 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6984 return true;
6985 QWidget *w = QApplication::activeWindow();
6986 while(w && tlw->windowType() == Qt::Tool &&
6987 !w->isModal() && w->parentWidget()) {
6988 w = w->parentWidget()->window();
6989 if (w == tlw)
6990 return true;
6991 }
6992 }
6993
6994 // Check for an active window container
6995 if (QWindow *ww = QGuiApplication::focusWindow()) {
6996 while (ww) {
6997 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6998 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6999 if (qwc && qwc->topLevelWidget() == tlw)
7000 return true;
7001 ww = ww->parent();
7002 }
7003 }
7004
7005 // Check if platform adaptation thinks the window is active. This is necessary for
7006 // example in case of ActiveQt servers that are embedded into another application.
7007 // Those are separate processes that are not part of the parent application Qt window/widget
7008 // hierarchy, so they need to rely on native methods to determine if they are part of the
7009 // active window.
7010 if (const QWindow *w = tlw->windowHandle()) {
7011 if (w->handle())
7012 return w->handle()->isActive();
7013 }
7014
7015 return false;
7016}
7017
7018/*!
7019 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7020 \overload
7021 \since 6.6
7022
7023 Sets the tab order for the widgets in the \a widgets list by calling
7024 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
7025 pair of widgets.
7026
7027 Instead of setting up each pair manually like this:
7028
7029 \snippet code/src_gui_kernel_qwidget.cpp 9
7030
7031 you can call:
7032
7033 \snippet code/src_gui_kernel_qwidget.cpp 9.list
7034
7035 The call does not create a closed tab focus loop. If there are more widgets
7036 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
7037 of those widgets, not back to \c{a}.
7038
7039 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7040*/
7041
7042/*!
7043 Puts the \a second widget after the \a first widget in the focus order.
7044
7045 It effectively removes the \a second widget from its focus chain and
7046 inserts it after the \a first widget.
7047
7048 Note that since the tab order of the \a second widget is changed, you
7049 should order a chain like this:
7050
7051 \snippet code/src_gui_kernel_qwidget.cpp 9
7052
7053 \e not like this:
7054
7055 \snippet code/src_gui_kernel_qwidget.cpp 10
7056
7057 If \a first or \a second has a focus proxy, setTabOrder()
7058 correctly substitutes the proxy.
7059
7060 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7061 a compound widget. When setting a tab order between one or two compound widgets, the
7062 local tab order inside each will be preserved. This means that if both widgets are
7063 compound widgets, the resulting tab order will be from the last child inside
7064 \a first, to the first child inside \a second.
7065
7066 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7067*/
7068void QWidget::setTabOrder(QWidget* first, QWidget *second)
7069{
7070 if (!first || !second || first == second
7071 || first->focusPolicy() == Qt::NoFocus
7072 || second->focusPolicy() == Qt::NoFocus)
7073 return;
7074
7075 if (Q_UNLIKELY(first->window() != second->window())) {
7076 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7077 return;
7078 }
7079
7080 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7081 {
7082 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7083 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7084 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7085 // 'lastFocusChild' will be set to the target itself.
7086 QWidget *lastFocusChild = target;
7087
7088 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7089 if (!focusProxy) {
7090 // QTBUG-81097: Another case is possible here. We can have a child
7091 // widget, that sets its focusProxy() to the parent (target).
7092 // An example of such widget is a QLineEdit, nested into
7093 // a QAbstractSpinBox. In this case such widget should be considered
7094 // the last focus child.
7095 for (auto *object : target->children()) {
7096 QWidget *w = qobject_cast<QWidget*>(object);
7097 if (w && w->focusProxy() == target) {
7098 lastFocusChild = w;
7099 break;
7100 }
7101 }
7102 } else if (target->isAncestorOf(focusProxy)) {
7103 lastFocusChild = focusProxy;
7104 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7105 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
7106 focusNext = focusNext->nextInFocusChain()) {
7107 if (focusNext == noFurtherThan)
7108 break;
7109 if (focusNext->focusPolicy() != Qt::NoFocus)
7110 lastFocusChild = focusNext;
7111 }
7112 }
7113 return lastFocusChild;
7114 };
7115 // detect inflection in case we have compound widgets
7116 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7117 if (lastFocusChildOfFirst == second)
7118 lastFocusChildOfFirst = first;
7119 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7120 if (lastFocusChildOfSecond == first)
7121 lastFocusChildOfSecond = second;
7122
7123 // Return if only NoFocus widgets are between first and second
7124 QWidget *oldPrev = second->previousInFocusChain();
7125 QWidget *prevWithFocus = oldPrev;
7126 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7127 prevWithFocus = prevWithFocus->previousInFocusChain();
7128 if (prevWithFocus == first)
7129 return;
7130 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
7131 QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
7132}
7133
7134void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7135{
7136 QWidget *prev = nullptr;
7137 for (const auto &widget : widgets) {
7138 if (!prev) {
7139 prev = widget;
7140 } else {
7141 QWidget::setTabOrder(prev, widget);
7142 prev = widget;
7143 }
7144 }
7145}
7146
7147
7148/*!\internal
7149
7150 Moves the relevant subwidgets of this widget from the \a oldtlw's
7151 tab chain to that of the new parent, if there's anything to move and
7152 we're really moving
7153
7154 This function is called from QWidget::reparent() *after* the widget
7155 has been reparented.
7156
7157 \sa reparent()
7158*/
7159
7160void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7161{
7162 Q_Q(QWidget);
7163 if (oldtlw == q->window())
7164 return; // nothing to do
7165
7166 if (focus_child)
7167 focus_child->clearFocus();
7168
7169 reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
7170}
7171
7172/*!
7173 \property QWidget::frameSize
7174 \brief the size of the widget including any window frame
7175
7176 By default, this property contains a value that depends on the user's
7177 platform and screen geometry.
7178*/
7179QSize QWidget::frameSize() const
7180{
7181 Q_D(const QWidget);
7182 if (isWindow() && !(windowType() == Qt::Popup)) {
7183 QRect fs = d->frameStrut();
7184 return QSize(data->crect.width() + fs.left() + fs.right(),
7185 data->crect.height() + fs.top() + fs.bottom());
7186 }
7187 return data->crect.size();
7188}
7189
7190/*! \fn void QWidget::move(int x, int y)
7191
7192 \overload
7193
7194 This corresponds to move(QPoint(\a x, \a y)).
7195*/
7196
7197void QWidget::move(const QPoint &p)
7198{
7199 Q_D(QWidget);
7200 setAttribute(Qt::WA_Moved);
7201 if (testAttribute(Qt::WA_WState_Created)) {
7202 if (isWindow())
7203 d->topData()->posIncludesFrame = false;
7204 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7205 p.y() + geometry().y() - QWidget::y(),
7206 width(), height(), true);
7207 d->setDirtyOpaqueRegion();
7208 } else {
7209 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7210 if (isWindow())
7211 d->topData()->posIncludesFrame = true;
7212 data->crect.moveTopLeft(p); // no frame yet
7213 setAttribute(Qt::WA_PendingMoveEvent);
7214 }
7215
7216 if (d->extra && d->extra->hasWindowContainer)
7217 QWindowContainer::parentWasMoved(this);
7218}
7219
7220// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7221// unknown), that is, crect has a position including the frame.
7222// If we can determine the frame strut, fix that and clear the flag.
7223// FIXME: This does not play well with window states other than
7224// Qt::WindowNoState, as we depend on calling setGeometry() on the
7225// platform window after fixing up the position so that the new
7226// geometry is reflected in the platform window, but when the frame
7227// comes in after the window has been shown (e.g. maximized), we're
7228// not in a position to do that kind of fixup.
7229void QWidgetPrivate::fixPosIncludesFrame()
7230{
7231 Q_Q(QWidget);
7232 if (QTLWExtra *te = maybeTopData()) {
7233 if (te->posIncludesFrame) {
7234 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7235 // example, in QGraphicsProxyWidget).
7236 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7237 te->posIncludesFrame = 0;
7238 } else {
7239 if (q->windowHandle() && q->windowHandle()->handle()) {
7240 updateFrameStrut();
7241 if (!q->data->fstrut_dirty) {
7242 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
7243 te->posIncludesFrame = 0;
7244 }
7245 } // windowHandle()
7246 } // !WA_DontShowOnScreen
7247 } // posIncludesFrame
7248 } // QTLWExtra
7249}
7250
7251/*! \fn void QWidget::resize(int w, int h)
7252 \overload
7253
7254 This corresponds to resize(QSize(\a w, \a h)).
7255*/
7256
7257void QWidget::resize(const QSize &s)
7258{
7259 Q_D(QWidget);
7260 setAttribute(Qt::WA_Resized);
7261 if (testAttribute(Qt::WA_WState_Created)) {
7262 d->fixPosIncludesFrame();
7263 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7264 d->setDirtyOpaqueRegion();
7265 } else {
7266 const auto oldRect = data->crect;
7267 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7268 if (oldRect != data->crect)
7269 setAttribute(Qt::WA_PendingResizeEvent);
7270 }
7271}
7272
7273void QWidget::setGeometry(const QRect &r)
7274{
7275 Q_D(QWidget);
7276 setAttribute(Qt::WA_Resized);
7277 setAttribute(Qt::WA_Moved);
7278 if (isWindow())
7279 d->topData()->posIncludesFrame = 0;
7280 if (testAttribute(Qt::WA_WState_Created)) {
7281 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7282 d->setDirtyOpaqueRegion();
7283 } else {
7284 const auto oldRect = data->crect;
7285 data->crect.setTopLeft(r.topLeft());
7286 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7287 if (oldRect != data->crect) {
7288 setAttribute(Qt::WA_PendingMoveEvent);
7289 setAttribute(Qt::WA_PendingResizeEvent);
7290 }
7291 }
7292
7293 if (d->extra && d->extra->hasWindowContainer)
7294 QWindowContainer::parentWasMoved(this);
7295}
7296
7297void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7298{
7299 Q_Q(QWidget);
7300 if (extra) { // any size restrictions?
7301 w = qMin(w,extra->maxw);
7302 h = qMin(h,extra->maxh);
7303 w = qMax(w,extra->minw);
7304 h = qMax(h,extra->minh);
7305 }
7306
7307 if (q->isWindow() && q->windowHandle()) {
7308 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7309 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7310 x = 0;
7311 y = 0;
7312 w = q->windowHandle()->width();
7313 h = q->windowHandle()->height();
7314 }
7315 }
7316
7317 QPoint oldp = q->geometry().topLeft();
7318 QSize olds = q->size();
7319 QRect r(x, y, w, h);
7320
7321 bool isResize = olds != r.size();
7322 if (!isMove)
7323 isMove = oldp != r.topLeft();
7324
7325
7326 // We only care about stuff that changes the geometry, or may
7327 // cause the window manager to change its state
7328 if (r.size() == olds && oldp == r.topLeft())
7329 return;
7330
7331 if (!data.in_set_window_state) {
7332 q->data->window_state &= ~Qt::WindowMaximized;
7333 q->data->window_state &= ~Qt::WindowFullScreen;
7334 if (q->isWindow())
7335 topData()->normalGeometry = QRect(0, 0, -1, -1);
7336 }
7337
7338 QPoint oldPos = q->pos();
7339 data.crect = r;
7340
7341 bool needsShow = false;
7342
7343 if (q->isWindow() || q->windowHandle()) {
7344 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7345 q->setAttribute(Qt::WA_OutsideWSRange, true);
7346 if (q->isVisible())
7347 hide_sys();
7348 data.crect = QRect(x, y, w, h);
7349 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7350 q->setAttribute(Qt::WA_OutsideWSRange, false);
7351 needsShow = true;
7352 }
7353 }
7354
7355 if (q->isVisible()) {
7356 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7357 if (QWindow *win = q->windowHandle()) {
7358 if (q->isWindow()) {
7359 if (isResize && !isMove)
7360 win->resize(w, h);
7361 else if (isMove && !isResize)
7362 win->setPosition(x, y);
7363 else
7364 win->setGeometry(q->geometry());
7365 } else {
7366 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7367 win->setGeometry(QRect(posInNativeParent,r.size()));
7368 }
7369
7370 if (needsShow)
7371 show_sys();
7372 }
7373
7374 if (!q->isWindow()) {
7375 if (renderToTexture) {
7376 QRegion updateRegion(q->geometry());
7377 updateRegion += QRect(oldPos, olds);
7378 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7379 } else if (isMove && !isResize) {
7380 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7381 } else {
7382 invalidateBackingStore_resizeHelper(oldPos, olds);
7383 }
7384 }
7385 }
7386
7387 if (isMove) {
7388 QMoveEvent e(q->pos(), oldPos);
7389 QCoreApplication::sendEvent(q, &e);
7390 }
7391 if (isResize) {
7392 QResizeEvent e(r.size(), olds);
7393 QCoreApplication::sendEvent(q, &e);
7394 if (q->windowHandle())
7395 q->update();
7396 }
7397 } else { // not visible
7398 if (isMove && q->pos() != oldPos)
7399 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7400 if (isResize)
7401 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7402 }
7403
7404#if QT_CONFIG(accessibility)
7405 if (QAccessible::isActive() && q->isVisible()) {
7406 QAccessibleEvent event(q, QAccessible::LocationChanged);
7407 QAccessible::updateAccessibility(&event);
7408 }
7409#endif
7410}
7411
7412/*!
7413 \since 4.2
7414 Saves the current geometry and state for top-level widgets.
7415
7416 To save the geometry when the window closes, you can
7417 implement a close event like this:
7418
7419 \snippet code/src_gui_kernel_qwidget.cpp 11
7420
7421 See the \l{Window Geometry} documentation for an overview of geometry
7422 issues with windows.
7423
7424 Use QMainWindow::saveState() to save the geometry and the state of
7425 toolbars and dock widgets.
7426
7427 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7428*/
7429QByteArray QWidget::saveGeometry() const
7430{
7431 QByteArray array;
7432 QDataStream stream(&array, QIODevice::WriteOnly);
7433 stream.setVersion(QDataStream::Qt_4_0);
7434 const quint32 magicNumber = 0x1D9D0CB;
7435 // Version history:
7436 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7437 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7438 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7439 quint16 majorVersion = 3;
7440 quint16 minorVersion = 0;
7441 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7442 stream << magicNumber
7443 << majorVersion
7444 << minorVersion
7445 << frameGeometry()
7446 << normalGeometry()
7447 << qint32(screenNumber)
7448 << quint8(windowState() & Qt::WindowMaximized)
7449 << quint8(windowState() & Qt::WindowFullScreen)
7450 << qint32(screen()->geometry().width()) // added in 2.0
7451 << geometry(); // added in 3.0
7452 return array;
7453}
7454
7455/*!
7456 \internal
7457
7458 Check a if \a restoredGeometry fits into \a availableGeometry
7459 This method is used to verify that a widget is restored to a geometry, which
7460 fits into the target screen.
7461
7462 \param frameHeight represents the height of the widget's title bar, which is expected
7463 to be on its top.
7464
7465 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7466 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7467 be full screen.
7468
7469 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7470 \a restoredGeometry will be moved
7471 \list
7472 \li down if its top is off screen
7473 \li up if its bottom is off screen
7474 \li right if its left edge is off screen
7475 \li left if its right edge is off screen
7476 \endlist
7477 */
7478void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7479 int frameHeight)
7480{
7481 // compare with restored geometry's height increased by frameHeight
7482 const int height = restoredGeometry->height() + frameHeight;
7483
7484 // Step 1: Resize if necessary:
7485 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7486 if (availableGeometry.height() <= height)
7487 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7488 if (availableGeometry.width() <= restoredGeometry->width())
7489 restoredGeometry->setWidth(availableGeometry.width() - 2);
7490
7491 // Step 2: Move if necessary:
7492 // Construct a rectangle from restored Geometry adjusted by frameHeight
7493 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7494
7495 // Return if restoredGeometry (including frame) fits into screen
7496 if (availableGeometry.contains(restored))
7497 return;
7498
7499 // (size is correct, but at least one edge is off screen)
7500
7501 // Top out of bounds => move down
7502 if (restored.top() <= availableGeometry.top()) {
7503 restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
7504 } else if (restored.bottom() >= availableGeometry.bottom()) {
7505 // Bottom out of bounds => move up
7506 restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
7507 }
7508
7509 // Left edge out of bounds => move right
7510 if (restored.left() <= availableGeometry.left()) {
7511 restoredGeometry->moveLeft(availableGeometry.left() + 1);
7512 } else if (restored.right() >= availableGeometry.right()) {
7513 // Right edge out of bounds => move left
7514 restoredGeometry->moveRight(availableGeometry.right() - 1);
7515 }
7516}
7517
7518/*!
7519 \since 4.2
7520
7521 Restores the geometry and state of top-level widgets stored in the
7522 byte array \a geometry. Returns \c true on success; otherwise
7523 returns \c false.
7524
7525 If the restored geometry is off-screen, it will be modified to be
7526 inside the available screen geometry.
7527
7528 To restore geometry saved using QSettings, you can use code like
7529 this:
7530
7531 \snippet code/src_gui_kernel_qwidget.cpp 12
7532
7533 See the \l{Window Geometry} documentation for an overview of geometry
7534 issues with windows.
7535
7536 Use QMainWindow::restoreState() to restore the geometry and the
7537 state of toolbars and dock widgets.
7538
7539 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7540*/
7541bool QWidget::restoreGeometry(const QByteArray &geometry)
7542{
7543 if (geometry.size() < 4)
7544 return false;
7545 QDataStream stream(geometry);
7546 stream.setVersion(QDataStream::Qt_4_0);
7547
7548 const quint32 magicNumber = 0x1D9D0CB;
7549 quint32 storedMagicNumber;
7550 stream >> storedMagicNumber;
7551 if (storedMagicNumber != magicNumber)
7552 return false;
7553
7554 const quint16 currentMajorVersion = 3;
7555 quint16 majorVersion = 0;
7556 quint16 minorVersion = 0;
7557
7558 stream >> majorVersion >> minorVersion;
7559
7560 if (majorVersion > currentMajorVersion)
7561 return false;
7562 // (Allow all minor versions.)
7563
7564 QRect restoredFrameGeometry;
7565 QRect restoredGeometry;
7566 QRect restoredNormalGeometry;
7567 qint32 restoredScreenNumber;
7568 quint8 maximized;
7569 quint8 fullScreen;
7570 qint32 restoredScreenWidth = 0;
7571
7572 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7573 >> restoredNormalGeometry
7574 >> restoredScreenNumber
7575 >> maximized
7576 >> fullScreen;
7577
7578 if (majorVersion > 1)
7579 stream >> restoredScreenWidth;
7580 if (majorVersion > 2)
7581 stream >> restoredGeometry;
7582
7583 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7584
7585 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7586 restoredScreenNumber = 0;
7587 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7588 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7589 // Sanity check bailing out when large variations of screen sizes occur due to
7590 // high DPI scaling or different levels of DPI awareness.
7591 if (restoredScreenWidth) {
7592 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7593 if (factor < 0.8 || factor > 1.25)
7594 return false;
7595 } else {
7596 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7597 // unless the size will be adapted by maximized or fullscreen.
7598 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7599 return false;
7600 }
7601
7602 const int frameHeight = QApplication::style()
7603 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7604 : 20;
7605
7606 if (!restoredNormalGeometry.isValid())
7607 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7608 if (!restoredNormalGeometry.isValid()) {
7609 // use the widget's adjustedSize if the sizeHint() doesn't help
7610 restoredNormalGeometry.setSize(restoredNormalGeometry
7611 .size()
7612 .expandedTo(d_func()->adjustedSize()));
7613 }
7614
7615 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7616 : QRect();
7617
7618 // Modify the restored geometry if we are about to restore to coordinates
7619 // that would make the window "lost". This happens if:
7620 // - The restored geometry is completely or partly oustside the available geometry
7621 // - The title bar is outside the available geometry.
7622
7623 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7624 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7625
7626 if (maximized || fullScreen) {
7627 // set geometry before setting the window state to make
7628 // sure the window is maximized to the right screen.
7629 Qt::WindowStates ws = windowState();
7630#ifndef Q_OS_WIN
7631 setGeometry(restoredNormalGeometry);
7632#else
7633 if (ws & Qt::WindowFullScreen) {
7634 // Full screen is not a real window state on Windows.
7635 move(availableGeometry.topLeft());
7636 } else if (ws & Qt::WindowMaximized) {
7637 // Setting a geometry on an already maximized window causes this to be
7638 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7639 // Move the window in normal state if needed.
7640 if (restoredScreen != screen()) {
7641 setWindowState(Qt::WindowNoState);
7642 setGeometry(restoredNormalGeometry);
7643 }
7644 } else {
7645 setGeometry(restoredNormalGeometry);
7646 }
7647#endif // Q_OS_WIN
7648 if (maximized)
7649 ws |= Qt::WindowMaximized;
7650 if (fullScreen)
7651 ws |= Qt::WindowFullScreen;
7652 setWindowState(ws);
7653 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7654 } else {
7655 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7656
7657 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7658 if (majorVersion > 2)
7659 setGeometry(restoredGeometry);
7660 else
7661 setGeometry(restoredNormalGeometry);
7662 }
7663 return true;
7664}
7665
7666/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7667 \overload
7668
7669 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7670*/
7671
7672/*!
7673 Sets the margins around the contents of the widget to have the sizes
7674 \a left, \a top, \a right, and \a bottom. The margins are used by
7675 the layout system, and may be used by subclasses to specify the area
7676 to draw in (e.g. excluding the frame).
7677
7678 Changing the margins will trigger a resizeEvent().
7679
7680 \sa contentsRect(), contentsMargins()
7681*/
7682void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7683{
7684 Q_D(QWidget);
7685 if (left == d->leftmargin && top == d->topmargin
7686 && right == d->rightmargin && bottom == d->bottommargin)
7687 return;
7688 d->leftmargin = left;
7689 d->topmargin = top;
7690 d->rightmargin = right;
7691 d->bottommargin = bottom;
7692
7693 d->updateContentsRect();
7694}
7695
7696/*!
7697 \overload
7698 \since 4.6
7699
7700 \brief The setContentsMargins function sets the margins around the
7701 widget's contents.
7702
7703 Sets the margins around the contents of the widget to have the
7704 sizes determined by \a margins. The margins are
7705 used by the layout system, and may be used by subclasses to
7706 specify the area to draw in (e.g. excluding the frame).
7707
7708 Changing the margins will trigger a resizeEvent().
7709
7710 \sa contentsRect(), contentsMargins()
7711*/
7712void QWidget::setContentsMargins(const QMargins &margins)
7713{
7714 setContentsMargins(margins.left(), margins.top(),
7715 margins.right(), margins.bottom());
7716}
7717
7718void QWidgetPrivate::updateContentsRect()
7719{
7720 Q_Q(QWidget);
7721
7722 if (layout)
7723 layout->update(); //force activate; will do updateGeometry
7724 else
7725 q->updateGeometry();
7726
7727 if (q->isVisible()) {
7728 q->update();
7729 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7730 QCoreApplication::sendEvent(q, &e);
7731 } else {
7732 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7733 }
7734
7735 QEvent e(QEvent::ContentsRectChange);
7736 QCoreApplication::sendEvent(q, &e);
7737}
7738
7739/*!
7740 \since 4.6
7741
7742 \brief The contentsMargins function returns the widget's contents margins.
7743
7744 \sa setContentsMargins(), contentsRect()
7745 */
7746QMargins QWidget::contentsMargins() const
7747{
7748 Q_D(const QWidget);
7749 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7750 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7751 userMargins | d->safeAreaMargins() : userMargins;
7752}
7753
7754/*!
7755 Returns the area inside the widget's margins.
7756
7757 \sa setContentsMargins(), contentsMargins()
7758*/
7759QRect QWidget::contentsRect() const
7760{
7761 return rect() - contentsMargins();
7762}
7763
7764QMargins QWidgetPrivate::safeAreaMargins() const
7765{
7766 Q_Q(const QWidget);
7767
7768#if QT_CONFIG(graphicsview)
7769 // Don't report margins for proxied widgets, as the logic
7770 // below doesn't handle that case (yet).
7771 if (nearestGraphicsProxyWidget(q))
7772 return QMargins();
7773#endif
7774
7775 QWidget *nativeWidget = q->window();
7776 if (!nativeWidget->windowHandle())
7777 return QMargins();
7778
7779 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7780
7781 if (!q->isWindow()) {
7782 // In theory the native parent widget already has a contents rect reflecting
7783 // the safe area of that widget, but we can't be sure that the widget or child
7784 // widgets of that widget have respected the contents rect when setting their
7785 // geometry, so we need to manually compute the safe area.
7786
7787 // Unless the native widget doesn't have any margins, in which case there's
7788 // nothing for us to compute.
7789 if (safeAreaMargins.isNull())
7790 return QMargins();
7791
7792 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7793 // set, and the widget respects the safe area, then we know that the layout has already
7794 // taken care of placing us inside the safe area, by taking the contents rect of its
7795 // parent widget into account.
7796 const QWidget *assumedSafeWidget = nullptr;
7797 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7798 QWidget *parentWidget = w->parentWidget();
7799 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7800 continue; // Layout can't help us
7801
7802 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7803 continue; // Layout not going to help us
7804
7805 QLayout *layout = parentWidget->layout();
7806 if (!layout)
7807 continue;
7808
7809 if (layout->geometry().isNull())
7810 continue; // Layout hasn't been activated yet
7811
7812 if (layout->indexOf(w) < 0)
7813 continue; // Widget is not in layout
7814
7815 assumedSafeWidget = w;
7816 break;
7817 }
7818
7819#if !defined(QT_DEBUG)
7820 if (assumedSafeWidget) {
7821 // We found a layout that we assume will take care of keeping us within the safe area
7822 // For debug builds we still map the safe area using the fallback logic, so that we
7823 // can detect any misbehaving layouts.
7824 return QMargins();
7825 }
7826#endif
7827
7828 // In all other cases we need to map the safe area of the native parent to the widget.
7829 // This depends on the widget being positioned and sized already, which means the initial
7830 // layout will be wrong, but the layout will then adjust itself.
7831 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7832 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7833 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7834 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7835
7836 // Margins should never be negative
7837 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7838 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7839
7840 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7841 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7842 qWarning() << layout << "is laying out" << assumedSafeWidget
7843 << "outside of the contents rect of" << layout->parentWidget();
7844 return QMargins(); // Return empty margin to visually highlight the error
7845 }
7846 }
7847
7848 return safeAreaMargins;
7849}
7850
7851/*!
7852 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7853
7854 This signal is emitted when the widget's \l contextMenuPolicy is
7855 Qt::CustomContextMenu, and the user has requested a context menu on
7856 the widget. The position \a pos is the position of the context menu
7857 event that the widget receives. Normally this is in widget
7858 coordinates. The exception to this rule is QAbstractScrollArea and
7859 its subclasses that map the context menu event to coordinates of the
7860 \l{QAbstractScrollArea::viewport()}{viewport()}.
7861
7862
7863 \sa mapToGlobal(), QMenu, contextMenuPolicy
7864*/
7865
7866
7867/*!
7868 \property QWidget::contextMenuPolicy
7869 \brief how the widget shows a context menu
7870
7871 The default value of this property is Qt::DefaultContextMenu,
7872 which means the contextMenuEvent() handler is called. Other values
7873 are Qt::NoContextMenu, Qt::PreventContextMenu,
7874 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7875 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7876 emitted.
7877
7878 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7879*/
7880
7881Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7882{
7883 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7884}
7885
7886void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7887{
7888 data->context_menu_policy = (uint) policy;
7889}
7890
7891/*!
7892 \property QWidget::focusPolicy
7893 \brief the way the widget accepts keyboard focus
7894
7895 The policy is Qt::TabFocus if the widget accepts keyboard
7896 focus by tabbing, Qt::ClickFocus if the widget accepts
7897 focus by clicking, Qt::StrongFocus if it accepts both, and
7898 Qt::NoFocus (the default) if it does not accept focus at
7899 all.
7900
7901 You must enable keyboard focus for a widget if it processes
7902 keyboard events. This is normally done from the widget's
7903 constructor. For instance, the QLineEdit constructor calls
7904 setFocusPolicy(Qt::StrongFocus).
7905
7906 If the widget has a focus proxy, then the focus policy will
7907 be propagated to it.
7908
7909 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7910*/
7911
7912
7913Qt::FocusPolicy QWidget::focusPolicy() const
7914{
7915 return (Qt::FocusPolicy)data->focus_policy;
7916}
7917
7918void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7919{
7920 data->focus_policy = (uint) policy;
7921 Q_D(QWidget);
7922 if (d->extra && d->extra->focus_proxy)
7923 d->extra->focus_proxy->setFocusPolicy(policy);
7924}
7925
7926/*!
7927 \property QWidget::updatesEnabled
7928 \brief whether updates are enabled
7929
7930 An updates enabled widget receives paint events and has a system
7931 background; a disabled widget does not. This also implies that
7932 calling update() and repaint() has no effect if updates are
7933 disabled.
7934
7935 By default, this property is \c true.
7936
7937 setUpdatesEnabled() is normally used to disable updates for a
7938 short period of time, for instance to avoid screen flicker during
7939 large changes. In Qt, widgets normally do not generate screen
7940 flicker, but on X11 the server might erase regions on the screen
7941 when widgets get hidden before they can be replaced by other
7942 widgets. Disabling updates solves this.
7943
7944 Example:
7945 \snippet code/src_gui_kernel_qwidget.cpp 13
7946
7947 Disabling a widget implicitly disables all its children. Enabling a widget
7948 enables all child widgets \e except top-level widgets or those that
7949 have been explicitly disabled. Re-enabling updates implicitly calls
7950 update() on the widget.
7951
7952 \sa paintEvent()
7953*/
7954void QWidget::setUpdatesEnabled(bool enable)
7955{
7956 Q_D(QWidget);
7957 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7958 d->setUpdatesEnabled_helper(enable);
7959}
7960
7961/*!
7962 Shows the widget and its child widgets.
7963
7964 For child windows, this is equivalent to calling setVisible(true).
7965 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7966 or setVisible(true), depending on the platform's default behavior for the window flags.
7967
7968 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7969 showNormal(), isVisible(), windowFlags()
7970*/
7971void QWidget::show()
7972{
7973 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7974
7975 if (!isWindow()) {
7976 setVisible(true);
7977 } else {
7978 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7979 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7980 if (defaultState == Qt::WindowFullScreen)
7981 showFullScreen();
7982 else if (defaultState == Qt::WindowMaximized)
7983 showMaximized();
7984 else
7985 setVisible(true);
7986 }
7987}
7988
7989/*! \internal
7990
7991 Makes the widget visible in the isVisible() meaning of the word.
7992 It is only called for toplevels or widgets with visible parents.
7993 */
7994void QWidgetPrivate::show_recursive()
7995{
7996 Q_Q(QWidget);
7997 // polish if necessary
7998
7999 if (!q->testAttribute(Qt::WA_WState_Created))
8000 createRecursively();
8001 q->ensurePolished();
8002
8003 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
8004 q->parentWidget()->d_func()->layout->activate();
8005 // activate our layout before we and our children become visible
8006 if (layout)
8007 layout->activate();
8008
8009 show_helper();
8010}
8011
8012void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
8013{
8014 Q_Q(QWidget);
8015
8016 disableUpdates = disableUpdates && q->updatesEnabled();
8017 if (disableUpdates)
8018 q->setAttribute(Qt::WA_UpdatesDisabled);
8019
8020 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
8021 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
8022 QCoreApplication::sendEvent(q, &e);
8023 q->setAttribute(Qt::WA_PendingMoveEvent, false);
8024 }
8025
8026 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
8027 QResizeEvent e(data.crect.size(), QSize());
8028 QCoreApplication::sendEvent(q, &e);
8029 q->setAttribute(Qt::WA_PendingResizeEvent, false);
8030 }
8031
8032 if (disableUpdates)
8033 q->setAttribute(Qt::WA_UpdatesDisabled, false);
8034
8035 if (!recursive)
8036 return;
8037
8038 for (int i = 0; i < children.size(); ++i) {
8039 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8040 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8041 }
8042}
8043
8044void QWidgetPrivate::activateChildLayoutsRecursively()
8045{
8046 sendPendingMoveAndResizeEvents(false, true);
8047
8048 for (int i = 0; i < children.size(); ++i) {
8049 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8050 if (!child || child->isHidden() || child->isWindow())
8051 continue;
8052
8053 child->ensurePolished();
8054
8055 // Activate child's layout
8056 QWidgetPrivate *childPrivate = child->d_func();
8057 if (childPrivate->layout)
8058 childPrivate->layout->activate();
8059
8060 // Pretend we're visible.
8061 const bool wasVisible = child->isVisible();
8062 if (!wasVisible)
8063 child->setAttribute(Qt::WA_WState_Visible);
8064
8065 // Do the same for all my children.
8066 childPrivate->activateChildLayoutsRecursively();
8067
8068 // We're not cheating anymore.
8069 if (!wasVisible)
8070 child->setAttribute(Qt::WA_WState_Visible, false);
8071 }
8072}
8073
8074void QWidgetPrivate::show_helper()
8075{
8076 Q_Q(QWidget);
8077 data.in_show = true; // qws optimization
8078 // make sure we receive pending move and resize events
8079 sendPendingMoveAndResizeEvents();
8080
8081 // become visible before showing all children
8082 q->setAttribute(Qt::WA_WState_Visible);
8083
8084 // finally show all children recursively
8085 showChildren(false);
8086
8087
8088
8089 const bool isWindow = q->isWindow();
8090#if QT_CONFIG(graphicsview)
8091 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8092#else
8093 bool isEmbedded = false;
8094#endif
8095
8096 // popup handling: new popups and tools need to be raised, and
8097 // existing popups must be closed. Also propagate the current
8098 // windows's KeyboardFocusChange status.
8099 if (isWindow && !isEmbedded) {
8100 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8101 q->raise();
8102 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8103 q->setAttribute(Qt::WA_KeyboardFocusChange);
8104 } else {
8105 while (QApplication::activePopupWidget()) {
8106 if (!QApplication::activePopupWidget()->close())
8107 break;
8108 }
8109 }
8110 }
8111
8112 // Automatic embedding of child windows of widgets already embedded into
8113 // QGraphicsProxyWidget when they are shown the first time.
8114#if QT_CONFIG(graphicsview)
8115 if (isWindow) {
8116 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8117 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8118 if (ancestorProxy) {
8119 isEmbedded = true;
8120 ancestorProxy->d_func()->embedSubWindow(q);
8121 }
8122 }
8123 }
8124#else
8125 Q_UNUSED(isEmbedded);
8126#endif
8127
8128 // send the show event before showing the window
8129 QShowEvent showEvent;
8130 QCoreApplication::sendEvent(q, &showEvent);
8131
8132 show_sys();
8133
8134 if (!isEmbedded && q->windowType() == Qt::Popup)
8135 qApp->d_func()->openPopup(q);
8136
8137#if QT_CONFIG(accessibility)
8138 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8139 QAccessibleEvent event(q, QAccessible::ObjectShow);
8140 QAccessible::updateAccessibility(&event);
8141 }
8142#endif
8143
8144 if (QApplicationPrivate::hidden_focus_widget == q) {
8145 QApplicationPrivate::hidden_focus_widget = nullptr;
8146 q->setFocus(Qt::OtherFocusReason);
8147 }
8148
8149 // Process events when showing a Qt::SplashScreen widget before the event loop
8150 // is spinnning; otherwise it might not show up on particular platforms.
8151 // This makes QSplashScreen behave the same on all platforms.
8152 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8153 QCoreApplication::processEvents();
8154
8155 data.in_show = false; // reset qws optimization
8156}
8157
8158void QWidgetPrivate::show_sys()
8159{
8160 Q_Q(QWidget);
8161
8162 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8163
8164 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8165 invalidateBackingStore(q->rect());
8166 q->setAttribute(Qt::WA_Mapped);
8167 // add our window the modal window list (native dialogs)
8168 if (window && q->isWindow()
8169#if QT_CONFIG(graphicsview)
8170 && (!extra || !extra->proxyWidget)
8171#endif
8172 && q->windowModality() != Qt::NonModal) {
8173 QGuiApplicationPrivate::showModalWindow(window);
8174 }
8175 return;
8176 }
8177
8178 if (renderToTexture && !q->isWindow())
8179 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8180 else
8181 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8182
8183 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8184 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8185 return;
8186 }
8187
8188 if (window) {
8189 if (q->isWindow())
8190 fixPosIncludesFrame();
8191 QRect geomRect = q->geometry();
8192 if (!q->isWindow()) {
8193 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8194 geomRect.moveTopLeft(topLeftOfWindow);
8195 }
8196 const QRect windowRect = window->geometry();
8197 if (windowRect != geomRect) {
8198 if (q->testAttribute(Qt::WA_Moved)
8199 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8200 window->setGeometry(geomRect);
8201 else
8202 window->resize(geomRect.size());
8203 }
8204
8205#ifndef QT_NO_CURSOR
8206 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8207#endif
8208 invalidateBackingStore(q->rect());
8209 window->setNativeWindowVisibility(true);
8210 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8211 if (window->isTopLevel()) {
8212 const QPoint crectTopLeft = q->data->crect.topLeft();
8213 const QPoint windowTopLeft = window->geometry().topLeft();
8214 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8215 q->data->crect.moveTopLeft(windowTopLeft);
8216 }
8217 }
8218}
8219
8220/*!
8221 Hides the widget. This function is equivalent to
8222 setVisible(false).
8223
8224
8225 \note If you are working with QDialog or its subclasses and you invoke
8226 the show() function after this function, the dialog will be displayed in
8227 its original position.
8228
8229 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8230*/
8231void QWidget::hide()
8232{
8233 setVisible(false);
8234}
8235
8236/*!\internal
8237 */
8238void QWidgetPrivate::hide_helper()
8239{
8240 Q_Q(QWidget);
8241
8242 bool isEmbedded = false;
8243#if QT_CONFIG(graphicsview)
8244 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8245#else
8246 Q_UNUSED(isEmbedded);
8247#endif
8248
8249 if (!isEmbedded && (q->windowType() == Qt::Popup))
8250 qApp->d_func()->closePopup(q);
8251
8252 q->setAttribute(Qt::WA_Mapped, false);
8253 hide_sys();
8254
8255 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8256
8257 if (wasVisible) {
8258 q->setAttribute(Qt::WA_WState_Visible, false);
8259
8260 }
8261
8262 QHideEvent hideEvent;
8263 QCoreApplication::sendEvent(q, &hideEvent);
8264 hideChildren(false);
8265
8266 // next bit tries to move the focus if the focus widget is now
8267 // hidden.
8268 if (wasVisible) {
8269 qApp->d_func()->sendSyntheticEnterLeave(q);
8270 QWidget *fw = QApplication::focusWidget();
8271 while (fw && !fw->isWindow()) {
8272 if (fw == q) {
8273 q->focusNextPrevChild(true);
8274 break;
8275 }
8276 fw = fw->parentWidget();
8277 }
8278 }
8279
8280 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8281 repaintManager->removeDirtyWidget(q);
8282
8283#if QT_CONFIG(accessibility)
8284 if (wasVisible) {
8285 QAccessibleEvent event(q, QAccessible::ObjectHide);
8286 QAccessible::updateAccessibility(&event);
8287 }
8288#endif
8289}
8290
8291void QWidgetPrivate::hide_sys()
8292{
8293 Q_Q(QWidget);
8294
8295 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8296
8297 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8298 q->setAttribute(Qt::WA_Mapped, false);
8299 // remove our window from the modal window list (native dialogs)
8300 if (window && q->isWindow()
8301#if QT_CONFIG(graphicsview)
8302 && (!extra || !extra->proxyWidget)
8303#endif
8304 && q->windowModality() != Qt::NonModal) {
8305 QGuiApplicationPrivate::hideModalWindow(window);
8306 }
8307 // do not return here, if window non-zero, we must hide it
8308 }
8309
8310 deactivateWidgetCleanup();
8311
8312 if (!q->isWindow()) {
8313 QWidget *p = q->parentWidget();
8314 if (p &&p->isVisible()) {
8315 if (renderToTexture)
8316 p->d_func()->invalidateBackingStore(q->geometry());
8317 else
8318 invalidateBackingStore(q->rect());
8319 }
8320 } else {
8321 invalidateBackingStore(q->rect());
8322 }
8323
8324 if (window)
8325 window->setNativeWindowVisibility(false);
8326}
8327
8328/*!
8329 \fn bool QWidget::isHidden() const
8330
8331 Returns \c true if the widget is hidden, otherwise returns \c false.
8332
8333 A hidden widget will only become visible when show() is called on
8334 it. It will not be automatically shown when the parent is shown.
8335
8336 To check visibility, use !isVisible() instead (notice the exclamation mark).
8337
8338 isHidden() implies !isVisible(), but a widget can be not visible
8339 and not hidden at the same time. This is the case for widgets that are children of
8340 widgets that are not visible.
8341
8342
8343 Widgets are hidden if:
8344 \list
8345 \li they were created as independent windows,
8346 \li they were created as children of visible widgets,
8347 \li hide() or setVisible(false) was called.
8348 \endlist
8349*/
8350
8351void QWidget::setVisible(bool visible)
8352{
8353 Q_D(QWidget);
8354 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8355 << "with attributes" << WidgetAttributes{this}
8356 << "to" << visible << "via QWidget";
8357
8358 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8359 return;
8360
8361 if (d->dontSetExplicitShowHide) {
8362 d->dontSetExplicitShowHide = false;
8363 } else {
8364 // Remember that setVisible was called explicitly
8365 setAttribute(Qt::WA_WState_ExplicitShowHide);
8366 }
8367
8368 d->setVisible(visible);
8369}
8370
8371// This method is called from QWidgetWindow in response to QWindow::setVisible,
8372// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8373// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8374void QWidgetPrivate::setVisible(bool visible)
8375{
8376 Q_Q(QWidget);
8377 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8378 << "with attributes" << WidgetAttributes{q}
8379 << "to" << visible << "via QWidgetPrivate";
8380
8381 if (visible) { // show
8382 // Designer uses a trick to make grabWidget work without showing
8383 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8384 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8385 q->parentWidget()->window()->d_func()->createRecursively();
8386
8387 //create toplevels but not children of non-visible parents
8388 QWidget *pw = q->parentWidget();
8389 if (!q->testAttribute(Qt::WA_WState_Created)
8390 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8391 q->create();
8392 }
8393
8394 bool wasResized = q->testAttribute(Qt::WA_Resized);
8395 Qt::WindowStates initialWindowState = q->windowState();
8396
8397 // polish if necessary
8398 q->ensurePolished();
8399
8400 // whether we need to inform the parent widget immediately
8401 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8402 // we are no longer hidden
8403 q->setAttribute(Qt::WA_WState_Hidden, false);
8404
8405 if (needUpdateGeometry)
8406 updateGeometry_helper(true);
8407
8408 // activate our layout before we and our children become visible
8409 if (layout)
8410 layout->activate();
8411
8412 if (!q->isWindow()) {
8413 QWidget *parent = q->parentWidget();
8414 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8415 parent->d_func()->layout->activate();
8416 if (parent->isWindow())
8417 break;
8418 parent = parent->parentWidget();
8419 }
8420 if (parent)
8421 parent->d_func()->setDirtyOpaqueRegion();
8422 }
8423
8424 // adjust size if necessary
8425 if (!wasResized
8426 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8427 if (q->isWindow()) {
8428 q->adjustSize();
8429 if (q->windowState() != initialWindowState)
8430 q->setWindowState(initialWindowState);
8431 } else {
8432 q->adjustSize();
8433 }
8434 q->setAttribute(Qt::WA_Resized, false);
8435 }
8436
8437 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8438
8439 if (q->isWindow() || q->parentWidget()->isVisible()) {
8440 show_helper();
8441
8442 qApp->d_func()->sendSyntheticEnterLeave(q);
8443 }
8444
8445 QEvent showToParentEvent(QEvent::ShowToParent);
8446 QCoreApplication::sendEvent(q, &showToParentEvent);
8447 } else { // hide
8448 if (QApplicationPrivate::hidden_focus_widget == q)
8449 QApplicationPrivate::hidden_focus_widget = nullptr;
8450
8451 // hw: The test on getOpaqueRegion() needs to be more intelligent
8452 // currently it doesn't work if the widget is hidden (the region will
8453 // be clipped). The real check should be testing the cached region
8454 // (and dirty flag) directly.
8455 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8456 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8457
8458 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8459 q->setAttribute(Qt::WA_WState_Hidden);
8460 hide_helper();
8461 }
8462
8463 // invalidate layout similar to updateGeometry()
8464 if (!q->isWindow() && q->parentWidget()) {
8465 if (q->parentWidget()->d_func()->layout)
8466 q->parentWidget()->d_func()->layout->invalidate();
8467 else if (q->parentWidget()->isVisible())
8468 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8469 }
8470
8471 QEvent hideToParentEvent(QEvent::HideToParent);
8472 QCoreApplication::sendEvent(q, &hideToParentEvent);
8473 }
8474}
8475
8476/*!
8477 Convenience function, equivalent to setVisible(!\a hidden).
8478*/
8479void QWidget::setHidden(bool hidden)
8480{
8481 setVisible(!hidden);
8482}
8483
8484bool QWidgetPrivate::isExplicitlyHidden() const
8485{
8486 Q_Q(const QWidget);
8487 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8488}
8489
8490void QWidgetPrivate::_q_showIfNotHidden()
8491{
8492 Q_Q(QWidget);
8493 if (!isExplicitlyHidden())
8494 q->setVisible(true);
8495}
8496
8497void QWidgetPrivate::showChildren(bool spontaneous)
8498{
8499 Q_Q(QWidget);
8500 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8501 << "spontaneously" << spontaneous;
8502
8503 QList<QObject*> childList = children;
8504 for (int i = 0; i < childList.size(); ++i) {
8505 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8506 if (!widget)
8507 continue;
8508 qCDebug(lcWidgetShowHide) << "Considering" << widget
8509 << "with attributes" << WidgetAttributes{widget};
8510 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8511 widget->setAttribute(Qt::WA_WState_Hidden, false);
8512 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8513 continue;
8514 if (spontaneous) {
8515 widget->setAttribute(Qt::WA_Mapped);
8516 widget->d_func()->showChildren(true);
8517 QShowEvent e;
8518 QApplication::sendSpontaneousEvent(widget, &e);
8519 } else {
8520 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8521 widget->d_func()->show_recursive();
8522 } else {
8523 // Call QWidget::setVisible() here, so that subclasses
8524 // that (wrongly) override setVisible to do initialization
8525 // will still be notified that they are made visible, but
8526 // do so without triggering ExplicitShowHide.
8527 widget->d_func()->dontSetExplicitShowHide = true;
8528 widget->setVisible(true);
8529 widget->d_func()->dontSetExplicitShowHide = false;
8530 }
8531 }
8532 }
8533}
8534
8535void QWidgetPrivate::hideChildren(bool spontaneous)
8536{
8537 Q_Q(QWidget);
8538 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8539 << "spontaneously" << spontaneous;
8540
8541 QList<QObject*> childList = children;
8542 for (int i = 0; i < childList.size(); ++i) {
8543 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8544 if (!widget)
8545 continue;
8546 qCDebug(lcWidgetShowHide) << "Considering" << widget
8547 << "with attributes" << WidgetAttributes{widget};
8548 if (widget->isWindow() || !widget->isVisible())
8549 continue;
8550
8551 if (spontaneous)
8552 widget->setAttribute(Qt::WA_Mapped, false);
8553 else
8554 widget->setAttribute(Qt::WA_WState_Visible, false);
8555 widget->d_func()->hideChildren(spontaneous);
8556 QHideEvent e;
8557 if (spontaneous) {
8558 QApplication::sendSpontaneousEvent(widget, &e);
8559 } else {
8560 QCoreApplication::sendEvent(widget, &e);
8561 if (widget->internalWinId()
8562 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8563 // hide_sys() on an ancestor won't have any affect on this
8564 // widget, so it needs an explicit hide_sys() of its own
8565 widget->d_func()->hide_sys();
8566 }
8567 }
8568 qApp->d_func()->sendSyntheticEnterLeave(widget);
8569#if QT_CONFIG(accessibility)
8570 if (!spontaneous) {
8571 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8572 QAccessible::updateAccessibility(&event);
8573 }
8574#endif
8575 }
8576
8577 // If the window of this widget is not closed, then the leave event
8578 // will eventually handle the widget under mouse use case.
8579 // Otherwise, we need to explicitly handle it here.
8580 if (QWidget* widgetWindow = q->window();
8581 widgetWindow && widgetWindow->data->is_closing) {
8582 q->setAttribute(Qt::WA_UnderMouse, false);
8583 }
8584}
8585
8586/*!
8587 \internal
8588
8589 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8590 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8591 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8592 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8593 system (i.e. the user clicked the close button in the title bar).
8594
8595 QDialog calls this method directly in its hide() implementation, which might be
8596 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8597 to prevent recursion.
8598
8599 For non-windows, this is called directly by QWidget::close, and \a mode will be
8600 CloseWithEvent.
8601
8602 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8603*/
8604bool QWidgetPrivate::handleClose(CloseMode mode)
8605{
8606 Q_Q(QWidget);
8607 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8608
8609 if (data.is_closing)
8610 return true;
8611
8612 // We might not have initiated the close, so update the state now that we know
8613 data.is_closing = true;
8614
8615 QPointer<QWidget> that = q;
8616
8617 if (data.in_destructor)
8618 mode = CloseNoEvent;
8619
8620 if (mode != CloseNoEvent) {
8621 QCloseEvent e;
8622 if (mode == CloseWithSpontaneousEvent)
8623 QApplication::sendSpontaneousEvent(q, &e);
8624 else
8625 QCoreApplication::sendEvent(q, &e);
8626 if (!that.isNull() && !e.isAccepted()) {
8627 data.is_closing = false;
8628 return false;
8629 }
8630 }
8631
8632 // even for windows, make sure we deliver a hide event and that all children get hidden
8633 if (!that.isNull() && !q->isHidden())
8634 q->hide();
8635
8636 if (!that.isNull()) {
8637 data.is_closing = false;
8638 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8639 q->setAttribute(Qt::WA_DeleteOnClose, false);
8640 q->deleteLater();
8641 }
8642 }
8643 return true;
8644}
8645
8646
8647/*!
8648 Closes this widget. Returns \c true if the widget was closed;
8649 otherwise returns \c false.
8650
8651 First it sends the widget a QCloseEvent. The widget is
8652 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8653 the close event. If it \l{QEvent::ignore()}{ignores}
8654 the event, nothing happens. The default
8655 implementation of QWidget::closeEvent() accepts the close event.
8656
8657 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8658 is also deleted. A close events is delivered to the widget no
8659 matter if the widget is visible or not.
8660
8661 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8662 last visible primary window (i.e. window with no parent) with the
8663 Qt::WA_QuitOnClose attribute set is closed. By default this
8664 attribute is set for all widgets except transient windows such as
8665 splash screens, tool windows, and popup menus.
8666
8667*/
8668
8669bool QWidget::close()
8670{
8671 return d_func()->close();
8672}
8673
8674bool QWidgetPrivate::close()
8675{
8676 // FIXME: We're not setting is_closing here, even though that would
8677 // make sense, as the code below will not end up in handleClose to
8678 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8679 // and we can't assume close is synchronous so we can't reset it here.
8680
8681 // Close native widgets via QWindow::close() in order to run QWindow
8682 // close code. The QWidget-specific close code in handleClose() will
8683 // in this case be called from the Close event handler in QWidgetWindow.
8684 if (QWindow *widgetWindow = windowHandle()) {
8685 if (widgetWindow->isTopLevel())
8686 return widgetWindow->close();
8687 }
8688
8689 return handleClose(QWidgetPrivate::CloseWithEvent);
8690}
8691
8692/*!
8693 \property QWidget::visible
8694 \brief whether the widget is visible
8695
8696 Calling setVisible(true) or show() sets the widget to visible
8697 status if all its parent widgets up to the window are visible. If
8698 an ancestor is not visible, the widget won't become visible until
8699 all its ancestors are shown. If its size or position has changed,
8700 Qt guarantees that a widget gets move and resize events just
8701 before it is shown. If the widget has not been resized yet, Qt
8702 will adjust the widget's size to a useful default using
8703 adjustSize().
8704
8705 Calling setVisible(false) or hide() hides a widget explicitly. An
8706 explicitly hidden widget will never become visible, even if all
8707 its ancestors become visible, unless you show it.
8708
8709 A widget receives show and hide events when its visibility status
8710 changes. Between a hide and a show event, there is no need to
8711 waste CPU cycles preparing or displaying information to the user.
8712 A video application, for example, might simply stop generating new
8713 frames.
8714
8715 A widget that happens to be obscured by other windows on the
8716 screen is considered to be visible. The same applies to iconified
8717 windows and windows that exist on another virtual
8718 desktop (on platforms that support this concept). A widget
8719 receives spontaneous show and hide events when its mapping status
8720 is changed by the window system, e.g. a spontaneous hide event
8721 when the user minimizes the window, and a spontaneous show event
8722 when the window is restored again.
8723
8724 You seldom have to reimplement the setVisible() function. If
8725 you need to change some settings before a widget is shown, use
8726 showEvent() instead. If you need to do some delayed initialization
8727 use the Polish event delivered to the event() function.
8728
8729 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8730 showEvent(), hideEvent()
8731*/
8732
8733
8734/*!
8735 Returns \c true if this widget would become visible if \a ancestor is
8736 shown; otherwise returns \c false.
8737
8738 The true case occurs if neither the widget itself nor any parent
8739 up to but excluding \a ancestor has been explicitly hidden.
8740
8741 This function will still return true if the widget is obscured by
8742 other windows on the screen, but could be physically visible if it
8743 or they were to be moved.
8744
8745 isVisibleTo(0) is identical to isVisible().
8746
8747 \sa show(), hide(), isVisible()
8748*/
8749
8750bool QWidget::isVisibleTo(const QWidget *ancestor) const
8751{
8752 if (!ancestor)
8753 return isVisible();
8754 const QWidget * w = this;
8755 while (!w->isHidden()
8756 && !w->isWindow()
8757 && w->parentWidget()
8758 && w->parentWidget() != ancestor)
8759 w = w->parentWidget();
8760 return !w->isHidden();
8761}
8762
8763
8764/*!
8765 Returns the unobscured region where paint events can occur.
8766
8767 For visible widgets, this is an approximation of the area not
8768 covered by other widgets; otherwise, this is an empty region.
8769
8770 The repaint() function calls this function if necessary, so in
8771 general you do not need to call it.
8772
8773*/
8774QRegion QWidget::visibleRegion() const
8775{
8776 Q_D(const QWidget);
8777
8778 QRect clipRect = d->clipRect();
8779 if (clipRect.isEmpty())
8780 return QRegion();
8781 QRegion r(clipRect);
8782 d->subtractOpaqueChildren(r, clipRect);
8783 d->subtractOpaqueSiblings(r);
8784 return r;
8785}
8786
8787
8788QSize QWidgetPrivate::adjustedSize() const
8789{
8790 Q_Q(const QWidget);
8791
8792 QSize s = q->sizeHint();
8793
8794 if (q->isWindow()) {
8795 Qt::Orientations exp;
8796 if (layout) {
8797 if (layout->hasHeightForWidth())
8798 s.setHeight(layout->totalHeightForWidth(s.width()));
8799 exp = layout->expandingDirections();
8800 } else
8801 {
8802 if (q->sizePolicy().hasHeightForWidth())
8803 s.setHeight(q->heightForWidth(s.width()));
8804 exp = q->sizePolicy().expandingDirections();
8805 }
8806 if (exp & Qt::Horizontal)
8807 s.setWidth(qMax(s.width(), 200));
8808 if (exp & Qt::Vertical)
8809 s.setHeight(qMax(s.height(), 100));
8810
8811 QRect screen;
8812 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8813 screen = screenAtPoint->geometry();
8814 else
8815 screen = QGuiApplication::primaryScreen()->geometry();
8816
8817 s.setWidth(qMin(s.width(), screen.width()*2/3));
8818 s.setHeight(qMin(s.height(), screen.height()*2/3));
8819
8820 if (QTLWExtra *extra = maybeTopData())
8821 extra->sizeAdjusted = true;
8822 }
8823
8824 if (!s.isValid()) {
8825 QRect r = q->childrenRect(); // get children rectangle
8826 if (r.isNull())
8827 return s;
8828 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8829 }
8830
8831 return s;
8832}
8833
8834/*!
8835 Adjusts the size of the widget to fit its contents.
8836
8837 This function uses sizeHint() if it is valid, i.e., the size hint's width
8838 and height are >= 0. Otherwise, it sets the size to the children
8839 rectangle that covers all child widgets (the union of all child widget
8840 rectangles).
8841
8842 For windows, the screen size is also taken into account. If the sizeHint()
8843 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8844 {expanding}, the window will be at least (200, 100). The maximum size of
8845 a window is 2/3 of the screen's width and height.
8846
8847 \sa sizeHint(), childrenRect()
8848*/
8849
8850void QWidget::adjustSize()
8851{
8852 Q_D(QWidget);
8853 ensurePolished();
8854 QSize s = d->adjustedSize();
8855
8856 if (d->layout)
8857 d->layout->activate();
8858
8859 if (s.isValid())
8860 resize(s);
8861}
8862
8863
8864/*!
8865 \property QWidget::sizeHint
8866 \brief the recommended size for the widget
8867
8868 If the value of this property is an invalid size, no size is
8869 recommended.
8870
8871 The default implementation of sizeHint() returns an invalid size
8872 if there is no layout for this widget, and returns the layout's
8873 preferred size otherwise.
8874
8875 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8876 setMinimumSize(), updateGeometry()
8877*/
8878
8879QSize QWidget::sizeHint() const
8880{
8881 Q_D(const QWidget);
8882 if (d->layout)
8883 return d->layout->totalSizeHint();
8884 return QSize(-1, -1);
8885}
8886
8887/*!
8888 \property QWidget::minimumSizeHint
8889 \brief the recommended minimum size for the widget
8890
8891 If the value of this property is an invalid size, no minimum size
8892 is recommended.
8893
8894 The default implementation of minimumSizeHint() returns an invalid
8895 size if there is no layout for this widget, and returns the
8896 layout's minimum size otherwise. Most built-in widgets reimplement
8897 minimumSizeHint().
8898
8899 \l QLayout will never resize a widget to a size smaller than the
8900 minimum size hint unless minimumSize() is set or the size policy is
8901 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8902 size hint will be ignored.
8903
8904 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8905*/
8906QSize QWidget::minimumSizeHint() const
8907{
8908 Q_D(const QWidget);
8909 if (d->layout)
8910 return d->layout->totalMinimumSize();
8911 return QSize(-1, -1);
8912}
8913
8914
8915/*!
8916 \fn QWidget *QWidget::parentWidget() const
8917
8918 Returns the parent of this widget, or \nullptr if it does not have any
8919 parent widget.
8920*/
8921
8922
8923/*!
8924 Returns \c true if this widget is a parent, (or grandparent and so on
8925 to any level), of the given \a child, and both widgets are within
8926 the same window; otherwise returns \c false.
8927*/
8928
8929bool QWidget::isAncestorOf(const QWidget *child) const
8930{
8931 while (child) {
8932 if (child == this)
8933 return true;
8934 if (child->isWindow())
8935 return false;
8936 child = child->parentWidget();
8937 }
8938 return false;
8939}
8940
8941/*****************************************************************************
8942 QWidget event handling
8943 *****************************************************************************/
8944
8945/*!
8946 This is the main event handler; it handles event \a event. You can
8947 reimplement this function in a subclass, but we recommend using
8948 one of the specialized event handlers instead.
8949
8950 Key press and release events are treated differently from other
8951 events. event() checks for Tab and Shift+Tab and tries to move the
8952 focus appropriately. If there is no widget to move the focus to
8953 (or the key press is not Tab or Shift+Tab), event() calls
8954 keyPressEvent().
8955
8956 Mouse and tablet event handling is also slightly special: only
8957 when the widget is \l enabled, event() will call the specialized
8958 handlers such as mousePressEvent(); otherwise it will discard the
8959 event.
8960
8961 This function returns \c true if the event was recognized, otherwise
8962 it returns \c false. If the recognized event was accepted (see \l
8963 QEvent::accepted), any further processing such as event
8964 propagation to the parent widget stops.
8965
8966 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8967 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8968 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8969 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8970 QObject::event(), QObject::timerEvent()
8971*/
8972
8973bool QWidget::event(QEvent *event)
8974{
8975 Q_D(QWidget);
8976
8977 // ignore mouse and key events when disabled
8978 if (!isEnabled()) {
8979 switch(event->type()) {
8980 case QEvent::TabletPress:
8981 case QEvent::TabletRelease:
8982 case QEvent::TabletMove:
8983 case QEvent::MouseButtonPress:
8984 case QEvent::MouseButtonRelease:
8985 case QEvent::MouseButtonDblClick:
8986 case QEvent::MouseMove:
8987 case QEvent::TouchBegin:
8988 case QEvent::TouchUpdate:
8989 case QEvent::TouchEnd:
8990 case QEvent::TouchCancel:
8991 case QEvent::ContextMenu:
8992 case QEvent::KeyPress:
8993 case QEvent::KeyRelease:
8994#if QT_CONFIG(wheelevent)
8995 case QEvent::Wheel:
8996#endif
8997 return false;
8998 default:
8999 break;
9000 }
9001 }
9002 switch (event->type()) {
9003 case QEvent::PlatformSurface: {
9004 // Sync up QWidget's view of whether or not the widget has been created
9005 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
9006 case QPlatformSurfaceEvent::SurfaceCreated:
9007 if (!testAttribute(Qt::WA_WState_Created))
9008 create();
9009 break;
9010 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
9011 if (testAttribute(Qt::WA_WState_Created)) {
9012 // Child windows have already been destroyed by QWindow,
9013 // so we skip them here.
9014 destroy(false, false);
9015 }
9016 break;
9017 }
9018 break;
9019 }
9020 case QEvent::MouseMove:
9021 mouseMoveEvent((QMouseEvent*)event);
9022 break;
9023
9024 case QEvent::MouseButtonPress:
9025 mousePressEvent((QMouseEvent*)event);
9026 break;
9027
9028 case QEvent::MouseButtonRelease:
9029 mouseReleaseEvent((QMouseEvent*)event);
9030 break;
9031
9032 case QEvent::MouseButtonDblClick:
9033 mouseDoubleClickEvent((QMouseEvent*)event);
9034 break;
9035#if QT_CONFIG(wheelevent)
9036 case QEvent::Wheel:
9037 wheelEvent((QWheelEvent*)event);
9038 break;
9039#endif
9040#if QT_CONFIG(tabletevent)
9041 case QEvent::TabletMove:
9042 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9043 break;
9044 Q_FALLTHROUGH();
9045 case QEvent::TabletPress:
9046 case QEvent::TabletRelease:
9047 tabletEvent((QTabletEvent*)event);
9048 break;
9049#endif
9050 case QEvent::KeyPress: {
9051 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9052 bool res = false;
9053 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9054 if (k->key() == Qt::Key_Backtab
9055 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9056 res = focusNextPrevChild(false);
9057 else if (k->key() == Qt::Key_Tab)
9058 res = focusNextPrevChild(true);
9059 if (res)
9060 break;
9061 }
9062 keyPressEvent(k);
9063#ifdef QT_KEYPAD_NAVIGATION
9064 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9065 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9066 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9067 if (k->key() == Qt::Key_Up)
9068 res = focusNextPrevChild(false);
9069 else if (k->key() == Qt::Key_Down)
9070 res = focusNextPrevChild(true);
9071 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9072 if (k->key() == Qt::Key_Up)
9073 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9074 else if (k->key() == Qt::Key_Right)
9075 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9076 else if (k->key() == Qt::Key_Down)
9077 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9078 else if (k->key() == Qt::Key_Left)
9079 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9080 }
9081 if (res) {
9082 k->accept();
9083 break;
9084 }
9085 }
9086#endif
9087#if QT_CONFIG(whatsthis)
9088 if (!k->isAccepted()
9089 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9090 && d->whatsThis.size()) {
9091 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9092 k->accept();
9093 }
9094#endif
9095 }
9096 break;
9097
9098 case QEvent::KeyRelease:
9099 keyReleaseEvent((QKeyEvent*)event);
9100 Q_FALLTHROUGH();
9101 case QEvent::ShortcutOverride:
9102 break;
9103
9104 case QEvent::InputMethod:
9105 inputMethodEvent((QInputMethodEvent *) event);
9106 break;
9107
9108 case QEvent::InputMethodQuery: {
9109 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9110 Qt::InputMethodQueries queries = query->queries();
9111 for (uint i = 0; i < 32; ++i) {
9112 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9113 if (q) {
9114 QVariant v = inputMethodQuery(q);
9115 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9116 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9117 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9118 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9119 // will only be set if the widget supports IM _and_ is not read-only. So for
9120 // read-only widgets, not all IM features will be supported when ImEnabled is
9121 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9122 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9123 }
9124 query->setValue(q, v);
9125 }
9126 }
9127 query->accept();
9128 }
9129 break;
9130
9131 case QEvent::PolishRequest:
9132 ensurePolished();
9133 break;
9134
9135 case QEvent::Polish: {
9136 style()->polish(this);
9137 setAttribute(Qt::WA_WState_Polished);
9138 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9139 d->resolveFont();
9140 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9141 d->resolvePalette();
9142 }
9143 break;
9144
9145 case QEvent::ApplicationWindowIconChange:
9146 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9147 d->setWindowIcon_sys();
9148 d->setWindowIcon_helper();
9149 }
9150 break;
9151 case QEvent::FocusIn:
9152 focusInEvent((QFocusEvent*)event);
9153 d->updateWidgetTransform(event);
9154 break;
9155
9156 case QEvent::FocusOut:
9157 focusOutEvent((QFocusEvent*)event);
9158 break;
9159
9160 case QEvent::Enter:
9161#if QT_CONFIG(statustip)
9162 if (d->statusTip.size()) {
9163 QStatusTipEvent tip(d->statusTip);
9164 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9165 }
9166#endif
9167 enterEvent(static_cast<QEnterEvent*>(event));
9168 break;
9169
9170 case QEvent::Leave:
9171#if QT_CONFIG(statustip)
9172 if (d->statusTip.size()) {
9173 QString empty;
9174 QStatusTipEvent tip(empty);
9175 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9176 }
9177#endif
9178 leaveEvent(event);
9179 break;
9180
9181 case QEvent::HoverEnter:
9182 case QEvent::HoverLeave:
9183 update();
9184 break;
9185
9186 case QEvent::Paint:
9187 // At this point the event has to be delivered, regardless
9188 // whether the widget isVisible() or not because it
9189 // already went through the filters
9190 paintEvent((QPaintEvent*)event);
9191 break;
9192
9193 case QEvent::Move:
9194 moveEvent((QMoveEvent*)event);
9195 d->updateWidgetTransform(event);
9196 break;
9197
9198 case QEvent::Resize:
9199 resizeEvent((QResizeEvent*)event);
9200 d->updateWidgetTransform(event);
9201 break;
9202
9203 case QEvent::Close:
9204 closeEvent((QCloseEvent *)event);
9205 break;
9206
9207#ifndef QT_NO_CONTEXTMENU
9208 case QEvent::ContextMenu:
9209 switch (data->context_menu_policy) {
9210 case Qt::PreventContextMenu:
9211 break;
9212 case Qt::DefaultContextMenu:
9213 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9214 break;
9215 case Qt::CustomContextMenu:
9216 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9217 break;
9218#if QT_CONFIG(menu)
9219 case Qt::ActionsContextMenu:
9220 if (d->actions.size()) {
9221 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9222 nullptr, this);
9223 break;
9224 }
9225 Q_FALLTHROUGH();
9226#endif
9227 default:
9228 event->ignore();
9229 break;
9230 }
9231 break;
9232#endif // QT_NO_CONTEXTMENU
9233
9234#if QT_CONFIG(draganddrop)
9235 case QEvent::Drop:
9236 dropEvent((QDropEvent*) event);
9237 break;
9238
9239 case QEvent::DragEnter:
9240 dragEnterEvent((QDragEnterEvent*) event);
9241 break;
9242
9243 case QEvent::DragMove:
9244 dragMoveEvent((QDragMoveEvent*) event);
9245 break;
9246
9247 case QEvent::DragLeave:
9248 dragLeaveEvent((QDragLeaveEvent*) event);
9249 break;
9250#endif
9251
9252 case QEvent::Show:
9253 showEvent((QShowEvent*) event);
9254 break;
9255
9256 case QEvent::Hide:
9257 hideEvent((QHideEvent*) event);
9258 break;
9259
9260 case QEvent::ShowWindowRequest:
9261 if (!isHidden())
9262 d->show_sys();
9263 break;
9264
9265 case QEvent::ApplicationFontChange:
9266 d->resolveFont();
9267 break;
9268 case QEvent::ApplicationPaletteChange:
9269 d->resolvePalette();
9270 break;
9271
9272 case QEvent::ToolBarChange:
9273 case QEvent::ActivationChange:
9274 case QEvent::EnabledChange:
9275 case QEvent::FontChange:
9276 case QEvent::StyleChange:
9277 case QEvent::PaletteChange:
9278 case QEvent::WindowTitleChange:
9279 case QEvent::IconTextChange:
9280 case QEvent::ModifiedChange:
9281 case QEvent::MouseTrackingChange:
9282 case QEvent::TabletTrackingChange:
9283 case QEvent::ParentChange:
9284 case QEvent::LocaleChange:
9285 case QEvent::MacSizeChange:
9286 case QEvent::ContentsRectChange:
9287 case QEvent::ThemeChange:
9288 case QEvent::ReadOnlyChange:
9289 changeEvent(event);
9290 break;
9291
9292 case QEvent::WindowStateChange: {
9293 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9294 if (wasMinimized != isMinimized()) {
9295 QWidget *widget = const_cast<QWidget *>(this);
9296 if (wasMinimized) {
9297 // Always send the spontaneous events here, otherwise it can break the application!
9298 if (!d->childrenShownByExpose) {
9299 // Show widgets only when they are not yet shown by the expose event
9300 d->showChildren(true);
9301 QShowEvent showEvent;
9302 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9303 }
9304 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9305 } else {
9306 QHideEvent hideEvent;
9307 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9308 d->hideChildren(true);
9309 d->childrenHiddenByWState = true;
9310 }
9311 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9312 }
9313 changeEvent(event);
9314 }
9315 break;
9316
9317 case QEvent::WindowActivate:
9318 case QEvent::WindowDeactivate: {
9319 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9320 update();
9321 QList<QObject*> childList = d->children;
9322 for (int i = 0; i < childList.size(); ++i) {
9323 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9324 if (w && w->isVisible() && !w->isWindow())
9325 QCoreApplication::sendEvent(w, event);
9326 }
9327 break; }
9328
9329 case QEvent::LanguageChange:
9330 changeEvent(event);
9331 {
9332 QList<QObject*> childList = d->children;
9333 for (int i = 0; i < childList.size(); ++i) {
9334 QObject *o = childList.at(i);
9335 if (o)
9336 QCoreApplication::sendEvent(o, event);
9337 }
9338 }
9339 update();
9340 break;
9341
9342 case QEvent::ApplicationLayoutDirectionChange:
9343 d->resolveLayoutDirection();
9344 break;
9345
9346 case QEvent::LayoutDirectionChange:
9347 if (d->layout)
9348 d->layout->invalidate();
9349 update();
9350 changeEvent(event);
9351 break;
9352 case QEvent::UpdateRequest:
9353 d->syncBackingStore();
9354 break;
9355 case QEvent::UpdateLater:
9356 update(static_cast<QUpdateLaterEvent*>(event)->region());
9357 break;
9358 case QEvent::StyleAnimationUpdate:
9359 if (isVisible() && !window()->isMinimized()) {
9360 event->accept();
9361 update();
9362 }
9363 break;
9364
9365 case QEvent::WindowBlocked:
9366 case QEvent::WindowUnblocked:
9367 if (!d->children.isEmpty()) {
9368 QWidget *modalWidget = QApplication::activeModalWidget();
9369 for (int i = 0; i < d->children.size(); ++i) {
9370 QObject *o = d->children.at(i);
9371 if (o && o != modalWidget && o->isWidgetType()) {
9372 QWidget *w = static_cast<QWidget *>(o);
9373 // do not forward the event to child windows; QApplication does this for us
9374 if (!w->isWindow())
9375 QCoreApplication::sendEvent(w, event);
9376 }
9377 }
9378 }
9379 break;
9380#if QT_CONFIG(tooltip)
9381 case QEvent::ToolTip:
9382 if (!d->toolTip.isEmpty())
9383 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9384 else
9385 event->ignore();
9386 break;
9387#endif
9388#if QT_CONFIG(whatsthis)
9389 case QEvent::WhatsThis:
9390 if (d->whatsThis.size())
9391 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9392 else
9393 event->ignore();
9394 break;
9395 case QEvent::QueryWhatsThis:
9396 if (d->whatsThis.isEmpty())
9397 event->ignore();
9398 break;
9399#endif
9400 case QEvent::EmbeddingControl:
9401 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9402 data->fstrut_dirty = false;
9403 break;
9404#ifndef QT_NO_ACTION
9405 case QEvent::ActionAdded:
9406 case QEvent::ActionRemoved:
9407 case QEvent::ActionChanged:
9408 actionEvent((QActionEvent*)event);
9409 break;
9410#endif
9411
9412 case QEvent::KeyboardLayoutChange:
9413 {
9414 changeEvent(event);
9415
9416 // inform children of the change
9417 QList<QObject*> childList = d->children;
9418 for (int i = 0; i < childList.size(); ++i) {
9419 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9420 if (w && w->isVisible() && !w->isWindow())
9421 QCoreApplication::sendEvent(w, event);
9422 }
9423 break;
9424 }
9425 case QEvent::TouchBegin:
9426 case QEvent::TouchUpdate:
9427 case QEvent::TouchEnd:
9428 case QEvent::TouchCancel:
9429 {
9430 event->ignore();
9431 break;
9432 }
9433#ifndef QT_NO_GESTURES
9434 case QEvent::Gesture:
9435 event->ignore();
9436 break;
9437#endif
9438 case QEvent::ScreenChangeInternal:
9439 if (const QTLWExtra *te = d->maybeTopData()) {
9440 const QWindow *win = te->window;
9441 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9442 }
9443 break;
9444 case QEvent::DevicePixelRatioChange:
9445 if (d->data.fnt.d->dpi != logicalDpiY())
9446 d->updateFont(d->data.fnt);
9447 d->renderToTextureReallyDirty = 1;
9448 break;
9449 case QEvent::DynamicPropertyChange: {
9450 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9451 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9452 uint value = property(propName.constData()).toUInt();
9453 if (!d->extra)
9454 d->createExtra();
9455 const char axis = propName.at(12);
9456 if (axis == 'X')
9457 d->extra->customDpiX = value;
9458 else if (axis == 'Y')
9459 d->extra->customDpiY = value;
9460 d->updateFont(d->data.fnt);
9461 }
9462 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9463 windowHandle()->setProperty(propName, property(propName));
9464 Q_FALLTHROUGH();
9465 }
9466 default:
9467 return QObject::event(event);
9468 }
9469 return true;
9470}
9471
9472/*!
9473 This event handler can be reimplemented to handle state changes.
9474
9475 The state being changed in this event can be retrieved through the \a event
9476 supplied.
9477
9478 Change events include: QEvent::ToolBarChange,
9479 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9480 QEvent::StyleChange, QEvent::PaletteChange,
9481 QEvent::WindowTitleChange, QEvent::IconTextChange,
9482 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9483 QEvent::ParentChange, QEvent::WindowStateChange,
9484 QEvent::LanguageChange, QEvent::LocaleChange,
9485 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9486
9487*/
9488void QWidget::changeEvent(QEvent * event)
9489{
9490 switch(event->type()) {
9491 case QEvent::EnabledChange: {
9492 update();
9493#if QT_CONFIG(accessibility)
9494 QAccessible::State s;
9495 s.disabled = true;
9496 QAccessibleStateChangeEvent event(this, s);
9497 QAccessible::updateAccessibility(&event);
9498#endif
9499 break;
9500 }
9501
9502 case QEvent::FontChange:
9503 case QEvent::StyleChange: {
9504 Q_D(QWidget);
9505 update();
9506 updateGeometry();
9507 if (d->layout)
9508 d->layout->invalidate();
9509 break;
9510 }
9511
9512 case QEvent::PaletteChange:
9513 update();
9514 break;
9515
9516 case QEvent::ThemeChange:
9517 if (QGuiApplication::desktopSettingsAware()
9518 && qApp && !QCoreApplication::closingDown()) {
9519 if (testAttribute(Qt::WA_WState_Polished))
9520 QApplication::style()->unpolish(this);
9521 if (testAttribute(Qt::WA_WState_Polished))
9522 QApplication::style()->polish(this);
9523 QEvent styleChangedEvent(QEvent::StyleChange);
9524 QCoreApplication::sendEvent(this, &styleChangedEvent);
9525 if (isVisible())
9526 update();
9527 }
9528 break;
9529
9530#ifdef Q_OS_MAC
9531 case QEvent::MacSizeChange:
9532 updateGeometry();
9533 break;
9534#endif
9535
9536 default:
9537 break;
9538 }
9539}
9540
9541/*!
9542 This event handler, for event \a event, can be reimplemented in a
9543 subclass to receive mouse move events for the widget.
9544
9545 If mouse tracking is switched off, mouse move events only occur if
9546 a mouse button is pressed while the mouse is being moved. If mouse
9547 tracking is switched on, mouse move events occur even if no mouse
9548 button is pressed.
9549
9550 QMouseEvent::position() reports the position of the mouse cursor,
9551 relative to this widget. For press and release events, the
9552 position is usually the same as the position of the last mouse
9553 move event, but it might be different if the user's hand shakes.
9554 This is a feature of the underlying window system, not Qt.
9555
9556 If you want to show a tooltip immediately, while the mouse is
9557 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9558 and show them as a tooltip), you must first enable mouse tracking
9559 as described above. Then, to ensure that the tooltip is updated
9560 immediately, you must call QToolTip::showText() instead of
9561 setToolTip() in your implementation of mouseMoveEvent().
9562
9563 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9564 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9565*/
9566
9567void QWidget::mouseMoveEvent(QMouseEvent *event)
9568{
9569 event->ignore();
9570}
9571
9572/*!
9573 This event handler, for event \a event, can be reimplemented in a
9574 subclass to receive mouse press events for the widget.
9575
9576 If you create new widgets in the mousePressEvent() the
9577 mouseReleaseEvent() may not end up where you expect, depending on
9578 the underlying window system (or X11 window manager), the widgets'
9579 location and maybe more.
9580
9581 The default implementation implements the closing of popup widgets
9582 when you click outside the window. For other widget types it does
9583 nothing.
9584
9585 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9586 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9587*/
9588
9589void QWidget::mousePressEvent(QMouseEvent *event)
9590{
9591 event->ignore();
9592 if ((windowType() == Qt::Popup)) {
9593 event->accept();
9594 QWidget* w;
9595 while ((w = QApplication::activePopupWidget()) && w != this){
9596 w->close();
9597 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9598 w->hide(); // hide at least
9599 }
9600 if (!rect().contains(event->position().toPoint())){
9601 close();
9602 }
9603 }
9604}
9605
9606/*!
9607 This event handler, for event \a event, can be reimplemented in a
9608 subclass to receive mouse release events for the widget.
9609
9610 \sa mousePressEvent(), mouseDoubleClickEvent(),
9611 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9612*/
9613
9614void QWidget::mouseReleaseEvent(QMouseEvent *event)
9615{
9616 event->ignore();
9617}
9618
9619/*!
9620 This event handler, for event \a event, can be reimplemented in a
9621 subclass to receive mouse double click events for the widget.
9622
9623 The default implementation calls mousePressEvent().
9624
9625 \note The widget will also receive mouse press and mouse release
9626 events in addition to the double click event. And if another widget
9627 that overlaps this widget disappears in response to press or
9628 release events, then this widget will only receive the double click
9629 event. It is up to the developer to ensure that the application
9630 interprets these events correctly.
9631
9632 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9633 event(), QMouseEvent
9634*/
9635
9636void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9637{
9638 mousePressEvent(event);
9639}
9640
9641#if QT_CONFIG(wheelevent)
9642/*!
9643 This event handler, for event \a event, can be reimplemented in a
9644 subclass to receive wheel events for the widget.
9645
9646 If you reimplement this handler, it is very important that you
9647 \l{QEvent}{ignore()} the event if you do not handle
9648 it, so that the widget's parent can interpret it.
9649
9650 The default implementation ignores the event.
9651
9652 \sa QEvent::ignore(), QEvent::accept(), event(),
9653 QWheelEvent
9654*/
9655
9656void QWidget::wheelEvent(QWheelEvent *event)
9657{
9658 event->ignore();
9659}
9660#endif // QT_CONFIG(wheelevent)
9661
9662#if QT_CONFIG(tabletevent)
9663/*!
9664 This event handler, for event \a event, can be reimplemented in a
9665 subclass to receive tablet events for the widget.
9666
9667 If you reimplement this handler, it is very important that you
9668 \l{QEvent}{ignore()} the event if you do not handle
9669 it, so that the widget's parent can interpret it.
9670
9671 The default implementation ignores the event.
9672
9673 If tablet tracking is switched off, tablet move events only occur if the
9674 stylus is in contact with the tablet, or at least one stylus button is
9675 pressed, while the stylus is being moved. If tablet tracking is switched on,
9676 tablet move events occur even while the stylus is hovering in proximity of
9677 the tablet, with no buttons pressed.
9678
9679 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9680 QTabletEvent
9681*/
9682
9683void QWidget::tabletEvent(QTabletEvent *event)
9684{
9685 event->ignore();
9686}
9687#endif // QT_CONFIG(tabletevent)
9688
9689/*!
9690 This event handler, for event \a event, can be reimplemented in a
9691 subclass to receive key press events for the widget.
9692
9693 A widget must call setFocusPolicy() to accept focus initially and
9694 have focus in order to receive a key press event.
9695
9696 If you reimplement this handler, it is very important that you
9697 call the base class implementation if you do not act upon the key.
9698
9699 The default implementation closes popup widgets if the user
9700 presses the key sequence for QKeySequence::Cancel (typically the
9701 Escape key). Otherwise the event is ignored, so that the widget's
9702 parent can interpret it.
9703
9704 Note that QKeyEvent starts with isAccepted() == true, so you do not
9705 need to call QKeyEvent::accept() - just do not call the base class
9706 implementation if you act upon the key.
9707
9708 \sa keyReleaseEvent(), setFocusPolicy(),
9709 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9710*/
9711
9712void QWidget::keyPressEvent(QKeyEvent *event)
9713{
9714#ifndef QT_NO_SHORTCUT
9715 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9716 event->accept();
9717 close();
9718 } else
9719#endif
9720 {
9721 event->ignore();
9722 }
9723}
9724
9725/*!
9726 This event handler, for event \a event, can be reimplemented in a
9727 subclass to receive key release events for the widget.
9728
9729 A widget must \l{setFocusPolicy()}{accept focus}
9730 initially and \l{hasFocus()}{have focus} in order to
9731 receive a key release event.
9732
9733 If you reimplement this handler, it is very important that you
9734 call the base class implementation if you do not act upon the key.
9735
9736 The default implementation ignores the event, so that the widget's
9737 parent can interpret it.
9738
9739 Note that QKeyEvent starts with isAccepted() == true, so you do not
9740 need to call QKeyEvent::accept() - just do not call the base class
9741 implementation if you act upon the key.
9742
9743 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9744 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9745*/
9746
9747void QWidget::keyReleaseEvent(QKeyEvent *event)
9748{
9749 event->ignore();
9750}
9751
9752/*!
9753 \fn void QWidget::focusInEvent(QFocusEvent *event)
9754
9755 This event handler can be reimplemented in a subclass to receive
9756 keyboard focus events (focus received) for the widget. The event
9757 is passed in the \a event parameter
9758
9759 A widget normally must setFocusPolicy() to something other than
9760 Qt::NoFocus to receive focus events. (Note that the
9761 application programmer can call setFocus() on any widget, even
9762 those that do not normally accept focus.)
9763
9764 The default implementation updates the widget (except for windows
9765 that do not specify a focusPolicy()).
9766
9767 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9768 keyReleaseEvent(), event(), QFocusEvent
9769*/
9770
9771void QWidget::focusInEvent(QFocusEvent *)
9772{
9773 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9774 update();
9775 }
9776}
9777
9778/*!
9779 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9780
9781 This event handler can be reimplemented in a subclass to receive
9782 keyboard focus events (focus lost) for the widget. The events is
9783 passed in the \a event parameter.
9784
9785 A widget normally must setFocusPolicy() to something other than
9786 Qt::NoFocus to receive focus events. (Note that the
9787 application programmer can call setFocus() on any widget, even
9788 those that do not normally accept focus.)
9789
9790 The default implementation updates the widget (except for windows
9791 that do not specify a focusPolicy()).
9792
9793 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9794 keyReleaseEvent(), event(), QFocusEvent
9795*/
9796
9797void QWidget::focusOutEvent(QFocusEvent *)
9798{
9799 if (focusPolicy() != Qt::NoFocus || !isWindow())
9800 update();
9801
9802#if !defined(QT_PLATFORM_UIKIT)
9803 // FIXME: revisit autoSIP logic, QTBUG-42906
9804 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9805 QGuiApplication::inputMethod()->hide();
9806#endif
9807}
9808
9809/*!
9810 \fn void QWidget::enterEvent(QEnterEvent *event)
9811
9812 This event handler can be reimplemented in a subclass to receive
9813 widget enter events which are passed in the \a event parameter.
9814
9815 An event is sent to the widget when the mouse cursor enters the
9816 widget.
9817
9818 \sa leaveEvent(), mouseMoveEvent(), event()
9819*/
9820
9821void QWidget::enterEvent(QEnterEvent *)
9822{
9823}
9824
9825/*!
9826 \fn void QWidget::leaveEvent(QEvent *event)
9827
9828 This event handler can be reimplemented in a subclass to receive
9829 widget leave events which are passed in the \a event parameter.
9830
9831 A leave event is sent to the widget when the mouse cursor leaves
9832 the widget.
9833
9834 \sa enterEvent(), mouseMoveEvent(), event()
9835*/
9836
9837void QWidget::leaveEvent(QEvent *)
9838{
9839}
9840
9841/*!
9842 \fn void QWidget::paintEvent(QPaintEvent *event)
9843
9844 This event handler can be reimplemented in a subclass to receive paint
9845 events passed in \a event.
9846
9847 A paint event is a request to repaint all or part of a widget. It can
9848 happen for one of the following reasons:
9849
9850 \list
9851 \li repaint() or update() was invoked,
9852 \li the widget was obscured and has now been uncovered, or
9853 \li many other reasons.
9854 \endlist
9855
9856 Many widgets can simply repaint their entire surface when asked to, but
9857 some slow widgets need to optimize by painting only the requested region:
9858 QPaintEvent::region(). This speed optimization does not change the result,
9859 as painting is clipped to that region during event processing. QListView
9860 and QTableView do this, for example.
9861
9862 Qt also tries to speed up painting by merging multiple paint events into
9863 one. When update() is called several times or the window system sends
9864 several paint events, Qt merges these events into one event with a larger
9865 region (see QRegion::united()). The repaint() function does not permit this
9866 optimization, so we suggest using update() whenever possible.
9867
9868 When the paint event occurs, the update region has normally been erased, so
9869 you are painting on the widget's background.
9870
9871 The background can be set using setBackgroundRole() and setPalette().
9872
9873 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9874 is no need to write double-buffering code in paintEvent() to avoid flicker.
9875
9876 \note Generally, you should refrain from calling update() or repaint()
9877 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9878 children inside a paintEvent() results in undefined behavior; the child may
9879 or may not get a paint event.
9880
9881 \warning If you are using a custom paint engine without Qt's backingstore,
9882 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9883 never be called; the backingstore will be used instead.
9884
9885 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9886 {Analog Clock}
9887*/
9888
9889void QWidget::paintEvent(QPaintEvent *)
9890{
9891}
9892
9893
9894/*!
9895 \fn void QWidget::moveEvent(QMoveEvent *event)
9896
9897 This event handler can be reimplemented in a subclass to receive
9898 widget move events which are passed in the \a event parameter.
9899 When the widget receives this event, it is already at the new
9900 position.
9901
9902 The old position is accessible through QMoveEvent::oldPos().
9903
9904 \sa resizeEvent(), event(), move(), QMoveEvent
9905*/
9906
9907void QWidget::moveEvent(QMoveEvent *)
9908{
9909}
9910
9911
9912/*!
9913 This event handler can be reimplemented in a subclass to receive
9914 widget resize events which are passed in the \a event parameter.
9915 When resizeEvent() is called, the widget already has its new
9916 geometry. The old size is accessible through
9917 QResizeEvent::oldSize().
9918
9919 The widget will be erased and receive a paint event immediately
9920 after processing the resize event. No drawing need be (or should
9921 be) done inside this handler.
9922
9923
9924 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9925 {Scribble Example}
9926*/
9927
9928void QWidget::resizeEvent(QResizeEvent * /* event */)
9929{
9930}
9931
9932#ifndef QT_NO_ACTION
9933/*!
9934 \fn void QWidget::actionEvent(QActionEvent *event)
9935
9936 This event handler is called with the given \a event whenever the
9937 widget's actions are changed.
9938
9939 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9940*/
9941void QWidget::actionEvent(QActionEvent *)
9942{
9943
9944}
9945#endif
9946
9947/*!
9948 This event handler is called with the given \a event when Qt receives a window
9949 close request for a top-level widget from the window system.
9950
9951 By default, the event is accepted and the widget is closed. You can reimplement
9952 this function to change the way the widget responds to window close requests.
9953 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9954 on all events.
9955
9956 Main window applications typically use reimplementations of this function to check
9957 whether the user's work has been saved and ask for permission before closing.
9958
9959 \sa event(), hide(), close(), QCloseEvent
9960*/
9961
9962void QWidget::closeEvent(QCloseEvent *event)
9963{
9964 event->accept();
9965}
9966
9967#ifndef QT_NO_CONTEXTMENU
9968/*!
9969 This event handler, for event \a event, can be reimplemented in a
9970 subclass to receive widget context menu events.
9971
9972 The handler is called when the widget's \l contextMenuPolicy is
9973 Qt::DefaultContextMenu.
9974
9975 The default implementation ignores the context event.
9976 See the \l QContextMenuEvent documentation for more details.
9977
9978 \sa event(), QContextMenuEvent, customContextMenuRequested()
9979*/
9980
9981void QWidget::contextMenuEvent(QContextMenuEvent *event)
9982{
9983 event->ignore();
9984}
9985#endif // QT_NO_CONTEXTMENU
9986
9987
9988/*!
9989 This event handler, for event \a event, can be reimplemented in a
9990 subclass to receive Input Method composition events. This handler
9991 is called when the state of the input method changes.
9992
9993 Note that when creating custom text editing widgets, the
9994 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9995 (using the setAttribute() function) in order to receive input
9996 method events.
9997
9998 The default implementation calls event->ignore(), which rejects the
9999 Input Method event. See the \l QInputMethodEvent documentation for more
10000 details.
10001
10002 \sa event(), QInputMethodEvent
10003*/
10004void QWidget::inputMethodEvent(QInputMethodEvent *event)
10005{
10006 event->ignore();
10007}
10008
10009/*!
10010 This method is only relevant for input widgets. It is used by the
10011 input method to query a set of properties of the widget to be
10012 able to support complex input method operations as support for
10013 surrounding text and reconversions.
10014
10015 \a query specifies which property is queried.
10016
10017 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
10018*/
10019QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
10020{
10021 switch(query) {
10022 case Qt::ImCursorRectangle:
10023 return QRect(width()/2, 0, 1, height());
10024 case Qt::ImFont:
10025 return font();
10026 case Qt::ImAnchorPosition:
10027 // Fallback.
10028 return inputMethodQuery(Qt::ImCursorPosition);
10029 case Qt::ImHints:
10030 return (int)inputMethodHints();
10031 case Qt::ImInputItemClipRectangle:
10032 return d_func()->clipRect();
10033 default:
10034 return QVariant();
10035 }
10036}
10037
10038/*!
10039 \property QWidget::inputMethodHints
10040 \brief What input method specific hints the widget has.
10041
10042 This is only relevant for input widgets. It is used by
10043 the input method to retrieve hints as to how the input method
10044 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
10045 is set, the input method may change its visual components to reflect
10046 that only numbers can be entered.
10047
10048 \warning Some widgets require certain flags to work as
10049 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
10050 instead of \c{w->setInputMethodHints(f)}.
10051
10052 \note The flags are only hints, so the particular input method
10053 implementation is free to ignore them. If you want to be
10054 sure that a certain type of characters are entered,
10055 you should also set a QValidator on the widget.
10056
10057 The default value is Qt::ImhNone.
10058
10059 \since 4.6
10060
10061 \sa inputMethodQuery()
10062*/
10063Qt::InputMethodHints QWidget::inputMethodHints() const
10064{
10065#if QT_CONFIG(im)
10066 const QWidgetPrivate *priv = d_func();
10067 while (priv->inheritsInputMethodHints) {
10068 priv = priv->q_func()->parentWidget()->d_func();
10069 Q_ASSERT(priv);
10070 }
10071 return priv->imHints;
10072#else
10073 return Qt::ImhNone;
10074#endif
10075}
10076
10077void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10078{
10079#ifndef QT_NO_IM
10080 Q_D(QWidget);
10081 if (d->imHints == hints)
10082 return;
10083 d->imHints = hints;
10084 if (this == QGuiApplication::focusObject())
10085 QGuiApplication::inputMethod()->update(Qt::ImHints);
10086#else
10087 Q_UNUSED(hints);
10088#endif //QT_NO_IM
10089}
10090
10091
10092#if QT_CONFIG(draganddrop)
10093
10094/*!
10095 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10096
10097 This event handler is called when a drag is in progress and the
10098 mouse enters this widget. The event is passed in the \a event parameter.
10099
10100 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10101 move events}.
10102
10103 See the \l{dnd.html}{Drag-and-drop documentation} for an
10104 overview of how to provide drag-and-drop in your application.
10105
10106 \sa QDrag, QDragEnterEvent
10107*/
10108void QWidget::dragEnterEvent(QDragEnterEvent *)
10109{
10110}
10111
10112/*!
10113 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10114
10115 This event handler is called if a drag is in progress, and when
10116 any of the following conditions occur: the cursor enters this widget,
10117 the cursor moves within this widget, or a modifier key is pressed on
10118 the keyboard while this widget has the focus. The event is passed
10119 in the \a event parameter.
10120
10121 See the \l{dnd.html}{Drag-and-drop documentation} for an
10122 overview of how to provide drag-and-drop in your application.
10123
10124 \sa QDrag, QDragMoveEvent
10125*/
10126void QWidget::dragMoveEvent(QDragMoveEvent *)
10127{
10128}
10129
10130/*!
10131 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10132
10133 This event handler is called when a drag is in progress and the
10134 mouse leaves this widget. The event is passed in the \a event
10135 parameter.
10136
10137 See the \l{dnd.html}{Drag-and-drop documentation} for an
10138 overview of how to provide drag-and-drop in your application.
10139
10140 \sa QDrag, QDragLeaveEvent
10141*/
10142void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10143{
10144}
10145
10146/*!
10147 \fn void QWidget::dropEvent(QDropEvent *event)
10148
10149 This event handler is called when the drag is dropped on this
10150 widget. The event is passed 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, QDropEvent
10156*/
10157void QWidget::dropEvent(QDropEvent *)
10158{
10159}
10160
10161#endif // QT_CONFIG(draganddrop)
10162
10163/*!
10164 \fn void QWidget::showEvent(QShowEvent *event)
10165
10166 This event handler can be reimplemented in a subclass to receive
10167 widget show events which are passed in the \a event parameter.
10168
10169 Non-spontaneous show events are sent to widgets immediately
10170 before they are shown. The spontaneous show events of windows are
10171 delivered afterwards.
10172
10173 Note: A widget receives spontaneous show and hide events when its
10174 mapping status is changed by the window system, e.g. a spontaneous
10175 hide event when the user minimizes the window, and a spontaneous
10176 show event when the window is restored again. After receiving a
10177 spontaneous hide event, a widget is still considered visible in
10178 the sense of isVisible().
10179
10180 \sa visible, event(), QShowEvent
10181*/
10182void QWidget::showEvent(QShowEvent *)
10183{
10184}
10185
10186/*!
10187 \fn void QWidget::hideEvent(QHideEvent *event)
10188
10189 This event handler can be reimplemented in a subclass to receive
10190 widget hide events. The event is passed in the \a event parameter.
10191
10192 Hide events are sent to widgets immediately after they have been
10193 hidden.
10194
10195 Note: A widget receives spontaneous show and hide events when its
10196 mapping status is changed by the window system, e.g. a spontaneous
10197 hide event when the user minimizes the window, and a spontaneous
10198 show event when the window is restored again. After receiving a
10199 spontaneous hide event, a widget is still considered visible in
10200 the sense of isVisible().
10201
10202 \sa visible, event(), QHideEvent
10203*/
10204void QWidget::hideEvent(QHideEvent *)
10205{
10206}
10207
10208/*!
10209 This special event handler can be reimplemented in a subclass to
10210 receive native platform events identified by \a eventType
10211 which are passed in the \a message parameter.
10212
10213 In your reimplementation of this function, if you want to stop the
10214 event being handled by Qt, return true and set \a result. The \a result
10215 parameter has meaning only on Windows. If you return false, this native
10216 event is passed back to Qt, which translates the event into a Qt event
10217 and sends it to the widget.
10218
10219 \note Events are only delivered to this event handler if the widget
10220 has a native window handle.
10221
10222 \note This function superseedes the event filter functions
10223 x11Event(), winEvent() and macEvent() of Qt 4.
10224
10225 \sa QAbstractNativeEventFilter
10226
10227 \table
10228 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10229 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10230 \row \li macOS \li "NSEvent" \li NSEvent * \li
10231 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10232 \endtable
10233*/
10234
10235bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10236{
10237 Q_UNUSED(eventType);
10238 Q_UNUSED(message);
10239 Q_UNUSED(result);
10240 return false;
10241}
10242
10243/*!
10244 Ensures that the widget and its children have been polished by
10245 QStyle (i.e., have a proper font and palette).
10246
10247 QWidget calls this function after it has been fully constructed
10248 but before it is shown the very first time. You can call this
10249 function if you want to ensure that the widget is polished before
10250 doing an operation, e.g., the correct font size might be needed in
10251 the widget's sizeHint() reimplementation. Note that this function
10252 \e is called from the default implementation of sizeHint().
10253
10254 Polishing is useful for final initialization that must happen after
10255 all constructors (from base classes as well as from subclasses)
10256 have been called.
10257
10258 If you need to change some settings when a widget is polished,
10259 reimplement event() and handle the QEvent::Polish event type.
10260
10261 \b{Note:} The function is declared const so that it can be called from
10262 other const functions (e.g., sizeHint()).
10263
10264 \sa event()
10265*/
10266void QWidget::ensurePolished() const
10267{
10268 Q_D(const QWidget);
10269
10270 const QMetaObject *m = metaObject();
10271 if (m == d->polished)
10272 return;
10273 d->polished = m;
10274
10275 QEvent e(QEvent::Polish);
10276 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10277
10278 // polish children after 'this'
10279 QList<QObject*> children = d->children;
10280 for (int i = 0; i < children.size(); ++i) {
10281 QObject *o = children.at(i);
10282 if (!o->isWidgetType())
10283 continue;
10284 if (QWidget *w = qobject_cast<QWidget *>(o))
10285 w->ensurePolished();
10286 }
10287
10288 if (d->parent && d->sendChildEvents) {
10289 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10290 QCoreApplication::sendEvent(d->parent, &e);
10291 }
10292}
10293
10294/*!
10295 Returns the mask currently set on a widget. If no mask is set the
10296 return value will be an empty region.
10297
10298 \sa setMask(), clearMask(), QRegion::isEmpty()
10299*/
10300QRegion QWidget::mask() const
10301{
10302 Q_D(const QWidget);
10303 return d->extra ? d->extra->mask : QRegion();
10304}
10305
10306/*!
10307 Returns the layout manager that is installed on this widget, or \nullptr
10308 if no layout manager is installed.
10309
10310 The layout manager sets the geometry of the widget's children
10311 that have been added to the layout.
10312
10313 \sa setLayout(), sizePolicy(), {Layout Management}
10314*/
10315QLayout *QWidget::layout() const
10316{
10317 return d_func()->layout;
10318}
10319
10320
10321/*!
10322 \fn void QWidget::setLayout(QLayout *layout)
10323
10324 Sets the layout manager for this widget to \a layout.
10325
10326 If there already is a layout manager installed on this widget,
10327 QWidget won't let you install another. You must first delete the
10328 existing layout manager (returned by layout()) before you can
10329 call setLayout() with the new layout.
10330
10331 If \a layout is the layout manager on a different widget, setLayout()
10332 will reparent the layout and make it the layout manager for this widget.
10333
10334 Example:
10335
10336 \snippet layouts/layouts.cpp 24
10337
10338 An alternative to calling this function is to pass this widget to
10339 the layout's constructor.
10340
10341 The QWidget will take ownership of \a layout.
10342
10343 \sa layout(), {Layout Management}
10344*/
10345
10346void QWidget::setLayout(QLayout *l)
10347{
10348 if (Q_UNLIKELY(!l)) {
10349 qWarning("QWidget::setLayout: Cannot set layout to 0");
10350 return;
10351 }
10352 if (layout()) {
10353 if (Q_UNLIKELY(layout() != l))
10354 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10355 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10356 objectName().toLocal8Bit().data());
10357 return;
10358 }
10359
10360 QObject *oldParent = l->parent();
10361 if (oldParent && oldParent != this) {
10362 if (oldParent->isWidgetType()) {
10363 // Steal the layout off a widget parent. Takes effect when
10364 // morphing laid-out container widgets in Designer.
10365 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10366 oldParentWidget->takeLayout();
10367 } else {
10368 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10369 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10370 objectName().toLocal8Bit().data());
10371 return;
10372 }
10373 }
10374
10375 Q_D(QWidget);
10376 l->d_func()->topLevel = true;
10377 d->layout = l;
10378 if (oldParent != this) {
10379 l->setParent(this);
10380 l->d_func()->reparentChildWidgets(this);
10381 l->invalidate();
10382 }
10383
10384 if (isWindow() && d->maybeTopData())
10385 d->topData()->sizeAdjusted = false;
10386}
10387
10388/*!
10389 \fn QLayout *QWidget::takeLayout()
10390
10391 Remove the layout from the widget.
10392 \since 4.5
10393*/
10394
10395QLayout *QWidget::takeLayout()
10396{
10397 Q_D(QWidget);
10398 QLayout *l = layout();
10399 if (!l)
10400 return nullptr;
10401 d->layout = nullptr;
10402 l->setParent(nullptr);
10403 return l;
10404}
10405
10406/*!
10407 \property QWidget::sizePolicy
10408 \brief the default layout behavior of the widget
10409
10410 If there is a QLayout that manages this widget's children, the
10411 size policy specified by that layout is used. If there is no such
10412 QLayout, the result of this function is used.
10413
10414 The default policy is Preferred/Preferred, which means that the
10415 widget can be freely resized, but prefers to be the size
10416 sizeHint() returns. Button-like widgets set the size policy to
10417 specify that they may stretch horizontally, but are fixed
10418 vertically. The same applies to lineedit controls (such as
10419 QLineEdit, QSpinBox or an editable QComboBox) and other
10420 horizontally orientated widgets (such as QProgressBar).
10421 QToolButton's are normally square, so they allow growth in both
10422 directions. Widgets that support different directions (such as
10423 QSlider, QScrollBar or QHeader) specify stretching in the
10424 respective direction only. Widgets that can provide scroll bars
10425 (usually subclasses of QScrollArea) tend to specify that they can
10426 use additional space, and that they can make do with less than
10427 sizeHint().
10428
10429 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10430*/
10431QSizePolicy QWidget::sizePolicy() const
10432{
10433 Q_D(const QWidget);
10434 return d->size_policy;
10435}
10436
10437void QWidget::setSizePolicy(QSizePolicy policy)
10438{
10439 Q_D(QWidget);
10440 setAttribute(Qt::WA_WState_OwnSizePolicy);
10441 if (policy == d->size_policy)
10442 return;
10443
10444 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10445 d->retainSizeWhenHiddenChanged = 1;
10446
10447 d->size_policy = policy;
10448
10449#if QT_CONFIG(graphicsview)
10450 if (const auto &extra = d->extra) {
10451 if (extra->proxyWidget)
10452 extra->proxyWidget->setSizePolicy(policy);
10453 }
10454#endif
10455
10456 updateGeometry();
10457 d->retainSizeWhenHiddenChanged = 0;
10458
10459 if (isWindow() && d->maybeTopData())
10460 d->topData()->sizeAdjusted = false;
10461}
10462
10463/*!
10464 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10465 \overload
10466
10467 Sets the size policy of the widget to \a horizontal and \a
10468 vertical, with standard stretch and no height-for-width.
10469
10470 \sa QSizePolicy::QSizePolicy()
10471*/
10472
10473/*!
10474 Returns the preferred height for this widget, given the width \a w.
10475
10476 If this widget has a layout, the default implementation returns
10477 the layout's preferred height. if there is no layout, the default
10478 implementation returns -1 indicating that the preferred height
10479 does not depend on the width.
10480*/
10481
10482int QWidget::heightForWidth(int w) const
10483{
10484 if (layout() && layout()->hasHeightForWidth())
10485 return layout()->totalHeightForWidth(w);
10486 return -1;
10487}
10488
10489
10490/*!
10491 \since 5.0
10492
10493 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10494*/
10495bool QWidget::hasHeightForWidth() const
10496{
10497 Q_D(const QWidget);
10498 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10499}
10500
10501/*!
10502 \fn QWidget *QWidget::childAt(int x, int y) const
10503
10504 Returns the visible child widget at the position (\a{x}, \a{y})
10505 in the widget's coordinate system. If there is no visible child
10506 widget at the specified position, the function returns \nullptr.
10507*/
10508
10509/*!
10510 \overload
10511
10512 Returns the visible child widget at point \a p in the widget's own
10513 coordinate system.
10514*/
10515
10516QWidget *QWidget::childAt(const QPoint &p) const
10517{
10518 return d_func()->childAt_helper(QPointF(p), false);
10519}
10520
10521/*!
10522 \overload
10523 \since 6.8
10524
10525 Returns the visible child widget at point \a p in the widget's own
10526 coordinate system.
10527*/
10528
10529QWidget *QWidget::childAt(const QPointF &p) const
10530{
10531 return d_func()->childAt_helper(p, false);
10532}
10533
10534QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10535{
10536 if (children.isEmpty())
10537 return nullptr;
10538
10539 if (!pointInsideRectAndMask(p))
10540 return nullptr;
10541 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10542}
10543
10544QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10545{
10546 for (int i = children.size() - 1; i >= 0; --i) {
10547 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10548 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10549 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10550 continue;
10551 }
10552
10553 // Map the point 'p' from parent coordinates to child coordinates.
10554 QPointF childPoint = p;
10555 childPoint -= child->data->crect.topLeft();
10556
10557 // Check if the point hits the child.
10558 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10559 continue;
10560
10561 // Do the same for the child's descendants.
10562 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10563 return w;
10564
10565 // We have found our target; namely the child at position 'p'.
10566 return child;
10567 }
10568 return nullptr;
10569}
10570
10571void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10572{
10573 Q_Q(QWidget);
10574 if (widgetItem)
10575 widgetItem->invalidateSizeCache();
10576 QWidget *parent;
10577 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10578 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10579
10580 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10581 if (parent->d_func()->layout)
10582 parent->d_func()->layout->invalidate();
10583 else if (parent->isVisible())
10584 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10585 }
10586 }
10587}
10588
10589/*!
10590 Notifies the layout system that this widget has changed and may
10591 need to change geometry.
10592
10593 Call this function if the sizeHint() or sizePolicy() have changed.
10594
10595 For explicitly hidden widgets, updateGeometry() is a no-op. The
10596 layout system will be notified as soon as the widget is shown.
10597*/
10598
10599void QWidget::updateGeometry()
10600{
10601 Q_D(QWidget);
10602 d->updateGeometry_helper(false);
10603}
10604
10605/*! \property QWidget::windowFlags
10606
10607 Window flags are a combination of a type (e.g. Qt::Dialog) and
10608 zero or more hints to the window system (e.g.
10609 Qt::FramelessWindowHint).
10610
10611 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10612 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10613 0) on the desktop. If the widget is a window and becomes a
10614 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10615 relative to its parent widget.
10616
10617 \note This function calls setParent() when changing the flags for
10618 a window, causing the widget to be hidden. You must call show() to make
10619 the widget visible again..
10620
10621 \sa windowType(), setWindowFlag(), {Window Flags Example}
10622*/
10623void QWidget::setWindowFlags(Qt::WindowFlags flags)
10624{
10625 Q_D(QWidget);
10626 d->setWindowFlags(flags);
10627}
10628
10629/*!
10630 \since 5.9
10631
10632 Sets the window flag \a flag on this widget if \a on is true;
10633 otherwise clears the flag.
10634
10635 \note This function calls setParent() when changing the flags for
10636 a window, causing the widget to be hidden. You must call show() to make
10637 the widget visible again.
10638
10639 \sa setWindowFlags(), windowFlags(), windowType()
10640*/
10641void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10642{
10643 Q_D(QWidget);
10644 if (on)
10645 d->setWindowFlags(data->window_flags | flag);
10646 else
10647 d->setWindowFlags(data->window_flags & ~flag);
10648}
10649
10650/*! \internal
10651
10652 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10653*/
10654void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10655{
10656 Q_Q(QWidget);
10657#if QT_DEPRECATED_SINCE(6, 11)
10658 QT_IGNORE_DEPRECATIONS(
10659 if (flags.testFlag(Qt::WindowType::Desktop)) {
10660 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10661 flags.setFlag(Qt::WindowType::Desktop, false);
10662 }
10663 )
10664#endif
10665
10666 if (q->data->window_flags == flags)
10667 return;
10668
10669 if ((q->data->window_flags | flags) & Qt::Window) {
10670 // the old type was a window and/or the new type is a window
10671 QPoint oldPos = q->pos();
10672 bool visible = q->isVisible();
10673 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10674 q->setParent(q->parentWidget(), flags);
10675
10676 // if both types are windows or neither of them are, we restore
10677 // the old position
10678 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10679 q->move(oldPos);
10680 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10681 adjustQuitOnCloseAttribute();
10682 } else {
10683 q->data->window_flags = flags;
10684 }
10685}
10686
10687/*!
10688 Sets the window flags for the widget to \a flags,
10689 \e without telling the window system.
10690
10691 \warning Do not call this function unless you really know what
10692 you're doing.
10693
10694 \sa setWindowFlags()
10695*/
10696void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10697{
10698 data->window_flags = flags;
10699}
10700
10701/*!
10702 \fn Qt::WindowType QWidget::windowType() const
10703
10704 Returns the window type of this widget. This is identical to
10705 windowFlags() & Qt::WindowType_Mask.
10706
10707 \sa windowFlags
10708*/
10709
10710/*!
10711 Sets the parent of the widget to \a parent, and resets the window
10712 flags. The widget is moved to position (0, 0) in its new parent.
10713
10714 If the new parent widget is in a different window, the
10715 reparented widget and its children are appended to the end of the
10716 \l{setFocusPolicy()}{tab chain} of the new parent
10717 widget, in the same internal order as before. If one of the moved
10718 widgets had keyboard focus, setParent() calls clearFocus() for that
10719 widget.
10720
10721 If the new parent widget is in the same window as the
10722 old parent, setting the parent doesn't change the tab order or
10723 keyboard focus.
10724
10725 If the "new" parent widget is the old parent widget, this function
10726 does nothing.
10727
10728 \note The widget becomes invisible as part of changing its parent,
10729 even if it was previously visible. You must call show() to make the
10730 widget visible again.
10731
10732 \warning It is very unlikely that you will ever need this
10733 function. If you have a widget that changes its content
10734 dynamically, it is far easier to use \l QStackedWidget.
10735
10736 \sa setWindowFlags()
10737*/
10738void QWidget::setParent(QWidget *parent)
10739{
10740 if (parent == parentWidget())
10741 return;
10742 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10743}
10744
10745void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10746{
10747 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10748 if (d->renderToTexture) {
10749 QEvent e(eventType);
10750 QCoreApplication::sendEvent(widget, &e);
10751 }
10752
10753 for (int i = 0; i < d->children.size(); ++i) {
10754 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10755 if (w && !w->isWindow())
10756 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10757 }
10758
10759 // Notify QWidgetWindow after we've notified all child QWidgets
10760 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10761 QEvent e(eventType);
10762 QCoreApplication::sendEvent(window, &e);
10763 }
10764}
10765
10766/*!
10767 \overload
10768
10769 This function also takes widget flags, \a f as an argument.
10770*/
10771
10772void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10773{
10774 Q_D(QWidget);
10775 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10776#ifdef QT_DEBUG
10777 const auto checkForParentChildLoops = qScopeGuard([&](){
10778 int depth = 0;
10779 auto p = parentWidget();
10780 while (p) {
10781 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10782 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10783 "this is undefined behavior",
10784 this, metaObject()->className(), qPrintable(objectName()));
10785 }
10786 p = p->parentWidget();
10787 }
10788 });
10789#endif
10790
10791 const bool resized = testAttribute(Qt::WA_Resized);
10792 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10793 QWidget *oldtlw = window();
10794 Q_ASSERT(oldtlw);
10795 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10796
10797 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10798 d->data.fstrut_dirty = true;
10799
10800 bool newParent = (parent != parentWidget());
10801
10802 if (newParent && parent) {
10803 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10804 parent->d_func()->enforceNativeChildren();
10805 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10806 setAttribute(Qt::WA_NativeWindow);
10807 }
10808
10809 if (wasCreated) {
10810 if (!testAttribute(Qt::WA_WState_Hidden)) {
10811 // Hiding the widget will set WA_WState_Hidden as well, which would
10812 // normally require the widget to be explicitly shown again to become
10813 // visible, even as a child widget. But we refine this value later in
10814 // setParent_sys(), applying WA_WState_Hidden based on whether the
10815 // widget is a top level or not.
10816 hide();
10817
10818 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10819 // when we only had QWidget::setVisible(), which is treated as an
10820 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10821 // that allows us to hide a widget without affecting ExplicitShowHide.
10822 // Though it can be argued that ExplicitShowHide should reflect the
10823 // last update of the widget's state, so if we hide the widget as a
10824 // side effect of changing parent, perhaps we _should_ reset it?
10825 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10826 }
10827 if (newParent) {
10828 QEvent e(QEvent::ParentAboutToChange);
10829 QCoreApplication::sendEvent(this, &e);
10830 }
10831 }
10832
10833 // texture-based widgets need a pre-notification when their associated top-level window changes
10834 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10835 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10836 : oldtlw->d_func()->usesRhiFlush;
10837 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10838 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10839
10840 // If we get parented into another window, children will be folded
10841 // into the new parent's focus chain, so clear focus now.
10842 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10843 focusWidget()->clearFocus();
10844
10845 d->setParent_sys(parent, f);
10846
10847 if (d->textureChildSeen && parent) {
10848 // set the textureChildSeen flag up the whole parent chain
10849 QWidgetPrivate::get(parent)->setTextureChildSeen();
10850 }
10851
10852 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10853 if (newParent)
10854 oldPaintManager->removeDirtyWidget(this);
10855 // Move the widget and all its static children from
10856 // the old backing store to the new one.
10857 oldPaintManager->moveStaticWidgets(this);
10858 }
10859
10860 d->reparentFocusWidgets(oldtlw);
10861 setAttribute(Qt::WA_Resized, resized);
10862
10863 const bool useStyleSheetPropagationInWidgetStyles =
10864 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10865
10866 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10867 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10868 // if the parent has a font set or inherited, then propagate the mask to the new child
10869 if (parent) {
10870 const auto pd = parent->d_func();
10871 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10872 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10873 }
10874 d->resolveFont();
10875 d->resolvePalette();
10876 }
10877 d->resolveLayoutDirection();
10878 d->resolveLocale();
10879
10880 // Note: GL widgets under WGL or EGL will always need a ParentChange
10881 // event to handle recreation/rebinding of the GL context, hence the
10882 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10883 // platforms).
10884 if (newParent || !wasCreated
10885#if QT_CONFIG(opengles2)
10886 || (f & Qt::MSWindowsOwnDC)
10887#endif
10888 ) {
10889 // propagate enabled updates enabled state to non-windows
10890 if (!isWindow()) {
10891 if (!testAttribute(Qt::WA_ForceDisabled))
10892 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10893 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10894 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10895 }
10896 d->inheritStyle();
10897
10898 // send and post remaining QObject events
10899 if (parent && d->sendChildEvents) {
10900 QChildEvent e(QEvent::ChildAdded, this);
10901 QCoreApplication::sendEvent(parent, &e);
10902 }
10903
10904 if (parent && d->sendChildEvents && d->polished) {
10905 QChildEvent e(QEvent::ChildPolished, this);
10906 QCoreApplication::sendEvent(parent, &e);
10907 }
10908
10909 QEvent e(QEvent::ParentChange);
10910 QCoreApplication::sendEvent(this, &e);
10911 }
10912
10913 // texture-based widgets need another event when their top-level window
10914 // changes (more precisely, has already changed at this point)
10915 if (oldWidgetUsesRhiFlush && oldtlw != window())
10916 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10917
10918 if (!wasCreated) {
10919 if (isWindow() || parentWidget()->isVisible())
10920 setAttribute(Qt::WA_WState_Hidden, true);
10921 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10922 setAttribute(Qt::WA_WState_Hidden, false);
10923 }
10924
10925 d->updateIsOpaque();
10926
10927#if QT_CONFIG(graphicsview)
10928 // Embed the widget into a proxy if the parent is embedded.
10929 // ### Doesn't handle reparenting out of an embedded widget.
10930 if (oldtlw->graphicsProxyWidget()) {
10931 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10932 ancestorProxy->d_func()->unembedSubWindow(this);
10933 }
10934 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10935 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10936 ancestorProxy->d_func()->embedSubWindow(this);
10937 }
10938#endif
10939
10940 if (d->extra && d->extra->hasWindowContainer)
10941 QWindowContainer::parentWasChanged(this);
10942
10943 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10944 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10945 // Check if the native parent now needs to switch to RHI
10946 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10947 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10948
10949 QPlatformBackingStoreRhiConfig rhiConfig;
10950 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10951
10952 // First evaluate whether the reparented widget uses RHI.
10953 // We do this as a separate step because the performance
10954 // implications of always checking the native parent are
10955 // problematic when it comes to large widget trees.
10956 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10957 // Then check whether the native parent requires RHI
10958 // as a result. It may not, if this widget is a native
10959 // window, and can handle its own RHI flushing.
10960 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10961 // Finally, check whether we need to recreate the
10962 // native parent to enable RHI flushing.
10963 auto *existingWindow = newParentWithWindow->windowHandle();
10964 auto existingSurfaceType = existingWindow->surfaceType();
10965 if (existingSurfaceType != surfaceType) {
10966 qCDebug(lcWidgetPainting)
10967 << "Recreating" << existingWindow
10968 << "with current type" << existingSurfaceType
10969 << "to support" << surfaceType;
10970 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10971 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10972 const auto positionBeforeDestroy = newParentWithWindow->pos();
10973 newParentWithWindow->destroy();
10974 newParentWithWindow->create();
10975 Q_ASSERT(newParentWithWindow->windowHandle());
10976 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10977 newParentWithWindow->move(positionBeforeDestroy);
10978 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10979 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10980 // If we don't recreate we still need to make sure the native parent
10981 // widget has a RHI config that the reparented widget can use.
10982 backingStore->handle()->createRhi(existingWindow, rhiConfig);
10983 // And that it knows it's now flushing with RHI
10984 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
10985 }
10986 }
10987 }
10988 }
10989
10990#if QT_CONFIG(accessibility)
10991 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
10992 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
10993 QAccessible::updateAccessibility(&qaEvent);
10994 }
10995#endif
10996
10997}
10998
10999void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
11000{
11001 Q_Q(QWidget);
11002
11003 Qt::WindowFlags oldFlags = data.window_flags;
11004 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
11005
11006 QScreen *targetScreen = nullptr;
11007 setWinId(0);
11008
11009 if (!newparent) {
11010 f |= Qt::Window;
11011 if (parent)
11012 targetScreen = q->parentWidget()->window()->screen();
11013 }
11014
11015 const bool destroyWindow = (
11016 // Reparenting top level to child
11017 (oldFlags & Qt::Window) && !(f & Qt::Window)
11018 // And we can dispose of the window
11019 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
11020 );
11021
11022 if (parent != newparent) {
11023 // Update object parent now, so we can resolve new parent window below
11024 QObjectPrivate::setParent_helper(newparent);
11025
11026 if (q->windowHandle())
11027 q->windowHandle()->setFlags(f);
11028
11029 // If the widget itself or any of its children have been created,
11030 // we need to reparent their QWindows as well.
11031 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11032 // But if the widget is about to be destroyed we must skip the
11033 // widget itself, and only reparent children.
11034 if (destroyWindow) {
11035 reparentWidgetWindowChildren(parentWithWindow);
11036 } else {
11037 // During reparentWidgetWindows() we need to know whether the reparented
11038 // QWindow should be a top level (with a transient parent) or not. This
11039 // widget has not updated its window flags yet, so we can't ask the widget
11040 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
11041 // the QWindow flags always reflect Qt::Window, even for child windows. And
11042 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
11043 // which we are in the process of updating. So we propagate the
11044 // new flags of the reparented window here.
11045 reparentWidgetWindows(parentWithWindow, f);
11046 }
11047 }
11048
11049 bool explicitlyHidden = isExplicitlyHidden();
11050
11051 if (destroyWindow) {
11052 if (extra && extra->hasWindowContainer)
11053 QWindowContainer::toplevelAboutToBeDestroyed(q);
11054
11055 // There shouldn't be any QWindow children left, but if there
11056 // are, re-parent them now, before we destroy.
11057 if (!q->windowHandle()->children().isEmpty()) {
11058 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11059 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
11060 for (QObject *child : q->windowHandle()->children()) {
11061 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
11062 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11063 << "before destroying" << this;
11064 childWindow->setParent(newParentWindow);
11065 }
11066 }
11067 }
11068
11069 // We have reparented any child windows of the widget we are
11070 // about to destroy to the new parent window handle, so we can
11071 // safely destroy this widget without destroying sub windows.
11072 q->destroy(true, false);
11073 }
11074
11075 adjustFlags(f, q);
11076 data.window_flags = f;
11077 q->setAttribute(Qt::WA_WState_Created, false);
11078 q->setAttribute(Qt::WA_WState_Visible, false);
11079 q->setAttribute(Qt::WA_WState_Hidden, false);
11080
11081 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11082 q->createWinId();
11083
11084 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11085 q->setAttribute(Qt::WA_WState_Hidden);
11086 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11087
11088 // move the window to the selected screen
11089 if (!newparent && targetScreen) {
11090 // only if it is already created
11091 if (q->testAttribute(Qt::WA_WState_Created))
11092 q->windowHandle()->setScreen(targetScreen);
11093 else
11094 topData()->initialScreen = targetScreen;
11095 }
11096}
11097
11098void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11099{
11100 if (QWindow *window = windowHandle()) {
11101 // Reparent this QWindow, and all QWindow children will follow
11102 if (parentWithWindow) {
11103 if (windowFlags & Qt::Window) {
11104 // Top level windows can only have transient parents,
11105 // and the transient parent must be another top level.
11106 QWidget *topLevel = parentWithWindow->window();
11107 auto *transientParent = topLevel->windowHandle();
11108 Q_ASSERT(transientParent);
11109 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11110 window->setTransientParent(transientParent);
11111 window->setParent(nullptr);
11112 } else {
11113 auto *parentWindow = parentWithWindow->windowHandle();
11114 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11115 window->setTransientParent(nullptr);
11116 window->setParent(parentWindow);
11117 }
11118 } else {
11119 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11120 window->setTransientParent(nullptr);
11121 window->setParent(nullptr);
11122 }
11123 } else {
11124 reparentWidgetWindowChildren(parentWithWindow);
11125 }
11126}
11127
11128void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11129{
11130 for (auto *child : std::as_const(children)) {
11131 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11132 auto *childPrivate = QWidgetPrivate::get(childWidget);
11133 // Child widgets with QWindows should always continue to be child
11134 // windows, so we pass on the child's current window flags here.
11135 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11136 }
11137 }
11138}
11139
11140/*!
11141 Scrolls the widget including its children \a dx pixels to the
11142 right and \a dy downward. Both \a dx and \a dy may be negative.
11143
11144 After scrolling, the widgets will receive paint events for
11145 the areas that need to be repainted. For widgets that Qt knows to
11146 be opaque, this is only the newly exposed parts.
11147 For example, if an opaque widget is scrolled 8 pixels to the left,
11148 only an 8-pixel wide stripe at the right edge needs updating.
11149
11150 Since widgets propagate the contents of their parents by default,
11151 you need to set the \l autoFillBackground property, or use
11152 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11153 a widget opaque.
11154
11155 For widgets that use contents propagation, a scroll will cause an
11156 update of the entire scroll area.
11157
11158 \sa {Transparency and Double Buffering}
11159*/
11160
11161void QWidget::scroll(int dx, int dy)
11162{
11163 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11164 return;
11165 if (dx == 0 && dy == 0)
11166 return;
11167 Q_D(QWidget);
11168#if QT_CONFIG(graphicsview)
11169 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11170 // Graphics View maintains its own dirty region as a list of rects;
11171 // until we can connect item updates directly to the view, we must
11172 // separately add a translated dirty region.
11173 for (const QRect &rect : d->dirty)
11174 proxy->update(rect.translated(dx, dy));
11175 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11176 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11177 return;
11178 }
11179#endif
11180 d->setDirtyOpaqueRegion();
11181 d->scroll_sys(dx, dy);
11182}
11183
11184void QWidgetPrivate::scroll_sys(int dx, int dy)
11185{
11186 Q_Q(QWidget);
11187 scrollChildren(dx, dy);
11188 scrollRect(q->rect(), dx, dy);
11189}
11190
11191/*!
11192 \overload
11193
11194 This version only scrolls \a r and does not move the children of
11195 the widget.
11196
11197 If \a r is empty or invalid, the result is undefined.
11198
11199 \sa QScrollArea
11200*/
11201void QWidget::scroll(int dx, int dy, const QRect &r)
11202{
11203
11204 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11205 return;
11206 if (dx == 0 && dy == 0)
11207 return;
11208 Q_D(QWidget);
11209#if QT_CONFIG(graphicsview)
11210 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11211 // Graphics View maintains its own dirty region as a list of rects;
11212 // until we can connect item updates directly to the view, we must
11213 // separately add a translated dirty region.
11214 if (!d->dirty.isEmpty()) {
11215 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11216 proxy->update(rect);
11217 }
11218 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11219 return;
11220 }
11221#endif
11222 d->scroll_sys(dx, dy, r);
11223}
11224
11225void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11226{
11227 scrollRect(r, dx, dy);
11228}
11229
11230/*!
11231 Repaints the widget directly by calling paintEvent() immediately,
11232 unless updates are disabled or the widget is hidden.
11233
11234 We suggest only using repaint() if you need an immediate repaint,
11235 for example during animation. In most circumstances update()
11236 is better, as it permits Qt to optimize for speed and minimize
11237 flicker.
11238
11239 \warning If you call repaint() in a function which may itself be
11240 called from paintEvent(), you may get infinite recursion. The
11241 update() function never causes recursion.
11242
11243 \sa update(), paintEvent(), setUpdatesEnabled()
11244*/
11245
11246void QWidget::repaint()
11247{
11248 repaint(rect());
11249}
11250
11251/*! \overload
11252
11253 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11254 the widget.
11255
11256 If \a w is negative, it is replaced with \c{width() - x}, and if
11257 \a h is negative, it is replaced width \c{height() - y}.
11258*/
11259void QWidget::repaint(int x, int y, int w, int h)
11260{
11261 if (x > data->crect.width() || y > data->crect.height())
11262 return;
11263
11264 if (w < 0)
11265 w = data->crect.width() - x;
11266 if (h < 0)
11267 h = data->crect.height() - y;
11268
11269 repaint(QRect(x, y, w, h));
11270}
11271
11272/*! \overload
11273
11274 This version repaints a rectangle \a rect inside the widget.
11275*/
11276void QWidget::repaint(const QRect &rect)
11277{
11278 Q_D(QWidget);
11279 d->repaint(rect);
11280}
11281
11282/*!
11283 \overload
11284
11285 This version repaints a region \a rgn inside the widget.
11286*/
11287void QWidget::repaint(const QRegion &rgn)
11288{
11289 Q_D(QWidget);
11290 d->repaint(rgn);
11291}
11292
11293template <typename T>
11294void QWidgetPrivate::repaint(T r)
11295{
11296 Q_Q(QWidget);
11297
11298 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11299 return;
11300
11301 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11302 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11303 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11304}
11305
11306/*!
11307 Updates the widget unless updates are disabled or the widget is
11308 hidden.
11309
11310 This function does not cause an immediate repaint; instead it
11311 schedules a paint event for processing when Qt returns to the main
11312 event loop. This permits Qt to optimize for more speed and less
11313 flicker than a call to repaint() does.
11314
11315 Calling update() several times normally results in just one
11316 paintEvent() call.
11317
11318 Qt normally erases the widget's area before the paintEvent() call.
11319 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11320 responsible for painting all its pixels with an opaque color.
11321
11322 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11323*/
11324void QWidget::update()
11325{
11326 update(rect());
11327}
11328
11329/*! \fn void QWidget::update(int x, int y, int w, int h)
11330 \overload
11331
11332 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11333 the widget.
11334*/
11335
11336/*!
11337 \overload
11338
11339 This version updates a rectangle \a rect inside the widget.
11340*/
11341void QWidget::update(const QRect &rect)
11342{
11343 Q_D(QWidget);
11344 d->update(rect);
11345}
11346
11347/*!
11348 \overload
11349
11350 This version repaints a region \a rgn inside the widget.
11351*/
11352void QWidget::update(const QRegion &rgn)
11353{
11354 Q_D(QWidget);
11355 d->update(rgn);
11356}
11357
11358template <typename T>
11359void QWidgetPrivate::update(T r)
11360{
11361 Q_Q(QWidget);
11362
11363 if (renderToTexture && !q->isVisible()) {
11364 renderToTextureReallyDirty = 1;
11365 return;
11366 }
11367
11368 if (!q->isVisible() || !q->updatesEnabled())
11369 return;
11370
11371 T clipped = r & q->rect();
11372
11373 if (clipped.isEmpty())
11374 return;
11375
11376 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11377 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11378 return;
11379 }
11380
11381 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11382 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11383 tlwExtra->repaintManager->markDirty(clipped, q);
11384}
11385
11386 /*!
11387 \internal
11388
11389 This just sets the corresponding attribute bit to 1 or 0
11390 */
11391static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11392 QWidgetPrivate *d)
11393{
11394 if (attribute < int(8*sizeof(uint))) {
11395 if (on)
11396 data->widget_attributes |= (1<<attribute);
11397 else
11398 data->widget_attributes &= ~(1<<attribute);
11399 } else {
11400 const int x = attribute - 8*sizeof(uint);
11401 const int int_off = x / (8*sizeof(uint));
11402 if (on)
11403 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11404 else
11405 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11406 }
11407}
11408
11409#ifdef Q_OS_MAC
11410void QWidgetPrivate::macUpdateSizeAttribute()
11411{
11412 Q_Q(QWidget);
11413 QEvent event(QEvent::MacSizeChange);
11414 QCoreApplication::sendEvent(q, &event);
11415 for (int i = 0; i < children.size(); ++i) {
11416 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11417 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11418 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11419 && !w->testAttribute(Qt::WA_MacSmallSize)
11420 && !w->testAttribute(Qt::WA_MacNormalSize))
11421 w->d_func()->macUpdateSizeAttribute();
11422 }
11423 resolveFont();
11424}
11425#endif
11426
11427/*!
11428 Sets the attribute \a attribute on this widget if \a on is true;
11429 otherwise clears the attribute.
11430
11431 \sa testAttribute()
11432*/
11433void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11434{
11435 Q_D(QWidget);
11436
11437 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11438 if (isWindow()) {
11439 auto *topExtra = d->topData();
11440 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11441 }
11442 }
11443
11444 if (testAttribute(attribute) == on)
11445 return;
11446
11447 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11448 "QWidget::setAttribute(WidgetAttribute, bool): "
11449 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11450#ifdef Q_OS_WIN
11451 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11452 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11453 // see ::paintEngine for details
11454 paintEngine();
11455 if (d->noPaintOnScreen)
11456 return;
11457 }
11458#endif
11459
11460 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11461 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11462 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11463 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11464 return;
11465 }
11466
11467 setAttribute_internal(attribute, on, data, d);
11468
11469 switch (attribute) {
11470
11471#if QT_CONFIG(draganddrop)
11472 case Qt::WA_AcceptDrops: {
11473 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11474 setAttribute(Qt::WA_DropSiteRegistered, true);
11475 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11476 setAttribute(Qt::WA_DropSiteRegistered, false);
11477 QEvent e(QEvent::AcceptDropsChange);
11478 QCoreApplication::sendEvent(this, &e);
11479 break;
11480 }
11481 case Qt::WA_DropSiteRegistered: {
11482 for (int i = 0; i < d->children.size(); ++i) {
11483 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11484 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11485 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11486 }
11487 break;
11488 }
11489#endif
11490
11491 case Qt::WA_NoChildEventsForParent:
11492 d->sendChildEvents = !on;
11493 break;
11494 case Qt::WA_NoChildEventsFromChildren:
11495 d->receiveChildEvents = !on;
11496 break;
11497 case Qt::WA_MacNormalSize:
11498 case Qt::WA_MacSmallSize:
11499 case Qt::WA_MacMiniSize:
11500#ifdef Q_OS_MAC
11501 {
11502 // We can only have one of these set at a time
11503 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11504 Qt::WA_MacMiniSize };
11505 for (int i = 0; i < 3; ++i) {
11506 if (MacSizes[i] != attribute)
11507 setAttribute_internal(MacSizes[i], false, data, d);
11508 }
11509 d->macUpdateSizeAttribute();
11510 }
11511#endif
11512 break;
11513 case Qt::WA_ShowModal:
11514 if (!on) {
11515 // reset modality type to NonModal when clearing WA_ShowModal
11516 data->window_modality = Qt::NonModal;
11517 } else if (data->window_modality == Qt::NonModal) {
11518 // If modality hasn't been set prior to setting WA_ShowModal, use
11519 // ApplicationModal.
11520 data->window_modality = Qt::ApplicationModal;
11521 // Some window managers do not allow us to enter modality after the
11522 // window is visible.The window must be hidden before changing the
11523 // windowModality property and then reshown.
11524 }
11525 if (testAttribute(Qt::WA_WState_Created)) {
11526 // don't call setModal_sys() before create()
11527 d->setModal_sys();
11528 }
11529 break;
11530 case Qt::WA_MouseTracking: {
11531 QEvent e(QEvent::MouseTrackingChange);
11532 QCoreApplication::sendEvent(this, &e);
11533 break; }
11534 case Qt::WA_TabletTracking: {
11535 QEvent e(QEvent::TabletTrackingChange);
11536 QCoreApplication::sendEvent(this, &e);
11537 break; }
11538 case Qt::WA_NativeWindow: {
11539 d->createTLExtra();
11540 if (on)
11541 d->createTLSysExtra();
11542#ifndef QT_NO_IM
11543 QWidget *focusWidget = d->effectiveFocusWidget();
11544 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11545 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11546 QGuiApplication::inputMethod()->commit();
11547 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11548 }
11549 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11550 parentWidget()->d_func()->enforceNativeChildren();
11551 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11552 d->createWinId();
11553 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11554 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11555 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11556 }
11557#endif //QT_NO_IM
11558 break;
11559 }
11560 case Qt::WA_PaintOnScreen:
11561 d->updateIsOpaque();
11562 Q_FALLTHROUGH();
11563 case Qt::WA_OpaquePaintEvent:
11564 d->updateIsOpaque();
11565 break;
11566 case Qt::WA_NoSystemBackground:
11567 d->updateIsOpaque();
11568 Q_FALLTHROUGH();
11569 case Qt::WA_UpdatesDisabled:
11570 d->updateSystemBackground();
11571 break;
11572 case Qt::WA_TransparentForMouseEvents:
11573 break;
11574 case Qt::WA_InputMethodEnabled: {
11575#ifndef QT_NO_IM
11576 if (QGuiApplication::focusObject() == this) {
11577 if (!on)
11578 QGuiApplication::inputMethod()->commit();
11579 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11580 }
11581#endif //QT_NO_IM
11582 break;
11583 }
11584 case Qt::WA_WindowPropagation:
11585 d->resolvePalette();
11586 d->resolveFont();
11587 d->resolveLocale();
11588 break;
11589 case Qt::WA_DontShowOnScreen: {
11590 if (on && isVisible()) {
11591 // Make sure we keep the current state and only hide the widget
11592 // from the desktop. show_sys will only update platform specific
11593 // attributes at this point.
11594 d->hide_sys();
11595 d->show_sys();
11596 }
11597 break;
11598 }
11599
11600 case Qt::WA_X11NetWmWindowTypeDesktop:
11601 case Qt::WA_X11NetWmWindowTypeDock:
11602 case Qt::WA_X11NetWmWindowTypeToolBar:
11603 case Qt::WA_X11NetWmWindowTypeMenu:
11604 case Qt::WA_X11NetWmWindowTypeUtility:
11605 case Qt::WA_X11NetWmWindowTypeSplash:
11606 case Qt::WA_X11NetWmWindowTypeDialog:
11607 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11608 case Qt::WA_X11NetWmWindowTypePopupMenu:
11609 case Qt::WA_X11NetWmWindowTypeToolTip:
11610 case Qt::WA_X11NetWmWindowTypeNotification:
11611 case Qt::WA_X11NetWmWindowTypeCombo:
11612 case Qt::WA_X11NetWmWindowTypeDND:
11613 d->setNetWmWindowTypes();
11614 break;
11615
11616 case Qt::WA_StaticContents:
11617 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11618 if (on)
11619 repaintManager->addStaticWidget(this);
11620 else
11621 repaintManager->removeStaticWidget(this);
11622 }
11623 break;
11624 case Qt::WA_TranslucentBackground:
11625 if (on)
11626 setAttribute(Qt::WA_NoSystemBackground);
11627 d->updateIsTranslucent();
11628
11629 break;
11630 case Qt::WA_AcceptTouchEvents:
11631 break;
11632 default:
11633 break;
11634 }
11635}
11636
11637/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11638
11639 Returns \c true if attribute \a attribute is set on this widget;
11640 otherwise returns \c false.
11641
11642 \sa setAttribute()
11643 */
11644bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11645{
11646 Q_D(const QWidget);
11647 const int x = attribute - 8*sizeof(uint);
11648 const int int_off = x / (8*sizeof(uint));
11649 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11650}
11651
11652/*!
11653 \property QWidget::windowOpacity
11654
11655 \brief The level of opacity for the window.
11656
11657 The valid range of opacity is from 1.0 (completely opaque) to
11658 0.0 (completely transparent).
11659
11660 By default the value of this property is 1.0.
11661
11662 This feature is available on Embedded Linux, \macos, Windows,
11663 and X11 platforms that support the Composite extension.
11664
11665 \note On X11 you need to have a composite manager running,
11666 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11667 supported by the window manager you are using.
11668
11669 \warning Changing this property from opaque to transparent might issue a
11670 paint event that needs to be processed before the window is displayed
11671 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11672 that semi-transparent windows update and resize significantly slower than
11673 opaque windows.
11674
11675 \sa setMask()
11676*/
11677qreal QWidget::windowOpacity() const
11678{
11679 Q_D(const QWidget);
11680 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11681}
11682
11683void QWidget::setWindowOpacity(qreal opacity)
11684{
11685 Q_D(QWidget);
11686 if (!isWindow())
11687 return;
11688
11689 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11690 QTLWExtra *extra = d->topData();
11691 extra->opacity = uint(opacity * 255);
11692 setAttribute(Qt::WA_WState_WindowOpacitySet);
11693 d->setWindowOpacity_sys(opacity);
11694
11695 if (!testAttribute(Qt::WA_WState_Created))
11696 return;
11697
11698#if QT_CONFIG(graphicsview)
11699 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11700 // Avoid invalidating the cache if set.
11701 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11702 proxy->update();
11703 else if (QGraphicsScene *scene = proxy->scene())
11704 scene->update(proxy->sceneBoundingRect());
11705 return;
11706 }
11707#endif
11708}
11709
11710void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11711{
11712 Q_Q(QWidget);
11713 if (q->windowHandle())
11714 q->windowHandle()->setOpacity(level);
11715}
11716
11717/*!
11718 \property QWidget::windowModified
11719 \brief whether the document shown in the window has unsaved changes
11720
11721 A modified window is a window whose content has changed but has
11722 not been saved to disk. This flag will have different effects
11723 varied by the platform. On \macos the close button will have a
11724 modified look; on other platforms, the window title will have an
11725 '*' (asterisk).
11726
11727 The window title must contain a "[*]" placeholder, which
11728 indicates where the '*' should appear. Normally, it should appear
11729 right after the file name (e.g., "document1.txt[*] - Text
11730 Editor"). If the window isn't modified, the placeholder is simply
11731 removed.
11732
11733 Note that if a widget is set as modified, all its ancestors will
11734 also be set as modified. However, if you call \c
11735 {setWindowModified(false)} on a widget, this will not propagate to
11736 its parent because other children of the parent might have been
11737 modified.
11738
11739 \sa windowTitle
11740*/
11741bool QWidget::isWindowModified() const
11742{
11743 return testAttribute(Qt::WA_WindowModified);
11744}
11745
11746void QWidget::setWindowModified(bool mod)
11747{
11748 Q_D(QWidget);
11749 setAttribute(Qt::WA_WindowModified, mod);
11750
11751 d->setWindowModified_helper();
11752
11753 QEvent e(QEvent::ModifiedChange);
11754 QCoreApplication::sendEvent(this, &e);
11755}
11756
11757void QWidgetPrivate::setWindowModified_helper()
11758{
11759 Q_Q(QWidget);
11760 QWindow *window = q->windowHandle();
11761 if (!window)
11762 return;
11763 QPlatformWindow *platformWindow = window->handle();
11764 if (!platformWindow)
11765 return;
11766 bool on = q->testAttribute(Qt::WA_WindowModified);
11767 if (!platformWindow->setWindowModified(on)) {
11768 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11769 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11770 setWindowTitle_helper(q->windowTitle());
11771 setWindowIconText_helper(q->windowIconText());
11772 }
11773}
11774
11775#if QT_CONFIG(tooltip)
11776/*!
11777 \property QWidget::toolTip
11778
11779 \brief the widget's tooltip
11780
11781 Note that by default tooltips are only shown for widgets that are
11782 children of the active window. You can change this behavior by
11783 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11784 not on the widget with the tooltip.
11785
11786 If you want to control a tooltip's behavior, you can intercept the
11787 event() function and catch the QEvent::ToolTip event (e.g., if you
11788 want to customize the area for which the tooltip should be shown).
11789
11790 By default, this property contains an empty string.
11791
11792 \sa QToolTip, statusTip, whatsThis
11793*/
11794void QWidget::setToolTip(const QString &s)
11795{
11796 Q_D(QWidget);
11797 d->toolTip = s;
11798
11799 QEvent event(QEvent::ToolTipChange);
11800 QCoreApplication::sendEvent(this, &event);
11801}
11802
11803QString QWidget::toolTip() const
11804{
11805 Q_D(const QWidget);
11806 return d->toolTip;
11807}
11808
11809/*!
11810 \property QWidget::toolTipDuration
11811 \brief the widget's tooltip duration
11812 \since 5.2
11813
11814 Specifies how long time the tooltip will be displayed, in milliseconds.
11815 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11816
11817 \sa toolTip
11818*/
11819
11820void QWidget::setToolTipDuration(int msec)
11821{
11822 Q_D(QWidget);
11823 d->toolTipDuration = msec;
11824}
11825
11826int QWidget::toolTipDuration() const
11827{
11828 Q_D(const QWidget);
11829 return d->toolTipDuration;
11830}
11831
11832#endif // QT_CONFIG(tooltip)
11833
11834
11835#if QT_CONFIG(statustip)
11836/*!
11837 \property QWidget::statusTip
11838 \brief the widget's status tip
11839
11840 By default, this property contains an empty string.
11841
11842 \sa toolTip, whatsThis
11843*/
11844void QWidget::setStatusTip(const QString &s)
11845{
11846 Q_D(QWidget);
11847 d->statusTip = s;
11848}
11849
11850QString QWidget::statusTip() const
11851{
11852 Q_D(const QWidget);
11853 return d->statusTip;
11854}
11855#endif // QT_CONFIG(statustip)
11856
11857#if QT_CONFIG(whatsthis)
11858/*!
11859 \property QWidget::whatsThis
11860
11861 \brief the widget's What's This help text.
11862
11863 By default, this property contains an empty string.
11864
11865 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11866*/
11867void QWidget::setWhatsThis(const QString &s)
11868{
11869 Q_D(QWidget);
11870 d->whatsThis = s;
11871}
11872
11873QString QWidget::whatsThis() const
11874{
11875 Q_D(const QWidget);
11876 return d->whatsThis;
11877}
11878#endif // QT_CONFIG(whatsthis)
11879
11880#if QT_CONFIG(accessibility)
11881/*!
11882 \property QWidget::accessibleName
11883
11884 \brief the widget's name as seen by assistive technologies
11885
11886 This is the primary name by which assistive technology such as screen readers
11887 announce this widget. For most widgets setting this property is not required.
11888 For example for QPushButton the button's text will be used.
11889
11890 It is important to set this property when the widget does not provide any
11891 text. For example a button that only contains an icon needs to set this
11892 property to work with screen readers.
11893 The name should be short and equivalent to the visual information conveyed
11894 by the widget.
11895
11896 This property has to be \l{Internationalization with Qt}{localized}.
11897
11898 By default, this property contains an empty string.
11899
11900 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11901*/
11902void QWidget::setAccessibleName(const QString &name)
11903{
11904 Q_D(QWidget);
11905 if (d->accessibleName == name)
11906 return;
11907
11908 d->accessibleName = name;
11909 QAccessibleEvent event(this, QAccessible::NameChanged);
11910 QAccessible::updateAccessibility(&event);
11911}
11912
11913QString QWidget::accessibleName() const
11914{
11915 Q_D(const QWidget);
11916 return d->accessibleName;
11917}
11918
11919/*!
11920 \property QWidget::accessibleDescription
11921
11922 \brief the widget's description as seen by assistive technologies
11923
11924 The accessible description of a widget should convey what a widget does.
11925 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11926 the description should give more context, such as \gui{Saves the current document}.
11927
11928 This property has to be \l{Internationalization with Qt}{localized}.
11929
11930 By default, this property contains an empty string and Qt falls back
11931 to using the tool tip to provide this information.
11932
11933 \sa QWidget::accessibleName, QAccessibleInterface::text()
11934*/
11935void QWidget::setAccessibleDescription(const QString &description)
11936{
11937 Q_D(QWidget);
11938 if (d->accessibleDescription == description)
11939 return;
11940
11941 d->accessibleDescription = description;
11942 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11943 QAccessible::updateAccessibility(&event);
11944}
11945
11946QString QWidget::accessibleDescription() const
11947{
11948 Q_D(const QWidget);
11949 return d->accessibleDescription;
11950}
11951
11952/*!
11953 \property QWidget::accessibleIdentifier
11954
11955 \brief the widget's identifier as seen by assistive technologies
11956
11957 If set, the accessible identifier of a widget can be used by assistive
11958 technologies in order to identify a specific widget, e.g. in automated
11959 tests.
11960
11961 \since 6.9
11962*/
11963void QWidget::setAccessibleIdentifier(const QString &identifier)
11964{
11965 Q_D(QWidget);
11966 if (d->accessibleIdentifier == identifier)
11967 return;
11968
11969 d->accessibleIdentifier = identifier;
11970 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11971 QAccessible::updateAccessibility(&event);
11972}
11973
11974QString QWidget::accessibleIdentifier() const
11975{
11976 Q_D(const QWidget);
11977 return d->accessibleIdentifier;
11978}
11979
11980#endif // QT_CONFIG(accessibility)
11981
11982#ifndef QT_NO_SHORTCUT
11983/*!
11984 Adds a shortcut to Qt's shortcut system that watches for the given
11985 \a key sequence in the given \a context. If the \a context is
11986 Qt::ApplicationShortcut, the shortcut applies to the application as a
11987 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11988 or to the window itself, Qt::WindowShortcut.
11989
11990 If the same \a key sequence has been grabbed by several widgets,
11991 when the \a key sequence occurs a QEvent::Shortcut event is sent
11992 to all the widgets to which it applies in a non-deterministic
11993 order, but with the ``ambiguous'' flag set to true.
11994
11995 \warning You should not normally need to use this function;
11996 instead create \l{QAction}s with the shortcut key sequences you
11997 require (if you also want equivalent menu options and toolbar
11998 buttons), or create \l{QShortcut}s if you just need key sequences.
11999 Both QAction and QShortcut handle all the event filtering for you,
12000 and provide signals which are triggered when the user triggers the
12001 key sequence, so are much easier to use than this low-level
12002 function.
12003
12004 \sa releaseShortcut(), setShortcutEnabled()
12005*/
12006int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
12007{
12008 Q_ASSERT(qApp);
12009 if (key.isEmpty())
12010 return 0;
12011 setAttribute(Qt::WA_GrabbedShortcut);
12012 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
12013}
12014
12015/*!
12016 Removes the shortcut with the given \a id from Qt's shortcut
12017 system. The widget will no longer receive QEvent::Shortcut events
12018 for the shortcut's key sequence (unless it has other shortcuts
12019 with the same key sequence).
12020
12021 \warning You should not normally need to use this function since
12022 Qt's shortcut system removes shortcuts automatically when their
12023 parent widget is destroyed. It is best to use QAction or
12024 QShortcut to handle shortcuts, since they are easier to use than
12025 this low-level function. Note also that this is an expensive
12026 operation.
12027
12028 \sa grabShortcut(), setShortcutEnabled()
12029*/
12030void QWidget::releaseShortcut(int id)
12031{
12032 Q_ASSERT(qApp);
12033 if (id)
12034 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
12035}
12036
12037/*!
12038 If \a enable is true, the shortcut with the given \a id is
12039 enabled; otherwise the shortcut is disabled.
12040
12041 \warning You should not normally need to use this function since
12042 Qt's shortcut system enables/disables shortcuts automatically as
12043 widgets become hidden/visible and gain or lose focus. It is best
12044 to use QAction or QShortcut to handle shortcuts, since they are
12045 easier to use than this low-level function.
12046
12047 \sa grabShortcut(), releaseShortcut()
12048*/
12049void QWidget::setShortcutEnabled(int id, bool enable)
12050{
12051 Q_ASSERT(qApp);
12052 if (id)
12053 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
12054}
12055
12056/*!
12057 \since 4.2
12058
12059 If \a enable is true, auto repeat of the shortcut with the
12060 given \a id is enabled; otherwise it is disabled.
12061
12062 \sa grabShortcut(), releaseShortcut()
12063*/
12064void QWidget::setShortcutAutoRepeat(int id, bool enable)
12065{
12066 Q_ASSERT(qApp);
12067 if (id)
12068 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12069}
12070#endif // QT_NO_SHORTCUT
12071
12072/*!
12073 Updates the widget's micro focus and informs input methods
12074 that the state specified by \a query has changed.
12075*/
12076void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12077{
12078 if (this == QGuiApplication::focusObject())
12079 QGuiApplication::inputMethod()->update(query);
12080}
12081
12082/*!
12083 Raises this widget to the top of the parent widget's stack.
12084
12085 After this call the widget will be visually in front of any
12086 overlapping sibling widgets.
12087
12088 \note When using activateWindow(), you can call this function to
12089 ensure that the window is stacked on top.
12090
12091 \sa lower(), stackUnder()
12092*/
12093
12094void QWidget::raise()
12095{
12096 Q_D(QWidget);
12097 if (!isWindow()) {
12098 QWidget *p = parentWidget();
12099 const int parentChildCount = p->d_func()->children.size();
12100 if (parentChildCount < 2)
12101 return;
12102 const int from = p->d_func()->children.indexOf(this);
12103 Q_ASSERT(from >= 0);
12104 // Do nothing if the widget is already in correct stacking order _and_ created.
12105 if (from != parentChildCount -1)
12106 p->d_func()->children.move(from, parentChildCount - 1);
12107 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12108 create();
12109 else if (from == parentChildCount - 1)
12110 return;
12111
12112 QRegion region(rect());
12113 d->subtractOpaqueSiblings(region);
12114 d->invalidateBackingStore(region);
12115 }
12116 if (testAttribute(Qt::WA_WState_Created))
12117 d->raise_sys();
12118
12119 if (d->extra && d->extra->hasWindowContainer)
12120 QWindowContainer::parentWasRaised(this);
12121
12122 QEvent e(QEvent::ZOrderChange);
12123 QCoreApplication::sendEvent(this, &e);
12124}
12125
12126void QWidgetPrivate::raise_sys()
12127{
12128 Q_Q(QWidget);
12129 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12130 q->windowHandle()->raise();
12131 } else if (renderToTexture) {
12132 if (QWidget *p = q->parentWidget()) {
12133 setDirtyOpaqueRegion();
12134 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12135 }
12136 }
12137}
12138
12139/*!
12140 Lowers the widget to the bottom of the parent widget's stack.
12141
12142 After this call the widget will be visually behind (and therefore
12143 obscured by) any overlapping sibling widgets.
12144
12145 \sa raise(), stackUnder()
12146*/
12147
12148void QWidget::lower()
12149{
12150 Q_D(QWidget);
12151 if (!isWindow()) {
12152 QWidget *p = parentWidget();
12153 const int parentChildCount = p->d_func()->children.size();
12154 if (parentChildCount < 2)
12155 return;
12156 const int from = p->d_func()->children.indexOf(this);
12157 Q_ASSERT(from >= 0);
12158 // Do nothing if the widget is already in correct stacking order _and_ created.
12159 if (from != 0)
12160 p->d_func()->children.move(from, 0);
12161 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12162 create();
12163 else if (from == 0)
12164 return;
12165 }
12166 if (testAttribute(Qt::WA_WState_Created))
12167 d->lower_sys();
12168
12169 if (d->extra && d->extra->hasWindowContainer)
12170 QWindowContainer::parentWasLowered(this);
12171
12172 QEvent e(QEvent::ZOrderChange);
12173 QCoreApplication::sendEvent(this, &e);
12174}
12175
12176void QWidgetPrivate::lower_sys()
12177{
12178 Q_Q(QWidget);
12179 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12180 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12181 q->windowHandle()->lower();
12182 } else if (QWidget *p = q->parentWidget()) {
12183 setDirtyOpaqueRegion();
12184 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12185 }
12186}
12187
12188/*!
12189 Places the widget under \a w in the parent widget's stack.
12190
12191 To make this work, the widget itself and \a w must be siblings.
12192
12193 \sa raise(), lower()
12194*/
12195void QWidget::stackUnder(QWidget* w)
12196{
12197 Q_D(QWidget);
12198 QWidget *p = parentWidget();
12199 if (!w || isWindow() || p != w->parentWidget() || this == w)
12200 return;
12201 if (p) {
12202 int from = p->d_func()->children.indexOf(this);
12203 int to = p->d_func()->children.indexOf(w);
12204 Q_ASSERT(from >= 0);
12205 Q_ASSERT(to >= 0);
12206 if (from < to)
12207 --to;
12208 // Do nothing if the widget is already in correct stacking order _and_ created.
12209 if (from != to)
12210 p->d_func()->children.move(from, to);
12211 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12212 create();
12213 else if (from == to)
12214 return;
12215 }
12216 if (testAttribute(Qt::WA_WState_Created))
12217 d->stackUnder_sys(w);
12218
12219 QEvent e(QEvent::ZOrderChange);
12220 QCoreApplication::sendEvent(this, &e);
12221}
12222
12223void QWidgetPrivate::stackUnder_sys(QWidget*)
12224{
12225 Q_Q(QWidget);
12226 if (QWidget *p = q->parentWidget()) {
12227 setDirtyOpaqueRegion();
12228 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12229 }
12230}
12231
12232/*!
12233 \fn bool QWidget::isTopLevel() const
12234 \deprecated
12235
12236 Use isWindow() instead.
12237*/
12238
12239/*!
12240 \fn bool QWidget::isRightToLeft() const
12241 \internal
12242*/
12243
12244/*!
12245 \fn bool QWidget::isLeftToRight() const
12246 \internal
12247*/
12248
12249/*!
12250 \macro QWIDGETSIZE_MAX
12251 \relates QWidget
12252
12253 Defines the maximum size for a QWidget object.
12254
12255 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12256 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12257
12258 \sa QWidget::setMaximumSize()
12259*/
12260
12261/*!
12262 \fn QWidget::setupUi(QWidget *widget)
12263
12264 Sets up the user interface for the specified \a widget.
12265
12266 \note This function is available with widgets that derive from user
12267 interface descriptions created using \l{uic}.
12268
12269 \sa {Using a Designer UI File in Your Application}
12270*/
12271
12272QRect QWidgetPrivate::frameStrut() const
12273{
12274 Q_Q(const QWidget);
12275 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12276 // x2 = x1 + w - 1, so w/h = 1
12277 return QRect(0, 0, 1, 1);
12278 }
12279
12280 if (data.fstrut_dirty
12281 // ### Fix properly for 4.3
12282 && q->isVisible()
12283 && q->testAttribute(Qt::WA_WState_Created))
12284 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12285
12286 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12287}
12288
12289void QWidgetPrivate::updateFrameStrut()
12290{
12291 Q_Q(QWidget);
12292 if (q->data->fstrut_dirty) {
12293 if (QTLWExtra *te = maybeTopData()) {
12294 if (te->window && te->window->handle()) {
12295 const QMargins margins = te->window->frameMargins();
12296 if (!margins.isNull()) {
12297 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12298 q->data->fstrut_dirty = false;
12299 }
12300 }
12301 }
12302 }
12303}
12304
12305#ifdef QT_KEYPAD_NAVIGATION
12306/*!
12307 \internal
12308
12309 Changes the focus from the current focusWidget to a widget in
12310 the \a direction.
12311
12312 Returns \c true, if there was a widget in that direction
12313*/
12314bool QWidgetPrivate::navigateToDirection(Direction direction)
12315{
12316 QWidget *targetWidget = widgetInNavigationDirection(direction);
12317 if (targetWidget)
12318 targetWidget->setFocus();
12319 return (targetWidget != 0);
12320}
12321
12322/*!
12323 \internal
12324
12325 Searches for a widget that is positioned in the \a direction, starting
12326 from the current focusWidget.
12327
12328 Returns the pointer to a found widget or \nullptr, if there was no widget
12329 in that direction.
12330*/
12331QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12332{
12333 const QWidget *sourceWidget = QApplication::focusWidget();
12334 if (!sourceWidget)
12335 return nullptr;
12336 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12337 const int sourceX =
12338 (direction == DirectionNorth || direction == DirectionSouth) ?
12339 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12340 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12341 const int sourceY =
12342 (direction == DirectionEast || direction == DirectionWest) ?
12343 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12344 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12345 const QPoint sourcePoint(sourceX, sourceY);
12346 const QPoint sourceCenter = sourceRect.center();
12347 const QWidget *sourceWindow = sourceWidget->window();
12348
12349 QWidget *targetWidget = nullptr;
12350 int shortestDistance = INT_MAX;
12351
12352 const auto targetCandidates = QApplication::allWidgets();
12353 for (QWidget *targetCandidate : targetCandidates) {
12354
12355 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12356
12357 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12358 // but the owner of the proxy cannot.
12359 // Additionally, empty widgets should be ignored.
12360 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12361 continue;
12362
12363 // Only navigate to a target widget that...
12364 if ( targetCandidate != sourceWidget
12365 // ...takes the focus,
12366 && targetCandidate->focusPolicy() & Qt::TabFocus
12367 // ...is above if DirectionNorth,
12368 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12369 // ...is on the right if DirectionEast,
12370 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12371 // ...is below if DirectionSouth,
12372 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12373 // ...is on the left if DirectionWest,
12374 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12375 // ...is enabled,
12376 && targetCandidate->isEnabled()
12377 // ...is visible,
12378 && targetCandidate->isVisible()
12379 // ...is in the same window,
12380 && targetCandidate->window() == sourceWindow) {
12381 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12382 const QRect &targetCandidateRect) {
12383 int dx = 0;
12384 int dy = 0;
12385 if (p.x() < r.left())
12386 dx = r.left() - p.x();
12387 else if (p.x() > r.right())
12388 dx = p.x() - r.right();
12389 if (p.y() < r.top())
12390 dy = r.top() - p.y();
12391 else if (p.y() > r.bottom())
12392 dy = p.y() - r.bottom();
12393 return dx + dy;
12394 }();
12395 if (targetCandidateDistance < shortestDistance) {
12396 shortestDistance = targetCandidateDistance;
12397 targetWidget = targetCandidate;
12398 }
12399 }
12400 }
12401 return targetWidget;
12402}
12403
12404/*!
12405 \internal
12406
12407 Tells us if it there is currently a reachable widget by keypad navigation in
12408 a certain \a orientation.
12409 If no navigation is possible, occurring key events in that \a orientation may
12410 be used to interact with the value in the focused widget, even though it
12411 currently has not the editFocus.
12412
12413 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12414*/
12415bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12416{
12417 return orientation == Qt::Horizontal?
12418 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12419 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12420 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12421 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12422}
12423/*!
12424 \internal
12425
12426 Checks, if the \a widget is inside a QTabWidget. If is is inside
12427 one, left/right key events will be used to switch between tabs in keypad
12428 navigation. If there is no QTabWidget, the horizontal key events can be used
12429to
12430 interact with the value in the focused widget, even though it currently has
12431 not the editFocus.
12432
12433 \sa QWidget::hasEditFocus()
12434*/
12435bool QWidgetPrivate::inTabWidget(QWidget *widget)
12436{
12437 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12438 if (qobject_cast<const QTabWidget*>(tabWidget))
12439 return true;
12440 return false;
12441}
12442#endif
12443
12444/*!
12445 \since 5.0
12446 \internal
12447
12448 Sets the backing store to be the \a store specified.
12449 The QWidget will take ownership of the \a store.
12450*/
12451void QWidget::setBackingStore(QBackingStore *store)
12452{
12453 // ### createWinId() ??
12454
12455 if (!isWindow())
12456 return;
12457
12458 Q_D(QWidget);
12459
12460 QTLWExtra *topData = d->topData();
12461 if (topData->backingStore == store)
12462 return;
12463
12464 QBackingStore *oldStore = topData->backingStore;
12465 delete topData->backingStore;
12466 topData->backingStore = store;
12467
12468 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12469 if (!repaintManager)
12470 return;
12471
12472 if (isWindow()) {
12473 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12474 delete repaintManager->backingStore();
12475 repaintManager->setBackingStore(store);
12476 }
12477}
12478
12479/*!
12480 \since 5.0
12481
12482 Returns the QBackingStore this widget will be drawn into.
12483*/
12484QBackingStore *QWidget::backingStore() const
12485{
12486 Q_D(const QWidget);
12487 QTLWExtra *extra = d->maybeTopData();
12488 if (extra && extra->backingStore)
12489 return extra->backingStore;
12490
12491 if (!isWindow())
12492 return window()->backingStore();
12493
12494 return nullptr;
12495}
12496
12497void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12498{
12499 if (left)
12500 *left = (int)leftLayoutItemMargin;
12501 if (top)
12502 *top = (int)topLayoutItemMargin;
12503 if (right)
12504 *right = (int)rightLayoutItemMargin;
12505 if (bottom)
12506 *bottom = (int)bottomLayoutItemMargin;
12507}
12508
12509void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12510{
12511 if (leftLayoutItemMargin == left
12512 && topLayoutItemMargin == top
12513 && rightLayoutItemMargin == right
12514 && bottomLayoutItemMargin == bottom)
12515 return;
12516
12517 Q_Q(QWidget);
12518 leftLayoutItemMargin = (signed char)left;
12519 topLayoutItemMargin = (signed char)top;
12520 rightLayoutItemMargin = (signed char)right;
12521 bottomLayoutItemMargin = (signed char)bottom;
12522 q->updateGeometry();
12523}
12524
12525void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12526{
12527 Q_Q(QWidget);
12528 QStyleOption myOpt;
12529 if (!opt) {
12530 myOpt.initFrom(q);
12531 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12532 opt = &myOpt;
12533 }
12534
12535 QRect liRect = q->style()->subElementRect(element, opt, q);
12536 if (liRect.isValid()) {
12537 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12538 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12539 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12540 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12541 } else {
12542 leftLayoutItemMargin = 0;
12543 topLayoutItemMargin = 0;
12544 rightLayoutItemMargin = 0;
12545 bottomLayoutItemMargin = 0;
12546 }
12547}
12548// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12549void QWidgetPrivate::adjustQuitOnCloseAttribute()
12550{
12551 Q_Q(QWidget);
12552
12553 if (!q->parentWidget()) {
12554 Qt::WindowType type = q->windowType();
12555 if (type == Qt::Widget || type == Qt::SubWindow)
12556 type = Qt::Window;
12557 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12558 q->setAttribute(Qt::WA_QuitOnClose, false);
12559 }
12560}
12561
12562void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12563{
12564 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12565 if (!wd->textureChildSeen)
12566 return;
12567 if (end)
12568 wd->endCompose();
12569 else
12570 wd->beginCompose();
12571 for (int i = 0; i < wd->children.size(); ++i) {
12572 w = qobject_cast<QWidget *>(wd->children.at(i));
12573 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12574 sendComposeStatus(w, end);
12575 }
12576}
12577
12578Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12579{
12580 return widget->data;
12581}
12582
12583Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12584{
12585 return widget->d_func();
12586}
12587
12588
12589#if QT_CONFIG(graphicsview)
12590/*!
12591 \since 4.5
12592
12593 Returns the proxy widget for the corresponding embedded widget in a graphics
12594 view; otherwise returns \nullptr.
12595
12596 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12597 QGraphicsScene::addWidget()
12598 */
12599QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12600{
12601 Q_D(const QWidget);
12602 if (d->extra) {
12603 return d->extra->proxyWidget;
12604 }
12605 return nullptr;
12606}
12607#endif
12608
12609#ifndef QT_NO_GESTURES
12610/*!
12611 Subscribes the widget to a given \a gesture with specific \a flags.
12612
12613 \sa ungrabGesture(), QGestureEvent
12614 \since 4.6
12615*/
12616void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12617{
12618 Q_D(QWidget);
12619 d->gestureContext.insert(gesture, flags);
12620 (void)QGestureManager::instance(); // create a gesture manager
12621}
12622
12623/*!
12624 Unsubscribes the widget from a given \a gesture type
12625
12626 \sa grabGesture(), QGestureEvent
12627 \since 4.6
12628*/
12629void QWidget::ungrabGesture(Qt::GestureType gesture)
12630{
12631 // if you modify this function, check the inlined version in ~QWidget, too
12632 Q_D(QWidget);
12633 if (d->gestureContext.remove(gesture)) {
12634 if (QGestureManager *manager = QGestureManager::instance())
12635 manager->cleanupCachedGestures(this, gesture);
12636 }
12637}
12638#endif // QT_NO_GESTURES
12639
12640/*!
12641 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12642
12643 Frees up window system resources. Destroys the widget window if \a
12644 destroyWindow is true.
12645
12646 destroy() calls itself recursively for all the child widgets,
12647 passing \a destroySubWindows for the \a destroyWindow parameter.
12648 To have more control over destruction of subwidgets, destroy
12649 subwidgets selectively first.
12650
12651 This function is usually called from the QWidget destructor.
12652*/
12653void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12654{
12655 Q_D(QWidget);
12656
12657 d->aboutToDestroy();
12658 if (!isWindow() && parentWidget())
12659 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12660 d->deactivateWidgetCleanup();
12661
12662 if ((windowType() == Qt::Popup) && qApp)
12663 qApp->d_func()->closePopup(this);
12664
12665 if (this == qApp->activeWindow())
12666 QApplicationPrivate::setActiveWindow(nullptr);
12667 if (QWidget::mouseGrabber() == this)
12668 releaseMouse();
12669 if (QWidget::keyboardGrabber() == this)
12670 releaseKeyboard();
12671
12672 setAttribute(Qt::WA_WState_Created, false);
12673
12674 if (destroySubWindows) {
12675 QObjectList childList(children());
12676 for (int i = 0; i < childList.size(); i++) {
12677 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12678 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12679 if (widget->windowHandle()) {
12680 widget->destroy();
12681 }
12682 }
12683 }
12684 }
12685 if (destroyWindow) {
12686 d->deleteTLSysExtra();
12687 } else {
12688 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12689 d->hide_sys();
12690 }
12691 }
12692
12693 d->setWinId(0);
12694}
12695
12696/*!
12697 \fn QPaintEngine *QWidget::paintEngine() const
12698
12699 Returns the widget's paint engine.
12700
12701 Note that this function should not be called explicitly by the
12702 user, since it's meant for reimplementation purposes only. The
12703 function is called by Qt internally, and the default
12704 implementation may not always return a valid pointer.
12705*/
12706QPaintEngine *QWidget::paintEngine() const
12707{
12708 qWarning("QWidget::paintEngine: Should no longer be called");
12709
12710#ifdef Q_OS_WIN
12711 // We set this bit which is checked in setAttribute for
12712 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12713 //
12714 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12715 // Windows which would mean suddenly their widgets stop working.
12716 //
12717 // 2. Users set paint on screen and subclass paintEngine() to
12718 // return 0, in which case we have a "hole" in the backingstore
12719 // allowing use of GDI or DirectX directly.
12720 //
12721 // 1 is WRONG, but to minimize silent failures, we have set this
12722 // bit to ignore the setAttribute call. 2. needs to be
12723 // supported because its our only means of embedding native
12724 // graphics stuff.
12725 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12726#endif
12727
12728 return nullptr; //##### @@@
12729}
12730
12731// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12732static inline bool canMapPosition(QWindow *window)
12733{
12734 return window->handle() && !qt_window_private(window)->resizeEventPending;
12735}
12736
12737#if QT_CONFIG(graphicsview)
12738static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12739{
12740 QGraphicsProxyWidget *result = nullptr;
12741 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12742 if (d->extra)
12743 result = d->extra->proxyWidget;
12744 return result;
12745}
12746#endif // QT_CONFIG(graphicsview)
12747
12749 QTransform transform;
12750 QWindow *window;
12751};
12752
12754{
12756 result.window = nullptr;
12757 for ( ; w ; w = w->parentWidget()) {
12758#if QT_CONFIG(graphicsview)
12759 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12760 if (const QGraphicsScene *scene = qgpw->scene()) {
12761 const QList <QGraphicsView *> views = scene->views();
12762 if (!views.isEmpty()) {
12763 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12764 result.transform *= viewP->mapToViewTransform(qgpw);
12765 w = views.first()->viewport();
12766 }
12767 }
12768 }
12769#endif // QT_CONFIG(graphicsview)
12770 QWindow *window = w->windowHandle();
12771 if (window && canMapPosition(window)) {
12772 result.window = window;
12773 break;
12774 }
12775
12776 const auto &geometry = w->geometry();
12777 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12778 if (w->isWindow())
12779 break;
12780 }
12781 return result;
12782}
12783
12784/*!
12785 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12786
12787 Translates the widget coordinate \a pos to global screen
12788 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12789 the global coordinates of the top-left pixel of the widget.
12790
12791 \sa mapFromGlobal(), mapTo(), mapToParent()
12792 \since 6.0
12793*/
12794QPointF QWidget::mapToGlobal(const QPointF &pos) const
12795{
12796 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12797 const QPointF g = t.transform.map(pos);
12798 return t.window ? t.window->mapToGlobal(g) : g;
12799}
12800
12801/*!
12802 \overload
12803*/
12804QPoint QWidget::mapToGlobal(const QPoint &pos) const
12805{
12806 return mapToGlobal(QPointF(pos)).toPoint();
12807}
12808
12809/*!
12810 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12811
12812 Translates the global screen coordinate \a pos to widget
12813 coordinates.
12814
12815 \sa mapToGlobal(), mapFrom(), mapFromParent()
12816 \since 6.0
12817*/
12818QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12819{
12820 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12821 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12822 return t.transform.inverted().map(windowLocal);
12823}
12824
12825/*!
12826 \overload
12827*/
12828QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12829{
12830 return mapFromGlobal(QPointF(pos)).toPoint();
12831}
12832
12834static bool mouseGrabWithCursor = false;
12835static QWidget *keyboardGrb = nullptr;
12836
12837static inline QWindow *grabberWindow(const QWidget *w)
12838{
12839 QWindow *window = w->windowHandle();
12840 if (!window)
12841 if (const QWidget *nativeParent = w->nativeParentWidget())
12842 window = nativeParent->windowHandle();
12843 return window;
12844}
12845
12846#ifndef QT_NO_CURSOR
12847static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12848#else
12849static void grabMouseForWidget(QWidget *widget)
12850#endif
12851{
12852 if (qt_mouseGrb)
12853 qt_mouseGrb->releaseMouse();
12854
12855 mouseGrabWithCursor = false;
12856 if (QWindow *window = grabberWindow(widget)) {
12857#ifndef QT_NO_CURSOR
12858 if (cursor) {
12859 mouseGrabWithCursor = true;
12860 QGuiApplication::setOverrideCursor(*cursor);
12861 }
12862#endif // !QT_NO_CURSOR
12863 window->setMouseGrabEnabled(true);
12864 }
12865
12866 qt_mouseGrb = widget;
12867}
12868
12870{
12871 if (qt_mouseGrb == widget) {
12872 if (QWindow *window = grabberWindow(widget)) {
12873#ifndef QT_NO_CURSOR
12874 if (mouseGrabWithCursor) {
12875 QGuiApplication::restoreOverrideCursor();
12876 mouseGrabWithCursor = false;
12877 }
12878#endif // !QT_NO_CURSOR
12879 window->setMouseGrabEnabled(false);
12880 }
12881 }
12882 qt_mouseGrb = nullptr;
12883}
12884
12885/*!
12886 \fn void QWidget::grabMouse()
12887
12888 Grabs the mouse input.
12889
12890 This widget receives all mouse events until releaseMouse() is
12891 called; other widgets get no mouse events at all. Keyboard
12892 events are not affected. Use grabKeyboard() if you want to grab
12893 that.
12894
12895 \warning Bugs in mouse-grabbing applications very often lock the
12896 terminal. Use this function with extreme caution, and consider
12897 using the \c -nograb command line option while debugging.
12898
12899 It is seldom necessary to grab the mouse when using Qt, as
12900 Qt grabs and releases it sensibly. In particular, Qt grabs the
12901 mouse when a mouse button is pressed and keeps it until the last
12902 button is released.
12903
12904 \note Only visible widgets can grab mouse input. If isVisible()
12905 returns \c false for a widget, that widget cannot call grabMouse().
12906
12907 \note On Windows, grabMouse() only works when the mouse is inside a window
12908 owned by the process.
12909 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12910
12911 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12912*/
12913void QWidget::grabMouse()
12914{
12915 grabMouseForWidget(this);
12916}
12917
12918/*!
12919 \fn void QWidget::grabMouse(const QCursor &cursor)
12920 \overload grabMouse()
12921
12922 Grabs the mouse input and changes the cursor shape.
12923
12924 The cursor will assume shape \a cursor (for as long as the mouse
12925 focus is grabbed) and this widget will be the only one to receive
12926 mouse events until releaseMouse() is called().
12927
12928 \warning Grabbing the mouse might lock the terminal.
12929
12930 \note See the note in QWidget::grabMouse().
12931
12932 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12933*/
12934#ifndef QT_NO_CURSOR
12935void QWidget::grabMouse(const QCursor &cursor)
12936{
12937 grabMouseForWidget(this, &cursor);
12938}
12939#endif
12940
12941bool QWidgetPrivate::stealMouseGrab(bool grab)
12942{
12943 // This is like a combination of grab/releaseMouse() but with error checking
12944 // and it has no effect on the result of mouseGrabber().
12945 Q_Q(QWidget);
12946 QWindow *window = grabberWindow(q);
12947 return window ? window->setMouseGrabEnabled(grab) : false;
12948}
12949
12950/*!
12951 \fn void QWidget::releaseMouse()
12952
12953 Releases the mouse grab.
12954
12955 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12956*/
12957void QWidget::releaseMouse()
12958{
12959 releaseMouseGrabOfWidget(this);
12960}
12961
12962/*!
12963 \fn void QWidget::grabKeyboard()
12964
12965 Grabs the keyboard input.
12966
12967 This widget receives all keyboard events until releaseKeyboard()
12968 is called; other widgets get no keyboard events at all. Mouse
12969 events are not affected. Use grabMouse() if you want to grab that.
12970
12971 The focus widget is not affected, except that it doesn't receive
12972 any keyboard events. setFocus() moves the focus as usual, but the
12973 new focus widget receives keyboard events only after
12974 releaseKeyboard() is called.
12975
12976 If a different widget is currently grabbing keyboard input, that
12977 widget's grab is released first.
12978
12979 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12980*/
12981void QWidget::grabKeyboard()
12982{
12983 if (keyboardGrb)
12984 keyboardGrb->releaseKeyboard();
12985 if (QWindow *window = grabberWindow(this))
12986 window->setKeyboardGrabEnabled(true);
12987 keyboardGrb = this;
12988}
12989
12990bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12991{
12992 // This is like a combination of grab/releaseKeyboard() but with error
12993 // checking and it has no effect on the result of keyboardGrabber().
12994 Q_Q(QWidget);
12995 QWindow *window = grabberWindow(q);
12996 return window ? window->setKeyboardGrabEnabled(grab) : false;
12997}
12998
12999/*!
13000 \fn void QWidget::releaseKeyboard()
13001
13002 Releases the keyboard grab.
13003
13004 \sa grabKeyboard(), grabMouse(), releaseMouse()
13005*/
13006void QWidget::releaseKeyboard()
13007{
13008 if (keyboardGrb == this) {
13009 if (QWindow *window = grabberWindow(this))
13010 window->setKeyboardGrabEnabled(false);
13011 keyboardGrb = nullptr;
13012 }
13013}
13014
13015/*!
13016 \fn QWidget *QWidget::mouseGrabber()
13017
13018 Returns the widget that is currently grabbing the mouse input.
13019
13020 If no widget in this application is currently grabbing the mouse,
13021 \nullptr is returned.
13022
13023 \sa grabMouse(), keyboardGrabber()
13024*/
13025QWidget *QWidget::mouseGrabber()
13026{
13027 return qt_mouseGrb;
13028}
13029
13030/*!
13031 \fn QWidget *QWidget::keyboardGrabber()
13032
13033 Returns the widget that is currently grabbing the keyboard input.
13034
13035 If no widget in this application is currently grabbing the
13036 keyboard, \nullptr is returned.
13037
13038 \sa grabMouse(), mouseGrabber()
13039*/
13040QWidget *QWidget::keyboardGrabber()
13041{
13042 return keyboardGrb;
13043}
13044
13045/*!
13046 \fn void QWidget::activateWindow()
13047
13048 Sets the top-level widget containing this widget to be the active
13049 window.
13050
13051 An active window is a visible top-level window that has the
13052 keyboard input focus.
13053
13054 This function performs the same operation as clicking the mouse on
13055 the title bar of a top-level window. On X11, the result depends on
13056 the Window Manager. If you want to ensure that the window is
13057 stacked on top as well you should also call raise(). Note that the
13058 window must be visible, otherwise activateWindow() has no effect.
13059
13060 On Windows, if you are calling this when the application is not
13061 currently the active one then it will not make it the active
13062 window. It will change the color of the taskbar entry to indicate
13063 that the window has changed in some way. This is because Microsoft
13064 does not allow an application to interrupt what the user is currently
13065 doing in another application.
13066
13067 \sa isActiveWindow(), window(), show()
13068*/
13069void QWidget::activateWindow()
13070{
13071 QWindow *const wnd = window()->windowHandle();
13072
13073 if (wnd)
13074 wnd->requestActivate();
13075}
13076
13077/*!
13078
13079 Internal implementation of the virtual QPaintDevice::metric()
13080 function.
13081
13082 \a m is the metric to get.
13083*/
13084int QWidget::metric(PaintDeviceMetric m) const
13085{
13086 QScreen *screen = this->screen();
13087
13088 if (!screen) {
13089 if (m == PdmDpiX || m == PdmDpiY)
13090 return 72;
13091 return QPaintDevice::metric(m);
13092 }
13093
13094 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
13095
13096 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
13097 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
13098 QWindow *window = this->window()->windowHandle();
13099 if (window)
13100 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
13101 return screen->devicePixelRatio();
13102 };
13103
13104 switch (m) {
13105 case PdmWidth:
13106 return data->crect.width();
13107 case PdmWidthMM:
13108 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
13109 case PdmHeight:
13110 return data->crect.height();
13111 case PdmHeightMM:
13112 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13113 case PdmDepth:
13114 return screen->depth();
13115 case PdmDpiX:
13116 for (const QWidget *p = this; p; p = p->parentWidget()) {
13117 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13118 return p->d_func()->extra->customDpiX;
13119 }
13120 return qRound(screen->logicalDotsPerInchX());
13121 case PdmDpiY:
13122 for (const QWidget *p = this; p; p = p->parentWidget()) {
13123 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13124 return p->d_func()->extra->customDpiY;
13125 }
13126 return qRound(screen->logicalDotsPerInchY());
13127 case PdmPhysicalDpiX:
13128 return qRound(screen->physicalDotsPerInchX());
13129 case PdmPhysicalDpiY:
13130 return qRound(screen->physicalDotsPerInchY());
13131 case PdmDevicePixelRatio:
13132 return resolveDevicePixelRatio();
13133 case PdmDevicePixelRatioScaled:
13134 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13135 case PdmDevicePixelRatioF_EncodedA:
13136 Q_FALLTHROUGH();
13137 case PdmDevicePixelRatioF_EncodedB:
13138 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
13139 default:
13140 break;
13141 }
13142 return QPaintDevice::metric(m);
13143}
13144
13145/*!
13146 Initializes the \a painter pen, background and font to the same as
13147 the given widget's. This function is called automatically when the
13148 painter is opened on a QWidget.
13149*/
13150void QWidget::initPainter(QPainter *painter) const
13151{
13152 const QPalette &pal = palette();
13153 QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
13154
13155 painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
13156 painterPrivate->state->bgBrush = pal.brush(backgroundRole());
13157 QFont f(font(), this);
13158 painterPrivate->state->deviceFont = f;
13159 painterPrivate->state->font = f;
13160
13161 painterPrivate->setEngineDirtyFlags({
13162 QPaintEngine::DirtyPen,
13163 QPaintEngine::DirtyBrush,
13164 QPaintEngine::DirtyFont,
13165 });
13166
13167 if (painterPrivate->extended)
13168 painterPrivate->extended->penChanged();
13169}
13170
13171/*!
13172 \internal
13173
13174 Do PaintDevice rendering with the specified \a offset.
13175*/
13176QPaintDevice *QWidget::redirected(QPoint *offset) const
13177{
13178 return d_func()->redirected(offset);
13179}
13180
13181/*!
13182 \internal
13183
13184 A painter that is shared among other instances of QPainter.
13185*/
13186QPainter *QWidget::sharedPainter() const
13187{
13188 // Someone sent a paint event directly to the widget
13189 if (!d_func()->redirectDev)
13190 return nullptr;
13191
13192 QPainter *sp = d_func()->sharedPainter();
13193 if (!sp || !sp->isActive())
13194 return nullptr;
13195
13196 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13197 return nullptr;
13198
13199 return sp;
13200}
13201
13202/*!
13203 \fn void QWidget::setMask(const QRegion &region)
13204 \overload
13205
13206 Causes only the parts of the widget which overlap \a region to be
13207 visible. If the region includes pixels outside the rect() of the
13208 widget, window system controls in that area may or may not be
13209 visible, depending on the platform.
13210
13211 Since QRegion allows arbitrarily complex regions to be created, widget
13212 masks can be made to suit the most unconventionally-shaped windows, and
13213 even allow widgets to be displayed with holes in them. Note that this
13214 effect can be slow if the region is particularly complex.
13215
13216 Widget masks are used to hint to the window system that the application
13217 does not want mouse events for areas outside the mask. On most systems,
13218 they also result in coarse visual clipping. To get smooth window edges, use
13219 translucent background and anti-aliased painting instead, as shown in the
13220 \l{Translucent Background} example.
13221
13222 \sa windowOpacity
13223*/
13224void QWidget::setMask(const QRegion &newMask)
13225{
13226 Q_D(QWidget);
13227
13228 d->createExtra();
13229 if (newMask == d->extra->mask)
13230 return;
13231
13232#ifndef QT_NO_BACKINGSTORE
13233 const QRegion oldMask(d->extra->mask);
13234#endif
13235
13236 d->extra->mask = newMask;
13237 d->extra->hasMask = !newMask.isEmpty();
13238
13239 if (!testAttribute(Qt::WA_WState_Created))
13240 return;
13241
13242 d->setMask_sys(newMask);
13243
13244#ifndef QT_NO_BACKINGSTORE
13245 if (!isVisible())
13246 return;
13247
13248 if (!d->extra->hasMask) {
13249 // Mask was cleared; update newly exposed area.
13250 QRegion expose(rect());
13251 expose -= oldMask;
13252 if (!expose.isEmpty()) {
13253 d->setDirtyOpaqueRegion();
13254 update(expose);
13255 }
13256 return;
13257 }
13258
13259 if (!isWindow()) {
13260 // Update newly exposed area on the parent widget.
13261 QRegion parentExpose(rect());
13262 parentExpose -= newMask;
13263 if (!parentExpose.isEmpty()) {
13264 d->setDirtyOpaqueRegion();
13265 parentExpose.translate(data->crect.topLeft());
13266 parentWidget()->update(parentExpose);
13267 }
13268
13269 // Update newly exposed area on this widget
13270 if (!oldMask.isEmpty())
13271 update(newMask - oldMask);
13272 }
13273#endif
13274}
13275
13276void QWidgetPrivate::setMask_sys(const QRegion &region)
13277{
13278 Q_Q(QWidget);
13279 if (QWindow *window = q->windowHandle())
13280 window->setMask(region);
13281}
13282
13283/*!
13284 \fn void QWidget::setMask(const QBitmap &bitmap)
13285
13286 Causes only the pixels of the widget for which \a bitmap has a
13287 corresponding 1 bit to be visible. If the region includes pixels
13288 outside the rect() of the widget, window system controls in that
13289 area may or may not be visible, depending on the platform.
13290
13291 Note that this effect can be slow if the region is particularly
13292 complex.
13293
13294 The following code shows how an image with an alpha channel can be
13295 used to generate a mask for a widget:
13296
13297 \snippet widget-mask/main.cpp 0
13298
13299 The label shown by this code is masked using the image it contains,
13300 giving the appearance that an irregularly-shaped image is being drawn
13301 directly onto the screen.
13302
13303 Masked widgets receive mouse events only on their visible
13304 portions.
13305
13306 \sa clearMask(), windowOpacity()
13307*/
13308void QWidget::setMask(const QBitmap &bitmap)
13309{
13310 setMask(QRegion(bitmap));
13311}
13312
13313/*!
13314 \fn void QWidget::clearMask()
13315
13316 Removes any mask set by setMask().
13317
13318 \sa setMask()
13319*/
13320void QWidget::clearMask()
13321{
13322 Q_D(QWidget);
13323 if (!d->extra || !d->extra->hasMask)
13324 return;
13325 setMask(QRegion());
13326}
13327
13328void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13329{
13330 Q_ASSERT(widgetAsObject->isWidgetType());
13331 Q_ASSERT(!newParent || newParent->isWidgetType());
13332 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13333 widget->setParent(static_cast<QWidget*>(newParent));
13334}
13335
13336std::string QWidgetPrivate::flagsForDumping() const
13337{
13338 Q_Q(const QWidget);
13339 std::string flags = QObjectPrivate::flagsForDumping();
13340 if (QApplication::focusWidget() == q)
13341 flags += 'F';
13342 if (q->isVisible()) {
13343 std::stringstream s;
13344 s << '<'
13345 << q->width() << 'x' << q->height()
13346 << std::showpos << q->x() << q->y()
13347 << '>';
13348 flags += s.str();
13349 } else {
13350 flags += 'I';
13351 }
13352 return flags;
13353}
13354
13355void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13356{
13357#if QT_CONFIG(xcb)
13358 Q_Q(QWidget);
13359
13360 if (!q->windowHandle())
13361 return;
13362
13363 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13364 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13365 wmWindowType |= QXcbWindow::Desktop;
13366 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13367 wmWindowType |= QXcbWindow::Dock;
13368 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13369 wmWindowType |= QXcbWindow::Toolbar;
13370 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13371 wmWindowType |= QXcbWindow::Menu;
13372 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13373 wmWindowType |= QXcbWindow::Utility;
13374 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13375 wmWindowType |= QXcbWindow::Splash;
13376 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13377 wmWindowType |= QXcbWindow::Dialog;
13378 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13379 wmWindowType |= QXcbWindow::DropDownMenu;
13380 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13381 wmWindowType |= QXcbWindow::PopupMenu;
13382 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13383 wmWindowType |= QXcbWindow::Tooltip;
13384 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13385 wmWindowType |= QXcbWindow::Notification;
13386 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13387 wmWindowType |= QXcbWindow::Combo;
13388 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13389 wmWindowType |= QXcbWindow::Dnd;
13390
13391 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13392 return;
13393
13394 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13395 xcbWindow->setWindowType(wmWindowType);
13396#else
13397 Q_UNUSED(skipIfMissing);
13398#endif
13399}
13400
13401/*!
13402 \internal
13403 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13404 Return false otherwise.
13405 */
13406bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13407{
13408 Q_Q(const QWidget);
13409 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13410 for (const auto *child : children) {
13411 if (child->focusPolicy() == policy && child->isEnabled()
13412 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13413 return true;
13414 }
13415 }
13416 return false;
13417}
13418
13419#ifndef QT_NO_DEBUG_STREAM
13420
13421namespace {
13422QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13423{
13424 const QDebugStateSaver saver(debug);
13425 debug.nospace();
13426 debug << '[';
13427 if (const QWidget *widget = attributes.widget) {
13428 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13429 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13430 int count = 0;
13431 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13432 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13433 if (count++)
13434 debug << ',';
13435 debug << me.valueToKey(a);
13436 }
13437 }
13438 }
13439 debug << ']';
13440 return debug;
13441}
13442}
13443
13444QDebug operator<<(QDebug debug, const QWidget *widget)
13445{
13446 const QDebugStateSaver saver(debug);
13447 debug.nospace();
13448 if (widget) {
13449 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13450 if (!widget->objectName().isEmpty())
13451 debug << ", name=" << widget->objectName();
13452 if (debug.verbosity() > 2) {
13453 const QRect geometry = widget->geometry();
13454 const QRect frameGeometry = widget->frameGeometry();
13455 if (widget->isVisible())
13456 debug << ", visible";
13457 if (!widget->isEnabled())
13458 debug << ", disabled";
13459 debug << ", states=" << widget->windowState()
13460 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13461 debug << ", attributes=" << WidgetAttributes{widget};
13462 if (widget->isWindow())
13463 debug << ", window";
13464 debug << ", " << geometry.width() << 'x' << geometry.height()
13465 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13466 if (frameGeometry != geometry) {
13467 const QMargins margins(geometry.x() - frameGeometry.x(),
13468 geometry.y() - frameGeometry.y(),
13469 frameGeometry.right() - geometry.right(),
13470 frameGeometry.bottom() - geometry.bottom());
13471 debug << ", margins=" << margins;
13472 }
13473 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13474 if (const WId wid = widget->internalWinId())
13475 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13476 }
13477 debug << ')';
13478 } else {
13479 debug << "QWidget(0x0)";
13480 }
13481 return debug;
13482}
13483#endif // !QT_NO_DEBUG_STREAM
13484
13485
13486// *************************** Focus abstraction ************************************
13487
13488#define FOCUS_NEXT(w) w->d_func()->focus_next
13489#define FOCUS_PREV(w) w->d_func()->focus_prev
13490
13491/*!
13492 \internal
13493 \return next or previous element in the focus chain, depending on
13494 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13495 */
13496QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13497{
13498 Q_Q(const QWidget);
13499 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13500}
13501
13502/*!
13503 \internal
13504 Removes a widget from the focus chain, respecting the flags set in \param rules.
13505 \list
13506 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13507 in the focus chain, depending on \param direction.
13508 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13509 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13510 \endlist
13511 \return \c true if the widget has been removed, otherwise \c false.
13512 */
13513bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13514{
13515 Q_Q(QWidget);
13516 if (!isFocusChainConsistent()) {
13517#ifdef QT_DEBUG
13518 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13519 qFatal() << q << "has inconsistent focus chain.";
13520#endif
13521 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13522 return false;
13523 }
13524
13525 if (!isInFocusChain()) {
13526 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13527 return false;
13528 }
13529
13530 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13531 q->focusNextPrevChild(direction == FocusDirection::Next);
13532
13535 initFocusChain();
13536 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13537 return true;
13538}
13539
13540/*!
13541 \internal
13542 Initialises the focus chain by making the widget point to itself.
13543 */
13544void QWidgetPrivate::initFocusChain()
13545{
13546 Q_Q(QWidget);
13547 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13548 FOCUS_PREV(q) = q;
13549 FOCUS_NEXT(q) = q;
13550}
13551
13552/*!
13553 \internal
13554 Reads QWidget children, which are not part of a focus chain yet.
13555 Inserts them into the focus chain before or after the widget,
13556 depending on \param direction and in the order of their creation.
13557 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13558 */
13559void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13560{
13561 Q_Q(QWidget);
13562
13563 // separate the focus chain into new (children of myself) and old (the rest)
13564 QWidget *firstOld = nullptr;
13565 QWidget *lastOld = nullptr; // last in the old list
13566 QWidget *lastNew = q; // last in the new list
13567 bool prevWasNew = true;
13568 QWidget *widget = nextPrevElementInFocusChain(direction);
13569
13570 // For efficiency, do not maintain the list invariant inside the loop.
13571 // Append items to the relevant list, and we optimize by not changing pointers,
13572 // when subsequent items are going into the same list.
13573 while (widget != q) {
13574 bool currentIsNew = q->isAncestorOf(widget);
13575 if (currentIsNew) {
13576 if (!prevWasNew) {
13577 // previous was old => append to new list
13578 FOCUS_NEXT(lastNew) = widget;
13579 FOCUS_PREV(widget) = lastNew;
13580 }
13581 lastNew = widget;
13582 } else {
13583 if (prevWasNew) {
13584 // prev was new => append to old list, if it exists
13585 if (lastOld) {
13586 FOCUS_NEXT(lastOld) = widget;
13587 FOCUS_PREV(widget) = lastOld;
13588 } else {
13589 // start the old list
13590 firstOld = widget;
13591 }
13592 }
13593 lastOld = widget;
13594 }
13595 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13596 prevWasNew = currentIsNew;
13597 }
13598
13599 // repair old list:
13600 if (firstOld) {
13601 FOCUS_NEXT(lastOld) = firstOld;
13602 FOCUS_PREV(firstOld) = lastOld;
13603 }
13604
13605 if (!q->isWindow()) {
13606 QWidget *topLevel = q->window();
13607 // insert new chain into toplevel's chain
13608 QWidget *prev = FOCUS_PREV(topLevel);
13609 FOCUS_PREV(topLevel) = lastNew;
13610 FOCUS_NEXT(prev) = q;
13611 FOCUS_PREV(q) = prev;
13612 FOCUS_NEXT(lastNew) = topLevel;
13613 } else {
13614 // repair new list
13615 FOCUS_NEXT(lastNew) = q;
13616 FOCUS_PREV(q) = lastNew;
13617 }
13618}
13619
13620/*!
13621 \internal
13622 Inserts a widget into the focus chain before or after \param position, depending on
13623 \param direction.
13624 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13625 */
13626bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13627{
13628 Q_Q(QWidget);
13629 Q_ASSERT(position);
13630 QWidget *next = FOCUS_NEXT(q);
13631 QWidget *previous = FOCUS_PREV(q);
13632
13633 switch (direction) {
13634 case FocusDirection::Next:
13635 if (previous == position) {
13636 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13637 return false;
13638 }
13639
13640 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13641
13642 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13643 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13644 FOCUS_NEXT(position) = q;
13645 FOCUS_PREV(q) = position;
13646 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13647 break;
13648
13649 case FocusDirection::Previous:
13650 if (next == position) {
13651 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13652 return false;
13653 }
13654
13655 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13656
13657 FOCUS_PREV(q) = FOCUS_PREV(position);
13658 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13659 FOCUS_PREV(position) = q;
13660 FOCUS_NEXT(q) = position;
13661 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13662 break;
13663 }
13664
13665 Q_ASSERT(isFocusChainConsistent());
13666 return true;
13667}
13668
13669/*!
13670 \internal
13671 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13672 before or after \param position, depending on \param direction.
13673 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13674 \note
13675 \param toBeInserted must be a consistent focus chain.
13676 */
13677bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13678 FocusDirection direction, QWidget *position)
13679{
13680 if (toBeInserted.isEmpty()) {
13681 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13682 return false;
13683 }
13684
13685 Q_ASSERT_X(!toBeInserted.contains(position),
13686 Q_FUNC_INFO,
13687 "Coding error: toBeInserted contains position");
13688
13689 QWidget *first = toBeInserted.constFirst();
13690 QWidget *last = toBeInserted.constLast();
13691
13692 // Call QWidget override to log accordingly
13693 if (toBeInserted.count() == 1)
13694 return first->d_func()->insertIntoFocusChain(direction, position);
13695
13696 Q_ASSERT(first != last);
13697 switch (direction) {
13698 case FocusDirection::Previous:
13699 if (FOCUS_PREV(position) == last) {
13700 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13701 << position;
13702 return false;
13703 }
13704 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13705 FOCUS_PREV(first) = FOCUS_PREV(position);
13706 FOCUS_NEXT(last) = position;
13707 FOCUS_PREV(position) = last;
13708 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13709 break;
13710 case FocusDirection::Next:
13711 if (FOCUS_PREV(position) == last) {
13712 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13713 << position;
13714 return false;
13715 }
13716 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13717 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13718 FOCUS_PREV(first) = position;
13719 FOCUS_NEXT(position) = first;
13720 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13721 break;
13722 }
13723
13724 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13725 return true;
13726}
13727
13728/*!
13729 \internal
13730 \return a QWidgetList, representing the part of the focus chain,
13731 starting with \param from and ending with \param to, in \param direction.
13732 */
13733QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13734{
13735 QWidgetList path({from});
13736 if (from == to)
13737 return path;
13738
13739 QWidget *current = from;
13740 do {
13741 switch (direction) {
13742 case QWidgetPrivate::FocusDirection::Previous:
13743 current = current->previousInFocusChain();
13744 break;
13745 case QWidgetPrivate::FocusDirection::Next:
13746 current = current->nextInFocusChain();
13747 break;
13748 }
13749 if (path.contains(current))
13750 return QWidgetList();
13751 path << current;
13752 } while (current != to);
13753
13754 return path;
13755}
13756
13757/*!
13758 \internal
13759 Removes the part from the focus chain starting with \param from and ending with \param to,
13760 in \param direction.
13761 \return removed part as a QWidgetList.
13762 */
13763QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13764 QWidget *to,
13765 FocusDirection direction)
13766{
13767 // Check if there is a path from->to in direction
13768 const QWidgetList path = focusPath(from, to , direction);
13769 if (path.isEmpty()) {
13770 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13771 return QWidgetList();
13772 }
13773
13774 QWidget *first = path.constFirst();
13775 QWidget *last = path.constLast();
13776 if (first == last) {
13777 first->d_func()->removeFromFocusChain();
13778 return QWidgetList({first});
13779 }
13780
13781 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13782 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13783 FOCUS_PREV(first) = last;
13784 FOCUS_NEXT(last) = first;
13785 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13786 return path;
13787}
13788
13789/*!
13790 \internal
13791 \return The last focus child of the widget, traversing the focus chain no further than
13792 \param noFurtherThan.
13793 */
13794QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13795{
13796 Q_Q(QWidget);
13797 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13798 // that determines the last focus child for a widget, taking proxies and compound widgets into
13799 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13800 // to a child), 'lastFocusChild' will be set to the target itself.
13801 QWidget *lastFocusChild = q;
13802
13803 QWidget *focusProxy = deepestFocusProxy();
13804 if (!focusProxy) {
13805 // QTBUG-81097: Another case is possible here. We can have a child
13806 // widget, that sets its focusProxy() to the parent (target).
13807 // An example of such widget is a QLineEdit, nested into
13808 // a QAbstractSpinBox. In this case such widget should be considered
13809 // the last focus child.
13810 for (auto *object : std::as_const(q->children())) {
13811 QWidget *w = qobject_cast<QWidget *>(object);
13812 if (w && w->focusProxy() == q) {
13813 lastFocusChild = w;
13814 break;
13815 }
13816 }
13817 } else if (q->isAncestorOf(focusProxy)) {
13818 lastFocusChild = focusProxy;
13819 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13820 focusNext != focusProxy && q->isAncestorOf(focusNext)
13821 && focusNext->window() == focusProxy->window();
13822 focusNext = focusNext->nextInFocusChain()) {
13823 if (focusNext == noFurtherThan)
13824 break;
13825 if (focusNext->focusPolicy() != Qt::NoFocus)
13826 lastFocusChild = focusNext;
13827 }
13828 }
13829 return lastFocusChild;
13830};
13831
13832/*!
13833 \internal
13834 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13835 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13836 are pointing to the widget itself.
13837
13838 \note
13839 This method doesn't check the consistency of the focus chain.
13840 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13841 isInFocusChain() will return \c true for all of those widgets, even if they represent
13842 an inconsistent focus chain.
13843 */
13844bool QWidgetPrivate::isInFocusChain() const
13845{
13846 Q_Q(const QWidget);
13847 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13848}
13849
13850/*!
13851 \internal
13852 A focus chain is consistent, when it is circular: Following the chain in either direction
13853 has to return to the beginning. This is why a newly constructed widget points to itself,
13854 when the focus chain has been initialized. A newly constructed widget is considered to have
13855 a consistent focus chain, while not being part of a focus chain.
13856
13857 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13858 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13859 It returns \c false, if one of the following is detected:
13860 \list
13861 \li nullptr found in a previous/next pointer.
13862 \li broken chain: widget A is B's previous, but B isn't A's next.
13863 \li chain isn't closed: starting at A doesn't lead back to A.
13864 \endlist
13865 It return \c true, if none of the above is observed.
13866
13867 \note
13868 The focus chain is checked only in forward direction.
13869 This is sufficient, because the check for a broken chain asserts consistent paths
13870 in both directions.
13871 */
13872bool QWidgetPrivate::isFocusChainConsistent() const
13873{
13874 Q_Q(const QWidget);
13875 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13876 if (skip)
13877 return true;
13878
13879 if (!isInFocusChain())
13880 return true;
13881
13882 const QWidget *position = q;
13883
13884 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13885 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13886 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13887 << "Previous pointing to" << FOCUS_PREV(position)
13888 << "Next pointing to" << FOCUS_NEXT(position);
13889 return false;
13890 }
13891 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13892 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13893 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13894 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13895 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13896 return false;
13897 }
13898 position = FOCUS_NEXT(position);
13899 if (position == q)
13900 return true;
13901
13902 }
13903
13904 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13905 return false;
13906}
13907
13908#undef FOCUS_NEXT
13909#undef FOCUS_PREV
13910
13911
13912QT_END_NAMESPACE
13913
13914#include "moc_qwidget.cpp"
13915#include "moc_qwidget_p.cpp"
friend class QWidgetPrivate
friend class QWidget
Definition qpainter.h:431
\inmodule QtWidgets
Definition qwidget_p.h:184
void qt_qpa_set_cursor(QWidget *w, bool force)
Definition qwidget.cpp:5077
#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:5071
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:6055
static void sendResizeEvents(QWidget *target)
Definition qwidget.cpp:5251
static void applyCursor(QWidget *w, const QCursor &c)
Definition qwidget.cpp:5065
#define FOCUS_PREV(w)
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6699
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:2343
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:102
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:2262
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:822