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 "qtooltip.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}.
563 \section1 Groups of Functions and Properties
564
565 \table
566 \header \li Context \li Functions and Properties
567
568 \row \li Window functions \li
569 show(),
570 hide(),
571 raise(),
572 lower(),
573 close().
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 QT_IGNORE_DEPRECATIONS(
945 Q_ASSERT_X(!f.testFlag(Qt::WindowType::Desktop), Q_FUNC_INFO, "Qt::WindowType::Desktop is not allowed.");
946 if (f.testFlag(Qt::WindowType::Desktop))
947 f.setFlag(Qt::WindowType::Desktop, false);
948 )
949
950 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
951
952 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
953 qFatal("QWidget: Cannot create a QWidget without QApplication");
954
955 Q_ASSERT(allWidgets);
956 if (allWidgets)
957 allWidgets->insert(q);
958
959#if QT_CONFIG(thread)
960 if (!parent) {
961 Q_ASSERT_X(QThread::isMainThread(), "QWidget",
962 "Widgets must be created in the GUI thread.");
963 }
964#endif
965
966 data.fstrut_dirty = true;
967
968 data.winid = 0;
969 data.widget_attributes = 0;
970 data.window_flags = f;
971 data.window_state = 0;
972 data.focus_policy = 0;
973 data.context_menu_policy = Qt::DefaultContextMenu;
974 data.window_modality = Qt::NonModal;
975
976 data.sizehint_forced = 0;
977 data.is_closing = false;
978 data.in_show = 0;
979 data.in_set_window_state = 0;
980 data.in_destructor = false;
981
982 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
983 if (f & Qt::MSWindowsOwnDC) {
984 mustHaveWindowHandle = 1;
985 q->setAttribute(Qt::WA_NativeWindow);
986 }
987
988 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
989 adjustQuitOnCloseAttribute();
990
991 q->setAttribute(Qt::WA_WState_Hidden);
992
993 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
994 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
995 initFocusChain();
996
997 if (parentWidget)
998 q->setParent(parentWidget, data.window_flags);
999 else {
1000 adjustFlags(data.window_flags, q);
1001 resolveLayoutDirection();
1002 // opaque system background?
1003 const QBrush &background = q->palette().brush(QPalette::Window);
1004 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1005 }
1006 data.fnt = QFont(data.fnt, q);
1007
1008 q->setAttribute(Qt::WA_PendingMoveEvent);
1009 q->setAttribute(Qt::WA_PendingResizeEvent);
1010
1011 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1012 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1013
1014 QEvent e(QEvent::Create);
1015 QCoreApplication::sendEvent(q, &e);
1016 QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1017
1018 extraPaintEngine = nullptr;
1019}
1020
1021void QWidgetPrivate::createRecursively()
1022{
1023 Q_Q(QWidget);
1024 q->create(0, true, true);
1025 for (int i = 0; i < children.size(); ++i) {
1026 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1027 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1028 child->d_func()->createRecursively();
1029 }
1030}
1031
1032QRhi *QWidgetPrivate::rhi() const
1033{
1034 Q_Q(const QWidget);
1035 if (auto *backingStore = q->backingStore()) {
1036 auto *window = windowHandle(WindowHandleMode::Closest);
1037 return backingStore->handle()->rhi(window);
1038 } else {
1039 return nullptr;
1040 }
1041}
1042
1043/*!
1044 \internal
1045 Returns the closest parent widget that has a QWindow window handle
1046
1047 \note This behavior is different from nativeParentWidget(), which
1048 returns the closest parent that has a QWindow window handle with
1049 a created QPlatformWindow, and hence native window (winId).
1050*/
1051QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
1052{
1053 Q_Q(const QWidget);
1054 QWidget *parent = q->parentWidget();
1055 while (parent && !parent->windowHandle())
1056 parent = parent->parentWidget();
1057 return parent;
1058}
1059
1060QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1061{
1062 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1063 if (QTLWExtra *x = maybeTopData()) {
1064 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1065 return x->window;
1066 }
1067 }
1068 if (mode == WindowHandleMode::Closest) {
1069 // FIXME: Use closestParentWidgetWithWindowHandle instead
1070 if (auto nativeParent = q_func()->nativeParentWidget()) {
1071 if (auto window = nativeParent->windowHandle())
1072 return window;
1073 }
1074 }
1075 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1076 if (auto topLevel = q_func()->topLevelWidget()) {
1077 if (auto window = topLevel ->windowHandle())
1078 return window;
1079 }
1080 }
1081 return nullptr;
1082}
1083
1084/*!
1085 \internal
1086
1087 Used by clients outside of widgets to get a handle to the
1088 closest QWindow without having to link to widgets.
1089*/
1090QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1091{
1092 return windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
1093}
1094
1095QScreen *QWidgetPrivate::associatedScreen() const
1096{
1097#if QT_CONFIG(graphicsview)
1098 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1099 if (nearestGraphicsProxyWidget(q_func()))
1100 return nullptr;
1101#endif
1102 if (auto window = windowHandle(WindowHandleMode::Closest))
1103 return window->screen();
1104 return nullptr;
1105}
1106
1107// finds the first rhiconfig in the hierarchy that has enable==true
1108static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1109{
1110 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1111 if (config.isEnabled()) {
1112 if (outConfig)
1113 *outConfig = config;
1114 if (outType)
1115 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1116 return true;
1117 }
1118 for (const QObject *child : w->children()) {
1119 if (const QWidget *childWidget = qobject_cast<const QWidget *>(child)) {
1120 if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType)) {
1121 static bool optOut = qEnvironmentVariableIsSet("QT_WIDGETS_NO_CHILD_RHI");
1122 // Native child widgets should not trigger RHI for its parent
1123 // hierarchy, but will still flush the native child using RHI.
1124 if (!optOut && childWidget->testAttribute(Qt::WA_NativeWindow))
1125 continue;
1126
1127 return true;
1128 }
1129 }
1130 }
1131 return false;
1132}
1133
1134bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1135{
1136 // First, check env.vars. or other means that force the usage of rhi-based
1137 // flushing with a specific graphics API. This takes precedence over what
1138 // the widgets themselves declare. This is global, applying to all
1139 // top-levels.
1140 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1141 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1142 return true;
1143 }
1144
1145 // Otherwise, check the widget hierarchy to see if there is a child (or
1146 // ourselves) that declare the need for rhi-based composition.
1147 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1148 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1149 return true;
1150 }
1151
1152 return false;
1153}
1154
1155// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1156
1157/*!
1158 Creates a new widget window.
1159
1160 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1161 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1162 QWindow wrapping a foreign window and pass it to
1163 QWidget::createWindowContainer() instead.
1164
1165 \sa createWindowContainer(), QWindow::fromWinId()
1166*/
1167
1168void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1169{
1170 Q_UNUSED(initializeWindow);
1171 Q_UNUSED(destroyOldWindow);
1172
1173 Q_D(QWidget);
1174 if (Q_UNLIKELY(window))
1175 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1176 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1177 return;
1178
1179 if (d->data.in_destructor)
1180 return;
1181
1182 Qt::WindowType type = windowType();
1183 Qt::WindowFlags &flags = data->window_flags;
1184
1185 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1186 type = Qt::Window;
1187 flags |= Qt::Window;
1188 }
1189
1190 if (QWidget *parent = parentWidget()) {
1191 if (type & Qt::Window) {
1192 if (!parent->testAttribute(Qt::WA_WState_Created))
1193 parent->createWinId();
1194 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1195 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1196 // We're about to create a native child widget that doesn't have a native parent;
1197 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1198 // attribute is set.
1199 d->createWinId();
1200 // Nothing more to do.
1201 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1202 Q_ASSERT(internalWinId());
1203 return;
1204 }
1205 }
1206
1207
1208 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1209 if (paintOnScreenEnv)
1210 setAttribute(Qt::WA_PaintOnScreen);
1211
1212 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1213 setAttribute(Qt::WA_NativeWindow);
1214
1215 if (isWindow()
1216#if QT_CONFIG(graphicsview)
1217 && !graphicsProxyWidget()
1218#endif
1219 ) {
1220 // Make top levels automatically respect safe areas by default
1221 auto *topExtra = d->maybeTopData();
1222 if (!topExtra || !topExtra->explicitContentsMarginsRespectsSafeArea) {
1223 setAttribute_internal(Qt::WA_ContentsMarginsRespectsSafeArea,
1224 true, data, d);
1225 }
1226 }
1227
1228 d->updateIsOpaque();
1229
1230 setAttribute(Qt::WA_WState_Created); // set created flag
1231 d->create();
1232
1233 // A real toplevel window needs a paint manager
1234 if (isWindow())
1235 d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1236
1237 d->setModal_sys();
1238
1239 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1240 setAttribute(Qt::WA_DropSiteRegistered, true);
1241
1242 // need to force the resting of the icon after changing parents
1243 if (testAttribute(Qt::WA_SetWindowIcon))
1244 d->setWindowIcon_sys();
1245
1246 if (isWindow() && !d->topData()->iconText.isEmpty())
1247 d->setWindowIconText_helper(d->topData()->iconText);
1248 if (isWindow() && !d->topData()->caption.isEmpty())
1249 d->setWindowTitle_helper(d->topData()->caption);
1250 if (isWindow() && !d->topData()->filePath.isEmpty())
1251 d->setWindowFilePath_helper(d->topData()->filePath);
1252 d->updateSystemBackground();
1253
1254 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1255 d->setWindowIcon_sys();
1256
1257 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1258 // as those force native window creation on their ancestors before they are shown.
1259 // If the strut is not updated, any subsequent move of the top level window before show
1260 // will cause window frame to be ignored when positioning the window.
1261 // Note that this only helps on platforms that handle window creation synchronously.
1262 d->updateFrameStrut();
1263}
1264
1266{
1267 QObjectList children = parentWidget->children();
1268 for (int i = 0; i < children.size(); i++) {
1269 if (children.at(i)->isWidgetType()) {
1270 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1271 if (childWidget) { // should not be necessary
1272 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1273 if (!childWidget->internalWinId())
1274 childWidget->winId();
1275 if (childWidget->windowHandle()) {
1276 if (childWidget->isWindow()) {
1277 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1278 } else {
1279 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1280 }
1281 }
1282 } else {
1284 }
1285 }
1286 }
1287 }
1288
1289}
1290
1291void QWidgetPrivate::create()
1292{
1293 Q_Q(QWidget);
1294
1295 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1296 return; // we only care about real toplevels
1297
1298 QWidgetWindow *win = topData()->window;
1299 // topData() ensures the extra is created but does not ensure 'window' is non-null
1300 // in case the extra was already valid.
1301 if (!win) {
1302 createTLSysExtra();
1303 Q_ASSERT(topData()->window);
1304 win = topData()->window;
1305 }
1306
1307 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1308 for (const QByteArray &propertyName : dynamicPropertyNames) {
1309 if (!qstrncmp(propertyName, "_q_platform_", 12))
1310 win->setProperty(propertyName, q->property(propertyName));
1311 }
1312
1313 Qt::WindowFlags &flags = data.window_flags;
1314
1315#if defined(QT_PLATFORM_UIKIT)
1316 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1317 flags |= Qt::ExpandedClientAreaHint;
1318#endif
1319
1320 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1321 win->setProperty("_q_showWithoutActivating", QVariant(true));
1322 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1323 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1324 win->setFlags(flags);
1325 fixPosIncludesFrame();
1326 if (q->testAttribute(Qt::WA_Moved)
1327 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1328 win->setGeometry(q->geometry());
1329 else
1330 win->resize(q->size());
1331 if (win->isTopLevel()) {
1332 QScreen *targetScreen = topData()->initialScreen;
1333 topData()->initialScreen = nullptr;
1334 if (!targetScreen)
1335 targetScreen = q->screen();
1336 win->setScreen(targetScreen);
1337 }
1338
1339 QSurfaceFormat format = win->requestedFormat();
1340 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1341 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1342 format.setAlphaBufferSize(8);
1343 }
1344 win->setFormat(format);
1345
1346 if (QWidget *nativeParent = q->nativeParentWidget()) {
1347 if (nativeParent->windowHandle()) {
1348 if (flags & Qt::Window) {
1349 win->setTransientParent(nativeParent->window()->windowHandle());
1350 win->setParent(nullptr);
1351 } else {
1352 win->setTransientParent(nullptr);
1353 win->setParent(nativeParent->windowHandle());
1354 }
1355 }
1356 }
1357
1358 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1359 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1360
1361 win->create();
1362 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1363 if (QPlatformWindow *platformWindow = win->handle())
1364 platformWindow->setFrameStrutEventsEnabled(true);
1365
1366 data.window_flags = win->flags();
1367
1368#if QT_CONFIG(xcb)
1369 if (!topData()->role.isNull()) {
1370 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1371 xcbWindow->setWindowRole(topData()->role);
1372 }
1373#endif
1374#if QT_CONFIG(wayland)
1375 if (!topData()->role.isNull()) {
1376 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(win->handle()))
1377 waylandWindow->setSessionRestoreId(topData()->role);
1378 }
1379#endif
1380
1381 QBackingStore *store = q->backingStore();
1382 usesRhiFlush = false;
1383
1384 if (!store && q->isWindow())
1385 q->setBackingStore(new QBackingStore(win));
1386
1387 QPlatformBackingStoreRhiConfig rhiConfig;
1388 usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr);
1389 if (usesRhiFlush && q->backingStore()) {
1390 // Trigger creation of support infrastructure up front,
1391 // now that we have a specific RHI configuration.
1392 q->backingStore()->handle()->createRhi(win, rhiConfig);
1393 }
1394
1395 setWindowModified_helper();
1396
1397 if (win->handle()) {
1398 WId id = win->winId();
1399 // See the QPlatformWindow::winId() documentation
1400 Q_ASSERT(id != WId(0));
1401 setWinId(id);
1402 }
1403 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1404
1405 // Check children and create windows for them if necessary
1406 q_createNativeChildrenAndSetParent(q);
1407
1408 if (extra && !extra->mask.isEmpty())
1409 setMask_sys(extra->mask);
1410
1411 if (data.crect.width() == 0 || data.crect.height() == 0) {
1412 q->setAttribute(Qt::WA_OutsideWSRange, true);
1413 } else {
1414 q->setAttribute(Qt::WA_OutsideWSRange, false);
1415 if (q->isVisible()) {
1416 // If widget is already shown, set window visible, too
1417 win->setNativeWindowVisibility(true);
1418 }
1419 }
1420}
1421
1422#ifdef Q_OS_WIN
1423static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1424#endif
1425
1426void QWidgetPrivate::createTLSysExtra()
1427{
1428 Q_Q(QWidget);
1429 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1430 extra->topextra->window = new QWidgetWindow(q);
1431 if (extra->minw || extra->minh)
1432 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1433 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1434 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1435 if (extra->topextra->opacity != 255 && q->isWindow())
1436 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1437
1438 const bool isTipLabel = q->inherits("QTipLabel");
1439 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1440#ifdef Q_OS_WIN
1441 // Pass on native parent handle for Widget embedded into Active X.
1442 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1443 if (activeXNativeParentHandle.isValid())
1444 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1445 if (isTipLabel || isAlphaWidget)
1446 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1447#endif
1448 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1449 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1450
1451 updateIsTranslucent();
1452 }
1453
1454}
1455
1456/*!
1457 Destroys the widget.
1458
1459 All this widget's children are deleted first. The application
1460 exits if this widget is the main widget.
1461*/
1462
1463QWidget::~QWidget()
1464{
1465 Q_D(QWidget);
1466 d->data.in_destructor = true;
1467
1468#if QT_CONFIG(accessibility)
1469 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive())
1470 QAccessibleCache::instance()->sendObjectDestroyedEvent(this);
1471#endif
1472
1473#if defined (QT_CHECK_STATE)
1474 if (Q_UNLIKELY(paintingActive()))
1475 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1476#endif
1477
1478#ifndef QT_NO_GESTURES
1479 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1480 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1481 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1482 manager->cleanupCachedGestures(this, *it);
1483 }
1484 d->gestureContext.clear();
1485#endif
1486
1487#ifndef QT_NO_ACTION
1488 // remove all actions from this widget
1489 for (auto action : std::as_const(d->actions)) {
1490 QActionPrivate *apriv = action->d_func();
1491 apriv->associatedObjects.removeAll(this);
1492 }
1493 d->actions.clear();
1494#endif
1495
1496#ifndef QT_NO_SHORTCUT
1497 // Remove all shortcuts grabbed by this
1498 // widget, unless application is closing
1499 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1500 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1501#endif
1502
1503 // delete layout while we still are a valid widget
1504 delete d->layout;
1505 d->layout = nullptr;
1506
1507 // Remove this from focus list
1508 d->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1509
1510 QT_TRY {
1511#if QT_CONFIG(graphicsview)
1512 const QWidget* w = this;
1513 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1514 w = w->d_func()->extra->focus_proxy;
1515 QWidget *window = w->window();
1516 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1517 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1518#endif
1519 clearFocus();
1520 } QT_CATCH(...) {
1521 // swallow this problem because we are in a destructor
1522 }
1523
1524 d->setDirtyOpaqueRegion();
1525
1526 if (isWindow() && isVisible() && internalWinId()) {
1527 QT_TRY {
1528 d->close();
1529 } QT_CATCH(...) {
1530 // if we're out of memory, at least hide the window.
1531 QT_TRY {
1532 hide();
1533 } QT_CATCH(...) {
1534 // and if that also doesn't work, then give up
1535 }
1536 }
1537 } else if (isVisible()) {
1538 qApp->d_func()->sendSyntheticEnterLeave(this);
1539 }
1540
1541 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1542 repaintManager->removeDirtyWidget(this);
1543 if (testAttribute(Qt::WA_StaticContents))
1544 repaintManager->removeStaticWidget(this);
1545 }
1546
1547 delete d->needsFlush;
1548 d->needsFlush = nullptr;
1549
1550 // The next 20 lines are duplicated from QObject, but required here
1551 // since QWidget deletes is children itself
1552 bool blocked = d->blockSig;
1553 d->blockSig = 0; // unblock signals so we always emit destroyed()
1554
1555 if (d->isSignalConnected(0)) {
1556 QT_TRY {
1557 emit destroyed(this);
1558 } QT_CATCH(...) {
1559 // all the signal/slots connections are still in place - if we don't
1560 // quit now, we will crash pretty soon.
1561 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1562 QT_RETHROW;
1563 }
1564 }
1565
1566 if (d->declarativeData) {
1567 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1568 if (QAbstractDeclarativeData::destroyed)
1569 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1570 d->declarativeData = nullptr; // don't activate again in ~QObject
1571 d->wasDeleted = false;
1572 }
1573
1574 d->blockSig = blocked;
1575
1576 if (!d->children.isEmpty())
1577 d->deleteChildren();
1578
1579 QCoreApplication::removePostedEvents(this);
1580
1581 QT_TRY {
1582 destroy(); // platform-dependent cleanup
1583 } QT_CATCH(...) {
1584 // if this fails we can't do anything about it but at least we are not allowed to throw.
1585 }
1586 --QWidgetPrivate::instanceCounter;
1587
1588 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1589 QWidgetPrivate::allWidgets->remove(this);
1590
1591 QT_TRY {
1592 QEvent e(QEvent::Destroy);
1593 QCoreApplication::sendEvent(this, &e);
1594 } QT_CATCH(const std::exception&) {
1595 // if this fails we can't do anything about it but at least we are not allowed to throw.
1596 }
1597
1598#if QT_CONFIG(graphicseffect)
1599 delete d->graphicsEffect;
1600#endif
1601 d->deleteExtra();
1602
1603 d->isWidget = false;
1604}
1605
1606int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1607int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1608
1609void QWidgetPrivate::setWinId(WId id) // set widget identifier
1610{
1611 Q_Q(QWidget);
1612 if (mapper && data.winid) {
1613 mapper->remove(data.winid);
1614 }
1615
1616 const WId oldWinId = data.winid;
1617
1618 data.winid = id;
1619 if (mapper && id) {
1620 mapper->insert(data.winid, q);
1621 }
1622
1623 if (oldWinId != id) {
1624 QEvent e(QEvent::WinIdChange);
1625 QCoreApplication::sendEvent(q, &e);
1626 }
1627}
1628
1629void QWidgetPrivate::createTLExtra()
1630{
1631 if (!extra)
1632 createExtra();
1633 if (!extra->topextra) {
1634 extra->topextra = std::make_unique<QTLWExtra>();
1635 QTLWExtra* x = extra->topextra.get();
1636 x->backingStore = nullptr;
1637 x->sharedPainter = nullptr;
1638 x->incw = x->inch = 0;
1639 x->basew = x->baseh = 0;
1640 x->frameStrut.setCoords(0, 0, 0, 0);
1641 x->normalGeometry = QRect(0,0,-1,-1);
1642 x->savedFlags = { };
1643 x->opacity = 255;
1644 x->posIncludesFrame = 0;
1645 x->sizeAdjusted = false;
1646 x->embedded = 0;
1647 x->explicitContentsMarginsRespectsSafeArea = 0;
1648 x->window = nullptr;
1649 x->initialScreen = nullptr;
1650
1651#ifdef QWIDGET_EXTRA_DEBUG
1652 static int count = 0;
1653 qDebug() << "tlextra" << ++count;
1654#endif
1655 }
1656}
1657
1658/*!
1659 \internal
1660 Creates the widget extra data.
1661*/
1662
1663void QWidgetPrivate::createExtra()
1664{
1665 if (!extra) { // if not exists
1666 extra = std::make_unique<QWExtra>();
1667 extra->glContext = nullptr;
1668#if QT_CONFIG(graphicsview)
1669 extra->proxyWidget = nullptr;
1670#endif
1671 extra->minw = 0;
1672 extra->minh = 0;
1673 extra->maxw = QWIDGETSIZE_MAX;
1674 extra->maxh = QWIDGETSIZE_MAX;
1675 extra->customDpiX = 0;
1676 extra->customDpiY = 0;
1677 extra->explicitMinSize = 0;
1678 extra->explicitMaxSize = 0;
1679 extra->autoFillBackground = 0;
1680 extra->nativeChildrenForced = 0;
1681 extra->inRenderWithPainter = 0;
1682 extra->hasWindowContainer = false;
1683 extra->hasMask = 0;
1684 createSysExtra();
1685#ifdef QWIDGET_EXTRA_DEBUG
1686 static int count = 0;
1687 qDebug() << "extra" << ++count;
1688#endif
1689 }
1690}
1691
1692void QWidgetPrivate::createSysExtra()
1693{
1694}
1695
1696/*!
1697 \internal
1698 Deletes the widget extra data.
1699*/
1700
1701void QWidgetPrivate::deleteExtra()
1702{
1703 if (extra) { // if exists
1704 deleteSysExtra();
1705#if QT_CONFIG(style_stylesheet)
1706 // dereference the stylesheet style
1707 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1708 proxy->deref();
1709#endif
1710 if (extra->topextra)
1711 deleteTLSysExtra();
1712
1713 // extra->xic destroyed in QWidget::destroy()
1714 extra.reset();
1715 }
1716}
1717
1718void QWidgetPrivate::deleteSysExtra()
1719{
1720}
1721
1722void QWidgetPrivate::deleteTLSysExtra()
1723{
1724 Q_Q(QWidget);
1725 if (extra && extra->topextra) {
1726 if (extra->hasWindowContainer)
1727 QWindowContainer::toplevelAboutToBeDestroyed(q);
1728
1729 delete extra->topextra->window;
1730 extra->topextra->window = nullptr;
1731 }
1732}
1733
1734/*
1735 Returns \c region of widgets above this which overlap with
1736 \a rect, which is in parent's coordinate system (same as crect).
1737*/
1738
1739QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1740{
1741 Q_Q(const QWidget);
1742
1743 const QWidget *w = q;
1744 QRect r = rect;
1745 QPoint p;
1746 QRegion region;
1747 while (w) {
1748 if (w->isWindow())
1749 break;
1750 QWidgetPrivate *pd = w->parentWidget()->d_func();
1751 bool above = false;
1752 for (int i = 0; i < pd->children.size(); ++i) {
1753 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1754 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1755 continue;
1756 if (!above) {
1757 above = (sibling == w);
1758 continue;
1759 }
1760
1761 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1762 if (qRectIntersects(siblingRect, r)) {
1763 const auto &siblingExtra = sibling->d_func()->extra;
1764 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1765 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1766 continue;
1767 }
1768 region += siblingRect.translated(-p);
1769 if (breakAfterFirst)
1770 break;
1771 }
1772 }
1773 w = w->parentWidget();
1774 r.translate(pd->data.crect.topLeft());
1775 p += pd->data.crect.topLeft();
1776 }
1777 return region;
1778}
1779
1780void QWidgetPrivate::syncBackingStore()
1781{
1782 if (shouldPaintOnScreen()) {
1783 paintOnScreen(dirty);
1784 dirty = QRegion();
1785 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1786 repaintManager->sync();
1787 }
1788}
1789
1790void QWidgetPrivate::syncBackingStore(const QRegion &region)
1791{
1792 if (shouldPaintOnScreen())
1793 paintOnScreen(region);
1794 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1795 repaintManager->sync(q_func(), region);
1796 }
1797}
1798
1799void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1800{
1801 if (data.in_destructor)
1802 return;
1803
1804 if (shouldDiscardSyncRequest())
1805 return;
1806
1807 Q_Q(QWidget);
1808 if (q->testAttribute(Qt::WA_StaticContents)) {
1809 if (!extra)
1810 createExtra();
1811 extra->staticContentsSize = data.crect.size();
1812 }
1813
1814 QPaintEngine *engine = q->paintEngine();
1815
1816 // QGLWidget does not support partial updates if:
1817 // 1) The context is double buffered
1818 // 2) The context is single buffered and auto-fill background is enabled.
1819 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1820 || engine->type() == QPaintEngine::OpenGL2))
1821 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1822 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1823
1824 toBePainted &= clipRect();
1825 clipToEffectiveMask(toBePainted);
1826 if (toBePainted.isEmpty())
1827 return; // Nothing to repaint.
1828
1829 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1830
1831 if (Q_UNLIKELY(q->paintingActive()))
1832 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1833}
1834
1835void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1836{
1837 Q_Q(QWidget);
1838
1839 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1840 return; // nothing we can do
1841
1842 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1843 return; // nothing to do
1844
1845 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1846 if (enable)
1847 q->update();
1848
1849 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1850 for (int i = 0; i < children.size(); ++i) {
1851 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1852 if (w && !w->isWindow() && !w->testAttribute(attribute))
1853 w->d_func()->setUpdatesEnabled_helper(enable);
1854 }
1855}
1856
1857/*!
1858 \internal
1859
1860 Propagate this widget's palette to all children, except style sheet
1861 widgets, and windows that don't enable window propagation (palettes don't
1862 normally propagate to windows).
1863*/
1864void QWidgetPrivate::propagatePaletteChange()
1865{
1866 Q_Q(QWidget);
1867 // Propagate a new inherited mask to all children.
1868#if QT_CONFIG(graphicsview)
1869 if (!q->parentWidget() && extra && extra->proxyWidget) {
1870 QGraphicsProxyWidget *p = extra->proxyWidget;
1871 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1872 } else
1873#endif // QT_CONFIG(graphicsview)
1874 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1875 inheritedPaletteResolveMask = 0;
1876 }
1877
1878 directPaletteResolveMask = data.pal.resolveMask();
1879 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1880
1881 const bool useStyleSheetPropagationInWidgetStyles =
1882 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1883
1884 QEvent pc(QEvent::PaletteChange);
1885 QCoreApplication::sendEvent(q, &pc);
1886 for (int i = 0; i < children.size(); ++i) {
1887 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1888 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1889 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1890 QWidgetPrivate *wd = w->d_func();
1891 wd->inheritedPaletteResolveMask = mask;
1892 wd->resolvePalette();
1893 }
1894 }
1895}
1896
1897/*
1898 Returns the widget's clipping rectangle.
1899*/
1900QRect QWidgetPrivate::clipRect() const
1901{
1902 Q_Q(const QWidget);
1903 const QWidget * w = q;
1904 if (!w->isVisible())
1905 return QRect();
1906 QRect r = effectiveRectFor(q->rect());
1907 int ox = 0;
1908 int oy = 0;
1909 while (w
1910 && w->isVisible()
1911 && !w->isWindow()
1912 && w->parentWidget()) {
1913 ox -= w->x();
1914 oy -= w->y();
1915 w = w->parentWidget();
1916 r &= QRect(ox, oy, w->width(), w->height());
1917 }
1918 return r;
1919}
1920
1921/*
1922 Returns the widget's clipping region (without siblings).
1923*/
1924QRegion QWidgetPrivate::clipRegion() const
1925{
1926 Q_Q(const QWidget);
1927 if (!q->isVisible())
1928 return QRegion();
1929 QRegion r(q->rect());
1930 const QWidget * w = q;
1931 const QWidget *ignoreUpTo;
1932 int ox = 0;
1933 int oy = 0;
1934 while (w
1935 && w->isVisible()
1936 && !w->isWindow()
1937 && w->parentWidget()) {
1938 ox -= w->x();
1939 oy -= w->y();
1940 ignoreUpTo = w;
1941 w = w->parentWidget();
1942 r &= QRegion(ox, oy, w->width(), w->height());
1943
1944 int i = 0;
1945 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1946 ;
1947 for ( ; i < w->d_func()->children.size(); ++i) {
1948 if (QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1949 if (sibling->isVisible() && !sibling->isWindow()) {
1950 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1951 sibling->width(), sibling->height());
1952 if (qRectIntersects(siblingRect, q->rect()))
1953 r -= QRegion(siblingRect);
1954 }
1955 }
1956 }
1957 }
1958 return r;
1959}
1960
1961void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1962{
1963// Transform the system clip region from device-independent pixels to device pixels
1964 QTransform scaleTransform;
1965 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1966
1967 paintEngine->d_func()->baseSystemClip = region;
1968 paintEngine->d_func()->setSystemTransform(scaleTransform);
1969
1970}
1971
1972#if QT_CONFIG(graphicseffect)
1973void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1974{
1975 Q_Q(QWidget);
1976 QWidget *w = q;
1977 do {
1978 if (w->graphicsEffect()) {
1979 QWidgetEffectSourcePrivate *sourced =
1980 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1981 if (!sourced->updateDueToGraphicsEffect)
1982 w->graphicsEffect()->source()->d_func()->invalidateCache();
1983 }
1984 w = w->parentWidget();
1985 } while (w);
1986}
1987#endif // QT_CONFIG(graphicseffect)
1988
1989void QWidgetPrivate::setDirtyOpaqueRegion()
1990{
1991 Q_Q(QWidget);
1992
1993 dirtyOpaqueChildren = true;
1994
1995#if QT_CONFIG(graphicseffect)
1996 invalidateGraphicsEffectsRecursively();
1997#endif // QT_CONFIG(graphicseffect)
1998
1999 if (q->isWindow())
2000 return;
2001
2002 QWidget *parent = q->parentWidget();
2003 if (!parent)
2004 return;
2005
2006 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2007 QWidgetPrivate *pd = parent->d_func();
2008 if (!pd->dirtyOpaqueChildren)
2009 pd->setDirtyOpaqueRegion();
2010}
2011
2012const QRegion &QWidgetPrivate::getOpaqueChildren() const
2013{
2014 if (!dirtyOpaqueChildren)
2015 return opaqueChildren;
2016
2017 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2018 that->opaqueChildren = QRegion();
2019
2020 for (int i = 0; i < children.size(); ++i) {
2021 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2022 if (!child || !child->isVisible() || child->isWindow())
2023 continue;
2024
2025 const QPoint offset = child->geometry().topLeft();
2026 QWidgetPrivate *childd = child->d_func();
2027 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2028 if (childd->extra && childd->extra->hasMask)
2029 r &= childd->extra->mask;
2030 if (r.isEmpty())
2031 continue;
2032 r.translate(offset);
2033 that->opaqueChildren += r;
2034 }
2035
2036 that->opaqueChildren &= q_func()->rect();
2037 that->dirtyOpaqueChildren = false;
2038
2039 return that->opaqueChildren;
2040}
2041
2042void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2043{
2044 if (children.isEmpty() || clipRect.isEmpty())
2045 return;
2046
2047 const QRegion &r = getOpaqueChildren();
2048 if (!r.isEmpty())
2049 source -= (r & clipRect);
2050}
2051
2052//subtract any relatives that are higher up than me --- this is too expensive !!!
2053void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2054 bool alsoNonOpaque) const
2055{
2056 Q_Q(const QWidget);
2057 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2058 if (disableSubtractOpaqueSiblings || q->isWindow())
2059 return;
2060
2061 QRect clipBoundingRect;
2062 bool dirtyClipBoundingRect = true;
2063
2064 QRegion parentClip;
2065 bool dirtyParentClip = true;
2066
2067 QPoint parentOffset = data.crect.topLeft();
2068
2069 const QWidget *w = q;
2070
2071 while (w) {
2072 if (w->isWindow())
2073 break;
2074 QWidgetPrivate *pd = w->parentWidget()->d_func();
2075 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2076 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2077 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2078 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2079 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2080 continue;
2081
2082 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2083 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2084 continue;
2085
2086 if (dirtyClipBoundingRect) {
2087 clipBoundingRect = sourceRegion.boundingRect();
2088 dirtyClipBoundingRect = false;
2089 }
2090
2091 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2092 continue;
2093
2094 if (dirtyParentClip) {
2095 parentClip = sourceRegion.translated(parentOffset);
2096 dirtyParentClip = false;
2097 }
2098
2099 const QPoint siblingPos(sibling->data->crect.topLeft());
2100 const QRect siblingClipRect(sibling->d_func()->clipRect());
2101 QRegion siblingDirty(parentClip);
2102 siblingDirty &= (siblingClipRect.translated(siblingPos));
2103 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2104 && !sibling->d_func()->graphicsEffect;
2105 if (hasMask)
2106 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2107 if (siblingDirty.isEmpty())
2108 continue;
2109
2110 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2111 if (hasMask) {
2112 siblingDirty.translate(-parentOffset);
2113 sourceRegion -= siblingDirty;
2114 } else {
2115 sourceRegion -= siblingGeometry.translated(-parentOffset);
2116 }
2117 } else {
2118 if (hasDirtySiblingsAbove)
2119 *hasDirtySiblingsAbove = true;
2120 if (sibling->d_func()->children.isEmpty())
2121 continue;
2122 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2123 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2124 sourceRegion -= opaqueSiblingChildren;
2125 }
2126 if (sourceRegion.isEmpty())
2127 return;
2128
2129 dirtyClipBoundingRect = true;
2130 dirtyParentClip = true;
2131 }
2132
2133 w = w->parentWidget();
2134 parentOffset += pd->data.crect.topLeft();
2135 dirtyParentClip = true;
2136 }
2137}
2138
2139void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2140{
2141 Q_Q(const QWidget);
2142
2143 const QWidget *w = q;
2144 QPoint offset;
2145
2146#if QT_CONFIG(graphicseffect)
2147 if (graphicsEffect && !w->isWindow()) {
2148 w = q->parentWidget();
2149 offset -= data.crect.topLeft();
2150 }
2151#endif // QT_CONFIG(graphicseffect)
2152
2153 while (w) {
2154 const QWidgetPrivate *wd = w->d_func();
2155 if (wd->extra && wd->extra->hasMask)
2156 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2157 if (w->isWindow())
2158 return;
2159 offset -= wd->data.crect.topLeft();
2160 w = w->parentWidget();
2161 }
2162}
2163
2164bool QWidgetPrivate::shouldPaintOnScreen() const
2165{
2166#if defined(QT_NO_BACKINGSTORE)
2167 return true;
2168#else
2169 Q_Q(const QWidget);
2170 if (q->testAttribute(Qt::WA_PaintOnScreen)
2171 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2172 return true;
2173 }
2174
2175 return false;
2176#endif
2177}
2178
2179void QWidgetPrivate::updateIsOpaque()
2180{
2181 // hw: todo: only needed if opacity actually changed
2182 setDirtyOpaqueRegion();
2183
2184#if QT_CONFIG(graphicseffect)
2185 if (graphicsEffect) {
2186 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2187 setOpaque(false);
2188 return;
2189 }
2190#endif // QT_CONFIG(graphicseffect)
2191
2192 Q_Q(QWidget);
2193 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2194 setOpaque(true);
2195 return;
2196 }
2197
2198 const QPalette &pal = q->palette();
2199
2200 if (q->autoFillBackground()) {
2201 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2202 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2203 setOpaque(true);
2204 return;
2205 }
2206 }
2207
2208 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2209 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2210 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2211 setOpaque(true);
2212 return;
2213 }
2214 }
2215 setOpaque(false);
2216}
2217
2218void QWidgetPrivate::setOpaque(bool opaque)
2219{
2220 if (isOpaque != opaque) {
2221 isOpaque = opaque;
2222 updateIsTranslucent();
2223 }
2224}
2225
2226void QWidgetPrivate::updateIsTranslucent()
2227{
2228 Q_Q(QWidget);
2229 if (QWindow *window = q->windowHandle()) {
2230 QSurfaceFormat format = window->format();
2231 const int oldAlpha = format.alphaBufferSize();
2232 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
2233 if (oldAlpha != newAlpha) {
2234 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2235 //
2236 // If that is not the case, then the setFormat() is not just futile
2237 // but downright dangerous. Futile because the format matters only
2238 // when creating the native window, no point in changing it
2239 // afterwards. Dangerous because a QOpenGLContext or something else
2240 // may eventually query the QWindow's format(), in order to ensure
2241 // compatibility (in terms of native concepts such as pixel format,
2242 // EGLConfig, etc.), and if we change it here, then the returned
2243 // format does not describe reality anymore. (reality being the
2244 // settings with which the native resource was created).
2245 //
2246 // Whereas if one does a destroy()-create() then this all here
2247 // won't matter because the format is updated in
2248 // QWidgetPrivate::create() again.
2249 //
2250 if (!window->handle()) {
2251 format.setAlphaBufferSize(newAlpha);
2252 window->setFormat(format);
2253 }
2254 }
2255 }
2256}
2257
2258static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2259{
2260 Q_ASSERT(painter);
2261
2262 if (brush.style() == Qt::TexturePattern) {
2263 const QRect rect(rgn.boundingRect());
2264 painter->setClipRegion(rgn);
2265 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2266 } else if (brush.gradient()
2267 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2268 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2269 painter->save();
2270 painter->setClipRegion(rgn);
2271 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2272 painter->restore();
2273 } else {
2274 for (const QRect &rect : rgn)
2275 painter->fillRect(rect, brush);
2276 }
2277}
2278
2279bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2280{
2281#if QT_CONFIG(scrollarea)
2282 Q_Q(const QWidget);
2283 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2284 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2285 return false;
2286 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2287 if (scrollArea && scrollArea->viewport() == q) {
2288 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2289 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2290 painter->setBrushOrigin(-priv->contentsOffset());
2291 }
2292#endif // QT_CONFIG(scrollarea)
2293 return true;
2294}
2295
2296void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2297{
2298 Q_Q(const QWidget);
2299
2300 bool brushOriginSet = false;
2301 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2302
2303 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2304 const QBrush bg = q->palette().brush(QPalette::Window);
2305 if (!brushOriginSet)
2306 brushOriginSet = updateBrushOrigin(painter, bg);
2307 if (!(flags & DontSetCompositionMode)) {
2308 //copy alpha straight in
2309 QPainter::CompositionMode oldMode = painter->compositionMode();
2310 painter->setCompositionMode(QPainter::CompositionMode_Source);
2311 fillRegion(painter, rgn, bg);
2312 painter->setCompositionMode(oldMode);
2313 } else {
2314 fillRegion(painter, rgn, bg);
2315 }
2316 }
2317
2318 if (q->autoFillBackground()) {
2319 if (!brushOriginSet)
2320 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2321 fillRegion(painter, rgn, autoFillBrush);
2322 }
2323
2324 if (q->testAttribute(Qt::WA_StyledBackground)) {
2325 painter->setClipRegion(rgn);
2326 QStyleOption opt;
2327 opt.initFrom(q);
2328 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2329 }
2330}
2331
2332/*
2333 \internal
2334 This function is called when a widget is hidden or destroyed.
2335 It resets some application global pointers that should only refer active,
2336 visible widgets.
2337*/
2338
2340
2341void QWidgetPrivate::deactivateWidgetCleanup()
2342{
2343 Q_Q(QWidget);
2344 // If this was the active application window, reset it
2345 if (QApplication::activeWindow() == q)
2346 QApplicationPrivate::setActiveWindow(nullptr);
2347 // If the is the active mouse press widget, reset it
2348 if (q == qt_button_down)
2349 qt_button_down = nullptr;
2350}
2351
2352
2353/*!
2354 Returns a pointer to the widget with window identifier/handle \a
2355 id.
2356
2357 The window identifier type depends on the underlying window
2358 system, see \c qwindowdefs.h for the actual definition. If there
2359 is no widget with this identifier, \nullptr is returned.
2360*/
2361
2362QWidget *QWidget::find(WId id)
2363{
2364 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2365}
2366
2367
2368
2369/*!
2370 \fn WId QWidget::internalWinId() const
2371 \internal
2372 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2373
2374*/
2375
2376/*!
2377 \fn WId QWidget::winId() const
2378
2379 Returns the window system identifier of the widget.
2380
2381 Portable in principle, but if you use it you are probably about to
2382 do something non-portable. Be careful.
2383
2384 If a widget is non-native (alien) and winId() is invoked on it, that widget
2385 will be provided a native handle.
2386
2387 This value may change at run-time. An event with type QEvent::WinIdChange
2388 will be sent to the widget following a change in window system identifier.
2389
2390 \sa find()
2391*/
2392WId QWidget::winId() const
2393{
2394 if (!data->in_destructor
2395 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2396 {
2397 QWidget *that = const_cast<QWidget*>(this);
2398 that->setAttribute(Qt::WA_NativeWindow);
2399 that->d_func()->createWinId();
2400 return that->data->winid;
2401 }
2402 return data->winid;
2403}
2404
2405void QWidgetPrivate::createWinId()
2406{
2407 Q_Q(QWidget);
2408
2409 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2410 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2411 if (!q->isWindow()) {
2412 QWidget *parent = q->parentWidget();
2413 QWidgetPrivate *pd = parent->d_func();
2414 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2415 parent->setAttribute(Qt::WA_NativeWindow);
2416 if (!parent->internalWinId()) {
2417 pd->createWinId();
2418 }
2419
2420 for (int i = 0; i < pd->children.size(); ++i) {
2421 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2422 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2423 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2424 w->create();
2425 }
2426 }
2427 } else {
2428 q->create();
2429 }
2430 }
2431}
2432
2433/*!
2434\internal
2435Ensures that the widget is set on the screen point is on. This is handy getting a correct
2436size hint before a resize in e.g QMenu and QToolTip.
2437Returns if the screen was changed.
2438*/
2439
2440bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2441{
2442 Q_Q(QWidget);
2443 if (!q->isWindow())
2444 return false;
2445 // Find the screen for pos and make the widget understand it is on that screen.
2446 return setScreen(QGuiApplication::screenAt(pos));
2447}
2448
2449/*!
2450\internal
2451Ensures that the widget's QWindow is set to be on the given \a screen.
2452Returns true if the screen was changed.
2453*/
2454
2455bool QWidgetPrivate::setScreen(QScreen *screen)
2456{
2457 Q_Q(QWidget);
2458 if (!screen || !q->isWindow())
2459 return false;
2460 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2461 if (currentScreen != screen) {
2462 topData()->initialScreen = screen;
2463 if (windowHandle())
2464 windowHandle()->setScreen(screen);
2465 return true;
2466 }
2467 return false;
2468}
2469
2470/*!
2471\internal
2472Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2473
2474*/
2475
2476void QWidget::createWinId()
2477{
2478 Q_D(QWidget);
2479 d->createWinId();
2480}
2481
2482/*!
2483 \since 4.4
2484
2485 Returns the effective window system identifier of the widget, i.e. the
2486 native parent's window system identifier.
2487
2488 If the widget is native, this function returns the native widget ID.
2489 Otherwise, the window ID of the first native parent widget, i.e., the
2490 top-level widget that contains this widget, is returned.
2491
2492 \note We recommend that you do not store this value as it is likely to
2493 change at run-time.
2494
2495 \sa nativeParentWidget()
2496*/
2497WId QWidget::effectiveWinId() const
2498{
2499 const WId id = internalWinId();
2500 if (id || !testAttribute(Qt::WA_WState_Created))
2501 return id;
2502 if (const QWidget *realParent = nativeParentWidget())
2503 return realParent->internalWinId();
2504 return 0;
2505}
2506
2507/*!
2508 If this is a native widget, return the associated QWindow.
2509 Otherwise return null.
2510
2511 Native widgets include toplevel widgets, QGLWidget, and child widgets
2512 on which winId() was called.
2513
2514 \since 5.0
2515
2516 \sa winId(), screen()
2517*/
2518QWindow *QWidget::windowHandle() const
2519{
2520 Q_D(const QWidget);
2521 return d->windowHandle();
2522}
2523
2524/*!
2525 Returns the screen the widget is on.
2526
2527 \since 5.14
2528
2529 \sa windowHandle()
2530*/
2531QScreen *QWidget::screen() const
2532{
2533 Q_D(const QWidget);
2534 if (auto associatedScreen = d->associatedScreen())
2535 return associatedScreen;
2536 if (auto topLevel = window()) {
2537 if (auto topData = qt_widget_private(topLevel)->topData()) {
2538 if (topData->initialScreen)
2539 return topData->initialScreen;
2540 }
2541 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2542 return screenByPos;
2543 }
2544 return QGuiApplication::primaryScreen();
2545}
2546
2547/*!
2548 Sets the screen on which the widget should be shown to \a screen.
2549
2550 Setting the screen only makes sense for windows. If necessary, the widget's
2551 window will get recreated on \a screen.
2552
2553 \note If the screen is part of a virtual desktop of multiple screens,
2554 the window will not move automatically to \a screen. To place the
2555 window relative to the screen, use the screen's topLeft() position.
2556
2557 \sa QWindow::setScreen()
2558*/
2559void QWidget::setScreen(QScreen *screen)
2560{
2561 Q_D(QWidget);
2562 d->setScreen(screen);
2563}
2564
2565#if QT_CONFIG(style_stylesheet)
2566
2567/*!
2568 \property QWidget::styleSheet
2569 \brief the widget's style sheet
2570 \since 4.2
2571
2572 The style sheet contains a textual description of customizations to the
2573 widget's style, as described in the \l{Qt Style Sheets} document.
2574
2575 Since Qt 4.5, Qt style sheets fully supports \macos.
2576
2577 \warning Qt style sheets are currently not supported for custom QStyle
2578 subclasses. We plan to address this in some future release.
2579
2580 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2581*/
2582QString QWidget::styleSheet() const
2583{
2584 Q_D(const QWidget);
2585 if (!d->extra)
2586 return QString();
2587 return d->extra->styleSheet;
2588}
2589
2590void QWidget::setStyleSheet(const QString& styleSheet)
2591{
2592 Q_D(QWidget);
2593 if (data->in_destructor)
2594 return;
2595 d->createExtra();
2596
2597 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2598 d->extra->styleSheet = styleSheet;
2599 if (styleSheet.isEmpty()) { // stylesheet removed
2600 if (!proxy)
2601 return;
2602
2603 d->inheritStyle();
2604 return;
2605 }
2606
2607 if (proxy) { // style sheet update
2608 bool repolish = d->polished;
2609 if (!repolish) {
2610 const auto childWidgets = findChildren<QWidget*>();
2611 for (auto child : childWidgets) {
2612 repolish = child->d_func()->polished;
2613 if (repolish)
2614 break;
2615 }
2616 }
2617 if (repolish)
2618 proxy->repolish(this);
2619 return;
2620 }
2621
2622 if (testAttribute(Qt::WA_SetStyle)) {
2623 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2624 } else {
2625 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2626 }
2627}
2628
2629#endif // QT_NO_STYLE_STYLESHEET
2630
2631/*!
2632 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2633*/
2634
2635QStyle *QWidget::style() const
2636{
2637 Q_D(const QWidget);
2638
2639 if (d->extra && d->extra->style)
2640 return d->extra->style;
2641 return QApplication::style();
2642}
2643
2644/*!
2645 Sets the widget's GUI style to \a style. The ownership of the style
2646 object is not transferred.
2647
2648 If no style is set, the widget uses the application's style,
2649 QApplication::style() instead.
2650
2651 Setting a widget's style has no effect on existing or future child
2652 widgets.
2653
2654 \warning This function is particularly useful for demonstration
2655 purposes, where you want to show Qt's styling capabilities. Real
2656 applications should avoid it and use one consistent GUI style
2657 instead.
2658
2659 \warning Qt style sheets are currently not supported for custom QStyle
2660 subclasses. We plan to address this in some future release.
2661
2662 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2663*/
2664
2665void QWidget::setStyle(QStyle *style)
2666{
2667 Q_D(QWidget);
2668 setAttribute(Qt::WA_SetStyle, style != nullptr);
2669 d->createExtra();
2670#if QT_CONFIG(style_stylesheet)
2671 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2672 //if for some reason someone try to set a QStyleSheetStyle, ref it
2673 //(this may happen for example in QButtonDialogBox which propagates its style)
2674 styleSheetStyle->ref();
2675 d->setStyle_helper(style, false);
2676 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2677 // if we have an application stylesheet or have a proxy already, propagate
2678 d->setStyle_helper(new QStyleSheetStyle(style), true);
2679 } else
2680#endif
2681 d->setStyle_helper(style, false);
2682}
2683
2684void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2685{
2686 Q_Q(QWidget);
2687 QStyle *oldStyle = q->style();
2688
2689 createExtra();
2690
2691#if QT_CONFIG(style_stylesheet)
2692 QPointer<QStyle> origStyle = extra->style;
2693#endif
2694 extra->style = newStyle;
2695
2696 // repolish
2697 if (polished) {
2698 oldStyle->unpolish(q);
2699 q->style()->polish(q);
2700 }
2701
2702 if (propagate) {
2703 // We copy the list because the order may be modified
2704 const QObjectList childrenList = children;
2705 for (int i = 0; i < childrenList.size(); ++i) {
2706 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2707 if (c)
2708 c->d_func()->inheritStyle();
2709 }
2710 }
2711
2712#if QT_CONFIG(style_stylesheet)
2713 if (!qt_styleSheet(newStyle)) {
2714 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2715 cssStyle->clearWidgetFont(q);
2716 }
2717 }
2718#endif
2719
2720 QEvent e(QEvent::StyleChange);
2721 QCoreApplication::sendEvent(q, &e);
2722
2723#if QT_CONFIG(style_stylesheet)
2724 // dereference the old stylesheet style
2725 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2726 proxy->deref();
2727#endif
2728}
2729
2730// Inherits style from the current parent and propagates it as necessary
2731void QWidgetPrivate::inheritStyle()
2732{
2733#if QT_CONFIG(style_stylesheet)
2734 Q_Q(QWidget);
2735
2736 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2737
2738 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2739
2740 if (!q->styleSheet().isEmpty()) {
2741 Q_ASSERT(proxy);
2742 proxy->repolish(q);
2743 return;
2744 }
2745 if (inheritStyleRecursionGuard)
2746 return;
2747 inheritStyleRecursionGuard = true;
2748 const auto resetGuard = qScopeGuard([&]() {
2749 inheritStyleRecursionGuard = false;
2750 });
2751
2752 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2753 QWidget *parent = q->parentWidget();
2754 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2755 // If we have stylesheet on app or parent has stylesheet style, we need
2756 // to be running a proxy
2757 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2758 QStyle *newStyle = parentStyle;
2759 if (q->testAttribute(Qt::WA_SetStyle) && qt_styleSheet(origStyle) == nullptr)
2760 newStyle = new QStyleSheetStyle(origStyle);
2761 else if (auto *styleSheetStyle = qt_styleSheet(origStyle))
2762 newStyle = styleSheetStyle;
2763 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2764 newProxy->ref();
2765
2766 setStyle_helper(newStyle, true);
2767 return;
2768 }
2769
2770 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2771 // we just need our original style back
2772 if (origStyle == extraStyle) // is it any different?
2773 return;
2774
2775 // We could have inherited the proxy from our parent (which has a custom style)
2776 // In such a case we need to start following the application style (i.e revert
2777 // the propagation behavior of QStyleSheetStyle)
2778 if (!q->testAttribute(Qt::WA_SetStyle))
2779 origStyle = nullptr;
2780
2781 setStyle_helper(origStyle, true);
2782#endif // QT_NO_STYLE_STYLESHEET
2783}
2784
2785
2786/*!
2787 \fn bool QWidget::isWindow() const
2788
2789 Returns \c true if the widget is an independent window, otherwise
2790 returns \c false.
2791
2792 A window is a widget that isn't visually the child of any other
2793 widget and that usually has a frame and a
2794 \l{QWidget::setWindowTitle()}{window title}.
2795
2796 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2797 It will then be grouped with its parent and deleted when the
2798 parent is deleted, minimized when the parent is minimized etc. If
2799 supported by the window manager, it will also have a common
2800 taskbar entry with its parent.
2801
2802 QDialog and QMainWindow widgets are by default windows, even if a
2803 parent widget is specified in the constructor. This behavior is
2804 specified by the Qt::Window flag.
2805
2806 \sa window(), isModal(), parentWidget()
2807*/
2808
2809/*!
2810 \property QWidget::modal
2811 \brief whether the widget is a modal widget
2812
2813 This property only makes sense for windows. A modal widget
2814 prevents widgets in all other windows from getting any input.
2815
2816 By default, this property is \c false.
2817
2818 \sa isWindow(), windowModality, QDialog
2819*/
2820
2821/*!
2822 \property QWidget::windowModality
2823 \brief which windows are blocked by the modal widget
2824 \since 4.1
2825
2826 This property only makes sense for windows. A modal widget
2827 prevents widgets in other windows from getting input. The value of
2828 this property controls which windows are blocked when the widget
2829 is visible. Changing this property while the window is visible has
2830 no effect; you must hide() the widget first, then show() it again.
2831
2832 By default, this property is Qt::NonModal.
2833
2834 \sa isWindow(), QWidget::modal, QDialog
2835*/
2836
2837Qt::WindowModality QWidget::windowModality() const
2838{
2839 return static_cast<Qt::WindowModality>(data->window_modality);
2840}
2841
2842void QWidget::setWindowModality(Qt::WindowModality windowModality)
2843{
2844 data->window_modality = windowModality;
2845 // setModal_sys() will be called by setAttribute()
2846 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2847 setAttribute(Qt::WA_SetWindowModality, true);
2848}
2849
2850void QWidgetPrivate::setModal_sys()
2851{
2852 Q_Q(QWidget);
2853 if (q->windowHandle())
2854 q->windowHandle()->setModality(q->windowModality());
2855}
2856
2857/*!
2858 \fn bool QWidget::underMouse() const
2859
2860 Returns \c true if the widget is under the mouse cursor; otherwise
2861 returns \c false.
2862
2863 This value is not updated properly during drag and drop
2864 operations.
2865
2866 \sa enterEvent(), leaveEvent()
2867*/
2868
2869/*!
2870 \property QWidget::minimized
2871 \brief whether this widget is minimized (iconified)
2872
2873 This property is only relevant for windows.
2874
2875 By default, this property is \c false.
2876
2877 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2878*/
2879bool QWidget::isMinimized() const
2880{ return data->window_state & Qt::WindowMinimized; }
2881
2882/*!
2883 Shows the widget minimized, as an icon.
2884
2885 Calling this function only affects \l{isWindow()}{windows}.
2886
2887 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2888 isMinimized()
2889*/
2890void QWidget::showMinimized()
2891{
2892 bool isMin = isMinimized();
2893 if (isMin && isVisible())
2894 return;
2895
2896 ensurePolished();
2897
2898 if (!isMin)
2899 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2900 setVisible(true);
2901}
2902
2903/*!
2904 \property QWidget::maximized
2905 \brief whether this widget is maximized
2906
2907 This property is only relevant for windows.
2908
2909 \note Due to limitations on some window systems, this does not always
2910 report the expected results (e.g., if the user on X11 maximizes the
2911 window via the window manager, Qt has no way of distinguishing this
2912 from any other resize). This is expected to improve as window manager
2913 protocols evolve.
2914
2915 By default, this property is \c false.
2916
2917 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2918*/
2919bool QWidget::isMaximized() const
2920{ return data->window_state & Qt::WindowMaximized; }
2921
2922
2923
2924/*!
2925 Returns the current window state. The window state is a OR'ed
2926 combination of Qt::WindowState: Qt::WindowMinimized,
2927 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2928
2929 \sa Qt::WindowState, setWindowState()
2930 */
2931Qt::WindowStates QWidget::windowState() const
2932{
2933 return Qt::WindowStates(data->window_state);
2934}
2935
2936/*!\internal
2937
2938 The function sets the window state on child widgets similar to
2939 setWindowState(). The difference is that the window state changed
2940 event has the isOverride() flag set. It exists mainly to keep
2941 QWorkspace working.
2942 */
2943void QWidget::overrideWindowState(Qt::WindowStates newstate)
2944{
2945 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2946 data->window_state = newstate;
2947 QCoreApplication::sendEvent(this, &e);
2948}
2949
2950/*!
2951 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2952
2953 Sets the window state to \a windowState. The window state is a OR'ed
2954 combination of Qt::WindowState: Qt::WindowMinimized,
2955 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2956
2957 If the window is not visible (i.e. isVisible() returns \c false), the
2958 window state will take effect when show() is called. For visible
2959 windows, the change is immediate. For example, to toggle between
2960 full-screen and normal mode, use the following code:
2961
2962 \snippet code/src_gui_kernel_qwidget.cpp 0
2963
2964 To restore and activate a minimized window (while
2965 preserving its maximized and/or full-screen state), use the following:
2966
2967 \snippet code/src_gui_kernel_qwidget.cpp 1
2968
2969 Calling this function will hide the widget. You must call show() to make
2970 the widget visible again.
2971
2972 \note On some window systems Qt::WindowActive is not immediate, and may be
2973 ignored in certain cases.
2974
2975 When the window state changes, the widget receives a changeEvent()
2976 of type QEvent::WindowStateChange.
2977
2978 \sa Qt::WindowState, windowState()
2979*/
2980void QWidget::setWindowState(Qt::WindowStates newstate)
2981{
2982 Q_D(QWidget);
2983 Qt::WindowStates oldstate = windowState();
2984 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2985 newstate.setFlag(Qt::WindowActive, false);
2986 if (oldstate == newstate)
2987 return;
2988 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2989 create();
2990
2991 data->window_state = newstate;
2992 data->in_set_window_state = 1;
2993 if (isWindow()) {
2994 // Ensure the initial size is valid, since we store it as normalGeometry below.
2995 if (!testAttribute(Qt::WA_Resized) && !isVisible())
2996 adjustSize();
2997
2998 d->createTLExtra();
2999 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3000 d->topData()->normalGeometry = geometry();
3001
3002 Q_ASSERT(windowHandle());
3003 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3004 }
3005 data->in_set_window_state = 0;
3006
3007 if (newstate & Qt::WindowActive)
3008 activateWindow();
3009
3010 QWindowStateChangeEvent e(oldstate);
3011 QCoreApplication::sendEvent(this, &e);
3012}
3013
3014/*!
3015 \property QWidget::fullScreen
3016 \brief whether the widget is shown in full screen mode
3017
3018 A widget in full screen mode occupies the whole screen area and does not
3019 display window decorations, such as a title bar.
3020
3021 By default, this property is \c false.
3022
3023 \sa windowState(), minimized, maximized
3024*/
3025bool QWidget::isFullScreen() const
3026{ return data->window_state & Qt::WindowFullScreen; }
3027
3028/*!
3029 Shows the widget in full-screen mode.
3030
3031 Calling this function only affects \l{isWindow()}{windows}.
3032
3033 To return from full-screen mode, call showNormal() or close().
3034
3035 \note Full-screen mode works fine under Windows, but has certain
3036 problems under X. These problems are due to limitations of the
3037 ICCCM protocol that specifies the communication between X11
3038 clients and the window manager. ICCCM simply does not understand
3039 the concept of non-decorated full-screen windows. Therefore, the
3040 best you can do is to request a borderless window and place and
3041 resize it to fill the entire screen. Depending on the window
3042 manager, this may or may not work. The borderless window is
3043 requested using MOTIF hints, which are at least partially
3044 supported by virtually all modern window managers.
3045
3046 An alternative would be to bypass the window manager entirely and
3047 create a window with the Qt::X11BypassWindowManagerHint flag. This
3048 has other severe problems though, like broken keyboard focus
3049 and very strange effects on desktop changes or when the user raises
3050 other windows.
3051
3052 X11 window managers that follow modern post-ICCCM specifications
3053 support full-screen mode properly.
3054
3055 On macOS, showing a window full screen puts the entire application in
3056 full-screen mode, providing it with a dedicated desktop. Showing another
3057 window while the application runs in full-screen mode might automatically
3058 make that window full screen as well. To prevent that, exit full-screen
3059 mode by calling showNormal() or by close() on the full screen window
3060 before showing another window.
3061
3062 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3063*/
3064void QWidget::showFullScreen()
3065{
3066 ensurePolished();
3067
3068 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3069 | Qt::WindowFullScreen);
3070 setVisible(true);
3071#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3072 // activating it here before libscreen activates it causes problems
3073 activateWindow();
3074#endif
3075}
3076
3077/*!
3078 Shows the widget maximized.
3079
3080 Calling this function only affects \l{isWindow()}{windows}.
3081
3082 On X11, this function may not work properly with certain window
3083 managers. See the \l{Window Geometry} documentation for an explanation.
3084
3085 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3086*/
3087void QWidget::showMaximized()
3088{
3089 ensurePolished();
3090
3091 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3092 | Qt::WindowMaximized);
3093 setVisible(true);
3094}
3095
3096/*!
3097 Restores the widget after it has been maximized or minimized.
3098
3099 Calling this function only affects \l{isWindow()}{windows}.
3100
3101 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3102*/
3103void QWidget::showNormal()
3104{
3105 ensurePolished();
3106
3107 setWindowState(windowState() & ~(Qt::WindowMinimized
3108 | Qt::WindowMaximized
3109 | Qt::WindowFullScreen));
3110 setVisible(true);
3111}
3112
3113/*!
3114 Returns \c true if this widget would become enabled if \a ancestor is
3115 enabled; otherwise returns \c false.
3116
3117
3118
3119 This is the case if neither the widget itself nor every parent up
3120 to but excluding \a ancestor has been explicitly disabled.
3121
3122 isEnabledTo(0) returns false if this widget or any if its ancestors
3123 was explicitly disabled.
3124
3125 The word ancestor here means a parent widget within the same window.
3126
3127 Therefore isEnabledTo(0) stops at this widget's window, unlike
3128 isEnabled() which also takes parent windows into considerations.
3129
3130 \sa setEnabled(), enabled
3131*/
3132
3133bool QWidget::isEnabledTo(const QWidget *ancestor) const
3134{
3135 const QWidget * w = this;
3136 while (!w->testAttribute(Qt::WA_ForceDisabled)
3137 && !w->isWindow()
3138 && w->parentWidget()
3139 && w->parentWidget() != ancestor)
3140 w = w->parentWidget();
3141 return !w->testAttribute(Qt::WA_ForceDisabled);
3142}
3143
3144#ifndef QT_NO_ACTION
3145/*!
3146 Appends the action \a action to this widget's list of actions.
3147
3148 All QWidgets have a list of \l{QAction}s. However, they can be
3149 represented graphically in many different ways. The default use of
3150 the QAction list (as returned by actions()) is to create a context
3151 QMenu.
3152
3153 A QWidget should only have one of each action and adding an action
3154 it already has will not cause the same action to be in the widget twice.
3155
3156 The ownership of \a action is not transferred to this QWidget.
3157
3158 \sa removeAction(), insertAction(), actions(), QMenu
3159*/
3160void QWidget::addAction(QAction *action)
3161{
3162 insertAction(nullptr, action);
3163}
3164
3165/*!
3166 Appends the actions \a actions to this widget's list of actions.
3167
3168 \sa removeAction(), QMenu, addAction()
3169*/
3170void QWidget::addActions(const QList<QAction *> &actions)
3171{
3172 for(int i = 0; i < actions.size(); i++)
3173 insertAction(nullptr, actions.at(i));
3174}
3175
3176/*!
3177 Inserts the action \a action to this widget's list of actions,
3178 before the action \a before. It appends the action if \a before is \nullptr or
3179 \a before is not a valid action for this widget.
3180
3181 A QWidget should only have one of each action.
3182
3183 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3184*/
3185void QWidget::insertAction(QAction *before, QAction *action)
3186{
3187 if (Q_UNLIKELY(!action)) {
3188 qWarning("QWidget::insertAction: Attempt to insert null action");
3189 return;
3190 }
3191
3192 Q_D(QWidget);
3193 if (d->actions.contains(action))
3194 removeAction(action);
3195
3196 int pos = d->actions.indexOf(before);
3197 if (pos < 0) {
3198 before = nullptr;
3199 pos = d->actions.size();
3200 }
3201 d->actions.insert(pos, action);
3202
3203 QActionPrivate *apriv = action->d_func();
3204 apriv->associatedObjects.append(this);
3205
3206 QActionEvent e(QEvent::ActionAdded, action, before);
3207 QCoreApplication::sendEvent(this, &e);
3208}
3209
3210/*!
3211 Inserts the actions \a actions to this widget's list of actions,
3212 before the action \a before. It appends the action if \a before is \nullptr or
3213 \a before is not a valid action for this widget.
3214
3215 A QWidget can have at most one of each action.
3216
3217 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3218*/
3219void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3220{
3221 for(int i = 0; i < actions.size(); ++i)
3222 insertAction(before, actions.at(i));
3223}
3224
3225/*!
3226 Removes the action \a action from this widget's list of actions.
3227 \sa insertAction(), actions(), insertAction()
3228*/
3229void QWidget::removeAction(QAction *action)
3230{
3231 if (!action)
3232 return;
3233
3234 Q_D(QWidget);
3235
3236 QActionPrivate *apriv = action->d_func();
3237 apriv->associatedObjects.removeAll(this);
3238
3239 if (d->actions.removeAll(action)) {
3240 QActionEvent e(QEvent::ActionRemoved, action);
3241 QCoreApplication::sendEvent(this, &e);
3242 }
3243}
3244
3245/*!
3246 Returns the (possibly empty) list of this widget's actions.
3247
3248 \sa contextMenuPolicy, insertAction(), removeAction()
3249*/
3250QList<QAction*> QWidget::actions() const
3251{
3252 Q_D(const QWidget);
3253 return d->actions;
3254}
3255
3256/*!
3257 \fn QAction *QWidget::addAction(const QString &text);
3258 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3259 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3260 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3261
3262 \since 6.3
3263
3264 These convenience functions create a new action with text \a text,
3265 icon \a icon and shortcut \a shortcut, if any.
3266
3267 The functions add the newly created action to the widget's
3268 list of actions, and return it.
3269
3270 QWidget takes ownership of the returned QAction.
3271*/
3272QAction *QWidget::addAction(const QString &text)
3273{
3274 QAction *ret = new QAction(text, this);
3275 addAction(ret);
3276 return ret;
3277}
3278
3279QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3280{
3281 QAction *ret = new QAction(icon, text, this);
3282 addAction(ret);
3283 return ret;
3284}
3285
3286#if QT_CONFIG(shortcut)
3287QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3288{
3289 QAction *ret = addAction(text);
3290 ret->setShortcut(shortcut);
3291 return ret;
3292}
3293
3294QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3295{
3296 QAction *ret = addAction(icon, text);
3297 ret->setShortcut(shortcut);
3298 return ret;
3299}
3300#endif
3301
3302/*!
3303 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3304 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3305 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3306 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3307
3308 \overload
3309 \since 6.3
3310
3311 This convenience function creates a new action with the text \a
3312 text, icon \a icon, and shortcut \a shortcut, if any.
3313
3314 The action's \l{QAction::triggered()}{triggered()} signal is connected
3315 to the \a receiver's \a member slot. The function adds the newly created
3316 action to the widget's list of actions and returns it.
3317
3318 QWidget takes ownership of the returned QAction.
3319*/
3320QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3321 Qt::ConnectionType type)
3322{
3323 QAction *action = addAction(text);
3324 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3325 return action;
3326}
3327
3328QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3329 const QObject *receiver, const char* member,
3330 Qt::ConnectionType type)
3331{
3332 QAction *action = addAction(icon, text);
3333 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3334 return action;
3335}
3336
3337#if QT_CONFIG(shortcut)
3338QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3339 const QObject *receiver, const char* member,
3340 Qt::ConnectionType type)
3341{
3342 QAction *action = addAction(text, receiver, member, type);
3343 action->setShortcut(shortcut);
3344 return action;
3345}
3346
3347QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3348 const QObject *receiver, const char* member,
3349 Qt::ConnectionType type)
3350{
3351 QAction *action = addAction(icon, text, receiver, member, type);
3352 action->setShortcut(shortcut);
3353 return action;
3354}
3355#endif // QT_CONFIG(shortcut)
3356
3357/*!
3358 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3359 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3360 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3361 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3362
3363 \since 6.3
3364 \overload
3365
3366 These convenience functions create a new action with the text \a text,
3367 icon \a icon, and shortcut \a shortcut, if any.
3368
3369 The action's \l{QAction::triggered()}{triggered()} signal is connected
3370 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3371 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3372
3373 The function adds the newly created action to the widget's list of
3374 actions and returns it.
3375
3376 QWidget takes ownership of the returned QAction.
3377*/
3378#endif // QT_NO_ACTION
3379
3380/*!
3381 \property QWidget::enabled
3382 \brief whether the widget is enabled
3383
3384 In general an enabled widget handles keyboard and mouse events; a disabled
3385 widget does not. An exception is made with \l{QAbstractButton}.
3386
3387 Some widgets display themselves differently when they are
3388 disabled. For example a button might draw its label grayed out. If
3389 your widget needs to know when it becomes enabled or disabled, you
3390 can use the changeEvent() with type QEvent::EnabledChange.
3391
3392 Disabling a widget implicitly disables all its children. Enabling
3393 respectively enables all child widgets unless they have been
3394 explicitly disabled. It it not possible to explicitly enable a child
3395 widget which is not a window while its parent widget remains disabled.
3396
3397 By default, this property is \c true.
3398
3399 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3400*/
3401void QWidget::setEnabled(bool enable)
3402{
3403 Q_D(QWidget);
3404
3405#if QT_CONFIG(accessibility)
3406 const bool wasEnabled = !testAttribute(Qt::WA_ForceDisabled);
3407#endif
3408
3409 setAttribute(Qt::WA_ForceDisabled, !enable);
3410 d->setEnabled_helper(enable);
3411
3412#if QT_CONFIG(accessibility)
3413 // A widget is enabled if it's parent and itself is enabled.
3414 // We do not send state changed events recursively. It is up
3415 // to the receiver of the events to check children if required.
3416 if (QAccessible::isActive() && wasEnabled != enable) {
3417 QAccessible::State states;
3418 states.disabled = 1;
3419 QAccessibleStateChangeEvent scEvent(this, states);
3420 QAccessible::updateAccessibility(&scEvent);
3421 }
3422#endif
3423}
3424
3425void QWidgetPrivate::setEnabled_helper(bool enable)
3426{
3427 Q_Q(QWidget);
3428
3429 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3430 return; // nothing we can do
3431
3432 if (enable != q->testAttribute(Qt::WA_Disabled))
3433 return; // nothing to do
3434
3435 q->setAttribute(Qt::WA_Disabled, !enable);
3436 updateSystemBackground();
3437
3438 if (!enable && q->window()->focusWidget() == q) {
3439 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3440 if (!parentIsEnabled || !q->focusNextChild())
3441 q->clearFocus();
3442 }
3443
3444 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3445 for (int i = 0; i < children.size(); ++i) {
3446 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3447 if (w && !w->testAttribute(attribute))
3448 w->d_func()->setEnabled_helper(enable);
3449 }
3450#ifndef QT_NO_CURSOR
3451 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3452 // enforce the windows behavior of clearing the cursor on
3453 // disabled widgets
3454 qt_qpa_set_cursor(q, false);
3455 }
3456#endif
3457#ifndef QT_NO_IM
3458 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3459 QWidget *focusWidget = effectiveFocusWidget();
3460
3461 if (enable) {
3462 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3463 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3464 } else {
3465 QGuiApplication::inputMethod()->commit();
3466 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3467 }
3468 }
3469#endif //QT_NO_IM
3470 QEvent e(QEvent::EnabledChange);
3471 QCoreApplication::sendEvent(q, &e);
3472}
3473
3474/*!
3475 \property QWidget::acceptDrops
3476 \brief whether drop events are enabled for this widget
3477
3478 Setting this property to true announces to the system that this
3479 widget \e may be able to accept drop events.
3480
3481 \warning Do not modify this property in a drag and drop event handler.
3482
3483 By default, this property is \c false.
3484
3485 \sa {Drag and Drop in Qt}{Drag and Drop}
3486*/
3487bool QWidget::acceptDrops() const
3488{
3489 return testAttribute(Qt::WA_AcceptDrops);
3490}
3491
3492void QWidget::setAcceptDrops(bool on)
3493{
3494 setAttribute(Qt::WA_AcceptDrops, on);
3495
3496}
3497
3498/*!
3499 Disables widget input events if \a disable is true; otherwise
3500 enables input events.
3501
3502 See the \l enabled documentation for more information.
3503
3504 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3505*/
3506void QWidget::setDisabled(bool disable)
3507{
3508 setEnabled(!disable);
3509}
3510
3511/*!
3512 \property QWidget::frameGeometry
3513 \brief geometry of the widget relative to its parent including any
3514 window frame
3515
3516 See the \l{Window Geometry} documentation for an overview of geometry
3517 issues with windows.
3518
3519 By default, this property contains a value that depends on the user's
3520 platform and screen geometry.
3521
3522 \sa geometry(), x(), y(), pos()
3523*/
3524QRect QWidget::frameGeometry() const
3525{
3526 Q_D(const QWidget);
3527 if (isWindow() && ! (windowType() == Qt::Popup)) {
3528 QRect fs = d->frameStrut();
3529 return QRect(data->crect.x() - fs.left(),
3530 data->crect.y() - fs.top(),
3531 data->crect.width() + fs.left() + fs.right(),
3532 data->crect.height() + fs.top() + fs.bottom());
3533 }
3534 return data->crect;
3535}
3536
3537/*!
3538 \property QWidget::x
3539
3540 \brief the x coordinate of the widget relative to its parent including
3541 any window frame
3542
3543 See the \l{Window Geometry} documentation for an overview of geometry
3544 issues with windows.
3545
3546 By default, this property has a value of 0.
3547
3548 \sa frameGeometry, y, pos
3549*/
3550int QWidget::x() const
3551{
3552 Q_D(const QWidget);
3553 if (isWindow() && ! (windowType() == Qt::Popup))
3554 return data->crect.x() - d->frameStrut().left();
3555 return data->crect.x();
3556}
3557
3558/*!
3559 \property QWidget::y
3560 \brief the y coordinate of the widget relative to its parent and
3561 including any window frame
3562
3563 See the \l{Window Geometry} documentation for an overview of geometry
3564 issues with windows.
3565
3566 By default, this property has a value of 0.
3567
3568 \sa frameGeometry, x, pos
3569*/
3570int QWidget::y() const
3571{
3572 Q_D(const QWidget);
3573 if (isWindow() && ! (windowType() == Qt::Popup))
3574 return data->crect.y() - d->frameStrut().top();
3575 return data->crect.y();
3576}
3577
3578/*!
3579 \property QWidget::pos
3580 \brief the position of the widget within its parent widget
3581
3582 If the widget is a window, the position is that of the widget on
3583 the desktop, including its frame.
3584
3585 When changing the position, the widget, if visible, receives a
3586 move event (moveEvent()) immediately. If the widget is not
3587 currently visible, it is guaranteed to receive an event before it
3588 is shown.
3589
3590 By default, this property contains a position that refers to the
3591 origin.
3592
3593 \warning Calling move() or setGeometry() inside moveEvent() can
3594 lead to infinite recursion.
3595
3596 See the \l{Window Geometry} documentation for an overview of geometry
3597 issues with windows.
3598
3599 \note Not all windowing systems support setting or querying top level window positions.
3600 On such a system, programmatically moving windows may not have any effect, and artificial
3601 values may be returned for the current positions, such as \c QPoint(0, 0).
3602
3603 \sa frameGeometry, size, x(), y()
3604*/
3605QPoint QWidget::pos() const
3606{
3607 Q_D(const QWidget);
3608 QPoint result = data->crect.topLeft();
3609 if (isWindow() && ! (windowType() == Qt::Popup))
3610 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3611 result -= d->frameStrut().topLeft();
3612 return result;
3613}
3614
3615/*!
3616 \property QWidget::geometry
3617 \brief the geometry of the widget relative to its parent and
3618 excluding the window frame
3619
3620 When changing the geometry, the widget, if visible, receives a
3621 move event (moveEvent()) and/or a resize event (resizeEvent())
3622 immediately. If the widget is not currently visible, it is
3623 guaranteed to receive appropriate events before it is shown.
3624
3625 The size component is adjusted if it lies outside the range
3626 defined by minimumSize() and maximumSize().
3627
3628 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3629 can lead to infinite recursion.
3630
3631 See the \l{Window Geometry} documentation for an overview of geometry
3632 issues with windows.
3633
3634 By default, this property contains a value that depends on the user's
3635 platform and screen geometry.
3636
3637 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3638 resizeEvent(), minimumSize(), maximumSize()
3639*/
3640
3641/*!
3642 \property QWidget::size
3643 \brief the size of the widget excluding any window frame
3644
3645 If the widget is visible when it is being resized, it receives a resize event
3646 (resizeEvent()) immediately. If the widget is not currently
3647 visible, it is guaranteed to receive an event before it is shown.
3648
3649 The size is adjusted if it lies outside the range defined by
3650 minimumSize() and maximumSize().
3651
3652 By default, this property contains a value that depends on the user's
3653 platform and screen geometry.
3654
3655 \warning Calling resize() or setGeometry() inside resizeEvent() can
3656 lead to infinite recursion.
3657
3658 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3659 appear on screen. This also applies to windows.
3660
3661 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3662*/
3663
3664/*!
3665 \property QWidget::width
3666 \brief the width of the widget excluding any window frame
3667
3668 See the \l{Window Geometry} documentation for an overview of geometry
3669 issues with windows.
3670
3671 \note Do not use this function to find the width of a screen on
3672 a multi-screen desktop. See QScreen for details.
3673
3674 By default, this property contains a value that depends on the user's
3675 platform and screen geometry.
3676
3677 \sa geometry, height, size
3678*/
3679
3680/*!
3681 \property QWidget::height
3682 \brief the height of the widget excluding any window frame
3683
3684 See the \l{Window Geometry} documentation for an overview of geometry
3685 issues with windows.
3686
3687 By default, this property contains a value that depends on the user's
3688 platform and \l{QScreen::geometry}{screen geometry}.
3689
3690 \sa geometry, width, size
3691*/
3692
3693/*!
3694 \property QWidget::rect
3695 \brief the internal geometry of the widget excluding any window
3696 frame
3697
3698 The rect property equals QRect(0, 0, width(), height()).
3699
3700 See the \l{Window Geometry} documentation for an overview of geometry
3701 issues with windows.
3702
3703 By default, this property contains a value that depends on the user's
3704 platform and screen geometry.
3705
3706 \sa size
3707*/
3708
3709/*!
3710 \property QWidget::normalGeometry
3711
3712 \brief the geometry of the widget as it will appear when shown as
3713 a normal (not maximized or full screen) top-level widget
3714
3715 If the widget is already in this state the normal geometry will
3716 reflect the widget's current geometry().
3717
3718 For child widgets this property always holds an empty rectangle.
3719
3720 By default, this property contains an empty rectangle.
3721
3722 \sa QWidget::windowState(), QWidget::geometry
3723*/
3724QRect QWidget::normalGeometry() const
3725{
3726 Q_D(const QWidget);
3727 if (!isWindow())
3728 return QRect();
3729
3730 if (!isMaximized() && !isFullScreen())
3731 return geometry();
3732
3733 return d->topData()->normalGeometry;
3734}
3735
3736
3737/*!
3738 \property QWidget::childrenRect
3739 \brief the bounding rectangle of the widget's children
3740
3741 Hidden children are excluded.
3742
3743 By default, for a widget with no children, this property contains a
3744 rectangle with zero width and height located at the origin.
3745
3746 \sa childrenRegion(), geometry()
3747*/
3748
3749QRect QWidget::childrenRect() const
3750{
3751 Q_D(const QWidget);
3752 QRect r(0, 0, 0, 0);
3753 for (int i = 0; i < d->children.size(); ++i) {
3754 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3755 if (w && !w->isWindow() && !w->isHidden())
3756 r |= w->geometry();
3757 }
3758 return r;
3759}
3760
3761/*!
3762 \property QWidget::childrenRegion
3763 \brief the combined region occupied by the widget's children
3764
3765 Hidden children are excluded.
3766
3767 By default, for a widget with no children, this property contains an
3768 empty region.
3769
3770 \sa childrenRect(), geometry(), mask()
3771*/
3772
3773QRegion QWidget::childrenRegion() const
3774{
3775 Q_D(const QWidget);
3776 QRegion r;
3777 for (int i = 0; i < d->children.size(); ++i) {
3778 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3779 if (w && !w->isWindow() && !w->isHidden()) {
3780 QRegion mask = w->mask();
3781 if (mask.isEmpty())
3782 r |= w->geometry();
3783 else
3784 r |= mask.translated(w->pos());
3785 }
3786 }
3787 return r;
3788}
3789
3790
3791/*!
3792 \property QWidget::minimumSize
3793 \brief the widget's minimum size
3794
3795 The widget cannot be resized to a smaller size than the minimum
3796 widget size. The widget's size is forced to the minimum size if
3797 the current size is smaller.
3798
3799 The minimum size set by this function will override the minimum size
3800 defined by QLayout. To unset the minimum size, use a
3801 value of \c{QSize(0, 0)}.
3802
3803 By default, this property contains a size with zero width and height.
3804
3805 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3806*/
3807
3808QSize QWidget::minimumSize() const
3809{
3810 Q_D(const QWidget);
3811 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3812}
3813
3814/*!
3815 \property QWidget::maximumSize
3816 \brief the widget's maximum size in pixels
3817
3818 The widget cannot be resized to a larger size than the maximum
3819 widget size.
3820
3821 By default, this property contains a size in which both width and height
3822 have values of 16777215.
3823
3824 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3825 of widgets.
3826
3827 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3828*/
3829
3830QSize QWidget::maximumSize() const
3831{
3832 Q_D(const QWidget);
3833 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3835}
3836
3837
3838/*!
3839 \property QWidget::minimumWidth
3840 \brief the widget's minimum width in pixels
3841
3842 This property corresponds to the width held by the \l minimumSize property.
3843
3844 By default, this property has a value of 0.
3845
3846 \sa minimumSize, minimumHeight
3847*/
3848
3849/*!
3850 \property QWidget::minimumHeight
3851 \brief the widget's minimum height in pixels
3852
3853 This property corresponds to the height held by the \l minimumSize property.
3854
3855 By default, this property has a value of 0.
3856
3857 \sa minimumSize, minimumWidth
3858*/
3859
3860/*!
3861 \property QWidget::maximumWidth
3862 \brief the widget's maximum width in pixels
3863
3864 This property corresponds to the width held by the \l maximumSize property.
3865
3866 By default, this property contains a value of 16777215.
3867
3868 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3869 of widgets.
3870
3871 \sa maximumSize, maximumHeight
3872*/
3873
3874/*!
3875 \property QWidget::maximumHeight
3876 \brief the widget's maximum height in pixels
3877
3878 This property corresponds to the height held by the \l maximumSize property.
3879
3880 By default, this property contains a value of 16777215.
3881
3882 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3883 of widgets.
3884
3885 \sa maximumSize, maximumWidth
3886*/
3887
3888/*!
3889 \property QWidget::sizeIncrement
3890 \brief the size increment of the widget
3891
3892 When the user resizes the window, the size will move in steps of
3893 sizeIncrement().width() pixels horizontally and
3894 sizeIncrement.height() pixels vertically, with baseSize() as the
3895 basis. Preferred widget sizes are for non-negative integers \e i
3896 and \e j:
3897 \snippet code/src_gui_kernel_qwidget.cpp 2
3898
3899 Note that while you can set the size increment for all widgets, it
3900 only affects windows.
3901
3902 By default, this property contains a size with zero width and height.
3903
3904 \warning The size increment has no effect under Windows, and may
3905 be disregarded by the window manager on X11.
3906
3907 \sa size, minimumSize, maximumSize
3908*/
3909QSize QWidget::sizeIncrement() const
3910{
3911 Q_D(const QWidget);
3912 return (d->extra && d->extra->topextra)
3913 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3914 : QSize(0, 0);
3915}
3916
3917/*!
3918 \property QWidget::baseSize
3919 \brief the base size of the widget
3920
3921 The base size is used to calculate a proper widget size if the
3922 widget defines sizeIncrement().
3923
3924 By default, for a newly-created widget, this property contains a size with
3925 zero width and height.
3926
3927 \sa setSizeIncrement()
3928*/
3929
3930QSize QWidget::baseSize() const
3931{
3932 Q_D(const QWidget);
3933 return (d->extra && d->extra->topextra)
3934 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3935 : QSize(0, 0);
3936}
3937
3938bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3939{
3940 Q_Q(QWidget);
3941
3942 int mw = minw, mh = minh;
3943 if (mw == QWIDGETSIZE_MAX)
3944 mw = 0;
3945 if (mh == QWIDGETSIZE_MAX)
3946 mh = 0;
3947 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3948 qWarning("QWidget::setMinimumSize: (%s/%s) "
3949 "The largest allowed size is (%d,%d)",
3950 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3952 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3953 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3954 }
3955 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3956 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3957 "are not possible",
3958 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3959 minw = mw = qMax(minw, 0);
3960 minh = mh = qMax(minh, 0);
3961 }
3962 createExtra();
3963 if (extra->minw == mw && extra->minh == mh)
3964 return false;
3965 extra->minw = mw;
3966 extra->minh = mh;
3967 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3968 return true;
3969}
3970
3971void QWidgetPrivate::setConstraints_sys()
3972{
3973 Q_Q(QWidget);
3974 if (extra && q->windowHandle()) {
3975 QWindow *win = q->windowHandle();
3976 QWindowPrivate *winp = qt_window_private(win);
3977
3978 winp->minimumSize = QSize(extra->minw, extra->minh);
3979 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3980
3981 if (extra->topextra) {
3982 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3983 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3984 }
3985
3986 if (winp->platformWindow) {
3987 fixPosIncludesFrame();
3988 winp->platformWindow->propagateSizeHints();
3989 }
3990 }
3991}
3992
3993/*!
3994 \overload
3995
3996 This function corresponds to setMinimumSize(QSize(minw, minh)).
3997 Sets the minimum width to \a minw and the minimum height to \a
3998 minh.
3999*/
4000
4001void QWidget::setMinimumSize(int minw, int minh)
4002{
4003 Q_D(QWidget);
4004 if (!d->setMinimumSize_helper(minw, minh))
4005 return;
4006
4007 if (isWindow())
4008 d->setConstraints_sys();
4009 if (minw > width() || minh > height()) {
4010 bool resized = testAttribute(Qt::WA_Resized);
4011 bool maximized = isMaximized();
4012 resize(qMax(minw,width()), qMax(minh,height()));
4013 setAttribute(Qt::WA_Resized, resized); //not a user resize
4014 if (maximized)
4015 data->window_state = data->window_state | Qt::WindowMaximized;
4016 }
4017#if QT_CONFIG(graphicsview)
4018 if (d->extra) {
4019 if (d->extra->proxyWidget)
4020 d->extra->proxyWidget->setMinimumSize(minw, minh);
4021 }
4022#endif
4023 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4024}
4025
4026bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
4027{
4028 Q_Q(QWidget);
4029 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
4030 qWarning("QWidget::setMaximumSize: (%s/%s) "
4031 "The largest allowed size is (%d,%d)",
4032 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4034 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4035 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4036 }
4037 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4038 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4039 "are not possible",
4040 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4041 maxw = qMax(maxw, 0);
4042 maxh = qMax(maxh, 0);
4043 }
4044 createExtra();
4045 if (extra->maxw == maxw && extra->maxh == maxh)
4046 return false;
4047 extra->maxw = maxw;
4048 extra->maxh = maxh;
4049 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4050 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4051 return true;
4052}
4053
4054/*!
4055 \overload
4056
4057 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4058 maxh)). Sets the maximum width to \a maxw and the maximum height
4059 to \a maxh.
4060*/
4061void QWidget::setMaximumSize(int maxw, int maxh)
4062{
4063 Q_D(QWidget);
4064 if (!d->setMaximumSize_helper(maxw, maxh))
4065 return;
4066
4067 if (isWindow())
4068 d->setConstraints_sys();
4069 if (maxw < width() || maxh < height()) {
4070 bool resized = testAttribute(Qt::WA_Resized);
4071 resize(qMin(maxw,width()), qMin(maxh,height()));
4072 setAttribute(Qt::WA_Resized, resized); //not a user resize
4073 }
4074
4075#if QT_CONFIG(graphicsview)
4076 if (d->extra) {
4077 if (d->extra->proxyWidget)
4078 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4079 }
4080#endif
4081
4082 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4083}
4084
4085/*!
4086 \overload
4087
4088 Sets the x (width) size increment to \a w and the y (height) size
4089 increment to \a h.
4090*/
4091void QWidget::setSizeIncrement(int w, int h)
4092{
4093 Q_D(QWidget);
4094 d->createTLExtra();
4095 QTLWExtra* x = d->topData();
4096 if (x->incw == w && x->inch == h)
4097 return;
4098 x->incw = w;
4099 x->inch = h;
4100 if (isWindow())
4101 d->setConstraints_sys();
4102}
4103
4104/*!
4105 \overload
4106
4107 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4108 the widgets base size to width \a basew and height \a baseh.
4109*/
4110void QWidget::setBaseSize(int basew, int baseh)
4111{
4112 Q_D(QWidget);
4113 d->createTLExtra();
4114 QTLWExtra* x = d->topData();
4115 if (x->basew == basew && x->baseh == baseh)
4116 return;
4117 x->basew = basew;
4118 x->baseh = baseh;
4119 if (isWindow())
4120 d->setConstraints_sys();
4121}
4122
4123/*!
4124 Sets both the minimum and maximum sizes of the widget to \a s,
4125 thereby preventing it from ever growing or shrinking.
4126
4127 This will override the default size constraints set by QLayout.
4128
4129 To remove constraints, set the size to QWIDGETSIZE_MAX.
4130
4131 Alternatively, if you want the widget to have a
4132 fixed size based on its contents, you can call
4133 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4134
4135 \sa maximumSize, minimumSize
4136*/
4137
4138void QWidget::setFixedSize(const QSize & s)
4139{
4140 setFixedSize(s.width(), s.height());
4141}
4142
4143
4144/*!
4145 \fn void QWidget::setFixedSize(int w, int h)
4146 \overload
4147
4148 Sets the width of the widget to \a w and the height to \a h.
4149*/
4150
4151void QWidget::setFixedSize(int w, int h)
4152{
4153 Q_D(QWidget);
4154 bool minSizeSet = d->setMinimumSize_helper(w, h);
4155 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4156 if (!minSizeSet && !maxSizeSet)
4157 return;
4158
4159 if (isWindow())
4160 d->setConstraints_sys();
4161 else
4162 d->updateGeometry_helper(true);
4163
4164 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4165 resize(w, h);
4166}
4167
4168void QWidget::setMinimumWidth(int w)
4169{
4170 Q_D(QWidget);
4171 d->createExtra();
4172 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4173 setMinimumSize(w, minimumSize().height());
4174 d->extra->explicitMinSize = expl;
4175}
4176
4177void QWidget::setMinimumHeight(int h)
4178{
4179 Q_D(QWidget);
4180 d->createExtra();
4181 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4182 setMinimumSize(minimumSize().width(), h);
4183 d->extra->explicitMinSize = expl;
4184}
4185
4186void QWidget::setMaximumWidth(int w)
4187{
4188 Q_D(QWidget);
4189 d->createExtra();
4190 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4191 setMaximumSize(w, maximumSize().height());
4192 d->extra->explicitMaxSize = expl;
4193}
4194
4195void QWidget::setMaximumHeight(int h)
4196{
4197 Q_D(QWidget);
4198 d->createExtra();
4199 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4200 setMaximumSize(maximumSize().width(), h);
4201 d->extra->explicitMaxSize = expl;
4202}
4203
4204/*!
4205 Sets both the minimum and maximum width of the widget to \a w
4206 without changing the heights. Provided for convenience.
4207
4208 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4209*/
4210
4211void QWidget::setFixedWidth(int w)
4212{
4213 Q_D(QWidget);
4214 d->createExtra();
4215 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4216 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4217 setMinimumSize(w, minimumSize().height());
4218 setMaximumSize(w, maximumSize().height());
4219 d->extra->explicitMinSize = explMin;
4220 d->extra->explicitMaxSize = explMax;
4221}
4222
4223
4224/*!
4225 Sets both the minimum and maximum heights of the widget to \a h
4226 without changing the widths. Provided for convenience.
4227
4228 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4229*/
4230
4231void QWidget::setFixedHeight(int h)
4232{
4233 Q_D(QWidget);
4234 d->createExtra();
4235 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4236 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4237 setMinimumSize(minimumSize().width(), h);
4238 setMaximumSize(maximumSize().width(), h);
4239 d->extra->explicitMinSize = explMin;
4240 d->extra->explicitMaxSize = explMax;
4241}
4242
4243
4244/*!
4245 Translates the widget coordinate \a pos to the coordinate system
4246 of \a parent. The \a parent must not be \nullptr and must be a parent
4247 of the calling widget.
4248
4249 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4250 \since 6.0
4251*/
4252
4253QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4254{
4255 QPointF p = pos;
4256 if (parent) {
4257 const QWidget * w = this;
4258 while (w != parent) {
4259 p = w->mapToParent(p);
4260 w = w->parentWidget();
4261 if (!w) {
4262 qWarning("QWidget::mapTo(): parent must be in parent hierarchy");
4263 break;
4264 }
4265 }
4266 }
4267 return p;
4268}
4269
4270/*!
4271 \overload
4272*/
4273QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4274{
4275 return mapTo(parent, QPointF(pos)).toPoint();
4276}
4277
4278/*!
4279 Translates the widget coordinate \a pos from the coordinate system
4280 of \a parent to this widget's coordinate system. The \a parent
4281 must not be \nullptr and must be a parent of the calling widget.
4282
4283 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4284 \since 6.0
4285*/
4286
4287QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4288{
4289 QPointF p(pos);
4290 if (parent) {
4291 const QWidget * w = this;
4292 while (w != parent) {
4293 p = w->mapFromParent(p);
4294 w = w->parentWidget();
4295 if (!w) {
4296 qWarning("QWidget::mapFrom(): parent must be in parent hierarchy");
4297 break;
4298 }
4299 }
4300 }
4301 return p;
4302}
4303
4304/*!
4305 \overload
4306*/
4307QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4308{
4309 return mapFrom(parent, QPointF(pos)).toPoint();
4310}
4311
4312/*!
4313 Translates the widget coordinate \a pos to a coordinate in the
4314 parent widget.
4315
4316 Same as mapToGlobal() if the widget has no parent.
4317
4318 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4319 \since 6.0
4320*/
4321
4322QPointF QWidget::mapToParent(const QPointF &pos) const
4323{
4324 return pos + QPointF(data->crect.topLeft());
4325}
4326
4327/*!
4328 \overload
4329*/
4330QPoint QWidget::mapToParent(const QPoint &pos) const
4331{
4332 return pos + data->crect.topLeft();
4333}
4334
4335/*!
4336 Translates the parent widget coordinate \a pos to widget
4337 coordinates.
4338
4339 Same as mapFromGlobal() if the widget has no parent.
4340
4341 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4342 \since 6.0
4343*/
4344
4345QPointF QWidget::mapFromParent(const QPointF &pos) const
4346{
4347 return pos - QPointF(data->crect.topLeft());
4348}
4349
4350/*!
4351 \overload
4352*/
4353QPoint QWidget::mapFromParent(const QPoint &pos) const
4354{
4355 return pos - data->crect.topLeft();
4356}
4357
4358
4359/*!
4360 Returns the window for this widget, i.e. the next ancestor widget
4361 that has (or could have) a window-system frame.
4362
4363 If the widget is a window, the widget itself is returned.
4364
4365 Typical usage is changing the window title:
4366
4367 \snippet code/src_gui_kernel_qwidget.cpp 3
4368
4369 \sa isWindow()
4370*/
4371
4372QWidget *QWidget::window() const
4373{
4374 QWidget *w = const_cast<QWidget *>(this);
4375 QWidget *p = w->parentWidget();
4376 while (!w->isWindow() && p) {
4377 w = p;
4378 p = p->parentWidget();
4379 }
4380 return w;
4381}
4382
4383/*!
4384 \since 4.4
4385
4386 Returns the native parent for this widget, i.e. the next ancestor widget
4387 that has a system identifier, or \nullptr if it does not have any native
4388 parent.
4389
4390 \sa effectiveWinId()
4391*/
4392QWidget *QWidget::nativeParentWidget() const
4393{
4394 QWidget *parent = parentWidget();
4395 while (parent && !parent->internalWinId())
4396 parent = parent->parentWidget();
4397 return parent;
4398}
4399
4400/*! \fn QWidget *QWidget::topLevelWidget() const
4401 \deprecated
4402
4403 Use window() instead.
4404*/
4405
4406
4407
4408/*!
4409 Returns the background role of the widget.
4410
4411 The background role defines the brush from the widget's \l palette that
4412 is used to render the background.
4413
4414 If no explicit background role is set, the widget inherits its parent
4415 widget's background role.
4416
4417 \sa setBackgroundRole(), foregroundRole()
4418 */
4419QPalette::ColorRole QWidget::backgroundRole() const
4420{
4421
4422 const QWidget *w = this;
4423 do {
4424 QPalette::ColorRole role = w->d_func()->bg_role;
4425 if (role != QPalette::NoRole)
4426 return role;
4427 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4428 break;
4429 w = w->parentWidget();
4430 } while (w);
4431 return QPalette::Window;
4432}
4433
4434/*!
4435 Sets the background role of the widget to \a role.
4436
4437 The background role defines the brush from the widget's \l palette that
4438 is used to render the background.
4439
4440 If \a role is QPalette::NoRole, then the widget inherits its
4441 parent's background role.
4442
4443 Note that styles are free to choose any color from the palette.
4444 You can modify the palette or set a style sheet if you don't
4445 achieve the result you want with setBackgroundRole().
4446
4447 \sa backgroundRole(), foregroundRole()
4448 */
4449
4450void QWidget::setBackgroundRole(QPalette::ColorRole role)
4451{
4452 Q_D(QWidget);
4453 d->bg_role = role;
4454 d->updateSystemBackground();
4455 d->propagatePaletteChange();
4456 d->updateIsOpaque();
4457}
4458
4459/*!
4460 Returns the foreground role.
4461
4462 The foreground role defines the color from the widget's \l palette that
4463 is used to draw the foreground.
4464
4465 If no explicit foreground role is set, the function returns a role
4466 that contrasts with the background role.
4467
4468 \sa setForegroundRole(), backgroundRole()
4469 */
4470QPalette::ColorRole QWidget::foregroundRole() const
4471{
4472 Q_D(const QWidget);
4473 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4474 if (rl != QPalette::NoRole)
4475 return rl;
4476 QPalette::ColorRole role = QPalette::WindowText;
4477 switch (backgroundRole()) {
4478 case QPalette::Button:
4479 role = QPalette::ButtonText;
4480 break;
4481 case QPalette::Base:
4482 role = QPalette::Text;
4483 break;
4484 case QPalette::Dark:
4485 case QPalette::Shadow:
4486 role = QPalette::Light;
4487 break;
4488 case QPalette::Highlight:
4489 role = QPalette::HighlightedText;
4490 break;
4491 case QPalette::ToolTipBase:
4492 role = QPalette::ToolTipText;
4493 break;
4494 default:
4495 ;
4496 }
4497 return role;
4498}
4499
4500/*!
4501 Sets the foreground role of the widget to \a role.
4502
4503 The foreground role defines the color from the widget's \l palette that
4504 is used to draw the foreground.
4505
4506 If \a role is QPalette::NoRole, the widget uses a foreground role
4507 that contrasts with the background role.
4508
4509 Note that styles are free to choose any color from the palette.
4510 You can modify the palette or set a style sheet if you don't
4511 achieve the result you want with setForegroundRole().
4512
4513 \sa foregroundRole(), backgroundRole()
4514 */
4515void QWidget::setForegroundRole(QPalette::ColorRole role)
4516{
4517 Q_D(QWidget);
4518 d->fg_role = role;
4519 d->updateSystemBackground();
4520 d->propagatePaletteChange();
4521}
4522
4523/*!
4524 \property QWidget::palette
4525 \brief the widget's palette
4526
4527 This property describes the widget's palette. The palette is used by the
4528 widget's style when rendering standard components, and is available as a
4529 means to ensure that custom widgets can maintain consistency with the
4530 native platform's look and feel. It's common that different platforms, or
4531 different styles, have different palettes.
4532
4533 When you assign a new palette to a widget, the color roles from this
4534 palette are combined with the widget's default palette to form the
4535 widget's final palette. The palette entry for the widget's background role
4536 is used to fill the widget's background (see QWidget::autoFillBackground),
4537 and the foreground role initializes QPainter's pen.
4538
4539 The default depends on the system environment. QApplication maintains a
4540 system/theme palette which serves as a default for all widgets. There may
4541 also be special palette defaults for certain types of widgets (e.g., on
4542 Windows Vista, all classes that derive from QMenuBar have a special
4543 default palette). You can also define default palettes for widgets
4544 yourself by passing a custom palette and the name of a widget to
4545 QApplication::setPalette(). Finally, the style always has the option of
4546 polishing the palette as it's assigned (see QStyle::polish()).
4547
4548 QWidget propagates explicit palette roles from parent to child. If you
4549 assign a brush or color to a specific role on a palette and assign that
4550 palette to a widget, that role will propagate to all the widget's
4551 children, overriding any system defaults for that role. Note that palettes
4552 by default don't propagate to windows (see isWindow()) unless the
4553 Qt::WA_WindowPropagation attribute is enabled.
4554
4555 QWidget's palette propagation is similar to its font propagation.
4556
4557 The current style, which is used to render the content of all standard Qt
4558 widgets, is free to choose colors and brushes from the widget palette, or,
4559 in some cases, to ignore the palette (partially, or completely). In
4560 particular, certain styles like GTK style, Mac style, and Windows Vista
4561 style, depend on third party APIs to render the content of widgets,
4562 and these styles typically do not follow the palette. Because of this,
4563 assigning roles to a widget's palette is not guaranteed to change the
4564 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4565
4566 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4567 When using style sheets, the palette of a widget can be customized using
4568 the "color", "background-color", "selection-color",
4569 "selection-background-color" and "alternate-background-color".
4570
4571 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4572*/
4573const QPalette &QWidget::palette() const
4574{
4575 if (!isEnabled()) {
4576 data->pal.setCurrentColorGroup(QPalette::Disabled);
4577 } else if ((!isVisible() || isActiveWindow())
4578#if defined(Q_OS_WIN)
4579 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4580#endif
4581 ) {
4582 data->pal.setCurrentColorGroup(QPalette::Active);
4583 } else {
4584 data->pal.setCurrentColorGroup(QPalette::Inactive);
4585 }
4586 return data->pal;
4587}
4588
4589void QWidget::setPalette(const QPalette &palette)
4590{
4591 Q_D(QWidget);
4592 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4593
4594 // Determine which palette is inherited from this widget's ancestors and
4595 // QApplication::palette, resolve this against \a palette (attributes from
4596 // the inherited palette are copied over this widget's palette). Then
4597 // propagate this palette to this widget's children.
4598 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4599 QPalette resolvedPalette = palette.resolve(naturalPalette);
4600 d->setPalette_helper(resolvedPalette);
4601}
4602
4603/*!
4604 \internal
4605
4606 Returns the palette that the widget \a w inherits from its ancestors and
4607 QApplication::palette. \a inheritedMask is the combination of the widget's
4608 ancestors palette request masks (i.e., which attributes from the parent
4609 widget's palette are implicitly imposed on this widget by the user). Note
4610 that this font does not take into account the palette set on \a w itself.
4611*/
4612QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4613{
4614 Q_Q(const QWidget);
4615
4616 const bool useStyleSheetPropagationInWidgetStyles =
4617 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4618
4619 QPalette naturalPalette = QApplication::palette(q);
4620 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4621 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4622#if QT_CONFIG(graphicsview)
4623 || (extra && extra->proxyWidget)
4624#endif // QT_CONFIG(graphicsview)
4625 )) {
4626 if (QWidget *p = q->parentWidget()) {
4627 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4628 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4629 QPalette inheritedPalette = p->palette();
4630 inheritedPalette.setResolveMask(inheritedMask);
4631 naturalPalette = inheritedPalette.resolve(naturalPalette);
4632 } else {
4633 naturalPalette = p->palette();
4634 }
4635 }
4636 }
4637#if QT_CONFIG(graphicsview)
4638 else if (extra && extra->proxyWidget) {
4639 QPalette inheritedPalette = extra->proxyWidget->palette();
4640 inheritedPalette.setResolveMask(inheritedMask);
4641 naturalPalette = inheritedPalette.resolve(naturalPalette);
4642 }
4643#endif // QT_CONFIG(graphicsview)
4644 }
4645 naturalPalette.setResolveMask(0);
4646 return naturalPalette;
4647}
4648/*!
4649 \internal
4650
4651 Determine which palette is inherited from this widget's ancestors and
4652 QApplication::palette, resolve this against this widget's palette
4653 (attributes from the inherited palette are copied over this widget's
4654 palette). Then propagate this palette to this widget's children.
4655*/
4656void QWidgetPrivate::resolvePalette()
4657{
4658 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4659 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4660 setPalette_helper(resolvedPalette);
4661}
4662
4663void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4664{
4665 Q_Q(QWidget);
4666 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4667 return;
4668 data.pal = palette;
4669 updateSystemBackground();
4670 propagatePaletteChange();
4671 updateIsOpaque();
4672 q->update();
4673 updateIsOpaque();
4674}
4675
4676void QWidgetPrivate::updateSystemBackground()
4677{
4678}
4679
4680/*!
4681 \property QWidget::font
4682 \brief the font currently set for the widget
4683
4684 This property describes the widget's requested font. The font is used by
4685 the widget's style when rendering standard components, and is available as
4686 a means to ensure that custom widgets can maintain consistency with the
4687 native platform's look and feel. It's common that different platforms, or
4688 different styles, define different fonts for an application.
4689
4690 When you assign a new font to a widget, the properties from this font are
4691 combined with the widget's default font to form the widget's final
4692 font. You can call fontInfo() to get a copy of the widget's final
4693 font. The final font is also used to initialize QPainter's font.
4694
4695 The default depends on the system environment. QApplication maintains a
4696 system/theme font which serves as a default for all widgets. There may
4697 also be special font defaults for certain types of widgets. You can also
4698 define default fonts for widgets yourself by passing a custom font and the
4699 name of a widget to QApplication::setFont(). Finally, the font is matched
4700 against Qt's font database to find the best match.
4701
4702 QWidget propagates explicit font properties from parent to child. If you
4703 change a specific property on a font and assign that font to a widget,
4704 that property will propagate to all the widget's children, overriding any
4705 system defaults for that property. Note that fonts by default don't
4706 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4707 attribute is enabled.
4708
4709 QWidget's font propagation is similar to its palette propagation.
4710
4711 The current style, which is used to render the content of all standard Qt
4712 widgets, is free to choose to use the widget font, or in some cases, to
4713 ignore it (partially, or completely). In particular, certain styles like
4714 GTK style, Mac style, and Windows Vista style, apply special
4715 modifications to the widget font to match the platform's native look and
4716 feel. Because of this, assigning properties to a widget's font is not
4717 guaranteed to change the appearance of the widget. Instead, you may choose
4718 to apply a \l styleSheet.
4719
4720 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4721 style sheets will take precedence if the settings conflict.
4722
4723 \sa fontInfo(), fontMetrics()
4724*/
4725
4726void QWidget::setFont(const QFont &font)
4727{
4728 Q_D(QWidget);
4729
4730#if QT_CONFIG(style_stylesheet)
4731 const QStyleSheetStyle* style;
4732 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4733 style->saveWidgetFont(this, font);
4734#endif
4735
4736 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4737
4738 // Determine which font is inherited from this widget's ancestors and
4739 // QApplication::font, resolve this against \a font (attributes from the
4740 // inherited font are copied over). Then propagate this font to this
4741 // widget's children.
4742 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4743 QFont resolvedFont = font.resolve(naturalFont);
4744 d->setFont_helper(resolvedFont);
4745}
4746
4747/*
4748 \internal
4749
4750 Returns the font that the widget \a w inherits from its ancestors and
4751 QApplication::font. \a inheritedMask is the combination of the widget's
4752 ancestors font request masks (i.e., which attributes from the parent
4753 widget's font are implicitly imposed on this widget by the user). Note
4754 that this font does not take into account the font set on \a w itself.
4755
4756 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4757 is applied, fonts are not propagated anymore
4758*/
4759QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4760{
4761 Q_Q(const QWidget);
4762
4763 const bool useStyleSheetPropagationInWidgetStyles =
4764 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4765
4766 QFont naturalFont = QApplication::font(q);
4767 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4768 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4769#if QT_CONFIG(graphicsview)
4770 || (extra && extra->proxyWidget)
4771#endif // QT_CONFIG(graphicsview)
4772 )) {
4773 if (QWidget *p = q->parentWidget()) {
4774 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4775 if (!naturalFont.isCopyOf(QApplication::font())) {
4776 if (inheritedMask != 0) {
4777 QFont inheritedFont = p->font();
4778 inheritedFont.setResolveMask(inheritedMask);
4779 naturalFont = inheritedFont.resolve(naturalFont);
4780 } // else nothing to do (naturalFont = naturalFont)
4781 } else {
4782 naturalFont = p->font();
4783 }
4784 }
4785 }
4786#if QT_CONFIG(graphicsview)
4787 else if (extra && extra->proxyWidget) {
4788 if (inheritedMask != 0) {
4789 QFont inheritedFont = extra->proxyWidget->font();
4790 inheritedFont.setResolveMask(inheritedMask);
4791 naturalFont = inheritedFont.resolve(naturalFont);
4792 } // else nothing to do (naturalFont = naturalFont)
4793 }
4794#endif // QT_CONFIG(graphicsview)
4795 }
4796 naturalFont.setResolveMask(0);
4797 return naturalFont;
4798}
4799
4800/*!
4801 \internal
4802
4803 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4804*/
4805QFont QWidgetPrivate::localFont() const
4806{
4807 QFont localfont = data.fnt;
4808 localfont.setResolveMask(directFontResolveMask);
4809 return localfont;
4810}
4811
4812/*!
4813 \internal
4814
4815 Determine which font is implicitly imposed on this widget by its ancestors
4816 and QApplication::font, resolve this against its own font (attributes from
4817 the implicit font are copied over). Then propagate this font to this
4818 widget's children.
4819*/
4820void QWidgetPrivate::resolveFont()
4821{
4822 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4823 QFont resolvedFont = localFont().resolve(naturalFont);
4824 setFont_helper(resolvedFont);
4825}
4826
4827/*!
4828 \internal
4829
4830 Assign \a font to this widget, and propagate it to all children, except
4831 style sheet widgets (handled differently) and windows that don't enable
4832 window propagation. \a implicitMask is the union of all ancestor widgets'
4833 font request masks, and determines which attributes from this widget's
4834 font should propagate.
4835*/
4836void QWidgetPrivate::updateFont(const QFont &font)
4837{
4838 Q_Q(QWidget);
4839#if QT_CONFIG(style_stylesheet)
4840 const QStyleSheetStyle* cssStyle;
4841 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4842 const bool useStyleSheetPropagationInWidgetStyles =
4843 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4844#endif
4845
4846 data.fnt = QFont(font, q);
4847
4848 // Combine new mask with natural mask and propagate to children.
4849#if QT_CONFIG(graphicsview)
4850 if (!q->parentWidget() && extra && extra->proxyWidget) {
4851 QGraphicsProxyWidget *p = extra->proxyWidget;
4852 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4853 } else
4854#endif // QT_CONFIG(graphicsview)
4855 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4856 inheritedFontResolveMask = 0;
4857 }
4858 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4859 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4860 // isn't all weak information, but save the original mask to be able to let new changes on the
4861 // parent widget font propagate correctly.
4862 directFontResolveMask = data.fnt.resolveMask();
4863 data.fnt.setResolveMask(newMask);
4864
4865 for (int i = 0; i < children.size(); ++i) {
4866 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4867 if (w) {
4868 if (0) {
4869#if QT_CONFIG(style_stylesheet)
4870 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4871 // Style sheets follow a different font propagation scheme.
4872 if (cssStyle)
4873 cssStyle->updateStyleSheetFont(w);
4874#endif
4875 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4876 // Propagate font changes.
4877 QWidgetPrivate *wd = w->d_func();
4878 wd->inheritedFontResolveMask = newMask;
4879 wd->resolveFont();
4880 }
4881 }
4882 }
4883
4884#if QT_CONFIG(style_stylesheet)
4885 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4886 cssStyle->updateStyleSheetFont(q);
4887 }
4888#endif
4889
4890 QEvent e(QEvent::FontChange);
4891 QCoreApplication::sendEvent(q, &e);
4892}
4893
4894void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4895{
4896 Q_Q(QWidget);
4897
4898 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4899 return;
4900 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4901 if (!children.isEmpty()) {
4902 for (int i = 0; i < children.size(); ++i) {
4903 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4904 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4905 w->d_func()->setLayoutDirection_helper(direction);
4906 }
4907 }
4908 QEvent e(QEvent::LayoutDirectionChange);
4909 QCoreApplication::sendEvent(q, &e);
4910}
4911
4912void QWidgetPrivate::resolveLayoutDirection()
4913{
4914 Q_Q(const QWidget);
4915 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4916 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4917}
4918
4919/*!
4920 \property QWidget::layoutDirection
4921
4922 \brief the layout direction for this widget.
4923
4924 \note This method no longer affects text layout direction since Qt 4.7.
4925
4926 By default, this property is set to Qt::LeftToRight.
4927
4928 When the layout direction is set on a widget, it will propagate to
4929 the widget's children, but not to a child that is a window and not
4930 to a child for which setLayoutDirection() has been explicitly
4931 called. Also, child widgets added \e after setLayoutDirection()
4932 has been called for the parent do not inherit the parent's layout
4933 direction.
4934
4935
4936 \sa QApplication::layoutDirection
4937*/
4938void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4939{
4940 Q_D(QWidget);
4941
4942 if (direction == Qt::LayoutDirectionAuto) {
4943 unsetLayoutDirection();
4944 return;
4945 }
4946
4947 setAttribute(Qt::WA_SetLayoutDirection);
4948 d->setLayoutDirection_helper(direction);
4949}
4950
4951Qt::LayoutDirection QWidget::layoutDirection() const
4952{
4953 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4954}
4955
4956void QWidget::unsetLayoutDirection()
4957{
4958 Q_D(QWidget);
4959 setAttribute(Qt::WA_SetLayoutDirection, false);
4960 d->resolveLayoutDirection();
4961}
4962
4963/*!
4964 \fn QFontMetrics QWidget::fontMetrics() const
4965
4966 Returns the font metrics for the widget's current font.
4967 Equivalent to \c QFontMetrics(widget->font()).
4968
4969 \sa font(), fontInfo(), setFont()
4970*/
4971
4972/*!
4973 \fn QFontInfo QWidget::fontInfo() const
4974
4975 Returns the font info for the widget's current font.
4976 Equivalent to \c QFontInfo(widget->font()).
4977
4978 \sa font(), fontMetrics(), setFont()
4979*/
4980
4981
4982/*!
4983 \property QWidget::cursor
4984 \brief the cursor shape for this widget
4985
4986 The mouse cursor will assume this shape when it's over this
4987 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4988
4989 An editor widget might use an I-beam cursor:
4990 \snippet code/src_gui_kernel_qwidget.cpp 6
4991
4992 If no cursor has been set, or after a call to unsetCursor(), the
4993 parent's cursor is used.
4994
4995 By default, this property contains a cursor with the Qt::ArrowCursor
4996 shape.
4997
4998 Some underlying window implementations will reset the cursor if it
4999 leaves a widget even if the mouse is grabbed. If you want to have
5000 a cursor set for all widgets, even when outside the window, consider
5001 QGuiApplication::setOverrideCursor().
5002
5003 \sa QGuiApplication::setOverrideCursor()
5004*/
5005
5006#ifndef QT_NO_CURSOR
5007QCursor QWidget::cursor() const
5008{
5009 Q_D(const QWidget);
5010 if (testAttribute(Qt::WA_SetCursor))
5011 return (d->extra && d->extra->curs)
5012 ? *d->extra->curs
5013 : QCursor(Qt::ArrowCursor);
5014 if (isWindow() || !parentWidget())
5015 return QCursor(Qt::ArrowCursor);
5016 return parentWidget()->cursor();
5017}
5018
5019void QWidget::setCursor(const QCursor &cursor)
5020{
5021 Q_D(QWidget);
5022 if (cursor.shape() != Qt::ArrowCursor
5023 || (d->extra && d->extra->curs))
5024 {
5025 d->createExtra();
5026 d->extra->curs = std::make_unique<QCursor>(cursor);
5027 }
5028 setAttribute(Qt::WA_SetCursor);
5029 d->setCursor_sys(cursor);
5030
5031 QEvent event(QEvent::CursorChange);
5032 QCoreApplication::sendEvent(this, &event);
5033}
5034
5035void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5036{
5037 Q_UNUSED(cursor);
5038 Q_Q(QWidget);
5039 qt_qpa_set_cursor(q, false);
5040}
5041
5042void QWidget::unsetCursor()
5043{
5044 Q_D(QWidget);
5045 if (d->extra)
5046 d->extra->curs.reset();
5047 if (!isWindow())
5048 setAttribute(Qt::WA_SetCursor, false);
5049 d->unsetCursor_sys();
5050
5051 QEvent event(QEvent::CursorChange);
5052 QCoreApplication::sendEvent(this, &event);
5053}
5054
5055void QWidgetPrivate::unsetCursor_sys()
5056{
5057 Q_Q(QWidget);
5058 qt_qpa_set_cursor(q, false);
5059}
5060
5061static inline void applyCursor(QWidget *w, const QCursor &c)
5062{
5063 if (QWindow *window = w->windowHandle())
5064 window->setCursor(c);
5065}
5066
5067static inline void unsetCursor(QWidget *w)
5068{
5069 if (QWindow *window = w->windowHandle())
5070 window->unsetCursor();
5071}
5072
5073void qt_qpa_set_cursor(QWidget *w, bool force)
5074{
5075 if (!w->testAttribute(Qt::WA_WState_Created))
5076 return;
5077
5078 static QPointer<QWidget> lastUnderMouse = nullptr;
5079 if (force) {
5080 lastUnderMouse = w;
5081 } else if (lastUnderMouse) {
5082 const WId lastWinId = lastUnderMouse->effectiveWinId();
5083 const WId winId = w->effectiveWinId();
5084 if (lastWinId && lastWinId == winId)
5085 w = lastUnderMouse;
5086 } else if (!w->internalWinId()) {
5087 return; // The mouse is not under this widget, and it's not native, so don't change it.
5088 }
5089
5090 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5091 && !w->testAttribute(Qt::WA_SetCursor))
5092 w = w->parentWidget();
5093
5094 QWidget *nativeParent = w;
5095 if (!w->internalWinId())
5096 nativeParent = w->nativeParentWidget();
5097 if (!nativeParent || !nativeParent->internalWinId())
5098 return;
5099
5100 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
5101 if (w->isEnabled())
5102 applyCursor(nativeParent, w->cursor());
5103 else
5104 // Enforce the windows behavior of clearing the cursor on
5105 // disabled widgets.
5106 unsetCursor(nativeParent);
5107 } else {
5108 unsetCursor(nativeParent);
5109 }
5110}
5111#endif
5112
5113/*!
5114 \enum QWidget::RenderFlag
5115
5116 This enum describes how to render the widget when calling QWidget::render().
5117
5118 \value DrawWindowBackground If you enable this option, the widget's background
5119 is rendered into the target even if autoFillBackground is not set. By default,
5120 this option is enabled.
5121
5122 \value DrawChildren If you enable this option, the widget's children
5123 are rendered recursively into the target. By default, this option is enabled.
5124
5125 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5126 is ignored when rendering into the target. By default, this option is disabled.
5127
5128 \since 4.3
5129*/
5130
5131/*!
5132 \since 4.3
5133
5134 Renders the \a sourceRegion of this widget into the \a target
5135 using \a renderFlags to determine how to render. Rendering
5136 starts at \a targetOffset in the \a target. For example:
5137
5138 \snippet code/src_gui_kernel_qwidget.cpp 7
5139
5140 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5141 the region, i.e. the entire widget.
5142
5143 Ensure that you call QPainter::end() for the \a target device's
5144 active painter (if any) before rendering. For example:
5145
5146 \snippet code/src_gui_kernel_qwidget.cpp 8
5147
5148 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5149 instead.
5150*/
5151void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5152 const QRegion &sourceRegion, RenderFlags renderFlags)
5153{
5154 QPainter p(target);
5155 render(&p, targetOffset, sourceRegion, renderFlags);
5156}
5157
5158/*!
5159 \overload
5160
5161 Renders the widget into the \a painter's QPainter::device().
5162
5163 Transformations and settings applied to the \a painter will be used
5164 when rendering.
5165
5166 \note The \a painter must be active. On \macos the widget will be
5167 rendered into a QPixmap and then drawn by the \a painter.
5168
5169 \sa QPainter::device()
5170*/
5171void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5172 const QRegion &sourceRegion, RenderFlags renderFlags)
5173{
5174 if (Q_UNLIKELY(!painter)) {
5175 qWarning("QWidget::render: Null pointer to painter");
5176 return;
5177 }
5178
5179 if (Q_UNLIKELY(!painter->isActive())) {
5180 qWarning("QWidget::render: Cannot render with an inactive painter");
5181 return;
5182 }
5183
5184 const qreal opacity = painter->opacity();
5185 if (qFuzzyIsNull(opacity))
5186 return; // Fully transparent.
5187
5188 Q_D(QWidget);
5189 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5190 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
5191 : sourceRegion;
5192 if (toBePainted.isEmpty())
5193 return;
5194
5195 if (!d->extra)
5196 d->createExtra();
5197 d->extra->inRenderWithPainter = true;
5198
5199 QPaintEngine *engine = painter->paintEngine();
5200 Q_ASSERT(engine);
5201 QPaintEnginePrivate *enginePriv = engine->d_func();
5202 Q_ASSERT(enginePriv);
5203 QPaintDevice *target = engine->paintDevice();
5204 Q_ASSERT(target);
5205
5206 // Render via a pixmap when dealing with non-opaque painters or printers.
5207 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5208 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
5209 d->extra->inRenderWithPainter = inRenderWithPainter;
5210 return;
5211 }
5212
5213 // Set new shared painter.
5214 QPainter *oldPainter = d->sharedPainter();
5215 d->setSharedPainter(painter);
5216
5217 // Save current system clip, viewport and transform,
5218 const QTransform oldTransform = enginePriv->systemTransform;
5219 const QRegion oldSystemClip = enginePriv->systemClip;
5220 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5221 const QRegion oldSystemViewport = enginePriv->systemViewport;
5222 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5223
5224 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5225 if (painter->hasClipping()) {
5226 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5227 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5228 } else {
5229 enginePriv->setSystemViewport(oldSystemClip);
5230 }
5231 painter->setLayoutDirection(layoutDirection());
5232
5233 d->render(target, targetOffset, toBePainted, renderFlags);
5234
5235 // Restore system clip, viewport and transform.
5236 enginePriv->baseSystemClip = oldBaseClip;
5237 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5238 enginePriv->systemStateChanged();
5239 painter->setLayoutDirection(oldLayoutDirection);
5240
5241 // Restore shared painter.
5242 d->setSharedPainter(oldPainter);
5243
5244 d->extra->inRenderWithPainter = inRenderWithPainter;
5245}
5246
5247static void sendResizeEvents(QWidget *target)
5248{
5249 QResizeEvent e(target->size(), QSize());
5250 QCoreApplication::sendEvent(target, &e);
5251
5252 const QObjectList children = target->children();
5253 for (int i = 0; i < children.size(); ++i) {
5254 if (!children.at(i)->isWidgetType())
5255 continue;
5256 QWidget *child = static_cast<QWidget*>(children.at(i));
5257 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5258 sendResizeEvents(child);
5259 }
5260}
5261
5262/*!
5263 \since 5.0
5264
5265 Renders the widget into a pixmap restricted by the
5266 given \a rectangle. If the widget has any children, then
5267 they are also painted in the appropriate positions.
5268
5269 If a rectangle with an invalid size is specified (the default),
5270 the entire widget is painted.
5271
5272 \sa render(), QPixmap
5273*/
5274QPixmap QWidget::grab(const QRect &rectangle)
5275{
5276 Q_D(QWidget);
5277 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5278 sendResizeEvents(this);
5279
5280 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5281
5282 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5283 QRect r(rectangle);
5284 if (r.width() < 0 || r.height() < 0) {
5285 // For grabbing widgets that haven't been shown yet,
5286 // we trigger the layouting mechanism to determine the widget's size.
5287 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5288 r.setTopLeft(rectangle.topLeft());
5289 }
5290
5291 if (!r.intersects(rect()))
5292 return QPixmap();
5293
5294 const qreal dpr = devicePixelRatio();
5295 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5296 res.setDevicePixelRatio(dpr);
5297 if (!d->isOpaque)
5298 res.fill(Qt::transparent);
5299 d->render(&res, QPoint(), QRegion(r), renderFlags);
5300
5301 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5302 return res;
5303}
5304
5305/*!
5306 \brief The graphicsEffect function returns a pointer to the
5307 widget's graphics effect.
5308
5309 If the widget has no graphics effect, \nullptr is returned.
5310
5311 \since 4.6
5312
5313 \sa setGraphicsEffect()
5314*/
5315#if QT_CONFIG(graphicseffect)
5316QGraphicsEffect *QWidget::graphicsEffect() const
5317{
5318 Q_D(const QWidget);
5319 return d->graphicsEffect;
5320}
5321#endif // QT_CONFIG(graphicseffect)
5322
5323/*!
5324
5325 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5326
5327 Sets \a effect as the widget's effect. If there already is an effect installed
5328 on this widget, QWidget will delete the existing effect before installing
5329 the new \a effect.
5330
5331 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5332 the effect from the widget and install it on this widget.
5333
5334 QWidget takes ownership of \a effect.
5335
5336 \note This function will apply the effect on itself and all its children.
5337
5338 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5339 QOpenGLWidget and QQuickWidget.
5340
5341 \since 4.6
5342
5343 \sa graphicsEffect()
5344*/
5345#if QT_CONFIG(graphicseffect)
5346void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5347{
5348 Q_D(QWidget);
5349 if (d->graphicsEffect == effect)
5350 return;
5351
5352 if (d->graphicsEffect) {
5353 d->invalidateBackingStore(rect());
5354 delete d->graphicsEffect;
5355 d->graphicsEffect = nullptr;
5356 }
5357
5358 if (effect) {
5359 // Set new effect.
5360 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5361 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5362 d->graphicsEffect = effect;
5363 effect->d_func()->setGraphicsEffectSource(source);
5364 update();
5365 }
5366
5367 d->updateIsOpaque();
5368}
5369#endif // QT_CONFIG(graphicseffect)
5370
5371bool QWidgetPrivate::isAboutToShow() const
5372{
5373 if (data.in_show)
5374 return true;
5375
5376 Q_Q(const QWidget);
5377 if (q->isHidden())
5378 return false;
5379
5380 // The widget will be shown if any of its ancestors are about to show.
5381 QWidget *parent = q->parentWidget();
5382 return parent ? parent->d_func()->isAboutToShow() : false;
5383}
5384
5385QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5386{
5387 Q_Q(QWidget);
5388 const bool isVisible = q->isVisible();
5389
5390 // Make sure the widget is laid out correctly.
5391 if (!isVisible && !isAboutToShow()) {
5392 QWidget *topLevel = q->window();
5393 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5394 topLevel->ensurePolished();
5395
5396 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5397 // they're not explicitly hidden.
5398 QWidget *widget = q;
5399 QWidgetList hiddenWidgets;
5400 while (widget) {
5401 if (widget->isHidden()) {
5402 widget->setAttribute(Qt::WA_WState_Hidden, false);
5403 hiddenWidgets.append(widget);
5404 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5405 widget->d_func()->updateGeometry_helper(true);
5406 }
5407 widget = widget->parentWidget();
5408 }
5409
5410 // Activate top-level layout.
5411 if (topLevel->d_func()->layout)
5412 topLevel->d_func()->layout->activate();
5413
5414 // Adjust size if necessary.
5415 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5416 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5417 && !topLevel->testAttribute(Qt::WA_Resized)) {
5418 topLevel->adjustSize();
5419 topLevel->setAttribute(Qt::WA_Resized, false);
5420 }
5421
5422 // Activate child layouts.
5423 topLevel->d_func()->activateChildLayoutsRecursively();
5424
5425 // We're not cheating with WA_WState_Hidden anymore.
5426 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5427 QWidget *widget = hiddenWidgets.at(i);
5428 widget->setAttribute(Qt::WA_WState_Hidden);
5429 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5430 widget->parentWidget()->d_func()->layout->invalidate();
5431 }
5432 } else if (isVisible) {
5433 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5434 }
5435
5436 // Calculate the region to be painted.
5437 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5438 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5439 toBePainted &= extra->mask;
5440 return toBePainted;
5441}
5442
5443void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5444 QWidget::RenderFlags renderFlags)
5445{
5446 Q_ASSERT(painter);
5447 Q_ASSERT(!toBePainted.isEmpty());
5448
5449 Q_Q(QWidget);
5450 const QTransform originalTransform = painter->worldTransform();
5451 const bool useDeviceCoordinates = originalTransform.isScaling();
5452 if (!useDeviceCoordinates) {
5453 // Render via a pixmap.
5454 const QRect rect = toBePainted.boundingRect();
5455 const QSize size = rect.size();
5456 if (size.isNull())
5457 return;
5458
5459 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5460 QPixmap pixmap(size * pixmapDevicePixelRatio);
5461 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5462
5463 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5464 pixmap.fill(Qt::transparent);
5465 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5466
5467 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5468 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5469
5470 painter->drawPixmap(targetOffset, pixmap);
5471
5472 if (restore)
5473 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5474
5475 } else {
5476 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5477 QTransform transform = originalTransform;
5478 transform.translate(targetOffset.x(), targetOffset.y());
5479
5480 QPaintDevice *device = painter->device();
5481 Q_ASSERT(device);
5482
5483 // Calculate device rect.
5484 const QRectF rect(toBePainted.boundingRect());
5485 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5486 deviceRect &= QRect(0, 0, device->width(), device->height());
5487
5488 QPixmap pixmap(deviceRect.size());
5489 pixmap.fill(Qt::transparent);
5490
5491 // Create a pixmap device coordinate painter.
5492 QPainter pixmapPainter(&pixmap);
5493 pixmapPainter.setRenderHints(painter->renderHints());
5494 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5495 pixmapPainter.setTransform(transform);
5496
5497 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5498 pixmapPainter.end();
5499
5500 // And then draw the pixmap.
5501 painter->setTransform(QTransform());
5502 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5503 painter->setTransform(originalTransform);
5504 }
5505}
5506
5507void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5508 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5509{
5510 if (rgn.isEmpty())
5511 return;
5512
5513 Q_Q(QWidget);
5514
5515 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5516 << "into paint device" << pdev << "with" << flags;
5517
5518 const bool asRoot = flags & DrawAsRoot;
5519 bool onScreen = shouldPaintOnScreen();
5520
5521#if QT_CONFIG(graphicseffect)
5522 if (graphicsEffect && graphicsEffect->isEnabled()) {
5523 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5524 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5525 (source->d_func());
5526 if (!sourced->context) {
5527 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5528 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5529 sourced->context = &context;
5530 if (!sharedPainter) {
5531 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), effectRgn.translated(offset));
5532 QPainter p(pdev);
5533 p.translate(offset);
5534 context.painter = &p;
5535 graphicsEffect->draw(&p);
5536 setSystemClip(pdev->paintEngine(), 1, QRegion());
5537 } else {
5538 context.painter = sharedPainter;
5539 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5540 sourced->invalidateCache();
5541 sourced->lastEffectTransform = sharedPainter->worldTransform();
5542 }
5543 sharedPainter->save();
5544 sharedPainter->translate(offset);
5545 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), effectRgn.translated(offset));
5546 graphicsEffect->draw(sharedPainter);
5547 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5548 sharedPainter->restore();
5549 }
5550 sourced->context = nullptr;
5551
5552 if (repaintManager)
5553 repaintManager->markNeedsFlush(q, effectRgn, offset);
5554
5555 return;
5556 }
5557 }
5558#endif // QT_CONFIG(graphicseffect)
5559 flags = flags & ~UseEffectRegionBounds;
5560
5561 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5562 const bool recursive = flags & DrawRecursive;
5563 const bool alsoInvisible = flags & DrawInvisible;
5564
5565 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5566
5567 QRegion toBePainted(rgn);
5568 if (asRoot && !alsoInvisible)
5569 toBePainted &= clipRect(); //(rgn & visibleRegion());
5570 if (!(flags & DontSubtractOpaqueChildren))
5571 subtractOpaqueChildren(toBePainted, q->rect());
5572
5573 if (!toBePainted.isEmpty()) {
5574 if (!onScreen || alsoOnScreen) {
5575 //update the "in paint event" flag
5576 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5577 qWarning("QWidget::repaint: Recursive repaint detected");
5578 q->setAttribute(Qt::WA_WState_InPaintEvent);
5579
5580 //clip away the new area
5581 QPaintEngine *paintEngine = pdev->paintEngine();
5582 if (paintEngine) {
5583 setRedirected(pdev, -offset);
5584
5585 if (sharedPainter)
5586 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5587 else
5588 paintEngine->d_func()->systemRect = q->data->crect;
5589
5590 //paint the background
5591 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5592 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5593 beginBackingStorePainting();
5594 QPainter p(q);
5595 p.setRenderHint(QPainter::SmoothPixmapTransform);
5596 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5597 endBackingStorePainting();
5598 }
5599
5600 if (!sharedPainter)
5601 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5602
5603 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5604 beginBackingStorePainting();
5605 QPainter p(q);
5606 QColor tint = q->palette().window().color();
5607 tint.setAlphaF(.6f);
5608 p.fillRect(toBePainted.boundingRect(), tint);
5609 endBackingStorePainting();
5610 }
5611 }
5612
5613#if 0
5614 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5615 qDebug() << "clipping to" << toBePainted << "location == " << offset
5616 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5617#endif
5618
5619 bool skipPaintEvent = false;
5620 if (renderToTexture) {
5621 // This widget renders into a texture which is composed later. We just need to
5622 // punch a hole in the backingstore, so the texture will be visible.
5623 beginBackingStorePainting();
5624 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5625 QPainter p(q);
5626 p.setCompositionMode(QPainter::CompositionMode_Source);
5627 p.fillRect(q->rect(), Qt::transparent);
5628 } else if (!repaintManager) {
5629 // We are not drawing to a backingstore: fall back to QImage
5630 QImage img = grabFramebuffer();
5631 // grabFramebuffer() always sets the format to RGB32
5632 // regardless of whether it is transparent or not.
5633 if (img.format() == QImage::Format_RGB32)
5634 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5635 QPainter p(q);
5636 p.drawImage(q->rect(), img);
5637 skipPaintEvent = true;
5638 }
5639 endBackingStorePainting();
5640 if (renderToTextureReallyDirty)
5641 renderToTextureReallyDirty = 0;
5642 else
5643 skipPaintEvent = true;
5644 }
5645
5646 if (!skipPaintEvent) {
5647 //actually send the paint event
5648 sendPaintEvent(toBePainted);
5649 }
5650
5651 if (repaintManager)
5652 repaintManager->markNeedsFlush(q, toBePainted, offset);
5653
5654 //restore
5655 if (paintEngine) {
5656 restoreRedirected();
5657 if (!sharedPainter)
5658 paintEngine->d_func()->systemRect = QRect();
5659 else
5660 paintEngine->d_func()->currentClipDevice = nullptr;
5661
5662 setSystemClip(pdev->paintEngine(), 1, QRegion());
5663 }
5664 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5665 if (Q_UNLIKELY(q->paintingActive()))
5666 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5667
5668 if (paintEngine && paintEngine->autoDestruct()) {
5669 delete paintEngine;
5670 }
5671 } else if (q->isWindow()) {
5672 QPaintEngine *engine = pdev->paintEngine();
5673 if (engine) {
5674 QPainter p(pdev);
5675 p.setClipRegion(toBePainted);
5676 const QBrush bg = q->palette().brush(QPalette::Window);
5677 if (bg.style() == Qt::TexturePattern)
5678 p.drawTiledPixmap(q->rect(), bg.texture());
5679 else
5680 p.fillRect(q->rect(), bg);
5681
5682 if (engine->autoDestruct())
5683 delete engine;
5684 }
5685 }
5686 }
5687
5688 if (recursive && !children.isEmpty()) {
5689 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5690 sharedPainter, repaintManager);
5691 }
5692}
5693
5694void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5695{
5696 Q_Q(QWidget);
5697 QPaintEvent e(toBePainted);
5698 QCoreApplication::sendSpontaneousEvent(q, &e);
5699
5700 if (renderToTexture)
5701 resolveSamples();
5702}
5703
5704void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5705 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5706{
5707 if (Q_UNLIKELY(!target)) {
5708 qWarning("QWidget::render: null pointer to paint device");
5709 return;
5710 }
5711
5712 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5713 QRegion paintRegion = !inRenderWithPainter
5714 ? prepareToRender(sourceRegion, renderFlags)
5715 : sourceRegion;
5716 if (paintRegion.isEmpty())
5717 return;
5718
5719 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5720
5721 // Use the target's shared painter if set (typically set when doing
5722 // "other->render(widget);" in the widget's paintEvent.
5723 if (target->devType() == QInternal::Widget) {
5724 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5725 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5726 QPainter *targetPainter = targetPrivate->sharedPainter();
5727 if (targetPainter && targetPainter->isActive())
5728 setSharedPainter(targetPainter);
5729 }
5730 }
5731
5732 // Use the target's redirected device if set and adjust offset and paint
5733 // region accordingly. This is typically the case when people call render
5734 // from the paintEvent.
5735 QPoint offset = targetOffset;
5736 offset -= paintRegion.boundingRect().topLeft();
5737 QPoint redirectionOffset;
5738 QPaintDevice *redirected = nullptr;
5739
5740 if (target->devType() == QInternal::Widget)
5741 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5742
5743 if (redirected) {
5744 target = redirected;
5745 offset -= redirectionOffset;
5746 }
5747
5748 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5749 if (QPaintEngine *targetEngine = target->paintEngine()) {
5750 const QRegion targetSystemClip = targetEngine->systemClip();
5751 if (!targetSystemClip.isEmpty())
5752 paintRegion &= targetSystemClip.translated(-offset);
5753 }
5754 }
5755
5756 // Set backingstore flags.
5757 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5758 if (renderFlags & QWidget::DrawWindowBackground)
5759 flags |= DrawAsRoot;
5760
5761 if (renderFlags & QWidget::DrawChildren)
5762 flags |= DrawRecursive;
5763 else
5764 flags |= DontSubtractOpaqueChildren;
5765
5766 flags |= DontSetCompositionMode;
5767
5768 // Render via backingstore.
5769 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5770
5771 // Restore shared painter.
5772 if (oldSharedPainter)
5773 setSharedPainter(oldSharedPainter);
5774}
5775
5776void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5777 const QPoint &offset, DrawWidgetFlags flags
5778 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5779{
5780 QWidget *w = nullptr;
5781 QRect boundingRect;
5782 bool dirtyBoundingRect = true;
5783 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5784 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5785
5786 do {
5787 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5788 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5789 && !(excludeNativeChildren && x->internalWinId())) {
5790 if (dirtyBoundingRect) {
5791 boundingRect = rgn.boundingRect();
5792 dirtyBoundingRect = false;
5793 }
5794
5795 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5796 w = x;
5797 break;
5798 }
5799 }
5800 --index;
5801 } while (index >= 0);
5802
5803 if (!w)
5804 return;
5805
5806 QWidgetPrivate *wd = w->d_func();
5807 const QPoint widgetPos(w->data->crect.topLeft());
5808 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5809 if (index > 0) {
5810 QRegion wr(rgn);
5811 if (wd->isOpaque)
5812 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5813 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5814 sharedPainter, repaintManager);
5815 }
5816
5817 if (w->updatesEnabled()
5818#if QT_CONFIG(graphicsview)
5819 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5820#endif // QT_CONFIG(graphicsview)
5821 ) {
5822 QRegion wRegion(rgn);
5823 wRegion &= wd->effectiveRectFor(w->data->crect);
5824 wRegion.translate(-widgetPos);
5825 if (hasMask)
5826 wRegion &= wd->extra->mask;
5827 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5828 }
5829}
5830
5831#if QT_CONFIG(graphicseffect)
5832QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5833{
5834 if (system != Qt::DeviceCoordinates)
5835 return m_widget->rect();
5836
5837 if (Q_UNLIKELY(!context)) {
5838 // Device coordinates without context not yet supported.
5839 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5840 return QRectF();
5841 }
5842
5843 return context->painter->worldTransform().mapRect(m_widget->rect());
5844}
5845
5846void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5847{
5848 if (!context || context->painter != painter) {
5849 m_widget->render(painter);
5850 return;
5851 }
5852
5853 // The region saved in the context is neither clipped to the rect
5854 // nor the mask, so we have to clip it here before calling drawWidget.
5855 QRegion toBePainted = context->rgn;
5856 toBePainted &= m_widget->rect();
5857 QWidgetPrivate *wd = qt_widget_private(m_widget);
5858 if (wd->extra && wd->extra->hasMask)
5859 toBePainted &= wd->extra->mask;
5860
5861 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5862 context->sharedPainter, context->repaintManager);
5863}
5864
5865QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5866 QGraphicsEffect::PixmapPadMode mode) const
5867{
5868 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5869 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5870 // Device coordinates without context not yet supported.
5871 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5872 return QPixmap();
5873 }
5874
5875 QPoint pixmapOffset;
5876 QRectF sourceRect = m_widget->rect();
5877
5878 if (deviceCoordinates) {
5879 const QTransform &painterTransform = context->painter->worldTransform();
5880 sourceRect = painterTransform.mapRect(sourceRect);
5881 pixmapOffset = painterTransform.map(pixmapOffset);
5882 }
5883
5884 QRect effectRect;
5885
5886 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5887 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5888 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5889 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5890 else
5891 effectRect = sourceRect.toAlignedRect();
5892
5893 if (offset)
5894 *offset = effectRect.topLeft();
5895
5896 pixmapOffset -= effectRect.topLeft();
5897
5898 qreal dpr(1.0);
5899 if (const auto *paintDevice = context->painter->device())
5900 dpr = paintDevice->devicePixelRatio();
5901 else
5902 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5903 QPixmap pixmap(effectRect.size() * dpr);
5904 pixmap.setDevicePixelRatio(dpr);
5905
5906 pixmap.fill(Qt::transparent);
5907 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5908 return pixmap;
5909}
5910#endif // QT_CONFIG(graphicseffect)
5911
5912#if QT_CONFIG(graphicsview)
5913/*!
5914 \internal
5915
5916 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5917 widget and its ancestors. The search starts at \a origin (inclusive).
5918 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5919 embedded widget was found.
5920*/
5921QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5922{
5923 if (origin) {
5924 const auto &extra = origin->d_func()->extra;
5925 if (extra && extra->proxyWidget)
5926 return extra->proxyWidget;
5927 return nearestGraphicsProxyWidget(origin->parentWidget());
5928 }
5929 return nullptr;
5930}
5931#endif
5932
5933/*!
5934 \property QWidget::locale
5935 \brief the widget's locale
5936 \since 4.3
5937
5938 As long as no special locale has been set, this is either
5939 the parent's locale or (if this widget is a top level widget),
5940 the default locale.
5941
5942 If the widget displays dates or numbers, these should be formatted
5943 using the widget's locale.
5944
5945 \sa QLocale, QLocale::setDefault()
5946*/
5947
5948void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5949{
5950 Q_Q(QWidget);
5951 if (locale == loc && !forceUpdate)
5952 return;
5953
5954 locale = loc;
5955
5956 if (!children.isEmpty()) {
5957 for (int i = 0; i < children.size(); ++i) {
5958 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5959 if (!w)
5960 continue;
5961 if (w->testAttribute(Qt::WA_SetLocale))
5962 continue;
5963 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5964 continue;
5965 w->d_func()->setLocale_helper(loc, forceUpdate);
5966 }
5967 }
5968 QEvent e(QEvent::LocaleChange);
5969 QCoreApplication::sendEvent(q, &e);
5970}
5971
5972void QWidget::setLocale(const QLocale &locale)
5973{
5974 Q_D(QWidget);
5975
5976 setAttribute(Qt::WA_SetLocale);
5977 d->setLocale_helper(locale);
5978}
5979
5980QLocale QWidget::locale() const
5981{
5982 Q_D(const QWidget);
5983
5984 return d->locale;
5985}
5986
5987void QWidgetPrivate::resolveLocale()
5988{
5989 Q_Q(const QWidget);
5990
5991 if (!q->testAttribute(Qt::WA_SetLocale)) {
5992 QWidget *parent = q->parentWidget();
5993 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5994 ? QLocale() : parent->locale());
5995 }
5996}
5997
5998void QWidget::unsetLocale()
5999{
6000 Q_D(QWidget);
6001 setAttribute(Qt::WA_SetLocale, false);
6002 d->resolveLocale();
6003}
6004
6005/*!
6006 \property QWidget::windowTitle
6007 \brief the window title (caption)
6008
6009 This property only makes sense for top-level widgets, such as
6010 windows and dialogs. If no caption has been set, the title is based of the
6011 \l windowFilePath. If neither of these is set, then the title is
6012 an empty string.
6013
6014 If you use the \l windowModified mechanism, the window title must
6015 contain a "[*]" placeholder, which indicates where the '*' should
6016 appear. Normally, it should appear right after the file name
6017 (e.g., "document1.txt[*] - Text Editor"). If the \l
6018 windowModified property is \c false (the default), the placeholder
6019 is simply removed.
6020
6021 On some desktop platforms (including Windows and Unix), the application name
6022 (from QGuiApplication::applicationDisplayName) is added at the end of the
6023 window title, if set. This is done by the QPA plugin, so it is shown to the
6024 user, but isn't part of the windowTitle string.
6025
6026 \sa windowIcon, windowModified, windowFilePath
6027*/
6028QString QWidget::windowTitle() const
6029{
6030 Q_D(const QWidget);
6031 if (d->extra && d->extra->topextra) {
6032 if (!d->extra->topextra->caption.isEmpty())
6033 return d->extra->topextra->caption;
6034 if (!d->extra->topextra->filePath.isEmpty())
6035 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6036 }
6037 return QString();
6038}
6039
6040/*!
6041 Returns a modified window title with the [*] place holder
6042 replaced according to the rules described in QWidget::setWindowTitle
6043
6044 This function assumes that "[*]" can be quoted by another
6045 "[*]", so it will replace two place holders by one and
6046 a single last one by either "*" or nothing depending on
6047 the modified flag.
6048
6049 \internal
6050*/
6051QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6052{
6053 Q_ASSERT(widget);
6054
6055 QString cap = title;
6056 if (cap.isEmpty())
6057 return cap;
6058
6059 const auto placeHolder = "[*]"_L1;
6060 int index = cap.indexOf(placeHolder);
6061
6062 // here the magic begins
6063 while (index != -1) {
6064 index += placeHolder.size();
6065 int count = 1;
6066 while (cap.indexOf(placeHolder, index) == index) {
6067 ++count;
6068 index += placeHolder.size();
6069 }
6070
6071 if (count%2) { // odd number of [*] -> replace last one
6072 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
6073 if (widget->isWindowModified()
6074 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
6075 cap.replace(lastIndex, 3, QWidget::tr("*"));
6076 else
6077 cap.remove(lastIndex, 3);
6078 }
6079
6080 index = cap.indexOf(placeHolder, index);
6081 }
6082
6083 cap.replace("[*][*]"_L1, placeHolder);
6084
6085 return cap;
6086}
6087
6088void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6089{
6090 Q_Q(QWidget);
6091 if (q->testAttribute(Qt::WA_WState_Created))
6092 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
6093}
6094
6095void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6096{
6097 Q_Q(QWidget);
6098 if (!q->isWindow())
6099 return;
6100
6101 if (QWindow *window = q->windowHandle())
6102 {
6103#if QT_CONFIG(accessibility)
6104 QString oldAccessibleName;
6105 const QAccessibleInterface *accessible = QAccessible::isActive()
6106 ? QAccessible::queryAccessibleInterface(q)
6107 : nullptr;
6108 if (accessible)
6109 oldAccessibleName = accessible->text(QAccessible::Name);
6110#endif
6111
6112 window->setTitle(caption);
6113
6114#if QT_CONFIG(accessibility)
6115 if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
6116 QAccessibleEvent event(q, QAccessible::NameChanged);
6117 QAccessible::updateAccessibility(&event);
6118 }
6119#endif
6120 }
6121}
6122
6123void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6124{
6125 Q_Q(QWidget);
6126 if (q->testAttribute(Qt::WA_WState_Created))
6127 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
6128}
6129
6130void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6131{
6132#if QT_CONFIG(xcb)
6133 Q_Q(QWidget);
6134 // ### The QWidget property is deprecated, but the XCB window function is not.
6135 // It should remain available for the rare application that needs it.
6136 if (QWindow *window = q->windowHandle()) {
6137 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6138 xcbWindow->setWindowIconText(iconText);
6139 }
6140#else
6141 Q_UNUSED(iconText);
6142#endif
6143}
6144
6145/*!
6146 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6147
6148 This signal is emitted when the window's icon text has changed, with the
6149 new \a iconText as an argument.
6150
6151 \since 5.2
6152 \deprecated
6153
6154 This signal is deprecated.
6155*/
6156
6157void QWidget::setWindowIconText(const QString &iconText)
6158{
6159 if (QWidget::windowIconText() == iconText)
6160 return;
6161
6162 Q_D(QWidget);
6163 d->topData()->iconText = iconText;
6164 d->setWindowIconText_helper(iconText);
6165
6166 QEvent e(QEvent::IconTextChange);
6167 QCoreApplication::sendEvent(this, &e);
6168
6169 emit windowIconTextChanged(iconText);
6170}
6171
6172/*!
6173 \fn void QWidget::windowTitleChanged(const QString &title)
6174
6175 This signal is emitted when the window's title has changed, with the
6176 new \a title as an argument.
6177
6178 \since 5.2
6179*/
6180
6181void QWidget::setWindowTitle(const QString &title)
6182{
6183 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6184 return;
6185
6186 Q_D(QWidget);
6187 d->topData()->caption = title;
6188 d->setWindowTitle_helper(title);
6189
6190 QEvent e(QEvent::WindowTitleChange);
6191 QCoreApplication::sendEvent(this, &e);
6192
6193 emit windowTitleChanged(title);
6194}
6195
6196
6197/*!
6198 \property QWidget::windowIcon
6199 \brief the widget's icon
6200
6201 This property only makes sense for windows. If no icon
6202 has been set, windowIcon() returns the application icon
6203 (QApplication::windowIcon()).
6204
6205 \note On \macos, window icons represent the active document,
6206 and will not be displayed unless a file path has also been
6207 set using setWindowFilePath.
6208
6209 \sa windowTitle, setWindowFilePath
6210*/
6211QIcon QWidget::windowIcon() const
6212{
6213 const QWidget *w = this;
6214 while (w) {
6215 const QWidgetPrivate *d = w->d_func();
6216 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6217 return *d->extra->topextra->icon;
6218 w = w->parentWidget();
6219 }
6220 return QApplication::windowIcon();
6221}
6222
6223void QWidgetPrivate::setWindowIcon_helper()
6224{
6225 Q_Q(QWidget);
6226 QEvent e(QEvent::WindowIconChange);
6227
6228 // Do not send the event if the widget is a top level.
6229 // In that case, setWindowIcon_sys does it, and event propagation from
6230 // QWidgetWindow to the top level QWidget ensures that the event reaches
6231 // the top level anyhow
6232 if (!q->windowHandle())
6233 QCoreApplication::sendEvent(q, &e);
6234 for (int i = 0; i < children.size(); ++i) {
6235 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6236 if (w && !w->isWindow())
6237 QCoreApplication::sendEvent(w, &e);
6238 }
6239}
6240
6241/*!
6242 \fn void QWidget::windowIconChanged(const QIcon &icon)
6243
6244 This signal is emitted when the window's icon has changed, with the
6245 new \a icon as an argument.
6246
6247 \since 5.2
6248*/
6249
6250void QWidget::setWindowIcon(const QIcon &icon)
6251{
6252 Q_D(QWidget);
6253
6254 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6255 d->createTLExtra();
6256
6257 if (!d->extra->topextra->icon)
6258 d->extra->topextra->icon = std::make_unique<QIcon>(icon);
6259 else
6260 *d->extra->topextra->icon = icon;
6261
6262 d->setWindowIcon_sys();
6263 d->setWindowIcon_helper();
6264
6265 emit windowIconChanged(icon);
6266}
6267
6268void QWidgetPrivate::setWindowIcon_sys()
6269{
6270 Q_Q(QWidget);
6271 if (QWindow *window = q->windowHandle())
6272 window->setIcon(q->windowIcon());
6273}
6274
6275/*!
6276 \property QWidget::windowIconText
6277 \brief the text to be displayed on the icon of a minimized window
6278
6279 This property only makes sense for windows. If no icon
6280 text has been set, this accessor returns an empty string.
6281 It is only implemented on the X11 platform, and only certain
6282 window managers use this window property.
6283
6284 \deprecated
6285 This property is deprecated.
6286
6287 \sa windowIcon, windowTitle
6288*/
6289
6290QString QWidget::windowIconText() const
6291{
6292 Q_D(const QWidget);
6293 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6294}
6295
6296/*!
6297 \property QWidget::windowFilePath
6298 \since 4.4
6299 \brief the file path associated with a widget
6300
6301 This property only makes sense for windows. It associates a file path with
6302 a window. If you set the file path, but have not set the window title, Qt
6303 sets the window title to the file name of the specified path, obtained using
6304 QFileInfo::fileName().
6305
6306 If the window title is set at any point, then the window title takes precedence and
6307 will be shown instead of the file path string.
6308
6309 Additionally, on \macos, this has an added benefit that it sets the
6310 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6311 for the window, assuming that the file path exists.
6312
6313 If no file path is set, this property contains an empty string.
6314
6315 By default, this property contains an empty string.
6316
6317 \sa windowTitle, windowIcon
6318*/
6319
6320QString QWidget::windowFilePath() const
6321{
6322 Q_D(const QWidget);
6323 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6324}
6325
6326void QWidget::setWindowFilePath(const QString &filePath)
6327{
6328 if (filePath == windowFilePath())
6329 return;
6330
6331 Q_D(QWidget);
6332
6333 d->createTLExtra();
6334 d->extra->topextra->filePath = filePath;
6335 d->setWindowFilePath_helper(filePath);
6336}
6337
6338void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6339{
6340 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6341#ifdef Q_OS_MAC
6342 setWindowTitle_helper(QFileInfo(filePath).fileName());
6343#else
6344 Q_Q(QWidget);
6345 Q_UNUSED(filePath);
6346 setWindowTitle_helper(q->windowTitle());
6347#endif
6348 }
6349#ifdef Q_OS_MAC
6350 setWindowFilePath_sys(filePath);
6351#endif
6352}
6353
6354void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6355{
6356 Q_Q(QWidget);
6357 if (!q->isWindow())
6358 return;
6359
6360 if (QWindow *window = q->windowHandle())
6361 window->setFilePath(filePath);
6362}
6363
6364/*!
6365 Returns the window's role, or an empty string.
6366
6367 \sa windowIcon, windowTitle
6368*/
6369
6370QString QWidget::windowRole() const
6371{
6372 Q_D(const QWidget);
6373 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6374}
6375
6376/*!
6377 Sets the window's role to \a role. This only makes sense for
6378 windows on X11.
6379*/
6380void QWidget::setWindowRole(const QString &role)
6381{
6382#if QT_CONFIG(xcb) || QT_CONFIG(wayland)
6383 Q_D(QWidget);
6384 d->createTLExtra();
6385 d->topData()->role = role;
6386#else
6387 Q_UNUSED(role);
6388#endif
6389
6390 if (windowHandle()) {
6391#if QT_CONFIG(xcb)
6392 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6393 xcbWindow->setWindowRole(role);
6394#endif
6395#if QT_CONFIG(wayland)
6396 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(windowHandle()->handle()))
6397 waylandWindow->setSessionRestoreId(role);
6398#endif
6399 }
6400}
6401
6402/*!
6403 \property QWidget::mouseTracking
6404 \brief whether mouse tracking is enabled for the widget
6405
6406 If mouse tracking is disabled (the default), the widget only
6407 receives mouse move events when at least one mouse button is
6408 pressed while the mouse is being moved.
6409
6410 If mouse tracking is enabled, the widget receives mouse move
6411 events even if no buttons are pressed.
6412
6413 \sa mouseMoveEvent()
6414*/
6415
6416/*!
6417 \property QWidget::tabletTracking
6418 \brief whether tablet tracking is enabled for the widget
6419 \since 5.9
6420
6421 If tablet tracking is disabled (the default), the widget only
6422 receives tablet move events when the stylus is in contact with
6423 the tablet, or at least one stylus button is pressed,
6424 while the stylus is being moved.
6425
6426 If tablet tracking is enabled, the widget receives tablet move
6427 events even while hovering in proximity. This is useful for
6428 monitoring position as well as the auxiliary properties such
6429 as rotation and tilt, and providing feedback in the UI.
6430
6431 \sa tabletEvent()
6432*/
6433
6434
6435/*!
6436 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6437 function resets this widget to have no focus proxy.
6438
6439 Some widgets can "have focus", but create a child widget, such as
6440 QLineEdit, to actually handle the focus. In this case, the widget
6441 can set the line edit to be its focus proxy.
6442
6443 setFocusProxy() sets the widget which will actually get focus when
6444 "this widget" gets it. If there is a focus proxy, setFocus() and
6445 hasFocus() operate on the focus proxy. If "this widget" is the focus
6446 widget, then setFocusProxy() moves focus to the new focus proxy.
6447
6448 \sa focusProxy()
6449*/
6450
6451void QWidget::setFocusProxy(QWidget * w)
6452{
6453 Q_D(QWidget);
6454 if (!w && !d->extra)
6455 return;
6456
6457 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6458 if (Q_UNLIKELY(fp == this)) {
6459 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6460 return;
6461 }
6462 }
6463
6464 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6465
6466 d->createExtra();
6467 d->extra->focus_proxy = w;
6468
6469 if (w && isAncestorOf(w)) {
6470 // If the focus proxy is a child of this (so this is a compound widget), then
6471 // we need to make sure that this widget is immediately in front of its own children
6472 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6473 // widgets that are positioned between this compound widget, and its proxy in
6474 // the focus chain.
6475 const QWidget *parentOfW = w->parentWidget();
6476 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6477 QWidget *firstChild = nullptr;
6478 const auto childList = children();
6479 for (QObject *child : childList) {
6480 if ((firstChild = qobject_cast<QWidget *>(child)))
6481 break;
6482 }
6483 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6484 d->insertIntoFocusChainBefore(firstChild);
6485 } else if (w && w->isAncestorOf(this)) {
6486 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6487 // remove it from the chain and insert this into the focus chain after its parent
6488
6489 // is this the case already?
6490 QWidget *parentsNext = w->nextInFocusChain();
6491 if (parentsNext == this) {
6492 // nothing to do.
6493 Q_ASSERT(previousInFocusChain() == w);
6494 } else {
6495 d->QWidgetPrivate::insertIntoFocusChainAfter(w);
6496 }
6497 }
6498
6499 if (moveFocusToProxy)
6500 setFocus(Qt::OtherFocusReason);
6501}
6502
6503
6504/*!
6505 Returns the focus proxy, or \nullptr if there is no focus proxy.
6506
6507 \sa setFocusProxy()
6508*/
6509
6510QWidget *QWidget::focusProxy() const
6511{
6512 Q_D(const QWidget);
6513 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6514}
6515
6516
6517/*!
6518 \property QWidget::focus
6519 \brief whether this widget (or its focus proxy) has the keyboard
6520 input focus
6521
6522 By default, this property is \c false.
6523
6524 \note Obtaining the value of this property for a widget is effectively equivalent
6525 to checking whether QApplication::focusWidget() refers to the widget.
6526
6527 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6528*/
6529bool QWidget::hasFocus() const
6530{
6531 const QWidget* w = this;
6532 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6533 w = w->d_func()->extra->focus_proxy;
6534#if QT_CONFIG(graphicsview)
6535 if (QWidget *window = w->window()) {
6536 const auto &e = window->d_func()->extra;
6537 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6538 return true;
6539 }
6540#endif // QT_CONFIG(graphicsview)
6541 return (QApplication::focusWidget() == w);
6542}
6543
6544/*!
6545 Gives the keyboard input focus to this widget (or its focus
6546 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6547 be passed into any focus event sent from this function, it is used
6548 to give an explanation of what caused the widget to get focus.
6549 If the window is not active, the widget will be given the focus when
6550 the window becomes active.
6551
6552 First, a focus about to change event is sent to the focus widget (if any) to
6553 tell it that it is about to lose the focus. Then focus is changed, a
6554 focus out event is sent to the previous focus item and a focus in event is sent
6555 to the new item to tell it that it just received the focus.
6556 (Nothing happens if the focus in and focus out widgets are the
6557 same.)
6558
6559 \note On embedded platforms, setFocus() will not cause an input panel
6560 to be opened by the input method. If you want this to happen, you
6561 have to send a QEvent::RequestSoftwareInputPanel event to the
6562 widget yourself.
6563
6564 setFocus() gives focus to a widget regardless of its focus policy,
6565 but does not clear any keyboard grab (see grabKeyboard()).
6566
6567 Be aware that if the widget is hidden, it will not accept focus
6568 until it is shown.
6569
6570 \warning If you call setFocus() in a function which may itself be
6571 called from focusOutEvent() or focusInEvent(), you may get an
6572 infinite recursion.
6573
6574 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6575 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6576 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6577*/
6578
6579void QWidget::setFocus(Qt::FocusReason reason)
6580{
6581 if (!isEnabled())
6582 return;
6583
6584 QWidget *f = d_func()->deepestFocusProxy();
6585 if (!f)
6586 f = this;
6587
6588 if (QApplication::focusWidget() == f)
6589 return;
6590
6591#if QT_CONFIG(graphicsview)
6592 QWidget *previousProxyFocus = nullptr;
6593 if (const auto &topData = window()->d_func()->extra) {
6594 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6595 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6596 if (previousProxyFocus && previousProxyFocus->focusProxy())
6597 previousProxyFocus = previousProxyFocus->focusProxy();
6598 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6599 return;
6600 }
6601 }
6602#endif
6603
6604#if QT_CONFIG(graphicsview)
6605 // Update proxy state
6606 if (const auto &topData = window()->d_func()->extra) {
6607 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6608 f->d_func()->updateFocusChild();
6609 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6610 topData->proxyWidget->setFocus(reason);
6611 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6612 }
6613 }
6614#endif
6615
6616 if (f->isActiveWindow()) {
6617 QWidget *prev = QApplicationPrivate::focus_widget;
6618 if (prev) {
6619 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6620 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6621 QGuiApplication::inputMethod()->commit();
6622 }
6623
6624 if (reason != Qt::NoFocusReason) {
6625 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6626 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6627 }
6628 }
6629
6630 f->d_func()->updateFocusChild();
6631
6632 QApplicationPrivate::setFocusWidget(f, reason);
6633#if QT_CONFIG(accessibility)
6634 // menus update the focus manually and this would create bogus events
6635 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6636 {
6637 QAccessibleEvent event(f, QAccessible::Focus);
6638 QAccessible::updateAccessibility(&event);
6639 }
6640#endif
6641#if QT_CONFIG(graphicsview)
6642 if (const auto &topData = window()->d_func()->extra) {
6643 if (topData->proxyWidget) {
6644 if (previousProxyFocus && previousProxyFocus != f) {
6645 // Send event to self
6646 QFocusEvent event(QEvent::FocusOut, reason);
6647 QPointer<QWidget> that = previousProxyFocus;
6648 QCoreApplication::sendEvent(previousProxyFocus, &event);
6649 if (that)
6650 QCoreApplication::sendEvent(that->style(), &event);
6651 }
6652 if (!isHidden()) {
6653#if QT_CONFIG(graphicsview)
6654 // Update proxy state
6655 if (const auto &topData = window()->d_func()->extra)
6656 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6657 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6658#endif
6659 // Send event to self
6660 QFocusEvent event(QEvent::FocusIn, reason);
6661 QPointer<QWidget> that = f;
6662 QCoreApplication::sendEvent(f, &event);
6663 if (that)
6664 QCoreApplication::sendEvent(that->style(), &event);
6665 }
6666 }
6667 }
6668#endif
6669 } else {
6670 f->d_func()->updateFocusChild();
6671 }
6672}
6673
6674
6675/*!\internal
6676 * A focus proxy can have its own focus proxy, which can have its own
6677 * proxy, and so on. This helper function returns the widget that sits
6678 * at the bottom of the proxy chain, and therefore the one that should
6679 * normally get focus if this widget receives a focus request.
6680 */
6681QWidget *QWidgetPrivate::deepestFocusProxy() const
6682{
6683 Q_Q(const QWidget);
6684
6685 QWidget *focusProxy = q->focusProxy();
6686 if (!focusProxy)
6687 return nullptr;
6688
6689 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6690 focusProxy = nextFocusProxy;
6691
6692 return focusProxy;
6693}
6694
6695static inline bool isEmbedded(const QWindow *w)
6696{
6697 const auto platformWindow = w->handle();
6698 return platformWindow && platformWindow->isEmbedded();
6699}
6700
6701void QWidgetPrivate::setFocus_sys()
6702{
6703 Q_Q(QWidget);
6704 // Embedded native widget may have taken the focus; get it back to toplevel
6705 // if that is the case (QTBUG-25852), unless widget is a window container.
6706 if (extra && extra->hasWindowContainer)
6707 return;
6708 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6709 // unless the application is embedded (QTBUG-71991).
6710 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6711 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6712 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6713 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6714 || isEmbedded(nativeWindow))) {
6715 nativeWindow->requestActivate();
6716 }
6717 }
6718}
6719
6720// updates focus_child on parent widgets to point into this widget
6721void QWidgetPrivate::updateFocusChild()
6722{
6723 Q_Q(QWidget);
6724
6725 QWidget *w = q;
6726 if (q->isHidden()) {
6727 while (w && w->isHidden()) {
6728 w->d_func()->focus_child = q;
6729 w = w->isWindow() ? nullptr : w->parentWidget();
6730 }
6731 } else {
6732 while (w) {
6733 w->d_func()->focus_child = q;
6734 w = w->isWindow() ? nullptr : w->parentWidget();
6735 }
6736 }
6737
6738 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6739 if (extra->window)
6740 emit extra->window->focusObjectChanged(q);
6741 }
6742}
6743
6744/*!
6745 \fn void QWidget::setFocus()
6746 \overload
6747
6748 Gives the keyboard input focus to this widget (or its focus
6749 proxy) if this widget or one of its parents is the
6750 \l{isActiveWindow()}{active window}.
6751*/
6752
6753/*!
6754 Takes keyboard input focus from the widget.
6755
6756 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6757 lost the focus.
6758
6759 This widget must enable focus setting to get the keyboard
6760 input focus; that is, it must call setFocusPolicy().
6761
6762 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6763 setFocusPolicy(), QApplication::focusWidget()
6764*/
6765
6766void QWidget::clearFocus()
6767{
6768 if (hasFocus()) {
6769 if (testAttribute(Qt::WA_InputMethodEnabled))
6770 QGuiApplication::inputMethod()->commit();
6771
6772 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6773 QCoreApplication::sendEvent(this, &focusAboutToChange);
6774 }
6775
6776 QTLWExtra *extra = window()->d_func()->maybeTopData();
6777 QObject *originalFocusObject = nullptr;
6778 if (extra && extra->window) {
6779 originalFocusObject = extra->window->focusObject();
6780 // the window's focus object might already be nullptr if we are in the destructor, but we still
6781 // need to update QGuiApplication and input context if we have a focus widget.
6782 if (!originalFocusObject)
6783 originalFocusObject = focusWidget();
6784 }
6785
6786 QWidget *w = this;
6787 while (w) {
6788 // Just like setFocus(), we update (clear) the focus_child of our parents
6789 if (w->d_func()->focus_child == this)
6790 w->d_func()->focus_child = nullptr;
6791 w = w->parentWidget();
6792 }
6793
6794 // We've potentially cleared the focus_child of our parents, so we need
6795 // to report this to the rest of Qt. Note that the focus_child is not the same
6796 // thing as the application's focusWidget, which is why this piece of code is
6797 // not inside a hasFocus() block.
6798 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6799 emit extra->window->focusObjectChanged(extra->window->focusObject());
6800
6801#if QT_CONFIG(graphicsview)
6802 const auto &topData = d_func()->extra;
6803 if (topData && topData->proxyWidget)
6804 topData->proxyWidget->clearFocus();
6805#endif
6806
6807 if (hasFocus()) {
6808 // Update proxy state
6809 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6810#if QT_CONFIG(accessibility)
6811 QAccessibleEvent event(this, QAccessible::Focus);
6812 QAccessible::updateAccessibility(&event);
6813#endif
6814 }
6815}
6816
6817
6818/*!
6819 \fn bool QWidget::focusNextChild()
6820
6821 Finds a new widget to give the keyboard focus to, as appropriate
6822 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6823 false if it can't.
6824
6825 \sa focusPreviousChild()
6826*/
6827
6828/*!
6829 \fn bool QWidget::focusPreviousChild()
6830
6831 Finds a new widget to give the keyboard focus to, as appropriate
6832 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6833 or false if it can't.
6834
6835 \sa focusNextChild()
6836*/
6837
6838/*!
6839 Finds a new widget to give the keyboard focus to, as appropriate
6840 for Tab and Shift+Tab, and returns \c true if it can find a new
6841 widget, or false if it can't.
6842
6843 If \a next is true, this function searches forward, if \a next
6844 is false, it searches backward.
6845
6846 Sometimes, you will want to reimplement this function. For
6847 example, a web browser might reimplement it to move its "current
6848 active link" forward or backward, and call
6849 focusNextPrevChild() only when it reaches the last or
6850 first link on the "page".
6851
6852 Child widgets call focusNextPrevChild() on their parent widgets,
6853 but only the window that contains the child widgets decides where
6854 to redirect focus. By reimplementing this function for an object,
6855 you thus gain control of focus traversal for all child widgets.
6856
6857 \sa focusNextChild(), focusPreviousChild()
6858*/
6859
6860bool QWidget::focusNextPrevChild(bool next)
6861{
6862 QWidget* p = parentWidget();
6863 bool isSubWindow = (windowType() == Qt::SubWindow);
6864 if (!isWindow() && !isSubWindow && p)
6865 return p->focusNextPrevChild(next);
6866#if QT_CONFIG(graphicsview)
6867 Q_D(QWidget);
6868 if (d->extra && d->extra->proxyWidget)
6869 return d->extra->proxyWidget->focusNextPrevChild(next);
6870#endif
6871
6872 bool wrappingOccurred = false;
6873 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6874 &wrappingOccurred);
6875 if (!w) return false;
6876
6877 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6878
6879 /* If we are about to wrap the focus chain, give the platform
6880 * implementation a chance to alter the wrapping behavior. This is
6881 * especially needed when the window is embedded in a window created by
6882 * another process.
6883 */
6884 if (wrappingOccurred) {
6885 QWindow *window = windowHandle();
6886 if (window != nullptr) {
6887 QWindowPrivate *winp = qt_window_private(window);
6888
6889 if (winp->platformWindow != nullptr) {
6890 QFocusEvent event(QEvent::FocusIn, reason);
6891 event.ignore();
6892 winp->platformWindow->windowEvent(&event);
6893 if (event.isAccepted()) return true;
6894 }
6895 }
6896 }
6897
6898 w->setFocus(reason);
6899 return true;
6900}
6901
6902/*!
6903 Returns the last child of this widget that setFocus had been
6904 called on. For top level widgets this is the widget that will get
6905 focus in case this window gets activated
6906
6907 This is not the same as QApplication::focusWidget(), which returns
6908 the focus widget in the currently active window.
6909*/
6910
6911QWidget *QWidget::focusWidget() const
6912{
6913 return const_cast<QWidget *>(d_func()->focus_child);
6914}
6915
6916QObject *QWidgetPrivate::focusObject()
6917{
6918 Q_Q(QWidget);
6919 QWidget *proxy = deepestFocusProxy();
6920 return proxy ? proxy : q;
6921}
6922
6923/*!
6924 Returns the next widget in this widget's focus chain.
6925
6926 \sa previousInFocusChain()
6927*/
6928QWidget *QWidget::nextInFocusChain() const
6929{
6930 Q_D(const QWidget);
6931 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
6932}
6933
6934/*!
6935 \brief The previousInFocusChain function returns the previous
6936 widget in this widget's focus chain.
6937
6938 \sa nextInFocusChain()
6939
6940 \since 4.6
6941*/
6942QWidget *QWidget::previousInFocusChain() const
6943{
6944 Q_D(const QWidget);
6945 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
6946}
6947
6948/*!
6949 \property QWidget::isActiveWindow
6950 \brief whether this widget's window is the active window
6951
6952 The active window is the window that contains the widget that has
6953 keyboard focus (The window may still have focus if it has no
6954 widgets or none of its widgets accepts keyboard focus).
6955
6956 When popup windows are visible, this property is \c true for both the
6957 active window \e and for the popup.
6958
6959 By default, this property is \c false.
6960
6961 \sa activateWindow(), QApplication::activeWindow()
6962*/
6963bool QWidget::isActiveWindow() const
6964{
6965 QWidget *tlw = window();
6966 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6967 return true;
6968
6969#if QT_CONFIG(graphicsview)
6970 if (const auto &tlwExtra = tlw->d_func()->extra) {
6971 if (isVisible() && tlwExtra->proxyWidget)
6972 return tlwExtra->proxyWidget->isActiveWindow();
6973 }
6974#endif
6975
6976 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6977 if (tlw->windowType() == Qt::Tool &&
6978 !tlw->isModal() &&
6979 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6980 return true;
6981 QWidget *w = QApplication::activeWindow();
6982 while(w && tlw->windowType() == Qt::Tool &&
6983 !w->isModal() && w->parentWidget()) {
6984 w = w->parentWidget()->window();
6985 if (w == tlw)
6986 return true;
6987 }
6988 }
6989
6990 // Check for an active window container
6991 if (QWindow *ww = QGuiApplication::focusWindow()) {
6992 while (ww) {
6993 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6994 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6995 if (qwc && qwc->topLevelWidget() == tlw)
6996 return true;
6997 ww = ww->parent();
6998 }
6999 }
7000
7001 // Check if platform adaptation thinks the window is active. This is necessary for
7002 // example in case of ActiveQt servers that are embedded into another application.
7003 // Those are separate processes that are not part of the parent application Qt window/widget
7004 // hierarchy, so they need to rely on native methods to determine if they are part of the
7005 // active window.
7006 if (const QWindow *w = tlw->windowHandle()) {
7007 if (w->handle())
7008 return w->handle()->isActive();
7009 }
7010
7011 return false;
7012}
7013
7014/*!
7015 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7016 \overload
7017 \since 6.6
7018
7019 Sets the tab order for the widgets in the \a widgets list by calling
7020 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
7021 pair of widgets.
7022
7023 Instead of setting up each pair manually like this:
7024
7025 \snippet code/src_gui_kernel_qwidget.cpp 9
7026
7027 you can call:
7028
7029 \snippet code/src_gui_kernel_qwidget.cpp 9.list
7030
7031 The call does not create a closed tab focus loop. If there are more widgets
7032 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
7033 of those widgets, not back to \c{a}.
7034
7035 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7036*/
7037
7038/*!
7039 Puts the \a second widget after the \a first widget in the focus order.
7040
7041 It effectively removes the \a second widget from its focus chain and
7042 inserts it after the \a first widget.
7043
7044 Note that since the tab order of the \a second widget is changed, you
7045 should order a chain like this:
7046
7047 \snippet code/src_gui_kernel_qwidget.cpp 9
7048
7049 \e not like this:
7050
7051 \snippet code/src_gui_kernel_qwidget.cpp 10
7052
7053 If \a first or \a second has a focus proxy, setTabOrder()
7054 correctly substitutes the proxy.
7055
7056 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7057 a compound widget. When setting a tab order between one or two compound widgets, the
7058 local tab order inside each will be preserved. This means that if both widgets are
7059 compound widgets, the resulting tab order will be from the last child inside
7060 \a first, to the first child inside \a second.
7061
7062 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7063*/
7064void QWidget::setTabOrder(QWidget* first, QWidget *second)
7065{
7066 if (!first || !second || first == second
7067 || first->focusPolicy() == Qt::NoFocus
7068 || second->focusPolicy() == Qt::NoFocus)
7069 return;
7070
7071 if (Q_UNLIKELY(first->window() != second->window())) {
7072 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7073 return;
7074 }
7075
7076 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7077 {
7078 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7079 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7080 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7081 // 'lastFocusChild' will be set to the target itself.
7082 QWidget *lastFocusChild = target;
7083
7084 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7085 if (!focusProxy) {
7086 // QTBUG-81097: Another case is possible here. We can have a child
7087 // widget, that sets its focusProxy() to the parent (target).
7088 // An example of such widget is a QLineEdit, nested into
7089 // a QAbstractSpinBox. In this case such widget should be considered
7090 // the last focus child.
7091 for (auto *object : target->children()) {
7092 QWidget *w = qobject_cast<QWidget*>(object);
7093 if (w && w->focusProxy() == target) {
7094 lastFocusChild = w;
7095 break;
7096 }
7097 }
7098 } else if (target->isAncestorOf(focusProxy)) {
7099 lastFocusChild = focusProxy;
7100 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7101 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
7102 focusNext = focusNext->nextInFocusChain()) {
7103 if (focusNext == noFurtherThan)
7104 break;
7105 if (focusNext->focusPolicy() != Qt::NoFocus)
7106 lastFocusChild = focusNext;
7107 }
7108 }
7109 return lastFocusChild;
7110 };
7111 // detect inflection in case we have compound widgets
7112 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7113 if (lastFocusChildOfFirst == second)
7114 lastFocusChildOfFirst = first;
7115 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7116 if (lastFocusChildOfSecond == first)
7117 lastFocusChildOfSecond = second;
7118
7119 // Return if only NoFocus widgets are between first and second
7120 QWidget *oldPrev = second->previousInFocusChain();
7121 QWidget *prevWithFocus = oldPrev;
7122 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7123 prevWithFocus = prevWithFocus->previousInFocusChain();
7124 if (prevWithFocus == first)
7125 return;
7126 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
7127 QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
7128}
7129
7130void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7131{
7132 QWidget *prev = nullptr;
7133 for (const auto &widget : widgets) {
7134 if (!prev) {
7135 prev = widget;
7136 } else {
7137 QWidget::setTabOrder(prev, widget);
7138 prev = widget;
7139 }
7140 }
7141}
7142
7143
7144/*!\internal
7145
7146 Moves the relevant subwidgets of this widget from the \a oldtlw's
7147 tab chain to that of the new parent, if there's anything to move and
7148 we're really moving
7149
7150 This function is called from QWidget::reparent() *after* the widget
7151 has been reparented.
7152
7153 \sa reparent()
7154*/
7155
7156void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7157{
7158 Q_Q(QWidget);
7159 if (oldtlw == q->window())
7160 return; // nothing to do
7161
7162 if (focus_child)
7163 focus_child->clearFocus();
7164
7165 reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
7166}
7167
7168/*!
7169 \property QWidget::frameSize
7170 \brief the size of the widget including any window frame
7171
7172 By default, this property contains a value that depends on the user's
7173 platform and screen geometry.
7174*/
7175QSize QWidget::frameSize() const
7176{
7177 Q_D(const QWidget);
7178 if (isWindow() && !(windowType() == Qt::Popup)) {
7179 QRect fs = d->frameStrut();
7180 return QSize(data->crect.width() + fs.left() + fs.right(),
7181 data->crect.height() + fs.top() + fs.bottom());
7182 }
7183 return data->crect.size();
7184}
7185
7186/*! \fn void QWidget::move(int x, int y)
7187
7188 \overload
7189
7190 This corresponds to move(QPoint(\a x, \a y)).
7191*/
7192
7193void QWidget::move(const QPoint &p)
7194{
7195 Q_D(QWidget);
7196 setAttribute(Qt::WA_Moved);
7197 if (testAttribute(Qt::WA_WState_Created)) {
7198 if (isWindow())
7199 d->topData()->posIncludesFrame = false;
7200 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7201 p.y() + geometry().y() - QWidget::y(),
7202 width(), height(), true);
7203 d->setDirtyOpaqueRegion();
7204 } else {
7205 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7206 if (isWindow())
7207 d->topData()->posIncludesFrame = true;
7208 data->crect.moveTopLeft(p); // no frame yet
7209 setAttribute(Qt::WA_PendingMoveEvent);
7210 }
7211
7212 if (d->extra && d->extra->hasWindowContainer)
7213 QWindowContainer::parentWasMoved(this);
7214}
7215
7216// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7217// unknown), that is, crect has a position including the frame.
7218// If we can determine the frame strut, fix that and clear the flag.
7219// FIXME: This does not play well with window states other than
7220// Qt::WindowNoState, as we depend on calling setGeometry() on the
7221// platform window after fixing up the position so that the new
7222// geometry is reflected in the platform window, but when the frame
7223// comes in after the window has been shown (e.g. maximized), we're
7224// not in a position to do that kind of fixup.
7225void QWidgetPrivate::fixPosIncludesFrame()
7226{
7227 Q_Q(QWidget);
7228 if (QTLWExtra *te = maybeTopData()) {
7229 if (te->posIncludesFrame) {
7230 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7231 // example, in QGraphicsProxyWidget).
7232 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7233 te->posIncludesFrame = 0;
7234 } else {
7235 if (q->windowHandle() && q->windowHandle()->handle()) {
7236 updateFrameStrut();
7237 if (!q->data->fstrut_dirty) {
7238 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
7239 te->posIncludesFrame = 0;
7240 }
7241 } // windowHandle()
7242 } // !WA_DontShowOnScreen
7243 } // posIncludesFrame
7244 } // QTLWExtra
7245}
7246
7247/*! \fn void QWidget::resize(int w, int h)
7248 \overload
7249
7250 This corresponds to resize(QSize(\a w, \a h)).
7251*/
7252
7253void QWidget::resize(const QSize &s)
7254{
7255 Q_D(QWidget);
7256 setAttribute(Qt::WA_Resized);
7257 if (testAttribute(Qt::WA_WState_Created)) {
7258 d->fixPosIncludesFrame();
7259 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7260 d->setDirtyOpaqueRegion();
7261 } else {
7262 const auto oldRect = data->crect;
7263 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7264 if (oldRect != data->crect)
7265 setAttribute(Qt::WA_PendingResizeEvent);
7266 }
7267}
7268
7269void QWidget::setGeometry(const QRect &r)
7270{
7271 Q_D(QWidget);
7272 setAttribute(Qt::WA_Resized);
7273 setAttribute(Qt::WA_Moved);
7274 if (isWindow())
7275 d->topData()->posIncludesFrame = 0;
7276 if (testAttribute(Qt::WA_WState_Created)) {
7277 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7278 d->setDirtyOpaqueRegion();
7279 } else {
7280 const auto oldRect = data->crect;
7281 data->crect.setTopLeft(r.topLeft());
7282 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7283 if (oldRect != data->crect) {
7284 setAttribute(Qt::WA_PendingMoveEvent);
7285 setAttribute(Qt::WA_PendingResizeEvent);
7286 }
7287 }
7288
7289 if (d->extra && d->extra->hasWindowContainer)
7290 QWindowContainer::parentWasMoved(this);
7291}
7292
7293void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7294{
7295 Q_Q(QWidget);
7296 if (extra) { // any size restrictions?
7297 w = qMin(w,extra->maxw);
7298 h = qMin(h,extra->maxh);
7299 w = qMax(w,extra->minw);
7300 h = qMax(h,extra->minh);
7301 }
7302
7303 if (q->isWindow() && q->windowHandle()) {
7304 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7305 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7306 x = 0;
7307 y = 0;
7308 w = q->windowHandle()->width();
7309 h = q->windowHandle()->height();
7310 }
7311 }
7312
7313 QPoint oldp = q->geometry().topLeft();
7314 QSize olds = q->size();
7315 QRect r(x, y, w, h);
7316
7317 bool isResize = olds != r.size();
7318 if (!isMove)
7319 isMove = oldp != r.topLeft();
7320
7321
7322 // We only care about stuff that changes the geometry, or may
7323 // cause the window manager to change its state
7324 if (r.size() == olds && oldp == r.topLeft())
7325 return;
7326
7327 if (!data.in_set_window_state) {
7328 q->data->window_state &= ~Qt::WindowMaximized;
7329 q->data->window_state &= ~Qt::WindowFullScreen;
7330 if (q->isWindow())
7331 topData()->normalGeometry = QRect(0, 0, -1, -1);
7332 }
7333
7334 QPoint oldPos = q->pos();
7335 data.crect = r;
7336
7337 bool needsShow = false;
7338
7339 if (q->isWindow() || q->windowHandle()) {
7340 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7341 q->setAttribute(Qt::WA_OutsideWSRange, true);
7342 if (q->isVisible())
7343 hide_sys();
7344 data.crect = QRect(x, y, w, h);
7345 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7346 q->setAttribute(Qt::WA_OutsideWSRange, false);
7347 needsShow = true;
7348 }
7349 }
7350
7351 if (q->isVisible()) {
7352 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7353 if (QWindow *win = q->windowHandle()) {
7354 if (q->isWindow()) {
7355 if (isResize && !isMove)
7356 win->resize(w, h);
7357 else if (isMove && !isResize)
7358 win->setPosition(x, y);
7359 else
7360 win->setGeometry(q->geometry());
7361 } else {
7362 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7363 win->setGeometry(QRect(posInNativeParent,r.size()));
7364 }
7365
7366 if (needsShow)
7367 show_sys();
7368 }
7369
7370 if (!q->isWindow()) {
7371 if (renderToTexture) {
7372 QRegion updateRegion(q->geometry());
7373 updateRegion += QRect(oldPos, olds);
7374 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7375 } else if (isMove && !isResize) {
7376 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7377 } else {
7378 invalidateBackingStore_resizeHelper(oldPos, olds);
7379 }
7380 }
7381 }
7382
7383 if (isMove) {
7384 QMoveEvent e(q->pos(), oldPos);
7385 QCoreApplication::sendEvent(q, &e);
7386 }
7387 if (isResize) {
7388 QResizeEvent e(r.size(), olds);
7389 QCoreApplication::sendEvent(q, &e);
7390 if (q->windowHandle())
7391 q->update();
7392 }
7393 } else { // not visible
7394 if (isMove && q->pos() != oldPos)
7395 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7396 if (isResize)
7397 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7398 }
7399
7400#if QT_CONFIG(accessibility)
7401 if (QAccessible::isActive() && q->isVisible()) {
7402 QAccessibleEvent event(q, QAccessible::LocationChanged);
7403 QAccessible::updateAccessibility(&event);
7404 }
7405#endif
7406}
7407
7408/*!
7409 \since 4.2
7410 Saves the current geometry and state for top-level widgets.
7411
7412 To save the geometry when the window closes, you can
7413 implement a close event like this:
7414
7415 \snippet code/src_gui_kernel_qwidget.cpp 11
7416
7417 See the \l{Window Geometry} documentation for an overview of geometry
7418 issues with windows.
7419
7420 Use QMainWindow::saveState() to save the geometry and the state of
7421 toolbars and dock widgets.
7422
7423 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7424*/
7425QByteArray QWidget::saveGeometry() const
7426{
7427 QByteArray array;
7428 QDataStream stream(&array, QIODevice::WriteOnly);
7429 stream.setVersion(QDataStream::Qt_4_0);
7430 const quint32 magicNumber = 0x1D9D0CB;
7431 // Version history:
7432 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7433 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7434 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7435 quint16 majorVersion = 3;
7436 quint16 minorVersion = 0;
7437 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7438 stream << magicNumber
7439 << majorVersion
7440 << minorVersion
7441 << frameGeometry()
7442 << normalGeometry()
7443 << qint32(screenNumber)
7444 << quint8(windowState() & Qt::WindowMaximized)
7445 << quint8(windowState() & Qt::WindowFullScreen)
7446 << qint32(screen()->geometry().width()) // added in 2.0
7447 << geometry(); // added in 3.0
7448 return array;
7449}
7450
7451/*!
7452 \internal
7453
7454 Check a if \a restoredGeometry fits into \a availableGeometry
7455 This method is used to verify that a widget is restored to a geometry, which
7456 fits into the target screen.
7457
7458 \param frameHeight represents the height of the widget's title bar, which is expected
7459 to be on its top.
7460
7461 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7462 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7463 be full screen.
7464
7465 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7466 \a restoredGeometry will be moved
7467 \list
7468 \li down if its top is off screen
7469 \li up if its bottom is off screen
7470 \li right if its left edge is off screen
7471 \li left if its right edge is off screen
7472 \endlist
7473 */
7474void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7475 int frameHeight)
7476{
7477 // compare with restored geometry's height increased by frameHeight
7478 const int height = restoredGeometry->height() + frameHeight;
7479
7480 // Step 1: Resize if necessary:
7481 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7482 if (availableGeometry.height() <= height)
7483 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7484 if (availableGeometry.width() <= restoredGeometry->width())
7485 restoredGeometry->setWidth(availableGeometry.width() - 2);
7486
7487 // Step 2: Move if necessary:
7488 // Construct a rectangle from restored Geometry adjusted by frameHeight
7489 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7490
7491 // Return if restoredGeometry (including frame) fits into screen
7492 if (availableGeometry.contains(restored))
7493 return;
7494
7495 // (size is correct, but at least one edge is off screen)
7496
7497 // Top out of bounds => move down
7498 if (restored.top() <= availableGeometry.top()) {
7499 restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
7500 } else if (restored.bottom() >= availableGeometry.bottom()) {
7501 // Bottom out of bounds => move up
7502 restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
7503 }
7504
7505 // Left edge out of bounds => move right
7506 if (restored.left() <= availableGeometry.left()) {
7507 restoredGeometry->moveLeft(availableGeometry.left() + 1);
7508 } else if (restored.right() >= availableGeometry.right()) {
7509 // Right edge out of bounds => move left
7510 restoredGeometry->moveRight(availableGeometry.right() - 1);
7511 }
7512}
7513
7514/*!
7515 \since 4.2
7516
7517 Restores the geometry and state of top-level widgets stored in the
7518 byte array \a geometry. Returns \c true on success; otherwise
7519 returns \c false.
7520
7521 If the restored geometry is off-screen, it will be modified to be
7522 inside the available screen geometry.
7523
7524 To restore geometry saved using QSettings, you can use code like
7525 this:
7526
7527 \snippet code/src_gui_kernel_qwidget.cpp 12
7528
7529 See the \l{Window Geometry} documentation for an overview of geometry
7530 issues with windows.
7531
7532 Use QMainWindow::restoreState() to restore the geometry and the
7533 state of toolbars and dock widgets.
7534
7535 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7536*/
7537bool QWidget::restoreGeometry(const QByteArray &geometry)
7538{
7539 if (geometry.size() < 4)
7540 return false;
7541 QDataStream stream(geometry);
7542 stream.setVersion(QDataStream::Qt_4_0);
7543
7544 const quint32 magicNumber = 0x1D9D0CB;
7545 quint32 storedMagicNumber;
7546 stream >> storedMagicNumber;
7547 if (storedMagicNumber != magicNumber)
7548 return false;
7549
7550 const quint16 currentMajorVersion = 3;
7551 quint16 majorVersion = 0;
7552 quint16 minorVersion = 0;
7553
7554 stream >> majorVersion >> minorVersion;
7555
7556 if (majorVersion > currentMajorVersion)
7557 return false;
7558 // (Allow all minor versions.)
7559
7560 QRect restoredFrameGeometry;
7561 QRect restoredGeometry;
7562 QRect restoredNormalGeometry;
7563 qint32 restoredScreenNumber;
7564 quint8 maximized;
7565 quint8 fullScreen;
7566 qint32 restoredScreenWidth = 0;
7567
7568 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7569 >> restoredNormalGeometry
7570 >> restoredScreenNumber
7571 >> maximized
7572 >> fullScreen;
7573
7574 if (majorVersion > 1)
7575 stream >> restoredScreenWidth;
7576 if (majorVersion > 2)
7577 stream >> restoredGeometry;
7578
7579 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7580
7581 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7582 restoredScreenNumber = 0;
7583 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7584 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7585 // Sanity check bailing out when large variations of screen sizes occur due to
7586 // high DPI scaling or different levels of DPI awareness.
7587 if (restoredScreenWidth) {
7588 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7589 if (factor < 0.8 || factor > 1.25)
7590 return false;
7591 } else {
7592 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7593 // unless the size will be adapted by maximized or fullscreen.
7594 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7595 return false;
7596 }
7597
7598 const int frameHeight = QApplication::style()
7599 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7600 : 20;
7601
7602 if (!restoredNormalGeometry.isValid())
7603 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7604 if (!restoredNormalGeometry.isValid()) {
7605 // use the widget's adjustedSize if the sizeHint() doesn't help
7606 restoredNormalGeometry.setSize(restoredNormalGeometry
7607 .size()
7608 .expandedTo(d_func()->adjustedSize()));
7609 }
7610
7611 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7612 : QRect();
7613
7614 // Modify the restored geometry if we are about to restore to coordinates
7615 // that would make the window "lost". This happens if:
7616 // - The restored geometry is completely or partly oustside the available geometry
7617 // - The title bar is outside the available geometry.
7618
7619 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7620 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7621
7622 if (maximized || fullScreen) {
7623 // set geometry before setting the window state to make
7624 // sure the window is maximized to the right screen.
7625 Qt::WindowStates ws = windowState();
7626#ifndef Q_OS_WIN
7627 setGeometry(restoredNormalGeometry);
7628#else
7629 if (ws & Qt::WindowFullScreen) {
7630 // Full screen is not a real window state on Windows.
7631 move(availableGeometry.topLeft());
7632 } else if (ws & Qt::WindowMaximized) {
7633 // Setting a geometry on an already maximized window causes this to be
7634 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7635 // Move the window in normal state if needed.
7636 if (restoredScreen != screen()) {
7637 setWindowState(Qt::WindowNoState);
7638 setGeometry(restoredNormalGeometry);
7639 }
7640 } else {
7641 setGeometry(restoredNormalGeometry);
7642 }
7643#endif // Q_OS_WIN
7644 if (maximized)
7645 ws |= Qt::WindowMaximized;
7646 if (fullScreen)
7647 ws |= Qt::WindowFullScreen;
7648 setWindowState(ws);
7649 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7650 } else {
7651 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7652
7653 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7654 if (majorVersion > 2)
7655 setGeometry(restoredGeometry);
7656 else
7657 setGeometry(restoredNormalGeometry);
7658 }
7659 return true;
7660}
7661
7662/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7663 \overload
7664
7665 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7666*/
7667
7668/*!
7669 Sets the margins around the contents of the widget to have the sizes
7670 \a left, \a top, \a right, and \a bottom. The margins are used by
7671 the layout system, and may be used by subclasses to specify the area
7672 to draw in (e.g. excluding the frame).
7673
7674 Changing the margins will trigger a resizeEvent().
7675
7676 \sa contentsRect(), contentsMargins()
7677*/
7678void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7679{
7680 Q_D(QWidget);
7681 if (left == d->leftmargin && top == d->topmargin
7682 && right == d->rightmargin && bottom == d->bottommargin)
7683 return;
7684 d->leftmargin = left;
7685 d->topmargin = top;
7686 d->rightmargin = right;
7687 d->bottommargin = bottom;
7688
7689 d->updateContentsRect();
7690}
7691
7692/*!
7693 \overload
7694 \since 4.6
7695
7696 \brief The setContentsMargins function sets the margins around the
7697 widget's contents.
7698
7699 Sets the margins around the contents of the widget to have the
7700 sizes determined by \a margins. The margins are
7701 used by the layout system, and may be used by subclasses to
7702 specify the area to draw in (e.g. excluding the frame).
7703
7704 Changing the margins will trigger a resizeEvent().
7705
7706 \sa contentsRect(), contentsMargins()
7707*/
7708void QWidget::setContentsMargins(const QMargins &margins)
7709{
7710 setContentsMargins(margins.left(), margins.top(),
7711 margins.right(), margins.bottom());
7712}
7713
7714void QWidgetPrivate::updateContentsRect()
7715{
7716 Q_Q(QWidget);
7717
7718 if (layout)
7719 layout->update(); //force activate; will do updateGeometry
7720 else
7721 q->updateGeometry();
7722
7723 if (q->isVisible()) {
7724 q->update();
7725 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7726 QCoreApplication::sendEvent(q, &e);
7727 } else {
7728 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7729 }
7730
7731 QEvent e(QEvent::ContentsRectChange);
7732 QCoreApplication::sendEvent(q, &e);
7733}
7734
7735/*!
7736 \since 4.6
7737
7738 \brief The contentsMargins function returns the widget's contents margins.
7739
7740 \sa setContentsMargins(), contentsRect()
7741 */
7742QMargins QWidget::contentsMargins() const
7743{
7744 Q_D(const QWidget);
7745 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7746 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7747 userMargins | d->safeAreaMargins() : userMargins;
7748}
7749
7750/*!
7751 Returns the area inside the widget's margins.
7752
7753 \sa setContentsMargins(), contentsMargins()
7754*/
7755QRect QWidget::contentsRect() const
7756{
7757 return rect() - contentsMargins();
7758}
7759
7760QMargins QWidgetPrivate::safeAreaMargins() const
7761{
7762 Q_Q(const QWidget);
7763
7764#if QT_CONFIG(graphicsview)
7765 // Don't report margins for proxied widgets, as the logic
7766 // below doesn't handle that case (yet).
7767 if (nearestGraphicsProxyWidget(q))
7768 return QMargins();
7769#endif
7770
7771 QWidget *nativeWidget = q->window();
7772 if (!nativeWidget->windowHandle())
7773 return QMargins();
7774
7775 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7776
7777 if (!q->isWindow()) {
7778 // In theory the native parent widget already has a contents rect reflecting
7779 // the safe area of that widget, but we can't be sure that the widget or child
7780 // widgets of that widget have respected the contents rect when setting their
7781 // geometry, so we need to manually compute the safe area.
7782
7783 // Unless the native widget doesn't have any margins, in which case there's
7784 // nothing for us to compute.
7785 if (safeAreaMargins.isNull())
7786 return QMargins();
7787
7788 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7789 // set, and the widget respects the safe area, then we know that the layout has already
7790 // taken care of placing us inside the safe area, by taking the contents rect of its
7791 // parent widget into account.
7792 const QWidget *assumedSafeWidget = nullptr;
7793 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7794 QWidget *parentWidget = w->parentWidget();
7795 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7796 continue; // Layout can't help us
7797
7798 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7799 continue; // Layout not going to help us
7800
7801 QLayout *layout = parentWidget->layout();
7802 if (!layout)
7803 continue;
7804
7805 if (layout->geometry().isNull())
7806 continue; // Layout hasn't been activated yet
7807
7808 if (layout->indexOf(w) < 0)
7809 continue; // Widget is not in layout
7810
7811 assumedSafeWidget = w;
7812 break;
7813 }
7814
7815#if !defined(QT_DEBUG)
7816 if (assumedSafeWidget) {
7817 // We found a layout that we assume will take care of keeping us within the safe area
7818 // For debug builds we still map the safe area using the fallback logic, so that we
7819 // can detect any misbehaving layouts.
7820 return QMargins();
7821 }
7822#endif
7823
7824 // In all other cases we need to map the safe area of the native parent to the widget.
7825 // This depends on the widget being positioned and sized already, which means the initial
7826 // layout will be wrong, but the layout will then adjust itself.
7827 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7828 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7829 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7830 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7831
7832 // Margins should never be negative
7833 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7834 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7835
7836 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7837 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7838 qWarning() << layout << "is laying out" << assumedSafeWidget
7839 << "outside of the contents rect of" << layout->parentWidget();
7840 return QMargins(); // Return empty margin to visually highlight the error
7841 }
7842 }
7843
7844 return safeAreaMargins;
7845}
7846
7847/*!
7848 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7849
7850 This signal is emitted when the widget's \l contextMenuPolicy is
7851 Qt::CustomContextMenu, and the user has requested a context menu on
7852 the widget. The position \a pos is the position of the context menu
7853 event that the widget receives. Normally this is in widget
7854 coordinates. The exception to this rule is QAbstractScrollArea and
7855 its subclasses that map the context menu event to coordinates of the
7856 \l{QAbstractScrollArea::viewport()}{viewport()}.
7857
7858
7859 \sa mapToGlobal(), QMenu, contextMenuPolicy
7860*/
7861
7862
7863/*!
7864 \property QWidget::contextMenuPolicy
7865 \brief how the widget shows a context menu
7866
7867 The default value of this property is Qt::DefaultContextMenu,
7868 which means the contextMenuEvent() handler is called. Other values
7869 are Qt::NoContextMenu, Qt::PreventContextMenu,
7870 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7871 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7872 emitted.
7873
7874 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7875*/
7876
7877Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7878{
7879 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7880}
7881
7882void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7883{
7884 data->context_menu_policy = (uint) policy;
7885}
7886
7887/*!
7888 \property QWidget::focusPolicy
7889 \brief the way the widget accepts keyboard focus
7890
7891 The policy is Qt::TabFocus if the widget accepts keyboard
7892 focus by tabbing, Qt::ClickFocus if the widget accepts
7893 focus by clicking, Qt::StrongFocus if it accepts both, and
7894 Qt::NoFocus (the default) if it does not accept focus at
7895 all.
7896
7897 You must enable keyboard focus for a widget if it processes
7898 keyboard events. This is normally done from the widget's
7899 constructor. For instance, the QLineEdit constructor calls
7900 setFocusPolicy(Qt::StrongFocus).
7901
7902 If the widget has a focus proxy, then the focus policy will
7903 be propagated to it.
7904
7905 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7906*/
7907
7908
7909Qt::FocusPolicy QWidget::focusPolicy() const
7910{
7911 return (Qt::FocusPolicy)data->focus_policy;
7912}
7913
7914void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7915{
7916 data->focus_policy = (uint) policy;
7917 Q_D(QWidget);
7918 if (d->extra && d->extra->focus_proxy)
7919 d->extra->focus_proxy->setFocusPolicy(policy);
7920}
7921
7922/*!
7923 \property QWidget::updatesEnabled
7924 \brief whether updates are enabled
7925
7926 An updates enabled widget receives paint events and has a system
7927 background; a disabled widget does not. This also implies that
7928 calling update() and repaint() has no effect if updates are
7929 disabled.
7930
7931 By default, this property is \c true.
7932
7933 setUpdatesEnabled() is normally used to disable updates for a
7934 short period of time, for instance to avoid screen flicker during
7935 large changes. In Qt, widgets normally do not generate screen
7936 flicker, but on X11 the server might erase regions on the screen
7937 when widgets get hidden before they can be replaced by other
7938 widgets. Disabling updates solves this.
7939
7940 Example:
7941 \snippet code/src_gui_kernel_qwidget.cpp 13
7942
7943 Disabling a widget implicitly disables all its children. Enabling a widget
7944 enables all child widgets \e except top-level widgets or those that
7945 have been explicitly disabled. Re-enabling updates implicitly calls
7946 update() on the widget.
7947
7948 \sa paintEvent()
7949*/
7950void QWidget::setUpdatesEnabled(bool enable)
7951{
7952 Q_D(QWidget);
7953 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7954 d->setUpdatesEnabled_helper(enable);
7955}
7956
7957/*!
7958 Shows the widget and its child widgets.
7959
7960 For child windows, this is equivalent to calling setVisible(true).
7961 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7962 or setVisible(true), depending on the platform's default behavior for the window flags.
7963
7964 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7965 showNormal(), isVisible(), windowFlags()
7966*/
7967void QWidget::show()
7968{
7969 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7970
7971 if (!isWindow()) {
7972 setVisible(true);
7973 } else {
7974 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7975 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7976 if (defaultState == Qt::WindowFullScreen)
7977 showFullScreen();
7978 else if (defaultState == Qt::WindowMaximized)
7979 showMaximized();
7980 else
7981 setVisible(true);
7982 }
7983}
7984
7985/*! \internal
7986
7987 Makes the widget visible in the isVisible() meaning of the word.
7988 It is only called for toplevels or widgets with visible parents.
7989 */
7990void QWidgetPrivate::show_recursive()
7991{
7992 Q_Q(QWidget);
7993 // polish if necessary
7994
7995 if (!q->testAttribute(Qt::WA_WState_Created))
7996 createRecursively();
7997 q->ensurePolished();
7998
7999 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
8000 q->parentWidget()->d_func()->layout->activate();
8001 // activate our layout before we and our children become visible
8002 if (layout)
8003 layout->activate();
8004
8005 show_helper();
8006}
8007
8008void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
8009{
8010 Q_Q(QWidget);
8011
8012 disableUpdates = disableUpdates && q->updatesEnabled();
8013 if (disableUpdates)
8014 q->setAttribute(Qt::WA_UpdatesDisabled);
8015
8016 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
8017 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
8018 QCoreApplication::sendEvent(q, &e);
8019 q->setAttribute(Qt::WA_PendingMoveEvent, false);
8020 }
8021
8022 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
8023 QResizeEvent e(data.crect.size(), QSize());
8024 QCoreApplication::sendEvent(q, &e);
8025 q->setAttribute(Qt::WA_PendingResizeEvent, false);
8026 }
8027
8028 if (disableUpdates)
8029 q->setAttribute(Qt::WA_UpdatesDisabled, false);
8030
8031 if (!recursive)
8032 return;
8033
8034 for (int i = 0; i < children.size(); ++i) {
8035 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8036 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8037 }
8038}
8039
8040void QWidgetPrivate::activateChildLayoutsRecursively()
8041{
8042 sendPendingMoveAndResizeEvents(false, true);
8043
8044 for (int i = 0; i < children.size(); ++i) {
8045 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8046 if (!child || child->isHidden() || child->isWindow())
8047 continue;
8048
8049 child->ensurePolished();
8050
8051 // Activate child's layout
8052 QWidgetPrivate *childPrivate = child->d_func();
8053 if (childPrivate->layout)
8054 childPrivate->layout->activate();
8055
8056 // Pretend we're visible.
8057 const bool wasVisible = child->isVisible();
8058 if (!wasVisible)
8059 child->setAttribute(Qt::WA_WState_Visible);
8060
8061 // Do the same for all my children.
8062 childPrivate->activateChildLayoutsRecursively();
8063
8064 // We're not cheating anymore.
8065 if (!wasVisible)
8066 child->setAttribute(Qt::WA_WState_Visible, false);
8067 }
8068}
8069
8070void QWidgetPrivate::show_helper()
8071{
8072 Q_Q(QWidget);
8073 data.in_show = true; // qws optimization
8074 // make sure we receive pending move and resize events
8075 sendPendingMoveAndResizeEvents();
8076
8077 // become visible before showing all children
8078 q->setAttribute(Qt::WA_WState_Visible);
8079
8080 // finally show all children recursively
8081 showChildren(false);
8082
8083
8084
8085 const bool isWindow = q->isWindow();
8086#if QT_CONFIG(graphicsview)
8087 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8088#else
8089 bool isEmbedded = false;
8090#endif
8091
8092 // popup handling: new popups and tools need to be raised, and
8093 // existing popups must be closed. Also propagate the current
8094 // windows's KeyboardFocusChange status.
8095 if (isWindow && !isEmbedded) {
8096 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8097 q->raise();
8098 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8099 q->setAttribute(Qt::WA_KeyboardFocusChange);
8100 } else {
8101 while (QApplication::activePopupWidget()) {
8102 if (!QApplication::activePopupWidget()->close())
8103 break;
8104 }
8105 }
8106 }
8107
8108 // Automatic embedding of child windows of widgets already embedded into
8109 // QGraphicsProxyWidget when they are shown the first time.
8110#if QT_CONFIG(graphicsview)
8111 if (isWindow) {
8112 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8113 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8114 if (ancestorProxy) {
8115 isEmbedded = true;
8116 ancestorProxy->d_func()->embedSubWindow(q);
8117 }
8118 }
8119 }
8120#else
8121 Q_UNUSED(isEmbedded);
8122#endif
8123
8124 // send the show event before showing the window
8125 QShowEvent showEvent;
8126 QCoreApplication::sendEvent(q, &showEvent);
8127
8128 show_sys();
8129
8130 if (!isEmbedded && q->windowType() == Qt::Popup)
8131 qApp->d_func()->openPopup(q);
8132
8133#if QT_CONFIG(accessibility)
8134 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8135 QAccessibleEvent event(q, QAccessible::ObjectShow);
8136 QAccessible::updateAccessibility(&event);
8137 }
8138#endif
8139
8140 if (QApplicationPrivate::hidden_focus_widget == q) {
8141 QApplicationPrivate::hidden_focus_widget = nullptr;
8142 q->setFocus(Qt::OtherFocusReason);
8143 }
8144
8145 // Process events when showing a Qt::SplashScreen widget before the event loop
8146 // is spinnning; otherwise it might not show up on particular platforms.
8147 // This makes QSplashScreen behave the same on all platforms.
8148 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8149 QCoreApplication::processEvents();
8150
8151 data.in_show = false; // reset qws optimization
8152}
8153
8154void QWidgetPrivate::show_sys()
8155{
8156 Q_Q(QWidget);
8157
8158 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8159
8160 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8161 invalidateBackingStore(q->rect());
8162 q->setAttribute(Qt::WA_Mapped);
8163 // add our window the modal window list (native dialogs)
8164 if (window && q->isWindow()
8165#if QT_CONFIG(graphicsview)
8166 && (!extra || !extra->proxyWidget)
8167#endif
8168 && q->windowModality() != Qt::NonModal) {
8169 QGuiApplicationPrivate::showModalWindow(window);
8170 }
8171 return;
8172 }
8173
8174 if (renderToTexture && !q->isWindow())
8175 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8176 else
8177 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8178
8179 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8180 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8181 return;
8182 }
8183
8184 if (window) {
8185 if (q->isWindow())
8186 fixPosIncludesFrame();
8187 QRect geomRect = q->geometry();
8188 if (!q->isWindow()) {
8189 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8190 geomRect.moveTopLeft(topLeftOfWindow);
8191 }
8192 const QRect windowRect = window->geometry();
8193 if (windowRect != geomRect) {
8194 if (q->testAttribute(Qt::WA_Moved)
8195 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8196 window->setGeometry(geomRect);
8197 else
8198 window->resize(geomRect.size());
8199 }
8200
8201#ifndef QT_NO_CURSOR
8202 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8203#endif
8204 invalidateBackingStore(q->rect());
8205 window->setNativeWindowVisibility(true);
8206 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8207 if (window->isTopLevel()) {
8208 const QPoint crectTopLeft = q->data->crect.topLeft();
8209 const QPoint windowTopLeft = window->geometry().topLeft();
8210 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8211 q->data->crect.moveTopLeft(windowTopLeft);
8212 }
8213 }
8214}
8215
8216/*!
8217 Hides the widget. This function is equivalent to
8218 setVisible(false).
8219
8220
8221 \note If you are working with QDialog or its subclasses and you invoke
8222 the show() function after this function, the dialog will be displayed in
8223 its original position.
8224
8225 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8226*/
8227void QWidget::hide()
8228{
8229 setVisible(false);
8230}
8231
8232/*!\internal
8233 */
8234void QWidgetPrivate::hide_helper()
8235{
8236 Q_Q(QWidget);
8237
8238 bool isEmbedded = false;
8239#if QT_CONFIG(graphicsview)
8240 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8241#else
8242 Q_UNUSED(isEmbedded);
8243#endif
8244
8245 if (!isEmbedded && (q->windowType() == Qt::Popup))
8246 qApp->d_func()->closePopup(q);
8247
8248 q->setAttribute(Qt::WA_Mapped, false);
8249 hide_sys();
8250
8251 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8252
8253 if (wasVisible) {
8254 q->setAttribute(Qt::WA_WState_Visible, false);
8255
8256 }
8257
8258 QHideEvent hideEvent;
8259 QCoreApplication::sendEvent(q, &hideEvent);
8260 hideChildren(false);
8261
8262 // next bit tries to move the focus if the focus widget is now
8263 // hidden.
8264 if (wasVisible) {
8265 qApp->d_func()->sendSyntheticEnterLeave(q);
8266 QWidget *fw = QApplication::focusWidget();
8267 while (fw && !fw->isWindow()) {
8268 if (fw == q) {
8269 q->focusNextPrevChild(true);
8270 break;
8271 }
8272 fw = fw->parentWidget();
8273 }
8274 }
8275
8276 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8277 repaintManager->removeDirtyWidget(q);
8278
8279#if QT_CONFIG(accessibility)
8280 if (wasVisible) {
8281 QAccessibleEvent event(q, QAccessible::ObjectHide);
8282 QAccessible::updateAccessibility(&event);
8283 }
8284#endif
8285}
8286
8287void QWidgetPrivate::hide_sys()
8288{
8289 Q_Q(QWidget);
8290
8291 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8292
8293 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8294 q->setAttribute(Qt::WA_Mapped, false);
8295 // remove our window from the modal window list (native dialogs)
8296 if (window && q->isWindow()
8297#if QT_CONFIG(graphicsview)
8298 && (!extra || !extra->proxyWidget)
8299#endif
8300 && q->windowModality() != Qt::NonModal) {
8301 QGuiApplicationPrivate::hideModalWindow(window);
8302 }
8303 // do not return here, if window non-zero, we must hide it
8304 }
8305
8306 deactivateWidgetCleanup();
8307
8308 if (!q->isWindow()) {
8309 QWidget *p = q->parentWidget();
8310 if (p &&p->isVisible()) {
8311 if (renderToTexture)
8312 p->d_func()->invalidateBackingStore(q->geometry());
8313 else
8314 invalidateBackingStore(q->rect());
8315 }
8316 } else {
8317 invalidateBackingStore(q->rect());
8318 }
8319
8320 if (window)
8321 window->setNativeWindowVisibility(false);
8322}
8323
8324/*!
8325 \fn bool QWidget::isHidden() const
8326
8327 Returns \c true if the widget is hidden, otherwise returns \c false.
8328
8329 A hidden widget will only become visible when show() is called on
8330 it. It will not be automatically shown when the parent is shown.
8331
8332 To check visibility, use !isVisible() instead (notice the exclamation mark).
8333
8334 isHidden() implies !isVisible(), but a widget can be not visible
8335 and not hidden at the same time. This is the case for widgets that are children of
8336 widgets that are not visible.
8337
8338
8339 Widgets are hidden if:
8340 \list
8341 \li they were created as independent windows,
8342 \li they were created as children of visible widgets,
8343 \li hide() or setVisible(false) was called.
8344 \endlist
8345*/
8346
8347void QWidget::setVisible(bool visible)
8348{
8349 Q_D(QWidget);
8350 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8351 << "with attributes" << WidgetAttributes{this}
8352 << "to" << visible << "via QWidget";
8353
8354 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8355 return;
8356
8357 if (d->dontSetExplicitShowHide) {
8358 d->dontSetExplicitShowHide = false;
8359 } else {
8360 // Remember that setVisible was called explicitly
8361 setAttribute(Qt::WA_WState_ExplicitShowHide);
8362 }
8363
8364 d->setVisible(visible);
8365}
8366
8367// This method is called from QWidgetWindow in response to QWindow::setVisible,
8368// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8369// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8370void QWidgetPrivate::setVisible(bool visible)
8371{
8372 Q_Q(QWidget);
8373 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8374 << "with attributes" << WidgetAttributes{q}
8375 << "to" << visible << "via QWidgetPrivate";
8376
8377 if (visible) { // show
8378 // Designer uses a trick to make grabWidget work without showing
8379 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8380 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8381 q->parentWidget()->window()->d_func()->createRecursively();
8382
8383 //create toplevels but not children of non-visible parents
8384 QWidget *pw = q->parentWidget();
8385 if (!q->testAttribute(Qt::WA_WState_Created)
8386 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8387 q->create();
8388 }
8389
8390 bool wasResized = q->testAttribute(Qt::WA_Resized);
8391 Qt::WindowStates initialWindowState = q->windowState();
8392
8393 // polish if necessary
8394 q->ensurePolished();
8395
8396 // whether we need to inform the parent widget immediately
8397 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8398 // we are no longer hidden
8399 q->setAttribute(Qt::WA_WState_Hidden, false);
8400
8401 if (needUpdateGeometry)
8402 updateGeometry_helper(true);
8403
8404 // activate our layout before we and our children become visible
8405 if (layout)
8406 layout->activate();
8407
8408 if (!q->isWindow()) {
8409 QWidget *parent = q->parentWidget();
8410 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8411 parent->d_func()->layout->activate();
8412 if (parent->isWindow())
8413 break;
8414 parent = parent->parentWidget();
8415 }
8416 if (parent)
8417 parent->d_func()->setDirtyOpaqueRegion();
8418 }
8419
8420 // adjust size if necessary
8421 if (!wasResized
8422 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8423 if (q->isWindow()) {
8424 q->adjustSize();
8425 if (q->windowState() != initialWindowState)
8426 q->setWindowState(initialWindowState);
8427 } else {
8428 q->adjustSize();
8429 }
8430 q->setAttribute(Qt::WA_Resized, false);
8431 }
8432
8433 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8434
8435 if (q->isWindow() || q->parentWidget()->isVisible()) {
8436 show_helper();
8437
8438 qApp->d_func()->sendSyntheticEnterLeave(q);
8439 }
8440
8441 QEvent showToParentEvent(QEvent::ShowToParent);
8442 QCoreApplication::sendEvent(q, &showToParentEvent);
8443 } else { // hide
8444 if (QApplicationPrivate::hidden_focus_widget == q)
8445 QApplicationPrivate::hidden_focus_widget = nullptr;
8446
8447 // hw: The test on getOpaqueRegion() needs to be more intelligent
8448 // currently it doesn't work if the widget is hidden (the region will
8449 // be clipped). The real check should be testing the cached region
8450 // (and dirty flag) directly.
8451 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8452 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8453
8454 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8455 q->setAttribute(Qt::WA_WState_Hidden);
8456 hide_helper();
8457 }
8458
8459 // invalidate layout similar to updateGeometry()
8460 if (!q->isWindow() && q->parentWidget()) {
8461 if (q->parentWidget()->d_func()->layout)
8462 q->parentWidget()->d_func()->layout->invalidate();
8463 else if (q->parentWidget()->isVisible())
8464 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8465 }
8466
8467 QEvent hideToParentEvent(QEvent::HideToParent);
8468 QCoreApplication::sendEvent(q, &hideToParentEvent);
8469 }
8470}
8471
8472/*!
8473 Convenience function, equivalent to setVisible(!\a hidden).
8474*/
8475void QWidget::setHidden(bool hidden)
8476{
8477 setVisible(!hidden);
8478}
8479
8480bool QWidgetPrivate::isExplicitlyHidden() const
8481{
8482 Q_Q(const QWidget);
8483 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8484}
8485
8486void QWidgetPrivate::_q_showIfNotHidden()
8487{
8488 Q_Q(QWidget);
8489 if (!isExplicitlyHidden())
8490 q->setVisible(true);
8491}
8492
8493void QWidgetPrivate::showChildren(bool spontaneous)
8494{
8495 Q_Q(QWidget);
8496 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8497 << "spontaneously" << spontaneous;
8498
8499 QList<QObject*> childList = children;
8500 for (int i = 0; i < childList.size(); ++i) {
8501 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8502 if (!widget)
8503 continue;
8504 qCDebug(lcWidgetShowHide) << "Considering" << widget
8505 << "with attributes" << WidgetAttributes{widget};
8506 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8507 widget->setAttribute(Qt::WA_WState_Hidden, false);
8508 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8509 continue;
8510 if (spontaneous) {
8511 widget->setAttribute(Qt::WA_Mapped);
8512 widget->d_func()->showChildren(true);
8513 QShowEvent e;
8514 QApplication::sendSpontaneousEvent(widget, &e);
8515 } else {
8516 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8517 widget->d_func()->show_recursive();
8518 } else {
8519 // Call QWidget::setVisible() here, so that subclasses
8520 // that (wrongly) override setVisible to do initialization
8521 // will still be notified that they are made visible, but
8522 // do so without triggering ExplicitShowHide.
8523 widget->d_func()->dontSetExplicitShowHide = true;
8524 widget->setVisible(true);
8525 widget->d_func()->dontSetExplicitShowHide = false;
8526 }
8527 }
8528 }
8529}
8530
8531void QWidgetPrivate::hideChildren(bool spontaneous)
8532{
8533 Q_Q(QWidget);
8534 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8535 << "spontaneously" << spontaneous;
8536
8537 QList<QObject*> childList = children;
8538 for (int i = 0; i < childList.size(); ++i) {
8539 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8540 if (!widget)
8541 continue;
8542 qCDebug(lcWidgetShowHide) << "Considering" << widget
8543 << "with attributes" << WidgetAttributes{widget};
8544 if (widget->isWindow() || !widget->isVisible())
8545 continue;
8546
8547 if (spontaneous)
8548 widget->setAttribute(Qt::WA_Mapped, false);
8549 else
8550 widget->setAttribute(Qt::WA_WState_Visible, false);
8551 widget->d_func()->hideChildren(spontaneous);
8552 QHideEvent e;
8553 if (spontaneous) {
8554 QApplication::sendSpontaneousEvent(widget, &e);
8555 } else {
8556 QCoreApplication::sendEvent(widget, &e);
8557 if (widget->internalWinId()
8558 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8559 // hide_sys() on an ancestor won't have any affect on this
8560 // widget, so it needs an explicit hide_sys() of its own
8561 widget->d_func()->hide_sys();
8562 }
8563 }
8564 qApp->d_func()->sendSyntheticEnterLeave(widget);
8565#if QT_CONFIG(accessibility)
8566 if (!spontaneous) {
8567 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8568 QAccessible::updateAccessibility(&event);
8569 }
8570#endif
8571 }
8572
8573 // If the window of this widget is not closed, then the leave event
8574 // will eventually handle the widget under mouse use case.
8575 // Otherwise, we need to explicitly handle it here.
8576 if (QWidget* widgetWindow = q->window();
8577 widgetWindow && widgetWindow->data->is_closing) {
8578 q->setAttribute(Qt::WA_UnderMouse, false);
8579 }
8580}
8581
8582/*!
8583 \internal
8584
8585 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8586 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8587 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8588 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8589 system (i.e. the user clicked the close button in the title bar).
8590
8591 QDialog calls this method directly in its hide() implementation, which might be
8592 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8593 to prevent recursion.
8594
8595 For non-windows, this is called directly by QWidget::close, and \a mode will be
8596 CloseWithEvent.
8597
8598 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8599*/
8600bool QWidgetPrivate::handleClose(CloseMode mode)
8601{
8602 Q_Q(QWidget);
8603 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8604
8605 if (data.is_closing)
8606 return true;
8607
8608 // We might not have initiated the close, so update the state now that we know
8609 data.is_closing = true;
8610
8611 QPointer<QWidget> that = q;
8612
8613 if (data.in_destructor)
8614 mode = CloseNoEvent;
8615
8616 if (mode != CloseNoEvent) {
8617 QCloseEvent e;
8618 if (mode == CloseWithSpontaneousEvent)
8619 QApplication::sendSpontaneousEvent(q, &e);
8620 else
8621 QCoreApplication::sendEvent(q, &e);
8622 if (!that.isNull() && !e.isAccepted()) {
8623 data.is_closing = false;
8624 return false;
8625 }
8626 }
8627
8628 // even for windows, make sure we deliver a hide event and that all children get hidden
8629 if (!that.isNull() && !q->isHidden())
8630 q->hide();
8631
8632 if (!that.isNull()) {
8633 data.is_closing = false;
8634 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8635 q->setAttribute(Qt::WA_DeleteOnClose, false);
8636 q->deleteLater();
8637 }
8638 }
8639 return true;
8640}
8641
8642
8643/*!
8644 Closes this widget. Returns \c true if the widget was closed;
8645 otherwise returns \c false.
8646
8647 First it sends the widget a QCloseEvent. The widget is
8648 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8649 the close event. If it \l{QEvent::ignore()}{ignores}
8650 the event, nothing happens. The default
8651 implementation of QWidget::closeEvent() accepts the close event.
8652
8653 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8654 is also deleted. A close events is delivered to the widget no
8655 matter if the widget is visible or not.
8656
8657 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8658 last visible primary window (i.e. window with no parent) with the
8659 Qt::WA_QuitOnClose attribute set is closed. By default this
8660 attribute is set for all widgets except transient windows such as
8661 splash screens, tool windows, and popup menus.
8662
8663*/
8664
8665bool QWidget::close()
8666{
8667 return d_func()->close();
8668}
8669
8670bool QWidgetPrivate::close()
8671{
8672 // FIXME: We're not setting is_closing here, even though that would
8673 // make sense, as the code below will not end up in handleClose to
8674 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8675 // and we can't assume close is synchronous so we can't reset it here.
8676
8677 // Close native widgets via QWindow::close() in order to run QWindow
8678 // close code. The QWidget-specific close code in handleClose() will
8679 // in this case be called from the Close event handler in QWidgetWindow.
8680 if (QWindow *widgetWindow = windowHandle()) {
8681 if (widgetWindow->isTopLevel())
8682 return widgetWindow->close();
8683 }
8684
8685 return handleClose(QWidgetPrivate::CloseWithEvent);
8686}
8687
8688/*!
8689 \property QWidget::visible
8690 \brief whether the widget is visible
8691
8692 Calling setVisible(true) or show() sets the widget to visible
8693 status if all its parent widgets up to the window are visible. If
8694 an ancestor is not visible, the widget won't become visible until
8695 all its ancestors are shown. If its size or position has changed,
8696 Qt guarantees that a widget gets move and resize events just
8697 before it is shown. If the widget has not been resized yet, Qt
8698 will adjust the widget's size to a useful default using
8699 adjustSize().
8700
8701 Calling setVisible(false) or hide() hides a widget explicitly. An
8702 explicitly hidden widget will never become visible, even if all
8703 its ancestors become visible, unless you show it.
8704
8705 A widget receives show and hide events when its visibility status
8706 changes. Between a hide and a show event, there is no need to
8707 waste CPU cycles preparing or displaying information to the user.
8708 A video application, for example, might simply stop generating new
8709 frames.
8710
8711 A widget that happens to be obscured by other windows on the
8712 screen is considered to be visible. The same applies to iconified
8713 windows and windows that exist on another virtual
8714 desktop (on platforms that support this concept). A widget
8715 receives spontaneous show and hide events when its mapping status
8716 is changed by the window system, e.g. a spontaneous hide event
8717 when the user minimizes the window, and a spontaneous show event
8718 when the window is restored again.
8719
8720 You seldom have to reimplement the setVisible() function. If
8721 you need to change some settings before a widget is shown, use
8722 showEvent() instead. If you need to do some delayed initialization
8723 use the Polish event delivered to the event() function.
8724
8725 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8726 showEvent(), hideEvent()
8727*/
8728
8729
8730/*!
8731 Returns \c true if this widget would become visible if \a ancestor is
8732 shown; otherwise returns \c false.
8733
8734 The true case occurs if neither the widget itself nor any parent
8735 up to but excluding \a ancestor has been explicitly hidden.
8736
8737 This function will still return true if the widget is obscured by
8738 other windows on the screen, but could be physically visible if it
8739 or they were to be moved.
8740
8741 isVisibleTo(0) is identical to isVisible().
8742
8743 \sa show(), hide(), isVisible()
8744*/
8745
8746bool QWidget::isVisibleTo(const QWidget *ancestor) const
8747{
8748 if (!ancestor)
8749 return isVisible();
8750 const QWidget * w = this;
8751 while (!w->isHidden()
8752 && !w->isWindow()
8753 && w->parentWidget()
8754 && w->parentWidget() != ancestor)
8755 w = w->parentWidget();
8756 return !w->isHidden();
8757}
8758
8759
8760/*!
8761 Returns the unobscured region where paint events can occur.
8762
8763 For visible widgets, this is an approximation of the area not
8764 covered by other widgets; otherwise, this is an empty region.
8765
8766 The repaint() function calls this function if necessary, so in
8767 general you do not need to call it.
8768
8769*/
8770QRegion QWidget::visibleRegion() const
8771{
8772 Q_D(const QWidget);
8773
8774 QRect clipRect = d->clipRect();
8775 if (clipRect.isEmpty())
8776 return QRegion();
8777 QRegion r(clipRect);
8778 d->subtractOpaqueChildren(r, clipRect);
8779 d->subtractOpaqueSiblings(r);
8780 return r;
8781}
8782
8783
8784QSize QWidgetPrivate::adjustedSize() const
8785{
8786 Q_Q(const QWidget);
8787
8788 QSize s = q->sizeHint();
8789
8790 if (q->isWindow()) {
8791 Qt::Orientations exp;
8792 if (layout) {
8793 if (layout->hasHeightForWidth())
8794 s.setHeight(layout->totalHeightForWidth(s.width()));
8795 exp = layout->expandingDirections();
8796 } else
8797 {
8798 if (q->sizePolicy().hasHeightForWidth())
8799 s.setHeight(q->heightForWidth(s.width()));
8800 exp = q->sizePolicy().expandingDirections();
8801 }
8802 if (exp & Qt::Horizontal)
8803 s.setWidth(qMax(s.width(), 200));
8804 if (exp & Qt::Vertical)
8805 s.setHeight(qMax(s.height(), 100));
8806
8807 QRect screen;
8808 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8809 screen = screenAtPoint->geometry();
8810 else
8811 screen = QGuiApplication::primaryScreen()->geometry();
8812
8813 s.setWidth(qMin(s.width(), screen.width()*2/3));
8814 s.setHeight(qMin(s.height(), screen.height()*2/3));
8815
8816 if (QTLWExtra *extra = maybeTopData())
8817 extra->sizeAdjusted = true;
8818 }
8819
8820 if (!s.isValid()) {
8821 QRect r = q->childrenRect(); // get children rectangle
8822 if (r.isNull())
8823 return s;
8824 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8825 }
8826
8827 return s;
8828}
8829
8830/*!
8831 Adjusts the size of the widget to fit its contents.
8832
8833 This function uses sizeHint() if it is valid, i.e., the size hint's width
8834 and height are >= 0. Otherwise, it sets the size to the children
8835 rectangle that covers all child widgets (the union of all child widget
8836 rectangles).
8837
8838 For windows, the screen size is also taken into account. If the sizeHint()
8839 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8840 {expanding}, the window will be at least (200, 100). The maximum size of
8841 a window is 2/3 of the screen's width and height.
8842
8843 \sa sizeHint(), childrenRect()
8844*/
8845
8846void QWidget::adjustSize()
8847{
8848 Q_D(QWidget);
8849 ensurePolished();
8850 QSize s = d->adjustedSize();
8851
8852 if (d->layout)
8853 d->layout->activate();
8854
8855 if (s.isValid())
8856 resize(s);
8857}
8858
8859
8860/*!
8861 \property QWidget::sizeHint
8862 \brief the recommended size for the widget
8863
8864 If the value of this property is an invalid size, no size is
8865 recommended.
8866
8867 The default implementation of sizeHint() returns an invalid size
8868 if there is no layout for this widget, and returns the layout's
8869 preferred size otherwise.
8870
8871 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8872 setMinimumSize(), updateGeometry()
8873*/
8874
8875QSize QWidget::sizeHint() const
8876{
8877 Q_D(const QWidget);
8878 if (d->layout)
8879 return d->layout->totalSizeHint();
8880 return QSize(-1, -1);
8881}
8882
8883/*!
8884 \property QWidget::minimumSizeHint
8885 \brief the recommended minimum size for the widget
8886
8887 If the value of this property is an invalid size, no minimum size
8888 is recommended.
8889
8890 The default implementation of minimumSizeHint() returns an invalid
8891 size if there is no layout for this widget, and returns the
8892 layout's minimum size otherwise. Most built-in widgets reimplement
8893 minimumSizeHint().
8894
8895 \l QLayout will never resize a widget to a size smaller than the
8896 minimum size hint unless minimumSize() is set or the size policy is
8897 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8898 size hint will be ignored.
8899
8900 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8901*/
8902QSize QWidget::minimumSizeHint() const
8903{
8904 Q_D(const QWidget);
8905 if (d->layout)
8906 return d->layout->totalMinimumSize();
8907 return QSize(-1, -1);
8908}
8909
8910
8911/*!
8912 \fn QWidget *QWidget::parentWidget() const
8913
8914 Returns the parent of this widget, or \nullptr if it does not have any
8915 parent widget.
8916*/
8917
8918
8919/*!
8920 Returns \c true if this widget is a parent, (or grandparent and so on
8921 to any level), of the given \a child, and both widgets are within
8922 the same window; otherwise returns \c false.
8923*/
8924
8925bool QWidget::isAncestorOf(const QWidget *child) const
8926{
8927 while (child) {
8928 if (child == this)
8929 return true;
8930 if (child->isWindow())
8931 return false;
8932 child = child->parentWidget();
8933 }
8934 return false;
8935}
8936
8937/*****************************************************************************
8938 QWidget event handling
8939 *****************************************************************************/
8940
8941/*!
8942 This is the main event handler; it handles event \a event. You can
8943 reimplement this function in a subclass, but we recommend using
8944 one of the specialized event handlers instead.
8945
8946 Key press and release events are treated differently from other
8947 events. event() checks for Tab and Shift+Tab and tries to move the
8948 focus appropriately. If there is no widget to move the focus to
8949 (or the key press is not Tab or Shift+Tab), event() calls
8950 keyPressEvent().
8951
8952 Mouse and tablet event handling is also slightly special: only
8953 when the widget is \l enabled, event() will call the specialized
8954 handlers such as mousePressEvent(); otherwise it will discard the
8955 event.
8956
8957 This function returns \c true if the event was recognized, otherwise
8958 it returns \c false. If the recognized event was accepted (see \l
8959 QEvent::accepted), any further processing such as event
8960 propagation to the parent widget stops.
8961
8962 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8963 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8964 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8965 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8966 QObject::event(), QObject::timerEvent()
8967*/
8968
8969bool QWidget::event(QEvent *event)
8970{
8971 Q_D(QWidget);
8972
8973 // ignore mouse and key events when disabled
8974 if (!isEnabled()) {
8975 switch(event->type()) {
8976 case QEvent::TabletPress:
8977 case QEvent::TabletRelease:
8978 case QEvent::TabletMove:
8979 case QEvent::MouseButtonPress:
8980 case QEvent::MouseButtonRelease:
8981 case QEvent::MouseButtonDblClick:
8982 case QEvent::MouseMove:
8983 case QEvent::TouchBegin:
8984 case QEvent::TouchUpdate:
8985 case QEvent::TouchEnd:
8986 case QEvent::TouchCancel:
8987 case QEvent::ContextMenu:
8988 case QEvent::KeyPress:
8989 case QEvent::KeyRelease:
8990#if QT_CONFIG(wheelevent)
8991 case QEvent::Wheel:
8992#endif
8993 return false;
8994 default:
8995 break;
8996 }
8997 }
8998 switch (event->type()) {
8999 case QEvent::PlatformSurface: {
9000 // Sync up QWidget's view of whether or not the widget has been created
9001 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
9002 case QPlatformSurfaceEvent::SurfaceCreated:
9003 if (!testAttribute(Qt::WA_WState_Created))
9004 create();
9005 break;
9006 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
9007 if (testAttribute(Qt::WA_WState_Created)) {
9008 // Child windows have already been destroyed by QWindow,
9009 // so we skip them here.
9010 destroy(false, false);
9011 }
9012 break;
9013 }
9014 break;
9015 }
9016 case QEvent::MouseMove:
9017 mouseMoveEvent((QMouseEvent*)event);
9018 break;
9019
9020 case QEvent::MouseButtonPress:
9021 mousePressEvent((QMouseEvent*)event);
9022 break;
9023
9024 case QEvent::MouseButtonRelease:
9025 mouseReleaseEvent((QMouseEvent*)event);
9026 break;
9027
9028 case QEvent::MouseButtonDblClick:
9029 mouseDoubleClickEvent((QMouseEvent*)event);
9030 break;
9031#if QT_CONFIG(wheelevent)
9032 case QEvent::Wheel:
9033 wheelEvent((QWheelEvent*)event);
9034 break;
9035#endif
9036#if QT_CONFIG(tabletevent)
9037 case QEvent::TabletMove:
9038 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9039 break;
9040 Q_FALLTHROUGH();
9041 case QEvent::TabletPress:
9042 case QEvent::TabletRelease:
9043 tabletEvent((QTabletEvent*)event);
9044 break;
9045#endif
9046 case QEvent::KeyPress: {
9047 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9048 bool res = false;
9049 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9050 if (k->key() == Qt::Key_Backtab
9051 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9052 res = focusNextPrevChild(false);
9053 else if (k->key() == Qt::Key_Tab)
9054 res = focusNextPrevChild(true);
9055 if (res)
9056 break;
9057 }
9058 keyPressEvent(k);
9059#ifdef QT_KEYPAD_NAVIGATION
9060 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9061 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9062 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9063 if (k->key() == Qt::Key_Up)
9064 res = focusNextPrevChild(false);
9065 else if (k->key() == Qt::Key_Down)
9066 res = focusNextPrevChild(true);
9067 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9068 if (k->key() == Qt::Key_Up)
9069 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9070 else if (k->key() == Qt::Key_Right)
9071 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9072 else if (k->key() == Qt::Key_Down)
9073 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9074 else if (k->key() == Qt::Key_Left)
9075 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9076 }
9077 if (res) {
9078 k->accept();
9079 break;
9080 }
9081 }
9082#endif
9083#if QT_CONFIG(whatsthis)
9084 if (!k->isAccepted()
9085 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9086 && d->whatsThis.size()) {
9087 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9088 k->accept();
9089 }
9090#endif
9091 }
9092 break;
9093
9094 case QEvent::KeyRelease:
9095 keyReleaseEvent((QKeyEvent*)event);
9096 Q_FALLTHROUGH();
9097 case QEvent::ShortcutOverride:
9098 break;
9099
9100 case QEvent::InputMethod:
9101 inputMethodEvent((QInputMethodEvent *) event);
9102 break;
9103
9104 case QEvent::InputMethodQuery: {
9105 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9106 Qt::InputMethodQueries queries = query->queries();
9107 for (uint i = 0; i < 32; ++i) {
9108 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9109 if (q) {
9110 QVariant v = inputMethodQuery(q);
9111 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9112 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9113 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9114 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9115 // will only be set if the widget supports IM _and_ is not read-only. So for
9116 // read-only widgets, not all IM features will be supported when ImEnabled is
9117 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9118 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9119 }
9120 query->setValue(q, v);
9121 }
9122 }
9123 query->accept();
9124 }
9125 break;
9126
9127 case QEvent::PolishRequest:
9128 ensurePolished();
9129 break;
9130
9131 case QEvent::Polish: {
9132 style()->polish(this);
9133 setAttribute(Qt::WA_WState_Polished);
9134 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9135 d->resolveFont();
9136 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9137 d->resolvePalette();
9138 }
9139 break;
9140
9141 case QEvent::ApplicationWindowIconChange:
9142 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9143 d->setWindowIcon_sys();
9144 d->setWindowIcon_helper();
9145 }
9146 break;
9147 case QEvent::FocusIn:
9148 focusInEvent((QFocusEvent*)event);
9149 d->updateWidgetTransform(event);
9150 break;
9151
9152 case QEvent::FocusOut:
9153 focusOutEvent((QFocusEvent*)event);
9154 break;
9155
9156 case QEvent::Enter:
9157#if QT_CONFIG(statustip)
9158 if (d->statusTip.size()) {
9159 QStatusTipEvent tip(d->statusTip);
9160 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9161 }
9162#endif
9163 enterEvent(static_cast<QEnterEvent*>(event));
9164 break;
9165
9166 case QEvent::Leave:
9167#if QT_CONFIG(statustip)
9168 if (d->statusTip.size()) {
9169 QString empty;
9170 QStatusTipEvent tip(empty);
9171 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9172 }
9173#endif
9174 leaveEvent(event);
9175 break;
9176
9177 case QEvent::HoverEnter:
9178 case QEvent::HoverLeave:
9179 update();
9180 break;
9181
9182 case QEvent::Paint:
9183 // At this point the event has to be delivered, regardless
9184 // whether the widget isVisible() or not because it
9185 // already went through the filters
9186 paintEvent((QPaintEvent*)event);
9187 break;
9188
9189 case QEvent::Move:
9190 moveEvent((QMoveEvent*)event);
9191 d->updateWidgetTransform(event);
9192 break;
9193
9194 case QEvent::Resize:
9195 resizeEvent((QResizeEvent*)event);
9196 d->updateWidgetTransform(event);
9197 break;
9198
9199 case QEvent::Close:
9200 closeEvent((QCloseEvent *)event);
9201 break;
9202
9203#ifndef QT_NO_CONTEXTMENU
9204 case QEvent::ContextMenu:
9205 switch (data->context_menu_policy) {
9206 case Qt::PreventContextMenu:
9207 break;
9208 case Qt::DefaultContextMenu:
9209 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9210 break;
9211 case Qt::CustomContextMenu:
9212 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9213 break;
9214#if QT_CONFIG(menu)
9215 case Qt::ActionsContextMenu:
9216 if (d->actions.size()) {
9217 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9218 nullptr, this);
9219 break;
9220 }
9221 Q_FALLTHROUGH();
9222#endif
9223 default:
9224 event->ignore();
9225 break;
9226 }
9227 break;
9228#endif // QT_NO_CONTEXTMENU
9229
9230#if QT_CONFIG(draganddrop)
9231 case QEvent::Drop:
9232 dropEvent((QDropEvent*) event);
9233 break;
9234
9235 case QEvent::DragEnter:
9236 dragEnterEvent((QDragEnterEvent*) event);
9237 break;
9238
9239 case QEvent::DragMove:
9240 dragMoveEvent((QDragMoveEvent*) event);
9241 break;
9242
9243 case QEvent::DragLeave:
9244 dragLeaveEvent((QDragLeaveEvent*) event);
9245 break;
9246#endif
9247
9248 case QEvent::Show:
9249 showEvent((QShowEvent*) event);
9250 break;
9251
9252 case QEvent::Hide:
9253 hideEvent((QHideEvent*) event);
9254 break;
9255
9256 case QEvent::ShowWindowRequest:
9257 if (!isHidden())
9258 d->show_sys();
9259 break;
9260
9261 case QEvent::ApplicationFontChange:
9262 d->resolveFont();
9263 break;
9264 case QEvent::ApplicationPaletteChange:
9265 d->resolvePalette();
9266 break;
9267
9268 case QEvent::ToolBarChange:
9269 case QEvent::ActivationChange:
9270 case QEvent::EnabledChange:
9271 case QEvent::FontChange:
9272 case QEvent::StyleChange:
9273 case QEvent::PaletteChange:
9274 case QEvent::WindowTitleChange:
9275 case QEvent::IconTextChange:
9276 case QEvent::ModifiedChange:
9277 case QEvent::MouseTrackingChange:
9278 case QEvent::TabletTrackingChange:
9279 case QEvent::ParentChange:
9280 case QEvent::LocaleChange:
9281 case QEvent::MacSizeChange:
9282 case QEvent::ContentsRectChange:
9283 case QEvent::ThemeChange:
9284 case QEvent::ReadOnlyChange:
9285 changeEvent(event);
9286 break;
9287
9288 case QEvent::WindowStateChange: {
9289 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9290 if (wasMinimized != isMinimized()) {
9291 QWidget *widget = const_cast<QWidget *>(this);
9292 if (wasMinimized) {
9293 // Always send the spontaneous events here, otherwise it can break the application!
9294 if (!d->childrenShownByExpose) {
9295 // Show widgets only when they are not yet shown by the expose event
9296 d->showChildren(true);
9297 QShowEvent showEvent;
9298 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9299 }
9300 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9301 } else {
9302 QHideEvent hideEvent;
9303 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9304 d->hideChildren(true);
9305 d->childrenHiddenByWState = true;
9306 }
9307 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9308 }
9309 changeEvent(event);
9310 }
9311 break;
9312
9313 case QEvent::WindowActivate:
9314 case QEvent::WindowDeactivate: {
9315 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9316 update();
9317 QList<QObject*> childList = d->children;
9318 for (int i = 0; i < childList.size(); ++i) {
9319 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9320 if (w && w->isVisible() && !w->isWindow())
9321 QCoreApplication::sendEvent(w, event);
9322 }
9323 break; }
9324
9325 case QEvent::LanguageChange:
9326 changeEvent(event);
9327 {
9328 QList<QObject*> childList = d->children;
9329 for (int i = 0; i < childList.size(); ++i) {
9330 QObject *o = childList.at(i);
9331 if (o)
9332 QCoreApplication::sendEvent(o, event);
9333 }
9334 }
9335 update();
9336 break;
9337
9338 case QEvent::ApplicationLayoutDirectionChange:
9339 d->resolveLayoutDirection();
9340 break;
9341
9342 case QEvent::LayoutDirectionChange:
9343 if (d->layout)
9344 d->layout->invalidate();
9345 update();
9346 changeEvent(event);
9347 break;
9348 case QEvent::UpdateRequest:
9349 d->syncBackingStore();
9350 break;
9351 case QEvent::UpdateLater:
9352 update(static_cast<QUpdateLaterEvent*>(event)->region());
9353 break;
9354 case QEvent::StyleAnimationUpdate:
9355 if (isVisible() && !window()->isMinimized()) {
9356 event->accept();
9357 update();
9358 }
9359 break;
9360
9361 case QEvent::WindowBlocked:
9362 case QEvent::WindowUnblocked:
9363 if (!d->children.isEmpty()) {
9364 QWidget *modalWidget = QApplication::activeModalWidget();
9365 for (int i = 0; i < d->children.size(); ++i) {
9366 QObject *o = d->children.at(i);
9367 if (o && o != modalWidget && o->isWidgetType()) {
9368 QWidget *w = static_cast<QWidget *>(o);
9369 // do not forward the event to child windows; QApplication does this for us
9370 if (!w->isWindow())
9371 QCoreApplication::sendEvent(w, event);
9372 }
9373 }
9374 }
9375 break;
9376#if QT_CONFIG(tooltip)
9377 case QEvent::ToolTip:
9378 if (!d->toolTip.isEmpty())
9379 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9380 else
9381 event->ignore();
9382 break;
9383#endif
9384#if QT_CONFIG(whatsthis)
9385 case QEvent::WhatsThis:
9386 if (d->whatsThis.size())
9387 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9388 else
9389 event->ignore();
9390 break;
9391 case QEvent::QueryWhatsThis:
9392 if (d->whatsThis.isEmpty())
9393 event->ignore();
9394 break;
9395#endif
9396 case QEvent::EmbeddingControl:
9397 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9398 data->fstrut_dirty = false;
9399 break;
9400#ifndef QT_NO_ACTION
9401 case QEvent::ActionAdded:
9402 case QEvent::ActionRemoved:
9403 case QEvent::ActionChanged:
9404 actionEvent((QActionEvent*)event);
9405 break;
9406#endif
9407
9408 case QEvent::KeyboardLayoutChange:
9409 {
9410 changeEvent(event);
9411
9412 // inform children of the change
9413 QList<QObject*> childList = d->children;
9414 for (int i = 0; i < childList.size(); ++i) {
9415 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9416 if (w && w->isVisible() && !w->isWindow())
9417 QCoreApplication::sendEvent(w, event);
9418 }
9419 break;
9420 }
9421 case QEvent::TouchBegin:
9422 case QEvent::TouchUpdate:
9423 case QEvent::TouchEnd:
9424 case QEvent::TouchCancel:
9425 {
9426 event->ignore();
9427 break;
9428 }
9429#ifndef QT_NO_GESTURES
9430 case QEvent::Gesture:
9431 event->ignore();
9432 break;
9433#endif
9434 case QEvent::ScreenChangeInternal:
9435 if (const QTLWExtra *te = d->maybeTopData()) {
9436 const QWindow *win = te->window;
9437 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9438 }
9439 break;
9440 case QEvent::DevicePixelRatioChange:
9441 if (d->data.fnt.d->dpi != logicalDpiY())
9442 d->updateFont(d->data.fnt);
9443 d->renderToTextureReallyDirty = 1;
9444 break;
9445 case QEvent::DynamicPropertyChange: {
9446 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9447 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9448 uint value = property(propName.constData()).toUInt();
9449 if (!d->extra)
9450 d->createExtra();
9451 const char axis = propName.at(12);
9452 if (axis == 'X')
9453 d->extra->customDpiX = value;
9454 else if (axis == 'Y')
9455 d->extra->customDpiY = value;
9456 d->updateFont(d->data.fnt);
9457 }
9458 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9459 windowHandle()->setProperty(propName, property(propName));
9460 Q_FALLTHROUGH();
9461 }
9462 default:
9463 return QObject::event(event);
9464 }
9465 return true;
9466}
9467
9468/*!
9469 This event handler can be reimplemented to handle state changes.
9470
9471 The state being changed in this event can be retrieved through the \a event
9472 supplied.
9473
9474 Change events include: QEvent::ToolBarChange,
9475 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9476 QEvent::StyleChange, QEvent::PaletteChange,
9477 QEvent::WindowTitleChange, QEvent::IconTextChange,
9478 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9479 QEvent::ParentChange, QEvent::WindowStateChange,
9480 QEvent::LanguageChange, QEvent::LocaleChange,
9481 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9482
9483*/
9484void QWidget::changeEvent(QEvent * event)
9485{
9486 switch(event->type()) {
9487 case QEvent::EnabledChange: {
9488 update();
9489#if QT_CONFIG(accessibility)
9490 QAccessible::State s;
9491 s.disabled = true;
9492 QAccessibleStateChangeEvent event(this, s);
9493 QAccessible::updateAccessibility(&event);
9494#endif
9495 break;
9496 }
9497
9498 case QEvent::FontChange:
9499 case QEvent::StyleChange: {
9500 Q_D(QWidget);
9501 update();
9502 updateGeometry();
9503 if (d->layout)
9504 d->layout->invalidate();
9505 break;
9506 }
9507
9508 case QEvent::PaletteChange:
9509 update();
9510 break;
9511
9512 case QEvent::ThemeChange:
9513 if (QGuiApplication::desktopSettingsAware()
9514 && qApp && !QCoreApplication::closingDown()) {
9515 if (testAttribute(Qt::WA_WState_Polished))
9516 QApplication::style()->unpolish(this);
9517 if (testAttribute(Qt::WA_WState_Polished))
9518 QApplication::style()->polish(this);
9519 QEvent styleChangedEvent(QEvent::StyleChange);
9520 QCoreApplication::sendEvent(this, &styleChangedEvent);
9521 if (isVisible())
9522 update();
9523 }
9524 break;
9525
9526#ifdef Q_OS_MAC
9527 case QEvent::MacSizeChange:
9528 updateGeometry();
9529 break;
9530#endif
9531
9532 default:
9533 break;
9534 }
9535}
9536
9537/*!
9538 This event handler, for event \a event, can be reimplemented in a
9539 subclass to receive mouse move events for the widget.
9540
9541 If mouse tracking is switched off, mouse move events only occur if
9542 a mouse button is pressed while the mouse is being moved. If mouse
9543 tracking is switched on, mouse move events occur even if no mouse
9544 button is pressed.
9545
9546 QMouseEvent::position() reports the position of the mouse cursor,
9547 relative to this widget. For press and release events, the
9548 position is usually the same as the position of the last mouse
9549 move event, but it might be different if the user's hand shakes.
9550 This is a feature of the underlying window system, not Qt.
9551
9552 If you want to show a tooltip immediately, while the mouse is
9553 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9554 and show them as a tooltip), you must first enable mouse tracking
9555 as described above. Then, to ensure that the tooltip is updated
9556 immediately, you must call QToolTip::showText() instead of
9557 setToolTip() in your implementation of mouseMoveEvent().
9558
9559 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9560 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9561*/
9562
9563void QWidget::mouseMoveEvent(QMouseEvent *event)
9564{
9565 event->ignore();
9566}
9567
9568/*!
9569 This event handler, for event \a event, can be reimplemented in a
9570 subclass to receive mouse press events for the widget.
9571
9572 If you create new widgets in the mousePressEvent() the
9573 mouseReleaseEvent() may not end up where you expect, depending on
9574 the underlying window system (or X11 window manager), the widgets'
9575 location and maybe more.
9576
9577 The default implementation implements the closing of popup widgets
9578 when you click outside the window. For other widget types it does
9579 nothing.
9580
9581 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9582 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9583*/
9584
9585void QWidget::mousePressEvent(QMouseEvent *event)
9586{
9587 event->ignore();
9588 if ((windowType() == Qt::Popup)) {
9589 event->accept();
9590 QWidget* w;
9591 while ((w = QApplication::activePopupWidget()) && w != this){
9592 w->close();
9593 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9594 w->hide(); // hide at least
9595 }
9596 if (!rect().contains(event->position().toPoint())){
9597 close();
9598 }
9599 }
9600}
9601
9602/*!
9603 This event handler, for event \a event, can be reimplemented in a
9604 subclass to receive mouse release events for the widget.
9605
9606 \sa mousePressEvent(), mouseDoubleClickEvent(),
9607 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9608*/
9609
9610void QWidget::mouseReleaseEvent(QMouseEvent *event)
9611{
9612 event->ignore();
9613}
9614
9615/*!
9616 This event handler, for event \a event, can be reimplemented in a
9617 subclass to receive mouse double click events for the widget.
9618
9619 The default implementation calls mousePressEvent().
9620
9621 \note The widget will also receive mouse press and mouse release
9622 events in addition to the double click event. And if another widget
9623 that overlaps this widget disappears in response to press or
9624 release events, then this widget will only receive the double click
9625 event. It is up to the developer to ensure that the application
9626 interprets these events correctly.
9627
9628 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9629 event(), QMouseEvent
9630*/
9631
9632void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9633{
9634 mousePressEvent(event);
9635}
9636
9637#if QT_CONFIG(wheelevent)
9638/*!
9639 This event handler, for event \a event, can be reimplemented in a
9640 subclass to receive wheel events for the widget.
9641
9642 If you reimplement this handler, it is very important that you
9643 \l{QEvent}{ignore()} the event if you do not handle
9644 it, so that the widget's parent can interpret it.
9645
9646 The default implementation ignores the event.
9647
9648 \sa QEvent::ignore(), QEvent::accept(), event(),
9649 QWheelEvent
9650*/
9651
9652void QWidget::wheelEvent(QWheelEvent *event)
9653{
9654 event->ignore();
9655}
9656#endif // QT_CONFIG(wheelevent)
9657
9658#if QT_CONFIG(tabletevent)
9659/*!
9660 This event handler, for event \a event, can be reimplemented in a
9661 subclass to receive tablet events for the widget.
9662
9663 If you reimplement this handler, it is very important that you
9664 \l{QEvent}{ignore()} the event if you do not handle
9665 it, so that the widget's parent can interpret it.
9666
9667 The default implementation ignores the event.
9668
9669 If tablet tracking is switched off, tablet move events only occur if the
9670 stylus is in contact with the tablet, or at least one stylus button is
9671 pressed, while the stylus is being moved. If tablet tracking is switched on,
9672 tablet move events occur even while the stylus is hovering in proximity of
9673 the tablet, with no buttons pressed.
9674
9675 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9676 QTabletEvent
9677*/
9678
9679void QWidget::tabletEvent(QTabletEvent *event)
9680{
9681 event->ignore();
9682}
9683#endif // QT_CONFIG(tabletevent)
9684
9685/*!
9686 This event handler, for event \a event, can be reimplemented in a
9687 subclass to receive key press events for the widget.
9688
9689 A widget must call setFocusPolicy() to accept focus initially and
9690 have focus in order to receive a key press event.
9691
9692 If you reimplement this handler, it is very important that you
9693 call the base class implementation if you do not act upon the key.
9694
9695 The default implementation closes popup widgets if the user
9696 presses the key sequence for QKeySequence::Cancel (typically the
9697 Escape key). Otherwise the event is ignored, so that the widget's
9698 parent can interpret it.
9699
9700 Note that QKeyEvent starts with isAccepted() == true, so you do not
9701 need to call QKeyEvent::accept() - just do not call the base class
9702 implementation if you act upon the key.
9703
9704 \sa keyReleaseEvent(), setFocusPolicy(),
9705 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9706*/
9707
9708void QWidget::keyPressEvent(QKeyEvent *event)
9709{
9710#ifndef QT_NO_SHORTCUT
9711 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9712 event->accept();
9713 close();
9714 } else
9715#endif
9716 {
9717 event->ignore();
9718 }
9719}
9720
9721/*!
9722 This event handler, for event \a event, can be reimplemented in a
9723 subclass to receive key release events for the widget.
9724
9725 A widget must \l{setFocusPolicy()}{accept focus}
9726 initially and \l{hasFocus()}{have focus} in order to
9727 receive a key release event.
9728
9729 If you reimplement this handler, it is very important that you
9730 call the base class implementation if you do not act upon the key.
9731
9732 The default implementation ignores the event, so that the widget's
9733 parent can interpret it.
9734
9735 Note that QKeyEvent starts with isAccepted() == true, so you do not
9736 need to call QKeyEvent::accept() - just do not call the base class
9737 implementation if you act upon the key.
9738
9739 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9740 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9741*/
9742
9743void QWidget::keyReleaseEvent(QKeyEvent *event)
9744{
9745 event->ignore();
9746}
9747
9748/*!
9749 \fn void QWidget::focusInEvent(QFocusEvent *event)
9750
9751 This event handler can be reimplemented in a subclass to receive
9752 keyboard focus events (focus received) for the widget. The event
9753 is passed in the \a event parameter
9754
9755 A widget normally must setFocusPolicy() to something other than
9756 Qt::NoFocus to receive focus events. (Note that the
9757 application programmer can call setFocus() on any widget, even
9758 those that do not normally accept focus.)
9759
9760 The default implementation updates the widget (except for windows
9761 that do not specify a focusPolicy()).
9762
9763 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9764 keyReleaseEvent(), event(), QFocusEvent
9765*/
9766
9767void QWidget::focusInEvent(QFocusEvent *)
9768{
9769 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9770 update();
9771 }
9772}
9773
9774/*!
9775 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9776
9777 This event handler can be reimplemented in a subclass to receive
9778 keyboard focus events (focus lost) for the widget. The events is
9779 passed in the \a event parameter.
9780
9781 A widget normally must setFocusPolicy() to something other than
9782 Qt::NoFocus to receive focus events. (Note that the
9783 application programmer can call setFocus() on any widget, even
9784 those that do not normally accept focus.)
9785
9786 The default implementation updates the widget (except for windows
9787 that do not specify a focusPolicy()).
9788
9789 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9790 keyReleaseEvent(), event(), QFocusEvent
9791*/
9792
9793void QWidget::focusOutEvent(QFocusEvent *)
9794{
9795 if (focusPolicy() != Qt::NoFocus || !isWindow())
9796 update();
9797
9798#if !defined(QT_PLATFORM_UIKIT)
9799 // FIXME: revisit autoSIP logic, QTBUG-42906
9800 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9801 QGuiApplication::inputMethod()->hide();
9802#endif
9803}
9804
9805/*!
9806 \fn void QWidget::enterEvent(QEnterEvent *event)
9807
9808 This event handler can be reimplemented in a subclass to receive
9809 widget enter events which are passed in the \a event parameter.
9810
9811 An event is sent to the widget when the mouse cursor enters the
9812 widget.
9813
9814 \sa leaveEvent(), mouseMoveEvent(), event()
9815*/
9816
9817void QWidget::enterEvent(QEnterEvent *)
9818{
9819}
9820
9821/*!
9822 \fn void QWidget::leaveEvent(QEvent *event)
9823
9824 This event handler can be reimplemented in a subclass to receive
9825 widget leave events which are passed in the \a event parameter.
9826
9827 A leave event is sent to the widget when the mouse cursor leaves
9828 the widget.
9829
9830 \sa enterEvent(), mouseMoveEvent(), event()
9831*/
9832
9833void QWidget::leaveEvent(QEvent *)
9834{
9835}
9836
9837/*!
9838 \fn void QWidget::paintEvent(QPaintEvent *event)
9839
9840 This event handler can be reimplemented in a subclass to receive paint
9841 events passed in \a event.
9842
9843 A paint event is a request to repaint all or part of a widget. It can
9844 happen for one of the following reasons:
9845
9846 \list
9847 \li repaint() or update() was invoked,
9848 \li the widget was obscured and has now been uncovered, or
9849 \li many other reasons.
9850 \endlist
9851
9852 Many widgets can simply repaint their entire surface when asked to, but
9853 some slow widgets need to optimize by painting only the requested region:
9854 QPaintEvent::region(). This speed optimization does not change the result,
9855 as painting is clipped to that region during event processing. QListView
9856 and QTableView do this, for example.
9857
9858 Qt also tries to speed up painting by merging multiple paint events into
9859 one. When update() is called several times or the window system sends
9860 several paint events, Qt merges these events into one event with a larger
9861 region (see QRegion::united()). The repaint() function does not permit this
9862 optimization, so we suggest using update() whenever possible.
9863
9864 When the paint event occurs, the update region has normally been erased, so
9865 you are painting on the widget's background.
9866
9867 The background can be set using setBackgroundRole() and setPalette().
9868
9869 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9870 is no need to write double-buffering code in paintEvent() to avoid flicker.
9871
9872 \note Generally, you should refrain from calling update() or repaint()
9873 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9874 children inside a paintEvent() results in undefined behavior; the child may
9875 or may not get a paint event.
9876
9877 \warning If you are using a custom paint engine without Qt's backingstore,
9878 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9879 never be called; the backingstore will be used instead.
9880
9881 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9882 {Analog Clock}
9883*/
9884
9885void QWidget::paintEvent(QPaintEvent *)
9886{
9887}
9888
9889
9890/*!
9891 \fn void QWidget::moveEvent(QMoveEvent *event)
9892
9893 This event handler can be reimplemented in a subclass to receive
9894 widget move events which are passed in the \a event parameter.
9895 When the widget receives this event, it is already at the new
9896 position.
9897
9898 The old position is accessible through QMoveEvent::oldPos().
9899
9900 \sa resizeEvent(), event(), move(), QMoveEvent
9901*/
9902
9903void QWidget::moveEvent(QMoveEvent *)
9904{
9905}
9906
9907
9908/*!
9909 This event handler can be reimplemented in a subclass to receive
9910 widget resize events which are passed in the \a event parameter.
9911 When resizeEvent() is called, the widget already has its new
9912 geometry. The old size is accessible through
9913 QResizeEvent::oldSize().
9914
9915 The widget will be erased and receive a paint event immediately
9916 after processing the resize event. No drawing need be (or should
9917 be) done inside this handler.
9918
9919
9920 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9921 {Scribble Example}
9922*/
9923
9924void QWidget::resizeEvent(QResizeEvent * /* event */)
9925{
9926}
9927
9928#ifndef QT_NO_ACTION
9929/*!
9930 \fn void QWidget::actionEvent(QActionEvent *event)
9931
9932 This event handler is called with the given \a event whenever the
9933 widget's actions are changed.
9934
9935 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9936*/
9937void QWidget::actionEvent(QActionEvent *)
9938{
9939
9940}
9941#endif
9942
9943/*!
9944 This event handler is called with the given \a event when Qt receives a window
9945 close request for a top-level widget from the window system.
9946
9947 By default, the event is accepted and the widget is closed. You can reimplement
9948 this function to change the way the widget responds to window close requests.
9949 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9950 on all events.
9951
9952 Main window applications typically use reimplementations of this function to check
9953 whether the user's work has been saved and ask for permission before closing.
9954
9955 \sa event(), hide(), close(), QCloseEvent
9956*/
9957
9958void QWidget::closeEvent(QCloseEvent *event)
9959{
9960 event->accept();
9961}
9962
9963#ifndef QT_NO_CONTEXTMENU
9964/*!
9965 This event handler, for event \a event, can be reimplemented in a
9966 subclass to receive widget context menu events.
9967
9968 The handler is called when the widget's \l contextMenuPolicy is
9969 Qt::DefaultContextMenu.
9970
9971 The default implementation ignores the context event.
9972 See the \l QContextMenuEvent documentation for more details.
9973
9974 \sa event(), QContextMenuEvent, customContextMenuRequested()
9975*/
9976
9977void QWidget::contextMenuEvent(QContextMenuEvent *event)
9978{
9979 event->ignore();
9980}
9981#endif // QT_NO_CONTEXTMENU
9982
9983
9984/*!
9985 This event handler, for event \a event, can be reimplemented in a
9986 subclass to receive Input Method composition events. This handler
9987 is called when the state of the input method changes.
9988
9989 Note that when creating custom text editing widgets, the
9990 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9991 (using the setAttribute() function) in order to receive input
9992 method events.
9993
9994 The default implementation calls event->ignore(), which rejects the
9995 Input Method event. See the \l QInputMethodEvent documentation for more
9996 details.
9997
9998 \sa event(), QInputMethodEvent
9999*/
10000void QWidget::inputMethodEvent(QInputMethodEvent *event)
10001{
10002 event->ignore();
10003}
10004
10005/*!
10006 This method is only relevant for input widgets. It is used by the
10007 input method to query a set of properties of the widget to be
10008 able to support complex input method operations as support for
10009 surrounding text and reconversions.
10010
10011 \a query specifies which property is queried.
10012
10013 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
10014*/
10015QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
10016{
10017 switch(query) {
10018 case Qt::ImCursorRectangle:
10019 return QRect(width()/2, 0, 1, height());
10020 case Qt::ImFont:
10021 return font();
10022 case Qt::ImAnchorPosition:
10023 // Fallback.
10024 return inputMethodQuery(Qt::ImCursorPosition);
10025 case Qt::ImHints:
10026 return (int)inputMethodHints();
10027 case Qt::ImInputItemClipRectangle:
10028 return d_func()->clipRect();
10029 default:
10030 return QVariant();
10031 }
10032}
10033
10034/*!
10035 \property QWidget::inputMethodHints
10036 \brief What input method specific hints the widget has.
10037
10038 This is only relevant for input widgets. It is used by
10039 the input method to retrieve hints as to how the input method
10040 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
10041 is set, the input method may change its visual components to reflect
10042 that only numbers can be entered.
10043
10044 \warning Some widgets require certain flags to work as
10045 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
10046 instead of \c{w->setInputMethodHints(f)}.
10047
10048 \note The flags are only hints, so the particular input method
10049 implementation is free to ignore them. If you want to be
10050 sure that a certain type of characters are entered,
10051 you should also set a QValidator on the widget.
10052
10053 The default value is Qt::ImhNone.
10054
10055 \since 4.6
10056
10057 \sa inputMethodQuery()
10058*/
10059Qt::InputMethodHints QWidget::inputMethodHints() const
10060{
10061#if QT_CONFIG(im)
10062 const QWidgetPrivate *priv = d_func();
10063 while (priv->inheritsInputMethodHints) {
10064 priv = priv->q_func()->parentWidget()->d_func();
10065 Q_ASSERT(priv);
10066 }
10067 return priv->imHints;
10068#else
10069 return Qt::ImhNone;
10070#endif
10071}
10072
10073void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10074{
10075#ifndef QT_NO_IM
10076 Q_D(QWidget);
10077 if (d->imHints == hints)
10078 return;
10079 d->imHints = hints;
10080 if (this == QGuiApplication::focusObject())
10081 QGuiApplication::inputMethod()->update(Qt::ImHints);
10082#else
10083 Q_UNUSED(hints);
10084#endif //QT_NO_IM
10085}
10086
10087
10088#if QT_CONFIG(draganddrop)
10089
10090/*!
10091 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10092
10093 This event handler is called when a drag is in progress and the
10094 mouse enters this widget. The event is passed in the \a event parameter.
10095
10096 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10097 move events}.
10098
10099 See the \l{dnd.html}{Drag-and-drop documentation} for an
10100 overview of how to provide drag-and-drop in your application.
10101
10102 \sa QDrag, QDragEnterEvent
10103*/
10104void QWidget::dragEnterEvent(QDragEnterEvent *)
10105{
10106}
10107
10108/*!
10109 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10110
10111 This event handler is called if a drag is in progress, and when
10112 any of the following conditions occur: the cursor enters this widget,
10113 the cursor moves within this widget, or a modifier key is pressed on
10114 the keyboard while this widget has the focus. The event is passed
10115 in the \a event parameter.
10116
10117 See the \l{dnd.html}{Drag-and-drop documentation} for an
10118 overview of how to provide drag-and-drop in your application.
10119
10120 \sa QDrag, QDragMoveEvent
10121*/
10122void QWidget::dragMoveEvent(QDragMoveEvent *)
10123{
10124}
10125
10126/*!
10127 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10128
10129 This event handler is called when a drag is in progress and the
10130 mouse leaves this widget. The event is passed in the \a event
10131 parameter.
10132
10133 See the \l{dnd.html}{Drag-and-drop documentation} for an
10134 overview of how to provide drag-and-drop in your application.
10135
10136 \sa QDrag, QDragLeaveEvent
10137*/
10138void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10139{
10140}
10141
10142/*!
10143 \fn void QWidget::dropEvent(QDropEvent *event)
10144
10145 This event handler is called when the drag is dropped on this
10146 widget. The event is passed in the \a event parameter.
10147
10148 See the \l{dnd.html}{Drag-and-drop documentation} for an
10149 overview of how to provide drag-and-drop in your application.
10150
10151 \sa QDrag, QDropEvent
10152*/
10153void QWidget::dropEvent(QDropEvent *)
10154{
10155}
10156
10157#endif // QT_CONFIG(draganddrop)
10158
10159/*!
10160 \fn void QWidget::showEvent(QShowEvent *event)
10161
10162 This event handler can be reimplemented in a subclass to receive
10163 widget show events which are passed in the \a event parameter.
10164
10165 Non-spontaneous show events are sent to widgets immediately
10166 before they are shown. The spontaneous show events of windows are
10167 delivered afterwards.
10168
10169 Note: A widget receives spontaneous show and hide events when its
10170 mapping status is changed by the window system, e.g. a spontaneous
10171 hide event when the user minimizes the window, and a spontaneous
10172 show event when the window is restored again. After receiving a
10173 spontaneous hide event, a widget is still considered visible in
10174 the sense of isVisible().
10175
10176 \sa visible, event(), QShowEvent
10177*/
10178void QWidget::showEvent(QShowEvent *)
10179{
10180}
10181
10182/*!
10183 \fn void QWidget::hideEvent(QHideEvent *event)
10184
10185 This event handler can be reimplemented in a subclass to receive
10186 widget hide events. The event is passed in the \a event parameter.
10187
10188 Hide events are sent to widgets immediately after they have been
10189 hidden.
10190
10191 Note: A widget receives spontaneous show and hide events when its
10192 mapping status is changed by the window system, e.g. a spontaneous
10193 hide event when the user minimizes the window, and a spontaneous
10194 show event when the window is restored again. After receiving a
10195 spontaneous hide event, a widget is still considered visible in
10196 the sense of isVisible().
10197
10198 \sa visible, event(), QHideEvent
10199*/
10200void QWidget::hideEvent(QHideEvent *)
10201{
10202}
10203
10204/*!
10205 This special event handler can be reimplemented in a subclass to
10206 receive native platform events identified by \a eventType
10207 which are passed in the \a message parameter.
10208
10209 In your reimplementation of this function, if you want to stop the
10210 event being handled by Qt, return true and set \a result. The \a result
10211 parameter has meaning only on Windows. If you return false, this native
10212 event is passed back to Qt, which translates the event into a Qt event
10213 and sends it to the widget.
10214
10215 \note Events are only delivered to this event handler if the widget
10216 has a native window handle.
10217
10218 \note This function superseedes the event filter functions
10219 x11Event(), winEvent() and macEvent() of Qt 4.
10220
10221 \sa QAbstractNativeEventFilter
10222
10223 \table
10224 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10225 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10226 \row \li macOS \li "NSEvent" \li NSEvent * \li
10227 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10228 \endtable
10229*/
10230
10231bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10232{
10233 Q_UNUSED(eventType);
10234 Q_UNUSED(message);
10235 Q_UNUSED(result);
10236 return false;
10237}
10238
10239/*!
10240 Ensures that the widget and its children have been polished by
10241 QStyle (i.e., have a proper font and palette).
10242
10243 QWidget calls this function after it has been fully constructed
10244 but before it is shown the very first time. You can call this
10245 function if you want to ensure that the widget is polished before
10246 doing an operation, e.g., the correct font size might be needed in
10247 the widget's sizeHint() reimplementation. Note that this function
10248 \e is called from the default implementation of sizeHint().
10249
10250 Polishing is useful for final initialization that must happen after
10251 all constructors (from base classes as well as from subclasses)
10252 have been called.
10253
10254 If you need to change some settings when a widget is polished,
10255 reimplement event() and handle the QEvent::Polish event type.
10256
10257 \b{Note:} The function is declared const so that it can be called from
10258 other const functions (e.g., sizeHint()).
10259
10260 \sa event()
10261*/
10262void QWidget::ensurePolished() const
10263{
10264 Q_D(const QWidget);
10265
10266 const QMetaObject *m = metaObject();
10267 if (m == d->polished)
10268 return;
10269 d->polished = m;
10270
10271 QEvent e(QEvent::Polish);
10272 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10273
10274 // polish children after 'this'
10275 QList<QObject*> children = d->children;
10276 for (int i = 0; i < children.size(); ++i) {
10277 QObject *o = children.at(i);
10278 if (!o->isWidgetType())
10279 continue;
10280 if (QWidget *w = qobject_cast<QWidget *>(o))
10281 w->ensurePolished();
10282 }
10283
10284 if (d->parent && d->sendChildEvents) {
10285 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10286 QCoreApplication::sendEvent(d->parent, &e);
10287 }
10288}
10289
10290/*!
10291 Returns the mask currently set on a widget. If no mask is set the
10292 return value will be an empty region.
10293
10294 \sa setMask(), clearMask(), QRegion::isEmpty()
10295*/
10296QRegion QWidget::mask() const
10297{
10298 Q_D(const QWidget);
10299 return d->extra ? d->extra->mask : QRegion();
10300}
10301
10302/*!
10303 Returns the layout manager that is installed on this widget, or \nullptr
10304 if no layout manager is installed.
10305
10306 The layout manager sets the geometry of the widget's children
10307 that have been added to the layout.
10308
10309 \sa setLayout(), sizePolicy(), {Layout Management}
10310*/
10311QLayout *QWidget::layout() const
10312{
10313 return d_func()->layout;
10314}
10315
10316
10317/*!
10318 \fn void QWidget::setLayout(QLayout *layout)
10319
10320 Sets the layout manager for this widget to \a layout.
10321
10322 If there already is a layout manager installed on this widget,
10323 QWidget won't let you install another. You must first delete the
10324 existing layout manager (returned by layout()) before you can
10325 call setLayout() with the new layout.
10326
10327 If \a layout is the layout manager on a different widget, setLayout()
10328 will reparent the layout and make it the layout manager for this widget.
10329
10330 Example:
10331
10332 \snippet layouts/layouts.cpp 24
10333
10334 An alternative to calling this function is to pass this widget to
10335 the layout's constructor.
10336
10337 The QWidget will take ownership of \a layout.
10338
10339 \sa layout(), {Layout Management}
10340*/
10341
10342void QWidget::setLayout(QLayout *l)
10343{
10344 if (Q_UNLIKELY(!l)) {
10345 qWarning("QWidget::setLayout: Cannot set layout to 0");
10346 return;
10347 }
10348 if (layout()) {
10349 if (Q_UNLIKELY(layout() != l))
10350 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10351 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10352 objectName().toLocal8Bit().data());
10353 return;
10354 }
10355
10356 QObject *oldParent = l->parent();
10357 if (oldParent && oldParent != this) {
10358 if (oldParent->isWidgetType()) {
10359 // Steal the layout off a widget parent. Takes effect when
10360 // morphing laid-out container widgets in Designer.
10361 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10362 oldParentWidget->takeLayout();
10363 } else {
10364 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10365 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10366 objectName().toLocal8Bit().data());
10367 return;
10368 }
10369 }
10370
10371 Q_D(QWidget);
10372 l->d_func()->topLevel = true;
10373 d->layout = l;
10374 if (oldParent != this) {
10375 l->setParent(this);
10376 l->d_func()->reparentChildWidgets(this);
10377 l->invalidate();
10378 }
10379
10380 if (isWindow() && d->maybeTopData())
10381 d->topData()->sizeAdjusted = false;
10382}
10383
10384/*!
10385 \fn QLayout *QWidget::takeLayout()
10386
10387 Remove the layout from the widget.
10388 \since 4.5
10389*/
10390
10391QLayout *QWidget::takeLayout()
10392{
10393 Q_D(QWidget);
10394 QLayout *l = layout();
10395 if (!l)
10396 return nullptr;
10397 d->layout = nullptr;
10398 l->setParent(nullptr);
10399 return l;
10400}
10401
10402/*!
10403 \property QWidget::sizePolicy
10404 \brief the default layout behavior of the widget
10405
10406 If there is a QLayout that manages this widget's children, the
10407 size policy specified by that layout is used. If there is no such
10408 QLayout, the result of this function is used.
10409
10410 The default policy is Preferred/Preferred, which means that the
10411 widget can be freely resized, but prefers to be the size
10412 sizeHint() returns. Button-like widgets set the size policy to
10413 specify that they may stretch horizontally, but are fixed
10414 vertically. The same applies to lineedit controls (such as
10415 QLineEdit, QSpinBox or an editable QComboBox) and other
10416 horizontally orientated widgets (such as QProgressBar).
10417 QToolButton's are normally square, so they allow growth in both
10418 directions. Widgets that support different directions (such as
10419 QSlider, QScrollBar or QHeader) specify stretching in the
10420 respective direction only. Widgets that can provide scroll bars
10421 (usually subclasses of QScrollArea) tend to specify that they can
10422 use additional space, and that they can make do with less than
10423 sizeHint().
10424
10425 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10426*/
10427QSizePolicy QWidget::sizePolicy() const
10428{
10429 Q_D(const QWidget);
10430 return d->size_policy;
10431}
10432
10433void QWidget::setSizePolicy(QSizePolicy policy)
10434{
10435 Q_D(QWidget);
10436 setAttribute(Qt::WA_WState_OwnSizePolicy);
10437 if (policy == d->size_policy)
10438 return;
10439
10440 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10441 d->retainSizeWhenHiddenChanged = 1;
10442
10443 d->size_policy = policy;
10444
10445#if QT_CONFIG(graphicsview)
10446 if (const auto &extra = d->extra) {
10447 if (extra->proxyWidget)
10448 extra->proxyWidget->setSizePolicy(policy);
10449 }
10450#endif
10451
10452 updateGeometry();
10453 d->retainSizeWhenHiddenChanged = 0;
10454
10455 if (isWindow() && d->maybeTopData())
10456 d->topData()->sizeAdjusted = false;
10457}
10458
10459/*!
10460 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10461 \overload
10462
10463 Sets the size policy of the widget to \a horizontal and \a
10464 vertical, with standard stretch and no height-for-width.
10465
10466 \sa QSizePolicy::QSizePolicy()
10467*/
10468
10469/*!
10470 Returns the preferred height for this widget, given the width \a w.
10471
10472 If this widget has a layout, the default implementation returns
10473 the layout's preferred height. if there is no layout, the default
10474 implementation returns -1 indicating that the preferred height
10475 does not depend on the width.
10476*/
10477
10478int QWidget::heightForWidth(int w) const
10479{
10480 if (layout() && layout()->hasHeightForWidth())
10481 return layout()->totalHeightForWidth(w);
10482 return -1;
10483}
10484
10485
10486/*!
10487 \since 5.0
10488
10489 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10490*/
10491bool QWidget::hasHeightForWidth() const
10492{
10493 Q_D(const QWidget);
10494 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10495}
10496
10497/*!
10498 \fn QWidget *QWidget::childAt(int x, int y) const
10499
10500 Returns the visible child widget at the position (\a{x}, \a{y})
10501 in the widget's coordinate system. If there is no visible child
10502 widget at the specified position, the function returns \nullptr.
10503*/
10504
10505/*!
10506 \overload
10507
10508 Returns the visible child widget at point \a p in the widget's own
10509 coordinate system.
10510*/
10511
10512QWidget *QWidget::childAt(const QPoint &p) const
10513{
10514 return d_func()->childAt_helper(QPointF(p), false);
10515}
10516
10517/*!
10518 \overload
10519 \since 6.8
10520
10521 Returns the visible child widget at point \a p in the widget's own
10522 coordinate system.
10523*/
10524
10525QWidget *QWidget::childAt(const QPointF &p) const
10526{
10527 return d_func()->childAt_helper(p, false);
10528}
10529
10530QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10531{
10532 if (children.isEmpty())
10533 return nullptr;
10534
10535 if (!pointInsideRectAndMask(p))
10536 return nullptr;
10537 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10538}
10539
10540QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10541{
10542 for (int i = children.size() - 1; i >= 0; --i) {
10543 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10544 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10545 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10546 continue;
10547 }
10548
10549 // Map the point 'p' from parent coordinates to child coordinates.
10550 QPointF childPoint = p;
10551 childPoint -= child->data->crect.topLeft();
10552
10553 // Check if the point hits the child.
10554 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10555 continue;
10556
10557 // Do the same for the child's descendants.
10558 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10559 return w;
10560
10561 // We have found our target; namely the child at position 'p'.
10562 return child;
10563 }
10564 return nullptr;
10565}
10566
10567void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10568{
10569 Q_Q(QWidget);
10570 if (widgetItem)
10571 widgetItem->invalidateSizeCache();
10572 QWidget *parent;
10573 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10574 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10575
10576 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10577 if (parent->d_func()->layout)
10578 parent->d_func()->layout->invalidate();
10579 else if (parent->isVisible())
10580 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10581 }
10582 }
10583}
10584
10585/*!
10586 Notifies the layout system that this widget has changed and may
10587 need to change geometry.
10588
10589 Call this function if the sizeHint() or sizePolicy() have changed.
10590
10591 For explicitly hidden widgets, updateGeometry() is a no-op. The
10592 layout system will be notified as soon as the widget is shown.
10593*/
10594
10595void QWidget::updateGeometry()
10596{
10597 Q_D(QWidget);
10598 d->updateGeometry_helper(false);
10599}
10600
10601/*! \property QWidget::windowFlags
10602
10603 Window flags are a combination of a type (e.g. Qt::Dialog) and
10604 zero or more hints to the window system (e.g.
10605 Qt::FramelessWindowHint).
10606
10607 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10608 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10609 0) on the desktop. If the widget is a window and becomes a
10610 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10611 relative to its parent widget.
10612
10613 \note This function calls setParent() when changing the flags for
10614 a window, causing the widget to be hidden. You must call show() to make
10615 the widget visible again..
10616
10617 \sa windowType(), setWindowFlag(), {Window Flags Example}
10618*/
10619void QWidget::setWindowFlags(Qt::WindowFlags flags)
10620{
10621 Q_D(QWidget);
10622 d->setWindowFlags(flags);
10623}
10624
10625/*!
10626 \since 5.9
10627
10628 Sets the window flag \a flag on this widget if \a on is true;
10629 otherwise clears the flag.
10630
10631 \note This function calls setParent() when changing the flags for
10632 a window, causing the widget to be hidden. You must call show() to make
10633 the widget visible again.
10634
10635 \sa setWindowFlags(), windowFlags(), windowType()
10636*/
10637void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10638{
10639 Q_D(QWidget);
10640 if (on)
10641 d->setWindowFlags(data->window_flags | flag);
10642 else
10643 d->setWindowFlags(data->window_flags & ~flag);
10644}
10645
10646/*! \internal
10647
10648 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10649*/
10650void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10651{
10652 Q_Q(QWidget);
10653 QT_IGNORE_DEPRECATIONS(
10654 if (flags.testFlag(Qt::WindowType::Desktop)) {
10655 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10656 flags.setFlag(Qt::WindowType::Desktop, false);
10657 }
10658 )
10659
10660 if (q->data->window_flags == flags)
10661 return;
10662
10663 if ((q->data->window_flags | flags) & Qt::Window) {
10664 // the old type was a window and/or the new type is a window
10665 QPoint oldPos = q->pos();
10666 bool visible = q->isVisible();
10667 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10668 q->setParent(q->parentWidget(), flags);
10669
10670 // if both types are windows or neither of them are, we restore
10671 // the old position
10672 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10673 q->move(oldPos);
10674 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10675 adjustQuitOnCloseAttribute();
10676 } else {
10677 q->data->window_flags = flags;
10678 }
10679}
10680
10681/*!
10682 Sets the window flags for the widget to \a flags,
10683 \e without telling the window system.
10684
10685 \warning Do not call this function unless you really know what
10686 you're doing.
10687
10688 \sa setWindowFlags()
10689*/
10690void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10691{
10692 data->window_flags = flags;
10693}
10694
10695/*!
10696 \fn Qt::WindowType QWidget::windowType() const
10697
10698 Returns the window type of this widget. This is identical to
10699 windowFlags() & Qt::WindowType_Mask.
10700
10701 \sa windowFlags
10702*/
10703
10704/*!
10705 Sets the parent of the widget to \a parent, and resets the window
10706 flags. The widget is moved to position (0, 0) in its new parent.
10707
10708 If the new parent widget is in a different window, the
10709 reparented widget and its children are appended to the end of the
10710 \l{setFocusPolicy()}{tab chain} of the new parent
10711 widget, in the same internal order as before. If one of the moved
10712 widgets had keyboard focus, setParent() calls clearFocus() for that
10713 widget.
10714
10715 If the new parent widget is in the same window as the
10716 old parent, setting the parent doesn't change the tab order or
10717 keyboard focus.
10718
10719 If the "new" parent widget is the old parent widget, this function
10720 does nothing.
10721
10722 \note The widget becomes invisible as part of changing its parent,
10723 even if it was previously visible. You must call show() to make the
10724 widget visible again.
10725
10726 \warning It is very unlikely that you will ever need this
10727 function. If you have a widget that changes its content
10728 dynamically, it is far easier to use \l QStackedWidget.
10729
10730 \sa setWindowFlags()
10731*/
10732void QWidget::setParent(QWidget *parent)
10733{
10734 if (parent == parentWidget())
10735 return;
10736 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10737}
10738
10739void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10740{
10741 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10742 if (d->renderToTexture) {
10743 QEvent e(eventType);
10744 QCoreApplication::sendEvent(widget, &e);
10745 }
10746
10747 for (int i = 0; i < d->children.size(); ++i) {
10748 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10749 if (w && !w->isWindow())
10750 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10751 }
10752
10753 // Notify QWidgetWindow after we've notified all child QWidgets
10754 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10755 QEvent e(eventType);
10756 QCoreApplication::sendEvent(window, &e);
10757 }
10758}
10759
10760/*!
10761 \overload
10762
10763 This function also takes widget flags, \a f as an argument.
10764*/
10765
10766void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10767{
10768 Q_D(QWidget);
10769 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10770#ifdef QT_DEBUG
10771 const auto checkForParentChildLoops = qScopeGuard([&](){
10772 int depth = 0;
10773 auto p = parentWidget();
10774 while (p) {
10775 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10776 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10777 "this is undefined behavior",
10778 this, metaObject()->className(), qPrintable(objectName()));
10779 }
10780 p = p->parentWidget();
10781 }
10782 });
10783#endif
10784
10785 const bool resized = testAttribute(Qt::WA_Resized);
10786 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10787 QWidget *oldtlw = window();
10788 Q_ASSERT(oldtlw);
10789 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10790
10791 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10792 d->data.fstrut_dirty = true;
10793
10794 bool newParent = (parent != parentWidget());
10795
10796 if (newParent && parent) {
10797 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10798 parent->d_func()->enforceNativeChildren();
10799 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10800 setAttribute(Qt::WA_NativeWindow);
10801 }
10802
10803 if (wasCreated) {
10804 if (!testAttribute(Qt::WA_WState_Hidden)) {
10805 // Hiding the widget will set WA_WState_Hidden as well, which would
10806 // normally require the widget to be explicitly shown again to become
10807 // visible, even as a child widget. But we refine this value later in
10808 // setParent_sys(), applying WA_WState_Hidden based on whether the
10809 // widget is a top level or not.
10810 hide();
10811
10812 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10813 // when we only had QWidget::setVisible(), which is treated as an
10814 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10815 // that allows us to hide a widget without affecting ExplicitShowHide.
10816 // Though it can be argued that ExplicitShowHide should reflect the
10817 // last update of the widget's state, so if we hide the widget as a
10818 // side effect of changing parent, perhaps we _should_ reset it?
10819 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10820 }
10821 if (newParent) {
10822 QEvent e(QEvent::ParentAboutToChange);
10823 QCoreApplication::sendEvent(this, &e);
10824 }
10825 }
10826
10827 // texture-based widgets need a pre-notification when their associated top-level window changes
10828 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10829 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10830 : oldtlw->d_func()->usesRhiFlush;
10831 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10832 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10833
10834 // If we get parented into another window, children will be folded
10835 // into the new parent's focus chain, so clear focus now.
10836 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10837 focusWidget()->clearFocus();
10838
10839 d->setParent_sys(parent, f);
10840
10841 if (d->textureChildSeen && parent) {
10842 // set the textureChildSeen flag up the whole parent chain
10843 QWidgetPrivate::get(parent)->setTextureChildSeen();
10844 }
10845
10846 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10847 if (newParent)
10848 oldPaintManager->removeDirtyWidget(this);
10849 // Move the widget and all its static children from
10850 // the old backing store to the new one.
10851 oldPaintManager->moveStaticWidgets(this);
10852 }
10853
10854 d->reparentFocusWidgets(oldtlw);
10855 setAttribute(Qt::WA_Resized, resized);
10856
10857 const bool useStyleSheetPropagationInWidgetStyles =
10858 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10859
10860 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10861 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10862 // if the parent has a font set or inherited, then propagate the mask to the new child
10863 if (parent) {
10864 const auto pd = parent->d_func();
10865 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10866 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10867 }
10868 d->resolveFont();
10869 d->resolvePalette();
10870 }
10871 d->resolveLayoutDirection();
10872 d->resolveLocale();
10873
10874 // Note: GL widgets under WGL or EGL will always need a ParentChange
10875 // event to handle recreation/rebinding of the GL context, hence the
10876 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10877 // platforms).
10878 if (newParent || !wasCreated
10879#if QT_CONFIG(opengles2)
10880 || (f & Qt::MSWindowsOwnDC)
10881#endif
10882 ) {
10883 // propagate enabled updates enabled state to non-windows
10884 if (!isWindow()) {
10885 if (!testAttribute(Qt::WA_ForceDisabled))
10886 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10887 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10888 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10889 }
10890 d->inheritStyle();
10891
10892 // send and post remaining QObject events
10893 if (parent && d->sendChildEvents) {
10894 QChildEvent e(QEvent::ChildAdded, this);
10895 QCoreApplication::sendEvent(parent, &e);
10896 }
10897
10898 if (parent && d->sendChildEvents && d->polished) {
10899 QChildEvent e(QEvent::ChildPolished, this);
10900 QCoreApplication::sendEvent(parent, &e);
10901 }
10902
10903 QEvent e(QEvent::ParentChange);
10904 QCoreApplication::sendEvent(this, &e);
10905 }
10906
10907 // texture-based widgets need another event when their top-level window
10908 // changes (more precisely, has already changed at this point)
10909 if (oldWidgetUsesRhiFlush && oldtlw != window())
10910 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10911
10912 if (!wasCreated) {
10913 if (isWindow() || parentWidget()->isVisible())
10914 setAttribute(Qt::WA_WState_Hidden, true);
10915 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10916 setAttribute(Qt::WA_WState_Hidden, false);
10917 }
10918
10919 d->updateIsOpaque();
10920
10921#if QT_CONFIG(graphicsview)
10922 // Embed the widget into a proxy if the parent is embedded.
10923 // ### Doesn't handle reparenting out of an embedded widget.
10924 if (oldtlw->graphicsProxyWidget()) {
10925 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10926 ancestorProxy->d_func()->unembedSubWindow(this);
10927 }
10928 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10929 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10930 ancestorProxy->d_func()->embedSubWindow(this);
10931 }
10932#endif
10933
10934 if (d->extra && d->extra->hasWindowContainer)
10935 QWindowContainer::parentWasChanged(this);
10936
10937 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10938 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10939 // Check if the native parent now needs to switch to RHI
10940 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10941 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10942
10943 QPlatformBackingStoreRhiConfig rhiConfig;
10944 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10945
10946 // First evaluate whether the reparented widget uses RHI.
10947 // We do this as a separate step because the performance
10948 // implications of always checking the native parent are
10949 // problematic when it comes to large widget trees.
10950 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10951 // Then check whether the native parent requires RHI
10952 // as a result. It may not, if this widget is a native
10953 // window, and can handle its own RHI flushing.
10954 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10955 // Finally, check whether we need to recreate the
10956 // native parent to enable RHI flushing.
10957 auto *existingWindow = newParentWithWindow->windowHandle();
10958 auto existingSurfaceType = existingWindow->surfaceType();
10959 if (existingSurfaceType != surfaceType) {
10960 qCDebug(lcWidgetPainting)
10961 << "Recreating" << existingWindow
10962 << "with current type" << existingSurfaceType
10963 << "to support" << surfaceType;
10964 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10965 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10966 const auto positionBeforeDestroy = newParentWithWindow->pos();
10967 newParentWithWindow->destroy();
10968 newParentWithWindow->create();
10969 Q_ASSERT(newParentWithWindow->windowHandle());
10970 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10971 newParentWithWindow->move(positionBeforeDestroy);
10972 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10973 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10974 // If we don't recreate we still need to make sure the native parent
10975 // widget has a RHI config that the reparented widget can use.
10976 backingStore->handle()->createRhi(existingWindow, rhiConfig);
10977 // And that it knows it's now flushing with RHI
10978 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
10979 }
10980 }
10981 }
10982 }
10983
10984#if QT_CONFIG(accessibility)
10985 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
10986 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
10987 QAccessible::updateAccessibility(&qaEvent);
10988 }
10989#endif
10990
10991}
10992
10993void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10994{
10995 Q_Q(QWidget);
10996
10997 Qt::WindowFlags oldFlags = data.window_flags;
10998 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10999
11000 QScreen *targetScreen = nullptr;
11001 setWinId(0);
11002
11003 if (!newparent) {
11004 f |= Qt::Window;
11005 if (parent)
11006 targetScreen = q->parentWidget()->window()->screen();
11007 }
11008
11009 const bool destroyWindow = (
11010 // Reparenting top level to child
11011 (oldFlags & Qt::Window) && !(f & Qt::Window)
11012 // And we can dispose of the window
11013 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
11014 );
11015
11016 if (parent != newparent) {
11017 // Update object parent now, so we can resolve new parent window below
11018 QObjectPrivate::setParent_helper(newparent);
11019
11020 if (q->windowHandle())
11021 q->windowHandle()->setFlags(f);
11022
11023 // If the widget itself or any of its children have been created,
11024 // we need to reparent their QWindows as well.
11025 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11026 // But if the widget is about to be destroyed we must skip the
11027 // widget itself, and only reparent children.
11028 if (destroyWindow) {
11029 reparentWidgetWindowChildren(parentWithWindow);
11030 } else {
11031 // During reparentWidgetWindows() we need to know whether the reparented
11032 // QWindow should be a top level (with a transient parent) or not. This
11033 // widget has not updated its window flags yet, so we can't ask the widget
11034 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
11035 // the QWindow flags always reflect Qt::Window, even for child windows. And
11036 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
11037 // which we are in the process of updating. So we propagate the
11038 // new flags of the reparented window here.
11039 reparentWidgetWindows(parentWithWindow, f);
11040 }
11041 }
11042
11043 bool explicitlyHidden = isExplicitlyHidden();
11044
11045 if (destroyWindow) {
11046 if (extra && extra->hasWindowContainer)
11047 QWindowContainer::toplevelAboutToBeDestroyed(q);
11048
11049 // There shouldn't be any QWindow children left, but if there
11050 // are, re-parent them now, before we destroy.
11051 if (!q->windowHandle()->children().isEmpty()) {
11052 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11053 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
11054 for (QObject *child : q->windowHandle()->children()) {
11055 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
11056 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11057 << "before destroying" << this;
11058 childWindow->setParent(newParentWindow);
11059 }
11060 }
11061 }
11062
11063 // We have reparented any child windows of the widget we are
11064 // about to destroy to the new parent window handle, so we can
11065 // safely destroy this widget without destroying sub windows.
11066 q->destroy(true, false);
11067 }
11068
11069 adjustFlags(f, q);
11070 data.window_flags = f;
11071 q->setAttribute(Qt::WA_WState_Created, false);
11072 q->setAttribute(Qt::WA_WState_Visible, false);
11073 q->setAttribute(Qt::WA_WState_Hidden, false);
11074
11075 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11076 q->createWinId();
11077
11078 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11079 q->setAttribute(Qt::WA_WState_Hidden);
11080 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11081
11082 // move the window to the selected screen
11083 if (!newparent && targetScreen) {
11084 // only if it is already created
11085 if (q->testAttribute(Qt::WA_WState_Created))
11086 q->windowHandle()->setScreen(targetScreen);
11087 else
11088 topData()->initialScreen = targetScreen;
11089 }
11090}
11091
11092void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11093{
11094 if (QWindow *window = windowHandle()) {
11095 // Reparent this QWindow, and all QWindow children will follow
11096 if (parentWithWindow) {
11097 if (windowFlags & Qt::Window) {
11098 // Top level windows can only have transient parents,
11099 // and the transient parent must be another top level.
11100 QWidget *topLevel = parentWithWindow->window();
11101 auto *transientParent = topLevel->windowHandle();
11102 Q_ASSERT(transientParent);
11103 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11104 window->setTransientParent(transientParent);
11105 window->setParent(nullptr);
11106 } else {
11107 auto *parentWindow = parentWithWindow->windowHandle();
11108 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11109 window->setTransientParent(nullptr);
11110 window->setParent(parentWindow);
11111 }
11112 } else {
11113 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11114 window->setTransientParent(nullptr);
11115 window->setParent(nullptr);
11116 }
11117 } else {
11118 reparentWidgetWindowChildren(parentWithWindow);
11119 }
11120}
11121
11122void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11123{
11124 for (auto *child : std::as_const(children)) {
11125 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11126 auto *childPrivate = QWidgetPrivate::get(childWidget);
11127 // Child widgets with QWindows should always continue to be child
11128 // windows, so we pass on the child's current window flags here.
11129 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11130 }
11131 }
11132}
11133
11134/*!
11135 Scrolls the widget including its children \a dx pixels to the
11136 right and \a dy downward. Both \a dx and \a dy may be negative.
11137
11138 After scrolling, the widgets will receive paint events for
11139 the areas that need to be repainted. For widgets that Qt knows to
11140 be opaque, this is only the newly exposed parts.
11141 For example, if an opaque widget is scrolled 8 pixels to the left,
11142 only an 8-pixel wide stripe at the right edge needs updating.
11143
11144 Since widgets propagate the contents of their parents by default,
11145 you need to set the \l autoFillBackground property, or use
11146 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11147 a widget opaque.
11148
11149 For widgets that use contents propagation, a scroll will cause an
11150 update of the entire scroll area.
11151
11152 \sa {Transparency and Double Buffering}
11153*/
11154
11155void QWidget::scroll(int dx, int dy)
11156{
11157 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11158 return;
11159 if (dx == 0 && dy == 0)
11160 return;
11161 Q_D(QWidget);
11162#if QT_CONFIG(graphicsview)
11163 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11164 // Graphics View maintains its own dirty region as a list of rects;
11165 // until we can connect item updates directly to the view, we must
11166 // separately add a translated dirty region.
11167 for (const QRect &rect : d->dirty)
11168 proxy->update(rect.translated(dx, dy));
11169 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11170 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11171 return;
11172 }
11173#endif
11174 d->setDirtyOpaqueRegion();
11175 d->scroll_sys(dx, dy);
11176}
11177
11178void QWidgetPrivate::scroll_sys(int dx, int dy)
11179{
11180 Q_Q(QWidget);
11181 scrollChildren(dx, dy);
11182 scrollRect(q->rect(), dx, dy);
11183}
11184
11185/*!
11186 \overload
11187
11188 This version only scrolls \a r and does not move the children of
11189 the widget.
11190
11191 If \a r is empty or invalid, the result is undefined.
11192
11193 \sa QScrollArea
11194*/
11195void QWidget::scroll(int dx, int dy, const QRect &r)
11196{
11197
11198 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11199 return;
11200 if (dx == 0 && dy == 0)
11201 return;
11202 Q_D(QWidget);
11203#if QT_CONFIG(graphicsview)
11204 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11205 // Graphics View maintains its own dirty region as a list of rects;
11206 // until we can connect item updates directly to the view, we must
11207 // separately add a translated dirty region.
11208 if (!d->dirty.isEmpty()) {
11209 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11210 proxy->update(rect);
11211 }
11212 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11213 return;
11214 }
11215#endif
11216 d->scroll_sys(dx, dy, r);
11217}
11218
11219void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11220{
11221 scrollRect(r, dx, dy);
11222}
11223
11224/*!
11225 Repaints the widget directly by calling paintEvent() immediately,
11226 unless updates are disabled or the widget is hidden.
11227
11228 We suggest only using repaint() if you need an immediate repaint,
11229 for example during animation. In most circumstances update()
11230 is better, as it permits Qt to optimize for speed and minimize
11231 flicker.
11232
11233 \warning If you call repaint() in a function which may itself be
11234 called from paintEvent(), you may get infinite recursion. The
11235 update() function never causes recursion.
11236
11237 \sa update(), paintEvent(), setUpdatesEnabled()
11238*/
11239
11240void QWidget::repaint()
11241{
11242 repaint(rect());
11243}
11244
11245/*! \overload
11246
11247 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11248 the widget.
11249
11250 If \a w is negative, it is replaced with \c{width() - x}, and if
11251 \a h is negative, it is replaced width \c{height() - y}.
11252*/
11253void QWidget::repaint(int x, int y, int w, int h)
11254{
11255 if (x > data->crect.width() || y > data->crect.height())
11256 return;
11257
11258 if (w < 0)
11259 w = data->crect.width() - x;
11260 if (h < 0)
11261 h = data->crect.height() - y;
11262
11263 repaint(QRect(x, y, w, h));
11264}
11265
11266/*! \overload
11267
11268 This version repaints a rectangle \a rect inside the widget.
11269*/
11270void QWidget::repaint(const QRect &rect)
11271{
11272 Q_D(QWidget);
11273 d->repaint(rect);
11274}
11275
11276/*!
11277 \overload
11278
11279 This version repaints a region \a rgn inside the widget.
11280*/
11281void QWidget::repaint(const QRegion &rgn)
11282{
11283 Q_D(QWidget);
11284 d->repaint(rgn);
11285}
11286
11287template <typename T>
11288void QWidgetPrivate::repaint(T r)
11289{
11290 Q_Q(QWidget);
11291
11292 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11293 return;
11294
11295 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11296 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11297 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11298}
11299
11300/*!
11301 Updates the widget unless updates are disabled or the widget is
11302 hidden.
11303
11304 This function does not cause an immediate repaint; instead it
11305 schedules a paint event for processing when Qt returns to the main
11306 event loop. This permits Qt to optimize for more speed and less
11307 flicker than a call to repaint() does.
11308
11309 Calling update() several times normally results in just one
11310 paintEvent() call.
11311
11312 Qt normally erases the widget's area before the paintEvent() call.
11313 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11314 responsible for painting all its pixels with an opaque color.
11315
11316 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11317*/
11318void QWidget::update()
11319{
11320 update(rect());
11321}
11322
11323/*! \fn void QWidget::update(int x, int y, int w, int h)
11324 \overload
11325
11326 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11327 the widget.
11328*/
11329
11330/*!
11331 \overload
11332
11333 This version updates a rectangle \a rect inside the widget.
11334*/
11335void QWidget::update(const QRect &rect)
11336{
11337 Q_D(QWidget);
11338 d->update(rect);
11339}
11340
11341/*!
11342 \overload
11343
11344 This version repaints a region \a rgn inside the widget.
11345*/
11346void QWidget::update(const QRegion &rgn)
11347{
11348 Q_D(QWidget);
11349 d->update(rgn);
11350}
11351
11352template <typename T>
11353void QWidgetPrivate::update(T r)
11354{
11355 Q_Q(QWidget);
11356
11357 if (renderToTexture && !q->isVisible()) {
11358 renderToTextureReallyDirty = 1;
11359 return;
11360 }
11361
11362 if (!q->isVisible() || !q->updatesEnabled())
11363 return;
11364
11365 T clipped = r & q->rect();
11366
11367 if (clipped.isEmpty())
11368 return;
11369
11370 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11371 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11372 return;
11373 }
11374
11375 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11376 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11377 tlwExtra->repaintManager->markDirty(clipped, q);
11378}
11379
11380 /*!
11381 \internal
11382
11383 This just sets the corresponding attribute bit to 1 or 0
11384 */
11385static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11386 QWidgetPrivate *d)
11387{
11388 if (attribute < int(8*sizeof(uint))) {
11389 if (on)
11390 data->widget_attributes |= (1<<attribute);
11391 else
11392 data->widget_attributes &= ~(1<<attribute);
11393 } else {
11394 const int x = attribute - 8*sizeof(uint);
11395 const int int_off = x / (8*sizeof(uint));
11396 if (on)
11397 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11398 else
11399 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11400 }
11401}
11402
11403#ifdef Q_OS_MAC
11404void QWidgetPrivate::macUpdateSizeAttribute()
11405{
11406 Q_Q(QWidget);
11407 QEvent event(QEvent::MacSizeChange);
11408 QCoreApplication::sendEvent(q, &event);
11409 for (int i = 0; i < children.size(); ++i) {
11410 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11411 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11412 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11413 && !w->testAttribute(Qt::WA_MacSmallSize)
11414 && !w->testAttribute(Qt::WA_MacNormalSize))
11415 w->d_func()->macUpdateSizeAttribute();
11416 }
11417 resolveFont();
11418}
11419#endif
11420
11421/*!
11422 Sets the attribute \a attribute on this widget if \a on is true;
11423 otherwise clears the attribute.
11424
11425 \sa testAttribute()
11426*/
11427void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11428{
11429 Q_D(QWidget);
11430
11431 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11432 if (isWindow()) {
11433 auto *topExtra = d->topData();
11434 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11435 }
11436 }
11437
11438 if (testAttribute(attribute) == on)
11439 return;
11440
11441 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11442 "QWidget::setAttribute(WidgetAttribute, bool): "
11443 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11444#ifdef Q_OS_WIN
11445 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11446 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11447 // see ::paintEngine for details
11448 paintEngine();
11449 if (d->noPaintOnScreen)
11450 return;
11451 }
11452#endif
11453
11454 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11455 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11456 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11457 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11458 return;
11459 }
11460
11461 setAttribute_internal(attribute, on, data, d);
11462
11463 switch (attribute) {
11464
11465#if QT_CONFIG(draganddrop)
11466 case Qt::WA_AcceptDrops: {
11467 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11468 setAttribute(Qt::WA_DropSiteRegistered, true);
11469 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11470 setAttribute(Qt::WA_DropSiteRegistered, false);
11471 QEvent e(QEvent::AcceptDropsChange);
11472 QCoreApplication::sendEvent(this, &e);
11473 break;
11474 }
11475 case Qt::WA_DropSiteRegistered: {
11476 for (int i = 0; i < d->children.size(); ++i) {
11477 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11478 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11479 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11480 }
11481 break;
11482 }
11483#endif
11484
11485 case Qt::WA_NoChildEventsForParent:
11486 d->sendChildEvents = !on;
11487 break;
11488 case Qt::WA_NoChildEventsFromChildren:
11489 d->receiveChildEvents = !on;
11490 break;
11491 case Qt::WA_MacNormalSize:
11492 case Qt::WA_MacSmallSize:
11493 case Qt::WA_MacMiniSize:
11494#ifdef Q_OS_MAC
11495 {
11496 // We can only have one of these set at a time
11497 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11498 Qt::WA_MacMiniSize };
11499 for (int i = 0; i < 3; ++i) {
11500 if (MacSizes[i] != attribute)
11501 setAttribute_internal(MacSizes[i], false, data, d);
11502 }
11503 d->macUpdateSizeAttribute();
11504 }
11505#endif
11506 break;
11507 case Qt::WA_ShowModal:
11508 if (!on) {
11509 // reset modality type to NonModal when clearing WA_ShowModal
11510 data->window_modality = Qt::NonModal;
11511 } else if (data->window_modality == Qt::NonModal) {
11512 // If modality hasn't been set prior to setting WA_ShowModal, use
11513 // ApplicationModal.
11514 data->window_modality = Qt::ApplicationModal;
11515 // Some window managers do not allow us to enter modality after the
11516 // window is visible.The window must be hidden before changing the
11517 // windowModality property and then reshown.
11518 }
11519 if (testAttribute(Qt::WA_WState_Created)) {
11520 // don't call setModal_sys() before create()
11521 d->setModal_sys();
11522 }
11523 break;
11524 case Qt::WA_MouseTracking: {
11525 QEvent e(QEvent::MouseTrackingChange);
11526 QCoreApplication::sendEvent(this, &e);
11527 break; }
11528 case Qt::WA_TabletTracking: {
11529 QEvent e(QEvent::TabletTrackingChange);
11530 QCoreApplication::sendEvent(this, &e);
11531 break; }
11532 case Qt::WA_NativeWindow: {
11533 d->createTLExtra();
11534 if (on)
11535 d->createTLSysExtra();
11536#ifndef QT_NO_IM
11537 QWidget *focusWidget = d->effectiveFocusWidget();
11538 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11539 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11540 QGuiApplication::inputMethod()->commit();
11541 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11542 }
11543 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11544 parentWidget()->d_func()->enforceNativeChildren();
11545 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11546 d->createWinId();
11547 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11548 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11549 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11550 }
11551#endif //QT_NO_IM
11552 break;
11553 }
11554 case Qt::WA_PaintOnScreen:
11555 d->updateIsOpaque();
11556 Q_FALLTHROUGH();
11557 case Qt::WA_OpaquePaintEvent:
11558 d->updateIsOpaque();
11559 break;
11560 case Qt::WA_NoSystemBackground:
11561 d->updateIsOpaque();
11562 Q_FALLTHROUGH();
11563 case Qt::WA_UpdatesDisabled:
11564 d->updateSystemBackground();
11565 break;
11566 case Qt::WA_TransparentForMouseEvents:
11567 break;
11568 case Qt::WA_InputMethodEnabled: {
11569#ifndef QT_NO_IM
11570 if (QGuiApplication::focusObject() == this) {
11571 if (!on)
11572 QGuiApplication::inputMethod()->commit();
11573 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11574 }
11575#endif //QT_NO_IM
11576 break;
11577 }
11578 case Qt::WA_WindowPropagation:
11579 d->resolvePalette();
11580 d->resolveFont();
11581 d->resolveLocale();
11582 break;
11583 case Qt::WA_DontShowOnScreen: {
11584 if (on && isVisible()) {
11585 // Make sure we keep the current state and only hide the widget
11586 // from the desktop. show_sys will only update platform specific
11587 // attributes at this point.
11588 d->hide_sys();
11589 d->show_sys();
11590 }
11591 break;
11592 }
11593
11594 case Qt::WA_X11NetWmWindowTypeDesktop:
11595 case Qt::WA_X11NetWmWindowTypeDock:
11596 case Qt::WA_X11NetWmWindowTypeToolBar:
11597 case Qt::WA_X11NetWmWindowTypeMenu:
11598 case Qt::WA_X11NetWmWindowTypeUtility:
11599 case Qt::WA_X11NetWmWindowTypeSplash:
11600 case Qt::WA_X11NetWmWindowTypeDialog:
11601 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11602 case Qt::WA_X11NetWmWindowTypePopupMenu:
11603 case Qt::WA_X11NetWmWindowTypeToolTip:
11604 case Qt::WA_X11NetWmWindowTypeNotification:
11605 case Qt::WA_X11NetWmWindowTypeCombo:
11606 case Qt::WA_X11NetWmWindowTypeDND:
11607 d->setNetWmWindowTypes();
11608 break;
11609
11610 case Qt::WA_StaticContents:
11611 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11612 if (on)
11613 repaintManager->addStaticWidget(this);
11614 else
11615 repaintManager->removeStaticWidget(this);
11616 }
11617 break;
11618 case Qt::WA_TranslucentBackground:
11619 if (on)
11620 setAttribute(Qt::WA_NoSystemBackground);
11621 d->updateIsTranslucent();
11622
11623 break;
11624 case Qt::WA_AcceptTouchEvents:
11625 break;
11626 default:
11627 break;
11628 }
11629}
11630
11631/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11632
11633 Returns \c true if attribute \a attribute is set on this widget;
11634 otherwise returns \c false.
11635
11636 \sa setAttribute()
11637 */
11638bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11639{
11640 Q_D(const QWidget);
11641 const int x = attribute - 8*sizeof(uint);
11642 const int int_off = x / (8*sizeof(uint));
11643 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11644}
11645
11646/*!
11647 \property QWidget::windowOpacity
11648
11649 \brief The level of opacity for the window.
11650
11651 The valid range of opacity is from 1.0 (completely opaque) to
11652 0.0 (completely transparent).
11653
11654 By default the value of this property is 1.0.
11655
11656 This feature is available on Embedded Linux, \macos, Windows,
11657 and X11 platforms that support the Composite extension.
11658
11659 \note On X11 you need to have a composite manager running,
11660 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11661 supported by the window manager you are using.
11662
11663 \warning Changing this property from opaque to transparent might issue a
11664 paint event that needs to be processed before the window is displayed
11665 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11666 that semi-transparent windows update and resize significantly slower than
11667 opaque windows.
11668
11669 \sa setMask()
11670*/
11671qreal QWidget::windowOpacity() const
11672{
11673 Q_D(const QWidget);
11674 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11675}
11676
11677void QWidget::setWindowOpacity(qreal opacity)
11678{
11679 Q_D(QWidget);
11680 if (!isWindow())
11681 return;
11682
11683 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11684 QTLWExtra *extra = d->topData();
11685 extra->opacity = uint(opacity * 255);
11686 setAttribute(Qt::WA_WState_WindowOpacitySet);
11687 d->setWindowOpacity_sys(opacity);
11688
11689 if (!testAttribute(Qt::WA_WState_Created))
11690 return;
11691
11692#if QT_CONFIG(graphicsview)
11693 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11694 // Avoid invalidating the cache if set.
11695 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11696 proxy->update();
11697 else if (QGraphicsScene *scene = proxy->scene())
11698 scene->update(proxy->sceneBoundingRect());
11699 return;
11700 }
11701#endif
11702}
11703
11704void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11705{
11706 Q_Q(QWidget);
11707 if (q->windowHandle())
11708 q->windowHandle()->setOpacity(level);
11709}
11710
11711/*!
11712 \property QWidget::windowModified
11713 \brief whether the document shown in the window has unsaved changes
11714
11715 A modified window is a window whose content has changed but has
11716 not been saved to disk. This flag will have different effects
11717 varied by the platform. On \macos the close button will have a
11718 modified look; on other platforms, the window title will have an
11719 '*' (asterisk).
11720
11721 The window title must contain a "[*]" placeholder, which
11722 indicates where the '*' should appear. Normally, it should appear
11723 right after the file name (e.g., "document1.txt[*] - Text
11724 Editor"). If the window isn't modified, the placeholder is simply
11725 removed.
11726
11727 Note that if a widget is set as modified, all its ancestors will
11728 also be set as modified. However, if you call \c
11729 {setWindowModified(false)} on a widget, this will not propagate to
11730 its parent because other children of the parent might have been
11731 modified.
11732
11733 \sa windowTitle
11734*/
11735bool QWidget::isWindowModified() const
11736{
11737 return testAttribute(Qt::WA_WindowModified);
11738}
11739
11740void QWidget::setWindowModified(bool mod)
11741{
11742 Q_D(QWidget);
11743 setAttribute(Qt::WA_WindowModified, mod);
11744
11745 d->setWindowModified_helper();
11746
11747 QEvent e(QEvent::ModifiedChange);
11748 QCoreApplication::sendEvent(this, &e);
11749}
11750
11751void QWidgetPrivate::setWindowModified_helper()
11752{
11753 Q_Q(QWidget);
11754 QWindow *window = q->windowHandle();
11755 if (!window)
11756 return;
11757 QPlatformWindow *platformWindow = window->handle();
11758 if (!platformWindow)
11759 return;
11760 bool on = q->testAttribute(Qt::WA_WindowModified);
11761 if (!platformWindow->setWindowModified(on)) {
11762 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11763 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11764 setWindowTitle_helper(q->windowTitle());
11765 setWindowIconText_helper(q->windowIconText());
11766 }
11767}
11768
11769#if QT_CONFIG(tooltip)
11770/*!
11771 \property QWidget::toolTip
11772
11773 \brief the widget's tooltip
11774
11775 Note that by default tooltips are only shown for widgets that are
11776 children of the active window. You can change this behavior by
11777 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11778 not on the widget with the tooltip.
11779
11780 If you want to control a tooltip's behavior, you can intercept the
11781 event() function and catch the QEvent::ToolTip event (e.g., if you
11782 want to customize the area for which the tooltip should be shown).
11783
11784 By default, this property contains an empty string.
11785
11786 \sa QToolTip, statusTip, whatsThis
11787*/
11788void QWidget::setToolTip(const QString &s)
11789{
11790 Q_D(QWidget);
11791 d->toolTip = s;
11792
11793 QEvent event(QEvent::ToolTipChange);
11794 QCoreApplication::sendEvent(this, &event);
11795}
11796
11797QString QWidget::toolTip() const
11798{
11799 Q_D(const QWidget);
11800 return d->toolTip;
11801}
11802
11803/*!
11804 \property QWidget::toolTipDuration
11805 \brief the widget's tooltip duration
11806 \since 5.2
11807
11808 Specifies how long time the tooltip will be displayed, in milliseconds.
11809 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11810
11811 \sa toolTip
11812*/
11813
11814void QWidget::setToolTipDuration(int msec)
11815{
11816 Q_D(QWidget);
11817 d->toolTipDuration = msec;
11818}
11819
11820int QWidget::toolTipDuration() const
11821{
11822 Q_D(const QWidget);
11823 return d->toolTipDuration;
11824}
11825
11826#endif // QT_CONFIG(tooltip)
11827
11828
11829#if QT_CONFIG(statustip)
11830/*!
11831 \property QWidget::statusTip
11832 \brief the widget's status tip
11833
11834 By default, this property contains an empty string.
11835
11836 \sa toolTip, whatsThis
11837*/
11838void QWidget::setStatusTip(const QString &s)
11839{
11840 Q_D(QWidget);
11841 d->statusTip = s;
11842}
11843
11844QString QWidget::statusTip() const
11845{
11846 Q_D(const QWidget);
11847 return d->statusTip;
11848}
11849#endif // QT_CONFIG(statustip)
11850
11851#if QT_CONFIG(whatsthis)
11852/*!
11853 \property QWidget::whatsThis
11854
11855 \brief the widget's What's This help text.
11856
11857 By default, this property contains an empty string.
11858
11859 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11860*/
11861void QWidget::setWhatsThis(const QString &s)
11862{
11863 Q_D(QWidget);
11864 d->whatsThis = s;
11865}
11866
11867QString QWidget::whatsThis() const
11868{
11869 Q_D(const QWidget);
11870 return d->whatsThis;
11871}
11872#endif // QT_CONFIG(whatsthis)
11873
11874#if QT_CONFIG(accessibility)
11875/*!
11876 \property QWidget::accessibleName
11877
11878 \brief the widget's name as seen by assistive technologies
11879
11880 This is the primary name by which assistive technology such as screen readers
11881 announce this widget. For most widgets setting this property is not required.
11882 For example for QPushButton the button's text will be used.
11883
11884 It is important to set this property when the widget does not provide any
11885 text. For example a button that only contains an icon needs to set this
11886 property to work with screen readers.
11887 The name should be short and equivalent to the visual information conveyed
11888 by the widget.
11889
11890 This property has to be \l{Internationalization with Qt}{localized}.
11891
11892 By default, this property contains an empty string.
11893
11894 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11895*/
11896void QWidget::setAccessibleName(const QString &name)
11897{
11898 Q_D(QWidget);
11899 if (d->accessibleName == name)
11900 return;
11901
11902 d->accessibleName = name;
11903 QAccessibleEvent event(this, QAccessible::NameChanged);
11904 QAccessible::updateAccessibility(&event);
11905}
11906
11907QString QWidget::accessibleName() const
11908{
11909 Q_D(const QWidget);
11910 return d->accessibleName;
11911}
11912
11913/*!
11914 \property QWidget::accessibleDescription
11915
11916 \brief the widget's description as seen by assistive technologies
11917
11918 The accessible description of a widget should convey what a widget does.
11919 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11920 the description should give more context, such as \gui{Saves the current document}.
11921
11922 This property has to be \l{Internationalization with Qt}{localized}.
11923
11924 By default, this property contains an empty string and Qt falls back
11925 to using the tool tip to provide this information.
11926
11927 \sa QWidget::accessibleName, QAccessibleInterface::text()
11928*/
11929void QWidget::setAccessibleDescription(const QString &description)
11930{
11931 Q_D(QWidget);
11932 if (d->accessibleDescription == description)
11933 return;
11934
11935 d->accessibleDescription = description;
11936 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11937 QAccessible::updateAccessibility(&event);
11938}
11939
11940QString QWidget::accessibleDescription() const
11941{
11942 Q_D(const QWidget);
11943 return d->accessibleDescription;
11944}
11945
11946/*!
11947 \property QWidget::accessibleIdentifier
11948
11949 \brief the widget's identifier as seen by assistive technologies
11950
11951 If set, the accessible identifier of a widget can be used by assistive
11952 technologies in order to identify a specific widget, e.g. in automated
11953 tests.
11954
11955 \since 6.9
11956*/
11957void QWidget::setAccessibleIdentifier(const QString &identifier)
11958{
11959 Q_D(QWidget);
11960 if (d->accessibleIdentifier == identifier)
11961 return;
11962
11963 d->accessibleIdentifier = identifier;
11964 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11965 QAccessible::updateAccessibility(&event);
11966}
11967
11968QString QWidget::accessibleIdentifier() const
11969{
11970 Q_D(const QWidget);
11971 return d->accessibleIdentifier;
11972}
11973
11974#endif // QT_CONFIG(accessibility)
11975
11976#ifndef QT_NO_SHORTCUT
11977/*!
11978 Adds a shortcut to Qt's shortcut system that watches for the given
11979 \a key sequence in the given \a context. If the \a context is
11980 Qt::ApplicationShortcut, the shortcut applies to the application as a
11981 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11982 or to the window itself, Qt::WindowShortcut.
11983
11984 If the same \a key sequence has been grabbed by several widgets,
11985 when the \a key sequence occurs a QEvent::Shortcut event is sent
11986 to all the widgets to which it applies in a non-deterministic
11987 order, but with the ``ambiguous'' flag set to true.
11988
11989 \warning You should not normally need to use this function;
11990 instead create \l{QAction}s with the shortcut key sequences you
11991 require (if you also want equivalent menu options and toolbar
11992 buttons), or create \l{QShortcut}s if you just need key sequences.
11993 Both QAction and QShortcut handle all the event filtering for you,
11994 and provide signals which are triggered when the user triggers the
11995 key sequence, so are much easier to use than this low-level
11996 function.
11997
11998 \sa releaseShortcut(), setShortcutEnabled()
11999*/
12000int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
12001{
12002 Q_ASSERT(qApp);
12003 if (key.isEmpty())
12004 return 0;
12005 setAttribute(Qt::WA_GrabbedShortcut);
12006 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
12007}
12008
12009/*!
12010 Removes the shortcut with the given \a id from Qt's shortcut
12011 system. The widget will no longer receive QEvent::Shortcut events
12012 for the shortcut's key sequence (unless it has other shortcuts
12013 with the same key sequence).
12014
12015 \warning You should not normally need to use this function since
12016 Qt's shortcut system removes shortcuts automatically when their
12017 parent widget is destroyed. It is best to use QAction or
12018 QShortcut to handle shortcuts, since they are easier to use than
12019 this low-level function. Note also that this is an expensive
12020 operation.
12021
12022 \sa grabShortcut(), setShortcutEnabled()
12023*/
12024void QWidget::releaseShortcut(int id)
12025{
12026 Q_ASSERT(qApp);
12027 if (id)
12028 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
12029}
12030
12031/*!
12032 If \a enable is true, the shortcut with the given \a id is
12033 enabled; otherwise the shortcut is disabled.
12034
12035 \warning You should not normally need to use this function since
12036 Qt's shortcut system enables/disables shortcuts automatically as
12037 widgets become hidden/visible and gain or lose focus. It is best
12038 to use QAction or QShortcut to handle shortcuts, since they are
12039 easier to use than this low-level function.
12040
12041 \sa grabShortcut(), releaseShortcut()
12042*/
12043void QWidget::setShortcutEnabled(int id, bool enable)
12044{
12045 Q_ASSERT(qApp);
12046 if (id)
12047 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
12048}
12049
12050/*!
12051 \since 4.2
12052
12053 If \a enable is true, auto repeat of the shortcut with the
12054 given \a id is enabled; otherwise it is disabled.
12055
12056 \sa grabShortcut(), releaseShortcut()
12057*/
12058void QWidget::setShortcutAutoRepeat(int id, bool enable)
12059{
12060 Q_ASSERT(qApp);
12061 if (id)
12062 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12063}
12064#endif // QT_NO_SHORTCUT
12065
12066/*!
12067 Updates the widget's micro focus and informs input methods
12068 that the state specified by \a query has changed.
12069*/
12070void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12071{
12072 if (this == QGuiApplication::focusObject())
12073 QGuiApplication::inputMethod()->update(query);
12074}
12075
12076/*!
12077 Raises this widget to the top of the parent widget's stack.
12078
12079 After this call the widget will be visually in front of any
12080 overlapping sibling widgets.
12081
12082 \note When using activateWindow(), you can call this function to
12083 ensure that the window is stacked on top.
12084
12085 \sa lower(), stackUnder()
12086*/
12087
12088void QWidget::raise()
12089{
12090 Q_D(QWidget);
12091 if (!isWindow()) {
12092 QWidget *p = parentWidget();
12093 const int parentChildCount = p->d_func()->children.size();
12094 if (parentChildCount < 2)
12095 return;
12096 const int from = p->d_func()->children.indexOf(this);
12097 Q_ASSERT(from >= 0);
12098 // Do nothing if the widget is already in correct stacking order _and_ created.
12099 if (from != parentChildCount -1)
12100 p->d_func()->children.move(from, parentChildCount - 1);
12101 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12102 create();
12103 else if (from == parentChildCount - 1)
12104 return;
12105
12106 QRegion region(rect());
12107 d->subtractOpaqueSiblings(region);
12108 d->invalidateBackingStore(region);
12109 }
12110 if (testAttribute(Qt::WA_WState_Created))
12111 d->raise_sys();
12112
12113 if (d->extra && d->extra->hasWindowContainer)
12114 QWindowContainer::parentWasRaised(this);
12115
12116 QEvent e(QEvent::ZOrderChange);
12117 QCoreApplication::sendEvent(this, &e);
12118}
12119
12120void QWidgetPrivate::raise_sys()
12121{
12122 Q_Q(QWidget);
12123 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12124 q->windowHandle()->raise();
12125 } else if (renderToTexture) {
12126 if (QWidget *p = q->parentWidget()) {
12127 setDirtyOpaqueRegion();
12128 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12129 }
12130 }
12131}
12132
12133/*!
12134 Lowers the widget to the bottom of the parent widget's stack.
12135
12136 After this call the widget will be visually behind (and therefore
12137 obscured by) any overlapping sibling widgets.
12138
12139 \sa raise(), stackUnder()
12140*/
12141
12142void QWidget::lower()
12143{
12144 Q_D(QWidget);
12145 if (!isWindow()) {
12146 QWidget *p = parentWidget();
12147 const int parentChildCount = p->d_func()->children.size();
12148 if (parentChildCount < 2)
12149 return;
12150 const int from = p->d_func()->children.indexOf(this);
12151 Q_ASSERT(from >= 0);
12152 // Do nothing if the widget is already in correct stacking order _and_ created.
12153 if (from != 0)
12154 p->d_func()->children.move(from, 0);
12155 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12156 create();
12157 else if (from == 0)
12158 return;
12159 }
12160 if (testAttribute(Qt::WA_WState_Created))
12161 d->lower_sys();
12162
12163 if (d->extra && d->extra->hasWindowContainer)
12164 QWindowContainer::parentWasLowered(this);
12165
12166 QEvent e(QEvent::ZOrderChange);
12167 QCoreApplication::sendEvent(this, &e);
12168}
12169
12170void QWidgetPrivate::lower_sys()
12171{
12172 Q_Q(QWidget);
12173 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12174 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12175 q->windowHandle()->lower();
12176 } else if (QWidget *p = q->parentWidget()) {
12177 setDirtyOpaqueRegion();
12178 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12179 }
12180}
12181
12182/*!
12183 Places the widget under \a w in the parent widget's stack.
12184
12185 To make this work, the widget itself and \a w must be siblings.
12186
12187 \sa raise(), lower()
12188*/
12189void QWidget::stackUnder(QWidget* w)
12190{
12191 Q_D(QWidget);
12192 QWidget *p = parentWidget();
12193 if (!w || isWindow() || p != w->parentWidget() || this == w)
12194 return;
12195 if (p) {
12196 int from = p->d_func()->children.indexOf(this);
12197 int to = p->d_func()->children.indexOf(w);
12198 Q_ASSERT(from >= 0);
12199 Q_ASSERT(to >= 0);
12200 if (from < to)
12201 --to;
12202 // Do nothing if the widget is already in correct stacking order _and_ created.
12203 if (from != to)
12204 p->d_func()->children.move(from, to);
12205 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12206 create();
12207 else if (from == to)
12208 return;
12209 }
12210 if (testAttribute(Qt::WA_WState_Created))
12211 d->stackUnder_sys(w);
12212
12213 QEvent e(QEvent::ZOrderChange);
12214 QCoreApplication::sendEvent(this, &e);
12215}
12216
12217void QWidgetPrivate::stackUnder_sys(QWidget*)
12218{
12219 Q_Q(QWidget);
12220 if (QWidget *p = q->parentWidget()) {
12221 setDirtyOpaqueRegion();
12222 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12223 }
12224}
12225
12226/*!
12227 \fn bool QWidget::isTopLevel() const
12228 \deprecated
12229
12230 Use isWindow() instead.
12231*/
12232
12233/*!
12234 \fn bool QWidget::isRightToLeft() const
12235 \internal
12236*/
12237
12238/*!
12239 \fn bool QWidget::isLeftToRight() const
12240 \internal
12241*/
12242
12243/*!
12244 \macro QWIDGETSIZE_MAX
12245 \relates QWidget
12246
12247 Defines the maximum size for a QWidget object.
12248
12249 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12250 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12251
12252 \sa QWidget::setMaximumSize()
12253*/
12254
12255/*!
12256 \fn QWidget::setupUi(QWidget *widget)
12257
12258 Sets up the user interface for the specified \a widget.
12259
12260 \note This function is available with widgets that derive from user
12261 interface descriptions created using \l{uic}.
12262
12263 \sa {Using a Designer UI File in Your Application}
12264*/
12265
12266QRect QWidgetPrivate::frameStrut() const
12267{
12268 Q_Q(const QWidget);
12269 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12270 // x2 = x1 + w - 1, so w/h = 1
12271 return QRect(0, 0, 1, 1);
12272 }
12273
12274 if (data.fstrut_dirty
12275 // ### Fix properly for 4.3
12276 && q->isVisible()
12277 && q->testAttribute(Qt::WA_WState_Created))
12278 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12279
12280 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12281}
12282
12283void QWidgetPrivate::updateFrameStrut()
12284{
12285 Q_Q(QWidget);
12286 if (q->data->fstrut_dirty) {
12287 if (QTLWExtra *te = maybeTopData()) {
12288 if (te->window && te->window->handle()) {
12289 const QMargins margins = te->window->frameMargins();
12290 if (!margins.isNull()) {
12291 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12292 q->data->fstrut_dirty = false;
12293 }
12294 }
12295 }
12296 }
12297}
12298
12299#ifdef QT_KEYPAD_NAVIGATION
12300/*!
12301 \internal
12302
12303 Changes the focus from the current focusWidget to a widget in
12304 the \a direction.
12305
12306 Returns \c true, if there was a widget in that direction
12307*/
12308bool QWidgetPrivate::navigateToDirection(Direction direction)
12309{
12310 QWidget *targetWidget = widgetInNavigationDirection(direction);
12311 if (targetWidget)
12312 targetWidget->setFocus();
12313 return (targetWidget != 0);
12314}
12315
12316/*!
12317 \internal
12318
12319 Searches for a widget that is positioned in the \a direction, starting
12320 from the current focusWidget.
12321
12322 Returns the pointer to a found widget or \nullptr, if there was no widget
12323 in that direction.
12324*/
12325QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12326{
12327 const QWidget *sourceWidget = QApplication::focusWidget();
12328 if (!sourceWidget)
12329 return nullptr;
12330 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12331 const int sourceX =
12332 (direction == DirectionNorth || direction == DirectionSouth) ?
12333 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12334 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12335 const int sourceY =
12336 (direction == DirectionEast || direction == DirectionWest) ?
12337 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12338 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12339 const QPoint sourcePoint(sourceX, sourceY);
12340 const QPoint sourceCenter = sourceRect.center();
12341 const QWidget *sourceWindow = sourceWidget->window();
12342
12343 QWidget *targetWidget = nullptr;
12344 int shortestDistance = INT_MAX;
12345
12346 const auto targetCandidates = QApplication::allWidgets();
12347 for (QWidget *targetCandidate : targetCandidates) {
12348
12349 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12350
12351 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12352 // but the owner of the proxy cannot.
12353 // Additionally, empty widgets should be ignored.
12354 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12355 continue;
12356
12357 // Only navigate to a target widget that...
12358 if ( targetCandidate != sourceWidget
12359 // ...takes the focus,
12360 && targetCandidate->focusPolicy() & Qt::TabFocus
12361 // ...is above if DirectionNorth,
12362 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12363 // ...is on the right if DirectionEast,
12364 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12365 // ...is below if DirectionSouth,
12366 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12367 // ...is on the left if DirectionWest,
12368 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12369 // ...is enabled,
12370 && targetCandidate->isEnabled()
12371 // ...is visible,
12372 && targetCandidate->isVisible()
12373 // ...is in the same window,
12374 && targetCandidate->window() == sourceWindow) {
12375 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12376 const QRect &targetCandidateRect) {
12377 int dx = 0;
12378 int dy = 0;
12379 if (p.x() < r.left())
12380 dx = r.left() - p.x();
12381 else if (p.x() > r.right())
12382 dx = p.x() - r.right();
12383 if (p.y() < r.top())
12384 dy = r.top() - p.y();
12385 else if (p.y() > r.bottom())
12386 dy = p.y() - r.bottom();
12387 return dx + dy;
12388 }();
12389 if (targetCandidateDistance < shortestDistance) {
12390 shortestDistance = targetCandidateDistance;
12391 targetWidget = targetCandidate;
12392 }
12393 }
12394 }
12395 return targetWidget;
12396}
12397
12398/*!
12399 \internal
12400
12401 Tells us if it there is currently a reachable widget by keypad navigation in
12402 a certain \a orientation.
12403 If no navigation is possible, occurring key events in that \a orientation may
12404 be used to interact with the value in the focused widget, even though it
12405 currently has not the editFocus.
12406
12407 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12408*/
12409bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12410{
12411 return orientation == Qt::Horizontal?
12412 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12413 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12414 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12415 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12416}
12417/*!
12418 \internal
12419
12420 Checks, if the \a widget is inside a QTabWidget. If is is inside
12421 one, left/right key events will be used to switch between tabs in keypad
12422 navigation. If there is no QTabWidget, the horizontal key events can be used
12423to
12424 interact with the value in the focused widget, even though it currently has
12425 not the editFocus.
12426
12427 \sa QWidget::hasEditFocus()
12428*/
12429bool QWidgetPrivate::inTabWidget(QWidget *widget)
12430{
12431 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12432 if (qobject_cast<const QTabWidget*>(tabWidget))
12433 return true;
12434 return false;
12435}
12436#endif
12437
12438/*!
12439 \since 5.0
12440 \internal
12441
12442 Sets the backing store to be the \a store specified.
12443 The QWidget will take ownership of the \a store.
12444*/
12445void QWidget::setBackingStore(QBackingStore *store)
12446{
12447 // ### createWinId() ??
12448
12449 if (!isWindow())
12450 return;
12451
12452 Q_D(QWidget);
12453
12454 QTLWExtra *topData = d->topData();
12455 if (topData->backingStore == store)
12456 return;
12457
12458 QBackingStore *oldStore = topData->backingStore;
12459 delete topData->backingStore;
12460 topData->backingStore = store;
12461
12462 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12463 if (!repaintManager)
12464 return;
12465
12466 if (isWindow()) {
12467 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12468 delete repaintManager->backingStore();
12469 repaintManager->setBackingStore(store);
12470 }
12471}
12472
12473/*!
12474 \since 5.0
12475
12476 Returns the QBackingStore this widget will be drawn into.
12477*/
12478QBackingStore *QWidget::backingStore() const
12479{
12480 Q_D(const QWidget);
12481 QTLWExtra *extra = d->maybeTopData();
12482 if (extra && extra->backingStore)
12483 return extra->backingStore;
12484
12485 if (!isWindow())
12486 return window()->backingStore();
12487
12488 return nullptr;
12489}
12490
12491void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12492{
12493 if (left)
12494 *left = (int)leftLayoutItemMargin;
12495 if (top)
12496 *top = (int)topLayoutItemMargin;
12497 if (right)
12498 *right = (int)rightLayoutItemMargin;
12499 if (bottom)
12500 *bottom = (int)bottomLayoutItemMargin;
12501}
12502
12503void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12504{
12505 if (leftLayoutItemMargin == left
12506 && topLayoutItemMargin == top
12507 && rightLayoutItemMargin == right
12508 && bottomLayoutItemMargin == bottom)
12509 return;
12510
12511 Q_Q(QWidget);
12512 leftLayoutItemMargin = (signed char)left;
12513 topLayoutItemMargin = (signed char)top;
12514 rightLayoutItemMargin = (signed char)right;
12515 bottomLayoutItemMargin = (signed char)bottom;
12516 q->updateGeometry();
12517}
12518
12519void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12520{
12521 Q_Q(QWidget);
12522 QStyleOption myOpt;
12523 if (!opt) {
12524 myOpt.initFrom(q);
12525 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12526 opt = &myOpt;
12527 }
12528
12529 QRect liRect = q->style()->subElementRect(element, opt, q);
12530 if (liRect.isValid()) {
12531 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12532 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12533 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12534 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12535 } else {
12536 leftLayoutItemMargin = 0;
12537 topLayoutItemMargin = 0;
12538 rightLayoutItemMargin = 0;
12539 bottomLayoutItemMargin = 0;
12540 }
12541}
12542// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12543void QWidgetPrivate::adjustQuitOnCloseAttribute()
12544{
12545 Q_Q(QWidget);
12546
12547 if (!q->parentWidget()) {
12548 Qt::WindowType type = q->windowType();
12549 if (type == Qt::Widget || type == Qt::SubWindow)
12550 type = Qt::Window;
12551 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12552 q->setAttribute(Qt::WA_QuitOnClose, false);
12553 }
12554}
12555
12556void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12557{
12558 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12559 if (!wd->textureChildSeen)
12560 return;
12561 if (end)
12562 wd->endCompose();
12563 else
12564 wd->beginCompose();
12565 for (int i = 0; i < wd->children.size(); ++i) {
12566 w = qobject_cast<QWidget *>(wd->children.at(i));
12567 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12568 sendComposeStatus(w, end);
12569 }
12570}
12571
12572Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12573{
12574 return widget->data;
12575}
12576
12577Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12578{
12579 return widget->d_func();
12580}
12581
12582
12583#if QT_CONFIG(graphicsview)
12584/*!
12585 \since 4.5
12586
12587 Returns the proxy widget for the corresponding embedded widget in a graphics
12588 view; otherwise returns \nullptr.
12589
12590 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12591 QGraphicsScene::addWidget()
12592 */
12593QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12594{
12595 Q_D(const QWidget);
12596 if (d->extra) {
12597 return d->extra->proxyWidget;
12598 }
12599 return nullptr;
12600}
12601#endif
12602
12603#ifndef QT_NO_GESTURES
12604/*!
12605 Subscribes the widget to a given \a gesture with specific \a flags.
12606
12607 \sa ungrabGesture(), QGestureEvent
12608 \since 4.6
12609*/
12610void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12611{
12612 Q_D(QWidget);
12613 d->gestureContext.insert(gesture, flags);
12614 (void)QGestureManager::instance(); // create a gesture manager
12615}
12616
12617/*!
12618 Unsubscribes the widget from a given \a gesture type
12619
12620 \sa grabGesture(), QGestureEvent
12621 \since 4.6
12622*/
12623void QWidget::ungrabGesture(Qt::GestureType gesture)
12624{
12625 // if you modify this function, check the inlined version in ~QWidget, too
12626 Q_D(QWidget);
12627 if (d->gestureContext.remove(gesture)) {
12628 if (QGestureManager *manager = QGestureManager::instance())
12629 manager->cleanupCachedGestures(this, gesture);
12630 }
12631}
12632#endif // QT_NO_GESTURES
12633
12634/*!
12635 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12636
12637 Frees up window system resources. Destroys the widget window if \a
12638 destroyWindow is true.
12639
12640 destroy() calls itself recursively for all the child widgets,
12641 passing \a destroySubWindows for the \a destroyWindow parameter.
12642 To have more control over destruction of subwidgets, destroy
12643 subwidgets selectively first.
12644
12645 This function is usually called from the QWidget destructor.
12646*/
12647void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12648{
12649 Q_D(QWidget);
12650
12651 d->aboutToDestroy();
12652 if (!isWindow() && parentWidget())
12653 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12654 d->deactivateWidgetCleanup();
12655
12656 if ((windowType() == Qt::Popup) && qApp)
12657 qApp->d_func()->closePopup(this);
12658
12659 if (this == qApp->activeWindow())
12660 QApplicationPrivate::setActiveWindow(nullptr);
12661 if (QWidget::mouseGrabber() == this)
12662 releaseMouse();
12663 if (QWidget::keyboardGrabber() == this)
12664 releaseKeyboard();
12665
12666 setAttribute(Qt::WA_WState_Created, false);
12667
12668 if (destroySubWindows) {
12669 QObjectList childList(children());
12670 for (int i = 0; i < childList.size(); i++) {
12671 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12672 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12673 if (widget->windowHandle()) {
12674 widget->destroy();
12675 }
12676 }
12677 }
12678 }
12679 if (destroyWindow) {
12680 d->deleteTLSysExtra();
12681 } else {
12682 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12683 d->hide_sys();
12684 }
12685 }
12686
12687 d->setWinId(0);
12688}
12689
12690/*!
12691 \fn QPaintEngine *QWidget::paintEngine() const
12692
12693 Returns the widget's paint engine.
12694
12695 Note that this function should not be called explicitly by the
12696 user, since it's meant for reimplementation purposes only. The
12697 function is called by Qt internally, and the default
12698 implementation may not always return a valid pointer.
12699*/
12700QPaintEngine *QWidget::paintEngine() const
12701{
12702 qWarning("QWidget::paintEngine: Should no longer be called");
12703
12704#ifdef Q_OS_WIN
12705 // We set this bit which is checked in setAttribute for
12706 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12707 //
12708 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12709 // Windows which would mean suddenly their widgets stop working.
12710 //
12711 // 2. Users set paint on screen and subclass paintEngine() to
12712 // return 0, in which case we have a "hole" in the backingstore
12713 // allowing use of GDI or DirectX directly.
12714 //
12715 // 1 is WRONG, but to minimize silent failures, we have set this
12716 // bit to ignore the setAttribute call. 2. needs to be
12717 // supported because its our only means of embedding native
12718 // graphics stuff.
12719 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12720#endif
12721
12722 return nullptr; //##### @@@
12723}
12724
12725// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12726static inline bool canMapPosition(QWindow *window)
12727{
12728 return window->handle() && !qt_window_private(window)->resizeEventPending;
12729}
12730
12731#if QT_CONFIG(graphicsview)
12732static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12733{
12734 QGraphicsProxyWidget *result = nullptr;
12735 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12736 if (d->extra)
12737 result = d->extra->proxyWidget;
12738 return result;
12739}
12740#endif // QT_CONFIG(graphicsview)
12741
12743 QTransform transform;
12744 QWindow *window;
12745};
12746
12748{
12750 result.window = nullptr;
12751 for ( ; w ; w = w->parentWidget()) {
12752#if QT_CONFIG(graphicsview)
12753 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12754 if (const QGraphicsScene *scene = qgpw->scene()) {
12755 const QList <QGraphicsView *> views = scene->views();
12756 if (!views.isEmpty()) {
12757 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12758 result.transform *= viewP->mapToViewTransform(qgpw);
12759 w = views.first()->viewport();
12760 }
12761 }
12762 }
12763#endif // QT_CONFIG(graphicsview)
12764 QWindow *window = w->windowHandle();
12765 if (window && canMapPosition(window)) {
12766 result.window = window;
12767 break;
12768 }
12769
12770 const auto &geometry = w->geometry();
12771 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12772 if (w->isWindow())
12773 break;
12774 }
12775 return result;
12776}
12777
12778/*!
12779 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12780
12781 Translates the widget coordinate \a pos to global screen
12782 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12783 the global coordinates of the top-left pixel of the widget.
12784
12785 \sa mapFromGlobal(), mapTo(), mapToParent()
12786 \since 6.0
12787*/
12788QPointF QWidget::mapToGlobal(const QPointF &pos) const
12789{
12790 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12791 const QPointF g = t.transform.map(pos);
12792 return t.window ? t.window->mapToGlobal(g) : g;
12793}
12794
12795/*!
12796 \overload
12797*/
12798QPoint QWidget::mapToGlobal(const QPoint &pos) const
12799{
12800 return mapToGlobal(QPointF(pos)).toPoint();
12801}
12802
12803/*!
12804 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12805
12806 Translates the global screen coordinate \a pos to widget
12807 coordinates.
12808
12809 \sa mapToGlobal(), mapFrom(), mapFromParent()
12810 \since 6.0
12811*/
12812QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12813{
12814 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12815 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12816 return t.transform.inverted().map(windowLocal);
12817}
12818
12819/*!
12820 \overload
12821*/
12822QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12823{
12824 return mapFromGlobal(QPointF(pos)).toPoint();
12825}
12826
12828static bool mouseGrabWithCursor = false;
12829static QWidget *keyboardGrb = nullptr;
12830
12831static inline QWindow *grabberWindow(const QWidget *w)
12832{
12833 QWindow *window = w->windowHandle();
12834 if (!window)
12835 if (const QWidget *nativeParent = w->nativeParentWidget())
12836 window = nativeParent->windowHandle();
12837 return window;
12838}
12839
12840#ifndef QT_NO_CURSOR
12841static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12842#else
12843static void grabMouseForWidget(QWidget *widget)
12844#endif
12845{
12846 if (qt_mouseGrb)
12847 qt_mouseGrb->releaseMouse();
12848
12849 mouseGrabWithCursor = false;
12850 if (QWindow *window = grabberWindow(widget)) {
12851#ifndef QT_NO_CURSOR
12852 if (cursor) {
12853 mouseGrabWithCursor = true;
12854 QGuiApplication::setOverrideCursor(*cursor);
12855 }
12856#endif // !QT_NO_CURSOR
12857 window->setMouseGrabEnabled(true);
12858 }
12859
12860 qt_mouseGrb = widget;
12861}
12862
12864{
12865 if (qt_mouseGrb == widget) {
12866 if (QWindow *window = grabberWindow(widget)) {
12867#ifndef QT_NO_CURSOR
12868 if (mouseGrabWithCursor) {
12869 QGuiApplication::restoreOverrideCursor();
12870 mouseGrabWithCursor = false;
12871 }
12872#endif // !QT_NO_CURSOR
12873 window->setMouseGrabEnabled(false);
12874 }
12875 }
12876 qt_mouseGrb = nullptr;
12877}
12878
12879/*!
12880 \fn void QWidget::grabMouse()
12881
12882 Grabs the mouse input.
12883
12884 This widget receives all mouse events until releaseMouse() is
12885 called; other widgets get no mouse events at all. Keyboard
12886 events are not affected. Use grabKeyboard() if you want to grab
12887 that.
12888
12889 \warning Bugs in mouse-grabbing applications very often lock the
12890 terminal. Use this function with extreme caution, and consider
12891 using the \c -nograb command line option while debugging.
12892
12893 It is seldom necessary to grab the mouse when using Qt, as
12894 Qt grabs and releases it sensibly. In particular, Qt grabs the
12895 mouse when a mouse button is pressed and keeps it until the last
12896 button is released.
12897
12898 \note Only visible widgets can grab mouse input. If isVisible()
12899 returns \c false for a widget, that widget cannot call grabMouse().
12900
12901 \note On Windows, grabMouse() only works when the mouse is inside a window
12902 owned by the process.
12903 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12904
12905 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12906*/
12907void QWidget::grabMouse()
12908{
12909 grabMouseForWidget(this);
12910}
12911
12912/*!
12913 \fn void QWidget::grabMouse(const QCursor &cursor)
12914 \overload grabMouse()
12915
12916 Grabs the mouse input and changes the cursor shape.
12917
12918 The cursor will assume shape \a cursor (for as long as the mouse
12919 focus is grabbed) and this widget will be the only one to receive
12920 mouse events until releaseMouse() is called().
12921
12922 \warning Grabbing the mouse might lock the terminal.
12923
12924 \note See the note in QWidget::grabMouse().
12925
12926 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12927*/
12928#ifndef QT_NO_CURSOR
12929void QWidget::grabMouse(const QCursor &cursor)
12930{
12931 grabMouseForWidget(this, &cursor);
12932}
12933#endif
12934
12935bool QWidgetPrivate::stealMouseGrab(bool grab)
12936{
12937 // This is like a combination of grab/releaseMouse() but with error checking
12938 // and it has no effect on the result of mouseGrabber().
12939 Q_Q(QWidget);
12940 QWindow *window = grabberWindow(q);
12941 return window ? window->setMouseGrabEnabled(grab) : false;
12942}
12943
12944/*!
12945 \fn void QWidget::releaseMouse()
12946
12947 Releases the mouse grab.
12948
12949 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12950*/
12951void QWidget::releaseMouse()
12952{
12953 releaseMouseGrabOfWidget(this);
12954}
12955
12956/*!
12957 \fn void QWidget::grabKeyboard()
12958
12959 Grabs the keyboard input.
12960
12961 This widget receives all keyboard events until releaseKeyboard()
12962 is called; other widgets get no keyboard events at all. Mouse
12963 events are not affected. Use grabMouse() if you want to grab that.
12964
12965 The focus widget is not affected, except that it doesn't receive
12966 any keyboard events. setFocus() moves the focus as usual, but the
12967 new focus widget receives keyboard events only after
12968 releaseKeyboard() is called.
12969
12970 If a different widget is currently grabbing keyboard input, that
12971 widget's grab is released first.
12972
12973 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12974*/
12975void QWidget::grabKeyboard()
12976{
12977 if (keyboardGrb)
12978 keyboardGrb->releaseKeyboard();
12979 if (QWindow *window = grabberWindow(this))
12980 window->setKeyboardGrabEnabled(true);
12981 keyboardGrb = this;
12982}
12983
12984bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12985{
12986 // This is like a combination of grab/releaseKeyboard() but with error
12987 // checking and it has no effect on the result of keyboardGrabber().
12988 Q_Q(QWidget);
12989 QWindow *window = grabberWindow(q);
12990 return window ? window->setKeyboardGrabEnabled(grab) : false;
12991}
12992
12993/*!
12994 \fn void QWidget::releaseKeyboard()
12995
12996 Releases the keyboard grab.
12997
12998 \sa grabKeyboard(), grabMouse(), releaseMouse()
12999*/
13000void QWidget::releaseKeyboard()
13001{
13002 if (keyboardGrb == this) {
13003 if (QWindow *window = grabberWindow(this))
13004 window->setKeyboardGrabEnabled(false);
13005 keyboardGrb = nullptr;
13006 }
13007}
13008
13009/*!
13010 \fn QWidget *QWidget::mouseGrabber()
13011
13012 Returns the widget that is currently grabbing the mouse input.
13013
13014 If no widget in this application is currently grabbing the mouse,
13015 \nullptr is returned.
13016
13017 \sa grabMouse(), keyboardGrabber()
13018*/
13019QWidget *QWidget::mouseGrabber()
13020{
13021 return qt_mouseGrb;
13022}
13023
13024/*!
13025 \fn QWidget *QWidget::keyboardGrabber()
13026
13027 Returns the widget that is currently grabbing the keyboard input.
13028
13029 If no widget in this application is currently grabbing the
13030 keyboard, \nullptr is returned.
13031
13032 \sa grabMouse(), mouseGrabber()
13033*/
13034QWidget *QWidget::keyboardGrabber()
13035{
13036 return keyboardGrb;
13037}
13038
13039/*!
13040 \fn void QWidget::activateWindow()
13041
13042 Sets the top-level widget containing this widget to be the active
13043 window.
13044
13045 An active window is a visible top-level window that has the
13046 keyboard input focus.
13047
13048 This function performs the same operation as clicking the mouse on
13049 the title bar of a top-level window. On X11, the result depends on
13050 the Window Manager. If you want to ensure that the window is
13051 stacked on top as well you should also call raise(). Note that the
13052 window must be visible, otherwise activateWindow() has no effect.
13053
13054 On Windows, if you are calling this when the application is not
13055 currently the active one then it will not make it the active
13056 window. It will change the color of the taskbar entry to indicate
13057 that the window has changed in some way. This is because Microsoft
13058 does not allow an application to interrupt what the user is currently
13059 doing in another application.
13060
13061 \sa isActiveWindow(), window(), show()
13062*/
13063void QWidget::activateWindow()
13064{
13065 QWindow *const wnd = window()->windowHandle();
13066
13067 if (wnd)
13068 wnd->requestActivate();
13069}
13070
13071/*!
13072
13073 Internal implementation of the virtual QPaintDevice::metric()
13074 function.
13075
13076 \a m is the metric to get.
13077*/
13078int QWidget::metric(PaintDeviceMetric m) const
13079{
13080 QScreen *screen = this->screen();
13081
13082 if (!screen) {
13083 if (m == PdmDpiX || m == PdmDpiY)
13084 return 72;
13085 return QPaintDevice::metric(m);
13086 }
13087
13088 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
13089
13090 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
13091 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
13092 QWindow *window = this->window()->windowHandle();
13093 if (window)
13094 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
13095 return screen->devicePixelRatio();
13096 };
13097
13098 switch (m) {
13099 case PdmWidth:
13100 return data->crect.width();
13101 case PdmWidthMM:
13102 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
13103 case PdmHeight:
13104 return data->crect.height();
13105 case PdmHeightMM:
13106 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13107 case PdmDepth:
13108 return screen->depth();
13109 case PdmDpiX:
13110 for (const QWidget *p = this; p; p = p->parentWidget()) {
13111 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13112 return p->d_func()->extra->customDpiX;
13113 }
13114 return qRound(screen->logicalDotsPerInchX());
13115 case PdmDpiY:
13116 for (const QWidget *p = this; p; p = p->parentWidget()) {
13117 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13118 return p->d_func()->extra->customDpiY;
13119 }
13120 return qRound(screen->logicalDotsPerInchY());
13121 case PdmPhysicalDpiX:
13122 return qRound(screen->physicalDotsPerInchX());
13123 case PdmPhysicalDpiY:
13124 return qRound(screen->physicalDotsPerInchY());
13125 case PdmDevicePixelRatio:
13126 return resolveDevicePixelRatio();
13127 case PdmDevicePixelRatioScaled:
13128 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13129 case PdmDevicePixelRatioF_EncodedA:
13130 Q_FALLTHROUGH();
13131 case PdmDevicePixelRatioF_EncodedB:
13132 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
13133 default:
13134 break;
13135 }
13136 return QPaintDevice::metric(m);
13137}
13138
13139/*!
13140 Initializes the \a painter pen, background and font to the same as
13141 the given widget's. This function is called automatically when the
13142 painter is opened on a QWidget.
13143*/
13144void QWidget::initPainter(QPainter *painter) const
13145{
13146 const QPalette &pal = palette();
13147 painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1);
13148 painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
13149 QFont f(font(), this);
13150 painter->d_func()->state->deviceFont = f;
13151 painter->d_func()->state->font = f;
13152}
13153
13154/*!
13155 \internal
13156
13157 Do PaintDevice rendering with the specified \a offset.
13158*/
13159QPaintDevice *QWidget::redirected(QPoint *offset) const
13160{
13161 return d_func()->redirected(offset);
13162}
13163
13164/*!
13165 \internal
13166
13167 A painter that is shared among other instances of QPainter.
13168*/
13169QPainter *QWidget::sharedPainter() const
13170{
13171 // Someone sent a paint event directly to the widget
13172 if (!d_func()->redirectDev)
13173 return nullptr;
13174
13175 QPainter *sp = d_func()->sharedPainter();
13176 if (!sp || !sp->isActive())
13177 return nullptr;
13178
13179 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13180 return nullptr;
13181
13182 return sp;
13183}
13184
13185/*!
13186 \fn void QWidget::setMask(const QRegion &region)
13187 \overload
13188
13189 Causes only the parts of the widget which overlap \a region to be
13190 visible. If the region includes pixels outside the rect() of the
13191 widget, window system controls in that area may or may not be
13192 visible, depending on the platform.
13193
13194 Since QRegion allows arbitrarily complex regions to be created, widget
13195 masks can be made to suit the most unconventionally-shaped windows, and
13196 even allow widgets to be displayed with holes in them. Note that this
13197 effect can be slow if the region is particularly complex.
13198
13199 Widget masks are used to hint to the window system that the application
13200 does not want mouse events for areas outside the mask. On most systems,
13201 they also result in coarse visual clipping. To get smooth window edges, use
13202 translucent background and anti-aliased painting instead, as shown in the
13203 \l{Translucent Background} example.
13204
13205 \sa windowOpacity
13206*/
13207void QWidget::setMask(const QRegion &newMask)
13208{
13209 Q_D(QWidget);
13210
13211 d->createExtra();
13212 if (newMask == d->extra->mask)
13213 return;
13214
13215#ifndef QT_NO_BACKINGSTORE
13216 const QRegion oldMask(d->extra->mask);
13217#endif
13218
13219 d->extra->mask = newMask;
13220 d->extra->hasMask = !newMask.isEmpty();
13221
13222 if (!testAttribute(Qt::WA_WState_Created))
13223 return;
13224
13225 d->setMask_sys(newMask);
13226
13227#ifndef QT_NO_BACKINGSTORE
13228 if (!isVisible())
13229 return;
13230
13231 if (!d->extra->hasMask) {
13232 // Mask was cleared; update newly exposed area.
13233 QRegion expose(rect());
13234 expose -= oldMask;
13235 if (!expose.isEmpty()) {
13236 d->setDirtyOpaqueRegion();
13237 update(expose);
13238 }
13239 return;
13240 }
13241
13242 if (!isWindow()) {
13243 // Update newly exposed area on the parent widget.
13244 QRegion parentExpose(rect());
13245 parentExpose -= newMask;
13246 if (!parentExpose.isEmpty()) {
13247 d->setDirtyOpaqueRegion();
13248 parentExpose.translate(data->crect.topLeft());
13249 parentWidget()->update(parentExpose);
13250 }
13251
13252 // Update newly exposed area on this widget
13253 if (!oldMask.isEmpty())
13254 update(newMask - oldMask);
13255 }
13256#endif
13257}
13258
13259void QWidgetPrivate::setMask_sys(const QRegion &region)
13260{
13261 Q_Q(QWidget);
13262 if (QWindow *window = q->windowHandle())
13263 window->setMask(region);
13264}
13265
13266/*!
13267 \fn void QWidget::setMask(const QBitmap &bitmap)
13268
13269 Causes only the pixels of the widget for which \a bitmap has a
13270 corresponding 1 bit to be visible. If the region includes pixels
13271 outside the rect() of the widget, window system controls in that
13272 area may or may not be visible, depending on the platform.
13273
13274 Note that this effect can be slow if the region is particularly
13275 complex.
13276
13277 The following code shows how an image with an alpha channel can be
13278 used to generate a mask for a widget:
13279
13280 \snippet widget-mask/main.cpp 0
13281
13282 The label shown by this code is masked using the image it contains,
13283 giving the appearance that an irregularly-shaped image is being drawn
13284 directly onto the screen.
13285
13286 Masked widgets receive mouse events only on their visible
13287 portions.
13288
13289 \sa clearMask(), windowOpacity()
13290*/
13291void QWidget::setMask(const QBitmap &bitmap)
13292{
13293 setMask(QRegion(bitmap));
13294}
13295
13296/*!
13297 \fn void QWidget::clearMask()
13298
13299 Removes any mask set by setMask().
13300
13301 \sa setMask()
13302*/
13303void QWidget::clearMask()
13304{
13305 Q_D(QWidget);
13306 if (!d->extra || !d->extra->hasMask)
13307 return;
13308 setMask(QRegion());
13309}
13310
13311void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13312{
13313 Q_ASSERT(widgetAsObject->isWidgetType());
13314 Q_ASSERT(!newParent || newParent->isWidgetType());
13315 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13316 widget->setParent(static_cast<QWidget*>(newParent));
13317}
13318
13319std::string QWidgetPrivate::flagsForDumping() const
13320{
13321 Q_Q(const QWidget);
13322 std::string flags = QObjectPrivate::flagsForDumping();
13323 if (QApplication::focusWidget() == q)
13324 flags += 'F';
13325 if (q->isVisible()) {
13326 std::stringstream s;
13327 s << '<'
13328 << q->width() << 'x' << q->height()
13329 << std::showpos << q->x() << q->y()
13330 << '>';
13331 flags += s.str();
13332 } else {
13333 flags += 'I';
13334 }
13335 return flags;
13336}
13337
13338void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13339{
13340#if QT_CONFIG(xcb)
13341 Q_Q(QWidget);
13342
13343 if (!q->windowHandle())
13344 return;
13345
13346 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13347 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13348 wmWindowType |= QXcbWindow::Desktop;
13349 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13350 wmWindowType |= QXcbWindow::Dock;
13351 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13352 wmWindowType |= QXcbWindow::Toolbar;
13353 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13354 wmWindowType |= QXcbWindow::Menu;
13355 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13356 wmWindowType |= QXcbWindow::Utility;
13357 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13358 wmWindowType |= QXcbWindow::Splash;
13359 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13360 wmWindowType |= QXcbWindow::Dialog;
13361 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13362 wmWindowType |= QXcbWindow::DropDownMenu;
13363 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13364 wmWindowType |= QXcbWindow::PopupMenu;
13365 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13366 wmWindowType |= QXcbWindow::Tooltip;
13367 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13368 wmWindowType |= QXcbWindow::Notification;
13369 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13370 wmWindowType |= QXcbWindow::Combo;
13371 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13372 wmWindowType |= QXcbWindow::Dnd;
13373
13374 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13375 return;
13376
13377 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13378 xcbWindow->setWindowType(wmWindowType);
13379#else
13380 Q_UNUSED(skipIfMissing);
13381#endif
13382}
13383
13384/*!
13385 \internal
13386 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13387 Return false otherwise.
13388 */
13389bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13390{
13391 Q_Q(const QWidget);
13392 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13393 for (const auto *child : children) {
13394 if (child->focusPolicy() == policy && child->isEnabled()
13395 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13396 return true;
13397 }
13398 }
13399 return false;
13400}
13401
13402#ifndef QT_NO_DEBUG_STREAM
13403
13404namespace {
13405QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13406{
13407 const QDebugStateSaver saver(debug);
13408 debug.nospace();
13409 debug << '[';
13410 if (const QWidget *widget = attributes.widget) {
13411 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13412 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13413 int count = 0;
13414 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13415 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13416 if (count++)
13417 debug << ',';
13418 debug << me.valueToKey(a);
13419 }
13420 }
13421 }
13422 debug << ']';
13423 return debug;
13424}
13425}
13426
13427QDebug operator<<(QDebug debug, const QWidget *widget)
13428{
13429 const QDebugStateSaver saver(debug);
13430 debug.nospace();
13431 if (widget) {
13432 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13433 if (!widget->objectName().isEmpty())
13434 debug << ", name=" << widget->objectName();
13435 if (debug.verbosity() > 2) {
13436 const QRect geometry = widget->geometry();
13437 const QRect frameGeometry = widget->frameGeometry();
13438 if (widget->isVisible())
13439 debug << ", visible";
13440 if (!widget->isEnabled())
13441 debug << ", disabled";
13442 debug << ", states=" << widget->windowState()
13443 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13444 debug << ", attributes=" << WidgetAttributes{widget};
13445 if (widget->isWindow())
13446 debug << ", window";
13447 debug << ", " << geometry.width() << 'x' << geometry.height()
13448 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13449 if (frameGeometry != geometry) {
13450 const QMargins margins(geometry.x() - frameGeometry.x(),
13451 geometry.y() - frameGeometry.y(),
13452 frameGeometry.right() - geometry.right(),
13453 frameGeometry.bottom() - geometry.bottom());
13454 debug << ", margins=" << margins;
13455 }
13456 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13457 if (const WId wid = widget->internalWinId())
13458 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13459 }
13460 debug << ')';
13461 } else {
13462 debug << "QWidget(0x0)";
13463 }
13464 return debug;
13465}
13466#endif // !QT_NO_DEBUG_STREAM
13467
13468
13469// *************************** Focus abstraction ************************************
13470
13471#define FOCUS_NEXT(w) w->d_func()->focus_next
13472#define FOCUS_PREV(w) w->d_func()->focus_prev
13473
13474/*!
13475 \internal
13476 \return next or previous element in the focus chain, depending on
13477 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13478 */
13479QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13480{
13481 Q_Q(const QWidget);
13482 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13483}
13484
13485/*!
13486 \internal
13487 Removes a widget from the focus chain, respecting the flags set in \param rules.
13488 \list
13489 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13490 in the focus chain, depending on \param direction.
13491 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13492 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13493 \endlist
13494 \return \c true if the widget has been removed, otherwise \c false.
13495 */
13496bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13497{
13498 Q_Q(QWidget);
13499 if (!isFocusChainConsistent()) {
13500#ifdef QT_DEBUG
13501 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13502 qFatal() << q << "has inconsistent focus chain.";
13503#endif
13504 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13505 return false;
13506 }
13507
13508 if (!isInFocusChain()) {
13509 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13510 return false;
13511 }
13512
13513 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13514 q->focusNextPrevChild(direction == FocusDirection::Next);
13515
13518 initFocusChain();
13519 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13520 return true;
13521}
13522
13523/*!
13524 \internal
13525 Initialises the focus chain by making the widget point to itself.
13526 */
13527void QWidgetPrivate::initFocusChain()
13528{
13529 Q_Q(QWidget);
13530 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13531 FOCUS_PREV(q) = q;
13532 FOCUS_NEXT(q) = q;
13533}
13534
13535/*!
13536 \internal
13537 Reads QWidget children, which are not part of a focus chain yet.
13538 Inserts them into the focus chain before or after the widget,
13539 depending on \param direction and in the order of their creation.
13540 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13541 */
13542void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13543{
13544 Q_Q(QWidget);
13545
13546 // separate the focus chain into new (children of myself) and old (the rest)
13547 QWidget *firstOld = nullptr;
13548 QWidget *lastOld = nullptr; // last in the old list
13549 QWidget *lastNew = q; // last in the new list
13550 bool prevWasNew = true;
13551 QWidget *widget = nextPrevElementInFocusChain(direction);
13552
13553 // For efficiency, do not maintain the list invariant inside the loop.
13554 // Append items to the relevant list, and we optimize by not changing pointers,
13555 // when subsequent items are going into the same list.
13556 while (widget != q) {
13557 bool currentIsNew = q->isAncestorOf(widget);
13558 if (currentIsNew) {
13559 if (!prevWasNew) {
13560 // previous was old => append to new list
13561 FOCUS_NEXT(lastNew) = widget;
13562 FOCUS_PREV(widget) = lastNew;
13563 }
13564 lastNew = widget;
13565 } else {
13566 if (prevWasNew) {
13567 // prev was new => append to old list, if it exists
13568 if (lastOld) {
13569 FOCUS_NEXT(lastOld) = widget;
13570 FOCUS_PREV(widget) = lastOld;
13571 } else {
13572 // start the old list
13573 firstOld = widget;
13574 }
13575 }
13576 lastOld = widget;
13577 }
13578 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13579 prevWasNew = currentIsNew;
13580 }
13581
13582 // repair old list:
13583 if (firstOld) {
13584 FOCUS_NEXT(lastOld) = firstOld;
13585 FOCUS_PREV(firstOld) = lastOld;
13586 }
13587
13588 if (!q->isWindow()) {
13589 QWidget *topLevel = q->window();
13590 // insert new chain into toplevel's chain
13591 QWidget *prev = FOCUS_PREV(topLevel);
13592 FOCUS_PREV(topLevel) = lastNew;
13593 FOCUS_NEXT(prev) = q;
13594 FOCUS_PREV(q) = prev;
13595 FOCUS_NEXT(lastNew) = topLevel;
13596 } else {
13597 // repair new list
13598 FOCUS_NEXT(lastNew) = q;
13599 FOCUS_PREV(q) = lastNew;
13600 }
13601}
13602
13603/*!
13604 \internal
13605 Inserts a widget into the focus chain before or after \param position, depending on
13606 \param direction.
13607 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13608 */
13609bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13610{
13611 Q_Q(QWidget);
13612 Q_ASSERT(position);
13613 QWidget *next = FOCUS_NEXT(q);
13614 QWidget *previous = FOCUS_PREV(q);
13615
13616 switch (direction) {
13617 case FocusDirection::Next:
13618 if (previous == position) {
13619 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13620 return false;
13621 }
13622
13623 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13624
13625 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13626 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13627 FOCUS_NEXT(position) = q;
13628 FOCUS_PREV(q) = position;
13629 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13630 break;
13631
13632 case FocusDirection::Previous:
13633 if (next == position) {
13634 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13635 return false;
13636 }
13637
13638 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13639
13640 FOCUS_PREV(q) = FOCUS_PREV(position);
13641 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13642 FOCUS_PREV(position) = q;
13643 FOCUS_NEXT(q) = position;
13644 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13645 break;
13646 }
13647
13648 Q_ASSERT(isFocusChainConsistent());
13649 return true;
13650}
13651
13652/*!
13653 \internal
13654 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13655 before or after \param position, depending on \param direction.
13656 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13657 \note
13658 \param toBeInserted must be a consistent focus chain.
13659 */
13660bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13661 FocusDirection direction, QWidget *position)
13662{
13663 if (toBeInserted.isEmpty()) {
13664 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13665 return false;
13666 }
13667
13668 Q_ASSERT_X(!toBeInserted.contains(position),
13669 Q_FUNC_INFO,
13670 "Coding error: toBeInserted contains position");
13671
13672 QWidget *first = toBeInserted.constFirst();
13673 QWidget *last = toBeInserted.constLast();
13674
13675 // Call QWidget override to log accordingly
13676 if (toBeInserted.count() == 1)
13677 return first->d_func()->insertIntoFocusChain(direction, position);
13678
13679 Q_ASSERT(first != last);
13680 switch (direction) {
13681 case FocusDirection::Previous:
13682 if (FOCUS_PREV(position) == last) {
13683 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13684 << position;
13685 return false;
13686 }
13687 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13688 FOCUS_PREV(first) = FOCUS_PREV(position);
13689 FOCUS_NEXT(last) = position;
13690 FOCUS_PREV(position) = last;
13691 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13692 break;
13693 case FocusDirection::Next:
13694 if (FOCUS_PREV(position) == last) {
13695 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13696 << position;
13697 return false;
13698 }
13699 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13700 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13701 FOCUS_PREV(first) = position;
13702 FOCUS_NEXT(position) = first;
13703 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13704 break;
13705 }
13706
13707 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13708 return true;
13709}
13710
13711/*!
13712 \internal
13713 \return a QWidgetList, representing the part of the focus chain,
13714 starting with \param from and ending with \param to, in \param direction.
13715 */
13716QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13717{
13718 QWidgetList path({from});
13719 if (from == to)
13720 return path;
13721
13722 QWidget *current = from;
13723 do {
13724 switch (direction) {
13725 case QWidgetPrivate::FocusDirection::Previous:
13726 current = current->previousInFocusChain();
13727 break;
13728 case QWidgetPrivate::FocusDirection::Next:
13729 current = current->nextInFocusChain();
13730 break;
13731 }
13732 if (path.contains(current))
13733 return QWidgetList();
13734 path << current;
13735 } while (current != to);
13736
13737 return path;
13738}
13739
13740/*!
13741 \internal
13742 Removes the part from the focus chain starting with \param from and ending with \param to,
13743 in \param direction.
13744 \return removed part as a QWidgetList.
13745 */
13746QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13747 QWidget *to,
13748 FocusDirection direction)
13749{
13750 // Check if there is a path from->to in direction
13751 const QWidgetList path = focusPath(from, to , direction);
13752 if (path.isEmpty()) {
13753 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13754 return QWidgetList();
13755 }
13756
13757 QWidget *first = path.constFirst();
13758 QWidget *last = path.constLast();
13759 if (first == last) {
13760 first->d_func()->removeFromFocusChain();
13761 return QWidgetList({first});
13762 }
13763
13764 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13765 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13766 FOCUS_PREV(first) = last;
13767 FOCUS_NEXT(last) = first;
13768 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13769 return path;
13770}
13771
13772/*!
13773 \internal
13774 \return The last focus child of the widget, traversing the focus chain no further than
13775 \param noFurtherThan.
13776 */
13777QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13778{
13779 Q_Q(QWidget);
13780 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13781 // that determines the last focus child for a widget, taking proxies and compound widgets into
13782 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13783 // to a child), 'lastFocusChild' will be set to the target itself.
13784 QWidget *lastFocusChild = q;
13785
13786 QWidget *focusProxy = deepestFocusProxy();
13787 if (!focusProxy) {
13788 // QTBUG-81097: Another case is possible here. We can have a child
13789 // widget, that sets its focusProxy() to the parent (target).
13790 // An example of such widget is a QLineEdit, nested into
13791 // a QAbstractSpinBox. In this case such widget should be considered
13792 // the last focus child.
13793 for (auto *object : std::as_const(q->children())) {
13794 QWidget *w = qobject_cast<QWidget *>(object);
13795 if (w && w->focusProxy() == q) {
13796 lastFocusChild = w;
13797 break;
13798 }
13799 }
13800 } else if (q->isAncestorOf(focusProxy)) {
13801 lastFocusChild = focusProxy;
13802 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13803 focusNext != focusProxy && q->isAncestorOf(focusNext)
13804 && focusNext->window() == focusProxy->window();
13805 focusNext = focusNext->nextInFocusChain()) {
13806 if (focusNext == noFurtherThan)
13807 break;
13808 if (focusNext->focusPolicy() != Qt::NoFocus)
13809 lastFocusChild = focusNext;
13810 }
13811 }
13812 return lastFocusChild;
13813};
13814
13815/*!
13816 \internal
13817 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13818 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13819 are pointing to the widget itself.
13820
13821 \note
13822 This method doesn't check the consistency of the focus chain.
13823 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13824 isInFocusChain() will return \c true for all of those widgets, even if they represent
13825 an inconsistent focus chain.
13826 */
13827bool QWidgetPrivate::isInFocusChain() const
13828{
13829 Q_Q(const QWidget);
13830 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13831}
13832
13833/*!
13834 \internal
13835 A focus chain is consistent, when it is circular: Following the chain in either direction
13836 has to return to the beginning. This is why a newly constructed widget points to itself,
13837 when the focus chain has been initialized. A newly constructed widget is considered to have
13838 a consistent focus chain, while not being part of a focus chain.
13839
13840 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13841 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13842 It returns \c false, if one of the following is detected:
13843 \list
13844 \li nullptr found in a previous/next pointer.
13845 \li broken chain: widget A is B's previous, but B isn't A's next.
13846 \li chain isn't closed: starting at A doesn't lead back to A.
13847 \endlist
13848 It return \c true, if none of the above is observed.
13849
13850 \note
13851 The focus chain is checked only in forward direction.
13852 This is sufficient, because the check for a broken chain asserts consistent paths
13853 in both directions.
13854 */
13855bool QWidgetPrivate::isFocusChainConsistent() const
13856{
13857 Q_Q(const QWidget);
13858 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13859 if (skip)
13860 return true;
13861
13862 if (!isInFocusChain())
13863 return true;
13864
13865 const QWidget *position = q;
13866
13867 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13868 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13869 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13870 << "Previous pointing to" << FOCUS_PREV(position)
13871 << "Next pointing to" << FOCUS_NEXT(position);
13872 return false;
13873 }
13874 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13875 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13876 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13877 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13878 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13879 return false;
13880 }
13881 position = FOCUS_NEXT(position);
13882 if (position == q)
13883 return true;
13884
13885 }
13886
13887 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13888 return false;
13889}
13890
13891#undef FOCUS_NEXT
13892#undef FOCUS_PREV
13893
13894
13895QT_END_NAMESPACE
13896
13897#include "moc_qwidget.cpp"
13898#include "moc_qwidget_p.cpp"
friend class QWidgetPrivate
friend class QWidget
Definition qpainter.h:431
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
void qt_qpa_set_cursor(QWidget *w, bool force)
Definition qwidget.cpp:5073
#define qApp
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
static bool canMapPosition(QWindow *window)
static void unsetCursor(QWidget *w)
Definition qwidget.cpp:5067
void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
Definition qwidget.cpp:1265
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:6051
static void sendResizeEvents(QWidget *target)
Definition qwidget.cpp:5247
static void applyCursor(QWidget *w, const QCursor &c)
Definition qwidget.cpp:5061
#define FOCUS_PREV(w)
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6695
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:2339
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:1134
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:2258
static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1108
#define QWIDGETSIZE_MAX
Definition qwidget.h:922
static void cleanup(QWidget *that, QWidgetPrivate *d)
Definition qwidget.cpp:822