1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtWidgets module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qapplication.h"
42#include "qapplication_p.h"
43#include "qbrush.h"
44#include "qcursor.h"
45#include "qevent.h"
46#include "qlayout.h"
47#if QT_CONFIG(menu)
48#include "qmenu.h"
49#endif
50#include "qmetaobject.h"
51#include "qpixmap.h"
52#include "qpointer.h"
53#include "qstack.h"
54#include "qstyle.h"
55#include "qstylefactory.h"
56#include "qvariant.h"
57#include "qwidget.h"
58#include "qstyleoption.h"
59#include "qstylehints.h"
60#ifndef QT_NO_ACCESSIBILITY
61# include "qaccessible.h"
62#endif
63#include <qpa/qplatformwindow.h>
64#include <qpa/qplatformwindow_p.h>
65#include "private/qwidgetwindow_p.h"
66#include "qpainter.h"
67#if QT_CONFIG(tooltip)
68#include "qtooltip.h"
69#endif
70#if QT_CONFIG(whatsthis)
71#include "qwhatsthis.h"
72#endif
73#include "qdebug.h"
74#include "private/qstylesheetstyle_p.h"
75#include "private/qstyle_p.h"
76#include "qfileinfo.h"
77#include "qscopeguard.h"
78#include <QtGui/private/qhighdpiscaling_p.h>
79#include <QtGui/qinputmethod.h>
80#include <QtGui/qopenglcontext.h>
81#include <QtGui/private/qopenglcontext_p.h>
82#include <QtGui/qoffscreensurface.h>
83
84#if QT_CONFIG(graphicseffect)
85#include <private/qgraphicseffect_p.h>
86#endif
87#include <qbackingstore.h>
88#include <private/qwidgetrepaintmanager_p.h>
89#include <private/qpaintengine_raster_p.h>
90
91#include "qwidget_p.h"
92#include <QtGui/private/qwindow_p.h>
93#if QT_CONFIG(action)
94# include "QtGui/private/qaction_p.h"
95#endif
96#include "qlayout_p.h"
97#if QT_CONFIG(graphicsview)
98#include "QtWidgets/qgraphicsproxywidget.h"
99#include "QtWidgets/qgraphicsscene.h"
100#include "private/qgraphicsproxywidget_p.h"
101#endif
102#include "QtWidgets/qabstractscrollarea.h"
103#include "private/qabstractscrollarea_p.h"
104#include "private/qevent_p.h"
105
106#include "private/qgesturemanager_p.h"
107
108#ifdef QT_KEYPAD_NAVIGATION
109#if QT_CONFIG(tabwidget)
110#include "qtabwidget.h" // Needed in inTabWidget()
111#endif
112#endif // QT_KEYPAD_NAVIGATION
113
114#include "qwindowcontainer_p.h"
115
116#include <private/qmemory_p.h>
117
118// widget/widget data creation count
119//#define QWIDGET_EXTRA_DEBUG
120//#define ALIEN_DEBUG
121
122QT_BEGIN_NAMESPACE
123
124using namespace QNativeInterface::Private;
125
126Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
127
128static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
129{
130 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
131 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
132}
133
134extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
135
136QWidgetPrivate::QWidgetPrivate(int version)
137 : QObjectPrivate(version)
138 , focus_next(nullptr)
139 , focus_prev(nullptr)
140 , focus_child(nullptr)
141 , layout(nullptr)
142 , needsFlush(nullptr)
143 , redirectDev(nullptr)
144 , widgetItem(nullptr)
145 , extraPaintEngine(nullptr)
146 , polished(nullptr)
147 , graphicsEffect(nullptr)
148#if !defined(QT_NO_IM)
149 , imHints(Qt::ImhNone)
150#endif
151#if QT_CONFIG(tooltip)
152 , toolTipDuration(-1)
153#endif
154 , directFontResolveMask(0)
155 , inheritedFontResolveMask(0)
156 , directPaletteResolveMask(0)
157 , inheritedPaletteResolveMask(0)
158 , leftmargin(0)
159 , topmargin(0)
160 , rightmargin(0)
161 , bottommargin(0)
162 , leftLayoutItemMargin(0)
163 , topLayoutItemMargin(0)
164 , rightLayoutItemMargin(0)
165 , bottomLayoutItemMargin(0)
166 , hd(nullptr)
167 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
168 , fg_role(QPalette::NoRole)
169 , bg_role(QPalette::NoRole)
170 , dirtyOpaqueChildren(1)
171 , isOpaque(0)
172 , retainSizeWhenHiddenChanged(0)
173 , inDirtyList(0)
174 , isScrolled(0)
175 , isMoved(0)
176 , usesDoubleBufferedGLContext(0)
177 , mustHaveWindowHandle(0)
178 , renderToTexture(0)
179 , textureChildSeen(0)
180#ifndef QT_NO_IM
181 , inheritsInputMethodHints(0)
182#endif
183#ifndef QT_NO_OPENGL
184 , renderToTextureReallyDirty(1)
185 , renderToTextureComposeActive(0)
186#endif
187 , childrenHiddenByWState(0)
188 , childrenShownByExpose(0)
189#if defined(Q_OS_WIN)
190 , noPaintOnScreen(0)
191#endif
192{
193 if (Q_UNLIKELY(!qApp)) {
194 qFatal("QWidget: Must construct a QApplication before a QWidget");
195 return;
196 }
197
198#ifdef QT_BUILD_INTERNAL
199 // Don't check the version parameter in internal builds.
200 // This allows incompatible versions to be loaded, possibly for testing.
201 Q_UNUSED(version);
202#else
203 if (Q_UNLIKELY(version != QObjectPrivateVersion))
204 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
205 version, QObjectPrivateVersion);
206#endif
207
208 isWidget = true;
209 memset(high_attributes, 0, sizeof(high_attributes));
210
211#ifdef QWIDGET_EXTRA_DEBUG
212 static int count = 0;
213 qDebug() << "widgets" << ++count;
214#endif
215}
216
217
218QWidgetPrivate::~QWidgetPrivate()
219{
220 if (widgetItem)
221 widgetItem->wid = nullptr;
222
223 if (extra)
224 deleteExtra();
225}
226
227/*!
228 \internal
229*/
230void QWidgetPrivate::scrollChildren(int dx, int dy)
231{
232 Q_Q(QWidget);
233 if (q->children().size() > 0) { // scroll children
234 QPoint pd(dx, dy);
235 QObjectList childObjects = q->children();
236 for (int i = 0; i < childObjects.size(); ++i) { // move all children
237 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
238 if (w && !w->isWindow()) {
239 QPoint oldp = w->pos();
240 QRect r(w->pos() + pd, w->size());
241 w->data->crect = r;
242 if (w->testAttribute(Qt::WA_WState_Created))
243 w->d_func()->setWSGeometry();
244 w->d_func()->setDirtyOpaqueRegion();
245 QMoveEvent e(r.topLeft(), oldp);
246 QCoreApplication::sendEvent(w, &e);
247 }
248 }
249 }
250}
251
252void QWidgetPrivate::setWSGeometry()
253{
254 Q_Q(QWidget);
255 if (QWindow *window = q->windowHandle())
256 window->setGeometry(data.crect);
257}
258
259void QWidgetPrivate::updateWidgetTransform(QEvent *event)
260{
261 Q_Q(QWidget);
262 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
263 QTransform t;
264 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
265 t.translate(p.x(), p.y());
266 QGuiApplication::inputMethod()->setInputItemTransform(t);
267 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
268 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
269 }
270}
271
272#ifdef QT_KEYPAD_NAVIGATION
273QPointer<QWidget> QWidgetPrivate::editingWidget;
274
275/*!
276 Returns \c true if this widget currently has edit focus; otherwise false.
277
278 This feature is only available in Qt for Embedded Linux.
279
280 \sa setEditFocus(), QApplication::navigationMode()
281*/
282bool QWidget::hasEditFocus() const
283{
284 const QWidget* w = this;
285 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
286 w = w->d_func()->extra->focus_proxy;
287 return QWidgetPrivate::editingWidget == w;
288}
289
290/*!
291 \fn void QWidget::setEditFocus(bool enable)
292
293 If \a enable is true, make this widget have edit focus, in which
294 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
295 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
296 change focus.
297
298 This feature is only available in Qt for Embedded Linux.
299
300 \sa hasEditFocus(), QApplication::navigationMode()
301*/
302void QWidget::setEditFocus(bool on)
303{
304 QWidget *f = this;
305 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
306 f = f->d_func()->extra->focus_proxy;
307
308 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
309 QWidgetPrivate::editingWidget->setEditFocus(false);
310
311 if (on && !f->hasFocus())
312 f->setFocus();
313
314 if ((!on && !QWidgetPrivate::editingWidget)
315 || (on && QWidgetPrivate::editingWidget == f)) {
316 return;
317 }
318
319 if (!on && QWidgetPrivate::editingWidget == f) {
320 QWidgetPrivate::editingWidget = 0;
321 QEvent event(QEvent::LeaveEditFocus);
322 QCoreApplication::sendEvent(f, &event);
323 QCoreApplication::sendEvent(f->style(), &event);
324 } else if (on) {
325 QWidgetPrivate::editingWidget = f;
326 QEvent event(QEvent::EnterEditFocus);
327 QCoreApplication::sendEvent(f, &event);
328 QCoreApplication::sendEvent(f->style(), &event);
329 }
330}
331#endif
332
333/*!
334 \property QWidget::autoFillBackground
335 \brief whether the widget background is filled automatically
336 \since 4.1
337
338 If enabled, this property will cause Qt to fill the background of the
339 widget before invoking the paint event. The color used is defined by the
340 QPalette::Window color role from the widget's \l{QPalette}{palette}.
341
342 In addition, Windows are always filled with QPalette::Window, unless the
343 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
344
345 This property cannot be turned off (i.e., set to false) if a widget's
346 parent has a static gradient for its background.
347
348 \warning Use this property with caution in conjunction with
349 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
350 background or a border-image, this property is automatically disabled.
351
352 By default, this property is \c false.
353
354 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
355 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
356*/
357bool QWidget::autoFillBackground() const
358{
359 Q_D(const QWidget);
360 return d->extra && d->extra->autoFillBackground;
361}
362
363void QWidget::setAutoFillBackground(bool enabled)
364{
365 Q_D(QWidget);
366 if (!d->extra)
367 d->createExtra();
368 if (d->extra->autoFillBackground == enabled)
369 return;
370
371 d->extra->autoFillBackground = enabled;
372 d->updateIsOpaque();
373 update();
374 d->updateIsOpaque();
375}
376
377/*!
378 \class QWidget
379 \brief The QWidget class is the base class of all user interface objects.
380
381 \ingroup basicwidgets
382 \inmodule QtWidgets
383
384 The widget is the atom of the user interface: it receives mouse, keyboard
385 and other events from the window system, and paints a representation of
386 itself on the screen. Every widget is rectangular, and they are sorted in a
387 Z-order. A widget is clipped by its parent and by the widgets in front of
388 it.
389
390 A widget that is not embedded in a parent widget is called a window.
391 Usually, windows have a frame and a title bar, although it is also possible
392 to create windows without such decoration using suitable
393 \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
394 subclasses of QDialog are the most common window types.
395
396 Every widget's constructor accepts one or two standard arguments:
397
398 \list 1
399 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
400 If it is \nullptr (the default), the new widget will be a window.
401 If not, it will be a child of \e parent, and be constrained by
402 \e parent's geometry (unless you specify Qt::Window as window flag).
403 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
404 the default is suitable for almost all widgets, but to get, for
405 example, a window without a window system frame, you must use
406 special flags.
407 \endlist
408
409 QWidget has many member functions, but some of them have little direct
410 functionality; for example, QWidget has a font property, but never uses
411 this itself. There are many subclasses which provide real functionality,
412 such as QLabel, QPushButton, QListWidget, and QTabWidget.
413
414
415 \section1 Top-Level and Child Widgets
416
417 A widget without a parent widget is always an independent window (top-level
418 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
419 title bar and icon respectively.
420
421 Non-window widgets are child widgets, displayed within their parent
422 widgets. Most widgets in Qt are mainly useful as child widgets. For
423 example, it is possible to display a button as a top-level window, but most
424 people prefer to put their buttons inside other widgets, such as QDialog.
425
426 \image parent-child-widgets.png A parent widget containing various child widgets.
427
428 The diagram above shows a QGroupBox widget being used to hold various child
429 widgets in a layout provided by QGridLayout. The QLabel child widgets have
430 been outlined to indicate their full sizes.
431
432 If you want to use a QWidget to hold child widgets you will usually want to
433 add a layout to the parent QWidget. See \l{Layout Management} for more
434 information.
435
436
437 \section1 Composite Widgets
438
439 When a widget is used as a container to group a number of child widgets, it
440 is known as a composite widget. These can be created by constructing a
441 widget with the required visual properties - a QFrame, for example - and
442 adding child widgets to it, usually managed by a layout. The above diagram
443 shows such a composite widget that was created using Qt Designer.
444
445 Composite widgets can also be created by subclassing a standard widget,
446 such as QWidget or QFrame, and adding the necessary layout and child
447 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
448 {examples provided with Qt} use this approach, and it is also covered in
449 the Qt \l{Tutorials}.
450
451
452 \section1 Custom Widgets and Painting
453
454 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
455 display custom content that is composed using a series of painting
456 operations with an instance of the QPainter class. This approach contrasts
457 with the canvas-style approach used by the \l{Graphics View}
458 {Graphics View Framework} where items are added to a scene by the
459 application and are rendered by the framework itself.
460
461 Each widget performs all painting operations from within its paintEvent()
462 function. This is called whenever the widget needs to be redrawn, either
463 as a result of some external change or when requested by the application.
464
465 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
466 can handle paint events.
467
468
469 \section1 Size Hints and Size Policies
470
471 When implementing a new widget, it is almost always useful to reimplement
472 sizeHint() to provide a reasonable default size for the widget and to set
473 the correct size policy with setSizePolicy().
474
475 By default, composite widgets which do not provide a size hint will be
476 sized according to the space requirements of their child widgets.
477
478 The size policy lets you supply good default behavior for the layout
479 management system, so that other widgets can contain and manage yours
480 easily. The default size policy indicates that the size hint represents
481 the preferred size of the widget, and this is often good enough for many
482 widgets.
483
484 \note The size of top-level widgets are constrained to 2/3 of the desktop's
485 height and width. You can resize() the widget manually if these bounds are
486 inadequate.
487
488
489 \section1 Events
490
491 Widgets respond to events that are typically caused by user actions. Qt
492 delivers events to widgets by calling specific event handler functions with
493 instances of QEvent subclasses containing information about each event.
494
495 If your widget only contains child widgets, you probably do not need to
496 implement any event handlers. If you want to detect a mouse click in a
497 child widget call the child's underMouse() function inside the widget's
498 mousePressEvent().
499
500 The \l{widgets/scribble}{Scribble example} implements a wider set of
501 events to handle mouse movement, button presses, and window resizing.
502
503 You will need to supply the behavior and content for your own widgets, but
504 here is a brief overview of the events that are relevant to QWidget,
505 starting with the most common ones:
506
507 \list
508 \li paintEvent() is called whenever the widget needs to be repainted.
509 Every widget displaying custom content must implement it. Painting
510 using a QPainter can only take place in a paintEvent() or a
511 function called by a paintEvent().
512 \li resizeEvent() is called when the widget has been resized.
513 \li mousePressEvent() is called when a mouse button is pressed while
514 the mouse cursor is inside the widget, or when the widget has
515 grabbed the mouse using grabMouse(). Pressing the mouse without
516 releasing it is effectively the same as calling grabMouse().
517 \li mouseReleaseEvent() is called when a mouse button is released. A
518 widget receives mouse release events when it has received the
519 corresponding mouse press event. This means that if the user
520 presses the mouse inside \e your widget, then drags the mouse
521 somewhere else before releasing the mouse button, \e your widget
522 receives the release event. There is one exception: if a popup menu
523 appears while the mouse button is held down, this popup immediately
524 steals the mouse events.
525 \li mouseDoubleClickEvent() is called when the user double-clicks in
526 the widget. If the user double-clicks, the widget receives a mouse
527 press event, a mouse release event, (a mouse click event,) a second
528 mouse press, this event and finally a second mouse release event.
529 (Some mouse move events may also be
530 received if the mouse is not held steady during this operation.) It
531 is \e{not possible} to distinguish a click from a double-click
532 until the second click arrives. (This is one reason why most GUI
533 books recommend that double-clicks be an extension of
534 single-clicks, rather than trigger a different action.)
535 \endlist
536
537 Widgets that accept keyboard input need to reimplement a few more event
538 handlers:
539
540 \list
541 \li keyPressEvent() is called whenever a key is pressed, and again when
542 a key has been held down long enough for it to auto-repeat. The
543 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
544 they are not used by the focus-change mechanisms. To force those
545 keys to be processed by your widget, you must reimplement
546 QWidget::event().
547 \li focusInEvent() is called when the widget gains keyboard focus
548 (assuming you have called setFocusPolicy()). Well-behaved widgets
549 indicate that they own the keyboard focus in a clear but discreet
550 way.
551 \li focusOutEvent() is called when the widget loses keyboard focus.
552 \endlist
553
554 You may be required to also reimplement some of the less common event
555 handlers:
556
557 \list
558 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
559 button is held down. This can be useful during drag and drop
560 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
561 you get mouse move events even when no buttons are held down.
562 (See also the \l{Drag and Drop} guide.)
563 \li keyReleaseEvent() is called whenever a key is released and while it
564 is held down (if the key is auto-repeating). In that case, the
565 widget will receive a pair of key release and key press event for
566 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
567 to the widget if they are not used by the focus-change mechanisms.
568 To force those keys to be processed by your widget, you must
569 reimplement QWidget::event().
570 \li wheelEvent() is called whenever the user turns the mouse wheel
571 while the widget has the focus.
572 \li enterEvent() is called when the mouse enters the widget's screen
573 space. (This excludes screen space owned by any of the widget's
574 children.)
575 \li leaveEvent() is called when the mouse leaves the widget's screen
576 space. If the mouse enters a child widget it will not cause a
577 leaveEvent().
578 \li moveEvent() is called when the widget has been moved relative to
579 its parent.
580 \li closeEvent() is called when the user closes the widget (or when
581 close() is called).
582 \endlist
583
584 There are also some rather obscure events described in the documentation
585 for QEvent::Type. To handle these events, you need to reimplement event()
586 directly.
587
588 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
589 (to move the keyboard focus), and passes on most of the other events to
590 one of the more specialized handlers above.
591
592 Events and the mechanism used to deliver them are covered in
593 \l{The Event System}.
594
595 \section1 Groups of Functions and Properties
596
597 \table
598 \header \li Context \li Functions and Properties
599
600 \row \li Window functions \li
601 show(),
602 hide(),
603 raise(),
604 lower(),
605 close().
606
607 \row \li Top-level windows \li
608 \l windowModified, \l windowTitle, \l windowIcon,
609 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
610 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
611 showNormal().
612
613 \row \li Window contents \li
614 update(),
615 repaint(),
616 scroll().
617
618 \row \li Geometry \li
619 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
620 \l sizePolicy, sizeHint(), minimumSizeHint(),
621 updateGeometry(), layout(),
622 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
623 adjustSize(),
624 mapFromGlobal(), mapToGlobal(),
625 mapFromParent(), mapToParent(),
626 \l maximumSize, \l minimumSize, \l sizeIncrement,
627 \l baseSize, setFixedSize()
628
629 \row \li Mode \li
630 \l visible, isVisibleTo(),
631 \l enabled, isEnabledTo(),
632 \l modal,
633 isWindow(),
634 \l mouseTracking,
635 \l updatesEnabled,
636 visibleRegion().
637
638 \row \li Look and feel \li
639 style(),
640 setStyle(),
641 \l styleSheet,
642 \l cursor,
643 \l font,
644 \l palette,
645 backgroundRole(), setBackgroundRole(),
646 fontInfo(), fontMetrics().
647
648 \row \li Keyboard focus functions \li
649 \l focus, \l focusPolicy,
650 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
651 focusNextChild(), focusPreviousChild().
652
653 \row \li Mouse and keyboard grabbing \li
654 grabMouse(), releaseMouse(),
655 grabKeyboard(), releaseKeyboard(),
656 mouseGrabber(), keyboardGrabber().
657
658 \row \li Event handlers \li
659 event(),
660 mousePressEvent(),
661 mouseReleaseEvent(),
662 mouseDoubleClickEvent(),
663 mouseMoveEvent(),
664 keyPressEvent(),
665 keyReleaseEvent(),
666 focusInEvent(),
667 focusOutEvent(),
668 wheelEvent(),
669 enterEvent(),
670 leaveEvent(),
671 paintEvent(),
672 moveEvent(),
673 resizeEvent(),
674 closeEvent(),
675 dragEnterEvent(),
676 dragMoveEvent(),
677 dragLeaveEvent(),
678 dropEvent(),
679 childEvent(),
680 showEvent(),
681 hideEvent(),
682 customEvent().
683 changeEvent(),
684
685 \row \li System functions \li
686 parentWidget(), window(), setParent(), winId(),
687 find(), metric().
688
689 \row \li Context menu \li
690 contextMenuPolicy, contextMenuEvent(),
691 customContextMenuRequested(), actions()
692
693 \row \li Interactive help \li
694 setToolTip(), setWhatsThis()
695
696 \endtable
697
698
699 \section1 Widget Style Sheets
700
701 In addition to the standard widget styles for each platform, widgets can
702 also be styled according to rules specified in a \l{styleSheet}
703 {style sheet}. This feature enables you to customize the appearance of
704 specific widgets to provide visual cues to users about their purpose. For
705 example, a button could be styled in a particular way to indicate that it
706 performs a destructive action.
707
708 The use of widget style sheets is described in more detail in the
709 \l{Qt Style Sheets} document.
710
711
712 \section1 Transparency and Double Buffering
713
714 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
715 is no need to write double-buffering code in paintEvent() to avoid
716 flicker.
717
718 Since Qt 4.1, the contents of parent widgets are propagated by
719 default to each of their children as long as Qt::WA_PaintOnScreen is not
720 set. Custom widgets can be written to take advantage of this feature by
721 updating irregular regions (to create non-rectangular child widgets), or
722 painting with colors that have less than full alpha component. The
723 following diagram shows how attributes and properties of a custom widget
724 can be fine-tuned to achieve different effects.
725
726 \image propagation-custom.png
727
728 In the above diagram, a semi-transparent rectangular child widget with an
729 area removed is constructed and added to a parent widget (a QLabel showing
730 a pixmap). Then, different properties and widget attributes are set to
731 achieve different effects:
732
733 \list
734 \li The left widget has no additional properties or widget attributes
735 set. This default state suits most custom widgets using
736 transparency, are irregularly-shaped, or do not paint over their
737 entire area with an opaque brush.
738 \li The center widget has the \l autoFillBackground property set. This
739 property is used with custom widgets that rely on the widget to
740 supply a default background, and do not paint over their entire
741 area with an opaque brush.
742 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
743 set. This indicates that the widget will paint over its entire area
744 with opaque colors. The widget's area will initially be
745 \e{uninitialized}, represented in the diagram with a red diagonal
746 grid pattern that shines through the overpainted area. The
747 Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
748 paint their own specialized contents quickly and do not need a
749 default filled background.
750 \endlist
751
752 To rapidly update custom widgets with simple background colors, such as
753 real-time plotting or graphing widgets, it is better to define a suitable
754 background color (using setBackgroundRole() with the
755 QPalette::Window role), set the \l autoFillBackground property, and only
756 implement the necessary drawing functionality in the widget's paintEvent().
757
758 To rapidly update custom widgets that constantly paint over their entire
759 areas with opaque content, e.g., video streaming widgets, it is better to
760 set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
761 associated with repainting the widget's background.
762
763 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
764 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
765 attribute takes precedence. Depending on your requirements, you should
766 choose either one of them.
767
768 Since Qt 4.1, the contents of parent widgets are also propagated to
769 standard Qt widgets. This can lead to some unexpected results if the
770 parent widget is decorated in a non-standard way, as shown in the diagram
771 below.
772
773 \image propagation-standard.png
774
775 The scope for customizing the painting behavior of standard Qt widgets,
776 without resorting to subclassing, is slightly less than that possible for
777 custom widgets. Usually, the desired appearance of a standard widget can be
778 achieved by setting its \l autoFillBackground property.
779
780
781 \section1 Creating Translucent Windows
782
783 Since Qt 4.5, it has been possible to create windows with translucent regions
784 on window systems that support compositing.
785
786 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
787 attribute with setAttribute() and ensure that its background is painted with
788 non-opaque colors in the regions you want to be partially transparent.
789
790 Platform notes:
791
792 \list
793 \li X11: This feature relies on the use of an X server that supports ARGB visuals
794 and a compositing window manager.
795 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
796 for the translucency to work.
797 \endlist
798
799
800 \section1 Native Widgets vs Alien Widgets
801
802 Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
803 system. They do not have a native window handle associated with them. This
804 feature significantly speeds up widget painting, resizing, and removes flicker.
805
806 Should you require the old behavior with native windows, you can choose
807 one of the following options:
808
809 \list 1
810 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
811 \li Set the Qt::AA_NativeWindows attribute on your application. All
812 widgets will be native widgets.
813 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
814 and all of its ancestors will become native (unless
815 Qt::WA_DontCreateNativeAncestors is set).
816 \li Call QWidget::winId to enforce a native window (this implies 3).
817 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
818 (this implies 3).
819 \endlist
820
821 \sa QEvent, QPainter, QGridLayout, QBoxLayout
822
823*/
824
825QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
826QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
827
828
829/*****************************************************************************
830 QWidget member functions
831 *****************************************************************************/
832
833/*
834 Widget state flags:
835 \list
836 \li Qt::WA_WState_Created The widget has a valid winId().
837 \li Qt::WA_WState_Visible The widget is currently visible.
838 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
839 become visible unless you call show() on it. Qt::WA_WState_Hidden
840 implies !Qt::WA_WState_Visible.
841 \li Qt::WA_WState_CompressKeys Compress keyboard events.
842 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
843 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
844 \li Qt::WA_WState_Reparented The widget has been reparented.
845 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
846 \endlist
847*/
848
849struct QWidgetExceptionCleaner
850{
851 /* this cleans up when the constructor throws an exception */
852 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
853 {
854#ifdef QT_NO_EXCEPTIONS
855 Q_UNUSED(that);
856 Q_UNUSED(d);
857#else
858 QWidgetPrivate::allWidgets->remove(that);
859 if (d->focus_next != that) {
860 if (d->focus_next)
861 d->focus_next->d_func()->focus_prev = d->focus_prev;
862 if (d->focus_prev)
863 d->focus_prev->d_func()->focus_next = d->focus_next;
864 }
865#endif
866 }
867};
868
869/*!
870 Constructs a widget which is a child of \a parent, with widget
871 flags set to \a f.
872
873 If \a parent is \nullptr, the new widget becomes a window. If
874 \a parent is another widget, this widget becomes a child window
875 inside \a parent. The new widget is deleted when its \a parent is
876 deleted.
877
878 The widget flags argument, \a f, is normally 0, but it can be set
879 to customize the frame of a window (i.e. \a parent must be
880 \nullptr). To customize the frame, use a value composed
881 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
882
883 If you add a child widget to an already visible widget you must
884 explicitly show the child to make it visible.
885
886 Note that the X11 version of Qt may not be able to deliver all
887 combinations of style flags on all systems. This is because on
888 X11, Qt can only ask the window manager, and the window manager
889 can override the application's settings. On Windows, Qt can set
890 whatever flags you want.
891
892 \sa windowFlags
893*/
894QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
895 : QObject(*new QWidgetPrivate, nullptr), QPaintDevice()
896{
897 QT_TRY {
898 d_func()->init(parent, f);
899 } QT_CATCH(...) {
900 QWidgetExceptionCleaner::cleanup(this, d_func());
901 QT_RETHROW;
902 }
903}
904
905
906/*! \internal
907*/
908QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
909 : QObject(dd, nullptr), QPaintDevice()
910{
911 Q_D(QWidget);
912 QT_TRY {
913 d->init(parent, f);
914 } QT_CATCH(...) {
915 QWidgetExceptionCleaner::cleanup(this, d_func());
916 QT_RETHROW;
917 }
918}
919
920/*!
921 \internal
922*/
923int QWidget::devType() const
924{
925 return QInternal::Widget;
926}
927
928
929//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
930void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
931{
932 bool customize = (flags & (Qt::CustomizeWindowHint
933 | Qt::FramelessWindowHint
934 | Qt::WindowTitleHint
935 | Qt::WindowSystemMenuHint
936 | Qt::WindowMinimizeButtonHint
937 | Qt::WindowMaximizeButtonHint
938 | Qt::WindowCloseButtonHint
939 | Qt::WindowContextHelpButtonHint));
940
941 uint type = (flags & Qt::WindowType_Mask);
942
943 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
944 type = Qt::Window;
945 flags |= Qt::Window;
946 }
947
948 if (flags & Qt::CustomizeWindowHint) {
949 // modify window flags to make them consistent.
950 // Only enable this on non-Mac platforms. Since the old way of doing this would
951 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
952 // we can't just add this in.
953 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
954# ifdef Q_OS_WIN
955 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
956# endif
957 ) {
958 flags |= Qt::WindowSystemMenuHint;
959 flags |= Qt::WindowTitleHint;
960 flags &= ~Qt::FramelessWindowHint;
961 }
962 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
963 // if any of the window hints that affect the titlebar are set
964 // and the window is supposed to have frame, we add a titlebar
965 // and system menu by default.
966 flags |= Qt::WindowSystemMenuHint;
967 flags |= Qt::WindowTitleHint;
968 }
969 if (!customize) { // don't modify window flags if the user explicitly set them.
970 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
971 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
972 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
973 }
974 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
975 flags |= Qt::WindowTransparentForInput;
976}
977
978void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
979{
980 Q_Q(QWidget);
981 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
982
983 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
984 qFatal("QWidget: Cannot create a QWidget without QApplication");
985
986 Q_ASSERT(allWidgets);
987 if (allWidgets)
988 allWidgets->insert(q);
989
990 q->data = &data;
991
992#if QT_CONFIG(thread)
993 if (!parent) {
994 Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
995 "Widgets must be created in the GUI thread.");
996 }
997#endif
998
999 data.fstrut_dirty = true;
1000
1001 data.winid = 0;
1002 data.widget_attributes = 0;
1003 data.window_flags = f;
1004 data.window_state = 0;
1005 data.focus_policy = 0;
1006 data.context_menu_policy = Qt::DefaultContextMenu;
1007 data.window_modality = Qt::NonModal;
1008
1009 data.sizehint_forced = 0;
1010 data.is_closing = 0;
1011 data.in_show = 0;
1012 data.in_set_window_state = 0;
1013 data.in_destructor = false;
1014
1015 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
1016 if (f & Qt::MSWindowsOwnDC) {
1017 mustHaveWindowHandle = 1;
1018 q->setAttribute(Qt::WA_NativeWindow);
1019 }
1020
1021 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
1022 adjustQuitOnCloseAttribute();
1023
1024 q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
1025 q->setAttribute(Qt::WA_WState_Hidden);
1026
1027 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
1028 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
1029 focus_next = focus_prev = q;
1030
1031 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
1032 q->create();
1033 else if (parentWidget)
1034 q->setParent(parentWidget, data.window_flags);
1035 else {
1036 adjustFlags(data.window_flags, q);
1037 resolveLayoutDirection();
1038 // opaque system background?
1039 const QBrush &background = q->palette().brush(QPalette::Window);
1040 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1041 }
1042 data.fnt = QFont(data.fnt, q);
1043
1044 q->setAttribute(Qt::WA_PendingMoveEvent);
1045 q->setAttribute(Qt::WA_PendingResizeEvent);
1046
1047 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1048 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1049
1050 QEvent e(QEvent::Create);
1051 QCoreApplication::sendEvent(q, &e);
1052 QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1053
1054 extraPaintEngine = nullptr;
1055}
1056
1057void QWidgetPrivate::createRecursively()
1058{
1059 Q_Q(QWidget);
1060 q->create(0, true, true);
1061 for (int i = 0; i < children.size(); ++i) {
1062 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1063 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1064 child->d_func()->createRecursively();
1065 }
1066}
1067
1068QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1069{
1070 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1071 if (QTLWExtra *x = maybeTopData()) {
1072 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1073 return x->window;
1074 }
1075 }
1076 if (mode == WindowHandleMode::Closest) {
1077 if (auto nativeParent = q_func()->nativeParentWidget()) {
1078 if (auto window = nativeParent->windowHandle())
1079 return window;
1080 }
1081 }
1082 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1083 if (auto topLevel = q_func()->topLevelWidget()) {
1084 if (auto window = topLevel ->windowHandle())
1085 return window;
1086 }
1087 }
1088 return nullptr;
1089}
1090
1091/*!
1092 \internal
1093
1094 Used by clients outside of widgets to get a handle to the
1095 closest QWindow without having to link to widgets.
1096*/
1097QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1098{
1099 return windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
1100}
1101
1102QScreen *QWidgetPrivate::associatedScreen() const
1103{
1104 if (auto window = windowHandle(WindowHandleMode::Closest))
1105 return window->screen();
1106 return nullptr;
1107}
1108
1109// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1110
1111/*!
1112 Creates a new widget window.
1113
1114 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1115 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1116 QWindow wrapping a foreign window and pass it to
1117 QWidget::createWindowContainer() instead.
1118
1119 \sa createWindowContainer(), QWindow::fromWinId()
1120*/
1121
1122void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1123{
1124 Q_UNUSED(initializeWindow);
1125 Q_UNUSED(destroyOldWindow);
1126
1127 Q_D(QWidget);
1128 if (Q_UNLIKELY(window))
1129 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1130 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1131 return;
1132
1133 if (d->data.in_destructor)
1134 return;
1135
1136 Qt::WindowType type = windowType();
1137 Qt::WindowFlags &flags = data->window_flags;
1138
1139 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1140 type = Qt::Window;
1141 flags |= Qt::Window;
1142 }
1143
1144 if (QWidget *parent = parentWidget()) {
1145 if (type & Qt::Window) {
1146 if (!parent->testAttribute(Qt::WA_WState_Created))
1147 parent->createWinId();
1148 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1149 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1150 // We're about to create a native child widget that doesn't have a native parent;
1151 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1152 // attribute is set.
1153 d->createWinId();
1154 // Nothing more to do.
1155 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1156 Q_ASSERT(internalWinId());
1157 return;
1158 }
1159 }
1160
1161
1162 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1163 if (paintOnScreenEnv)
1164 setAttribute(Qt::WA_PaintOnScreen);
1165
1166 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1167 setAttribute(Qt::WA_NativeWindow);
1168
1169#ifdef ALIEN_DEBUG
1170 qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
1171 << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
1172#endif
1173
1174 d->updateIsOpaque();
1175
1176 setAttribute(Qt::WA_WState_Created); // set created flag
1177 d->create();
1178
1179 // A real toplevel window needs a paint manager
1180 if (isWindow() && windowType() != Qt::Desktop)
1181 d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1182
1183 d->setModal_sys();
1184
1185 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1186 setAttribute(Qt::WA_DropSiteRegistered, true);
1187
1188 // need to force the resting of the icon after changing parents
1189 if (testAttribute(Qt::WA_SetWindowIcon))
1190 d->setWindowIcon_sys();
1191
1192 if (isWindow() && !d->topData()->iconText.isEmpty())
1193 d->setWindowIconText_helper(d->topData()->iconText);
1194 if (isWindow() && !d->topData()->caption.isEmpty())
1195 d->setWindowTitle_helper(d->topData()->caption);
1196 if (isWindow() && !d->topData()->filePath.isEmpty())
1197 d->setWindowFilePath_helper(d->topData()->filePath);
1198 if (windowType() != Qt::Desktop) {
1199 d->updateSystemBackground();
1200
1201 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1202 d->setWindowIcon_sys();
1203 }
1204
1205 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1206 // as those force native window creation on their ancestors before they are shown.
1207 // If the strut is not updated, any subsequent move of the top level window before show
1208 // will cause window frame to be ignored when positioning the window.
1209 // Note that this only helps on platforms that handle window creation synchronously.
1210 d->updateFrameStrut();
1211}
1212
1213void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1214{
1215 QObjectList children = parentWidget->children();
1216 for (int i = 0; i < children.size(); i++) {
1217 if (children.at(i)->isWidgetType()) {
1218 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1219 if (childWidget) { // should not be necessary
1220 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1221 if (!childWidget->internalWinId())
1222 childWidget->winId();
1223 if (childWidget->windowHandle()) {
1224 if (childWidget->isWindow()) {
1225 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1226 } else {
1227 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1228 }
1229 }
1230 } else {
1231 q_createNativeChildrenAndSetParent(childWidget);
1232 }
1233 }
1234 }
1235 }
1236
1237}
1238
1239void QWidgetPrivate::create()
1240{
1241 Q_Q(QWidget);
1242
1243 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1244 return; // we only care about real toplevels
1245
1246 QWidgetWindow *win = topData()->window;
1247 // topData() ensures the extra is created but does not ensure 'window' is non-null
1248 // in case the extra was already valid.
1249 if (!win) {
1250 createTLSysExtra();
1251 win = topData()->window;
1252 }
1253
1254 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1255 for (const QByteArray &propertyName : dynamicPropertyNames) {
1256 if (!qstrncmp(propertyName, "_q_platform_", 12))
1257 win->setProperty(propertyName, q->property(propertyName));
1258 }
1259
1260 Qt::WindowFlags &flags = data.window_flags;
1261
1262#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
1263 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1264 flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1265#endif
1266
1267 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1268 win->setProperty("_q_showWithoutActivating", QVariant(true));
1269 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1270 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1271 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1272 win->setFlags(flags);
1273 fixPosIncludesFrame();
1274 if (q->testAttribute(Qt::WA_Moved)
1275 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1276 win->setGeometry(q->geometry());
1277 else
1278 win->resize(q->size());
1279 if (win->isTopLevel()) {
1280 QScreen *targetScreen = topData()->initialScreen;
1281 topData()->initialScreen = nullptr;
1282 if (!targetScreen) {
1283 targetScreen = q->windowType() != Qt::Desktop
1284 ? q->screen() : nullptr;
1285 }
1286 win->setScreen(targetScreen);
1287 }
1288
1289 QSurfaceFormat format = win->requestedFormat();
1290 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1291 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1292 format.setAlphaBufferSize(8);
1293 }
1294 win->setFormat(format);
1295
1296 if (QWidget *nativeParent = q->nativeParentWidget()) {
1297 if (nativeParent->windowHandle()) {
1298 if (flags & Qt::Window) {
1299 win->setTransientParent(nativeParent->window()->windowHandle());
1300 win->setParent(nullptr);
1301 } else {
1302 win->setTransientParent(nullptr);
1303 win->setParent(nativeParent->windowHandle());
1304 }
1305 }
1306 }
1307
1308 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1309 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1310
1311 if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
1312 win->create();
1313 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1314 if (QPlatformWindow *platformWindow = win->handle())
1315 platformWindow->setFrameStrutEventsEnabled(true);
1316 }
1317
1318 data.window_flags = win->flags();
1319 if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1320 data.window_flags &= ~Qt::ForeignWindow;
1321
1322#if QT_CONFIG(xcb)
1323 if (!topData()->role.isNull()) {
1324 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1325 xcbWindow->setWindowRole(topData()->role);
1326 }
1327#endif
1328
1329 QBackingStore *store = q->backingStore();
1330
1331 if (!store) {
1332 if (q->windowType() != Qt::Desktop) {
1333 if (q->isTopLevel())
1334 q->setBackingStore(new QBackingStore(win));
1335 } else {
1336 q->setAttribute(Qt::WA_PaintOnScreen, true);
1337 }
1338 }
1339
1340 setWindowModified_helper();
1341
1342 if (win->handle()) {
1343 WId id = win->winId();
1344 // See the QPlatformWindow::winId() documentation
1345 Q_ASSERT(id != WId(0));
1346 setWinId(id);
1347 }
1348
1349 // Check children and create windows for them if necessary
1350 q_createNativeChildrenAndSetParent(q);
1351
1352 if (extra && !extra->mask.isEmpty())
1353 setMask_sys(extra->mask);
1354
1355 if (data.crect.width() == 0 || data.crect.height() == 0) {
1356 q->setAttribute(Qt::WA_OutsideWSRange, true);
1357 } else if (q->isVisible()) {
1358 // If widget is already shown, set window visible, too
1359 win->setNativeWindowVisibility(true);
1360 }
1361}
1362
1363#ifdef Q_OS_WIN
1364static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1365#endif
1366
1367void QWidgetPrivate::createTLSysExtra()
1368{
1369 Q_Q(QWidget);
1370 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1371 extra->topextra->window = new QWidgetWindow(q);
1372 if (extra->minw || extra->minh)
1373 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1374 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1375 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1376 if (extra->topextra->opacity != 255 && q->isWindow())
1377 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1378
1379 const bool isTipLabel = q->inherits("QTipLabel");
1380 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1381#ifdef Q_OS_WIN
1382 // Pass on native parent handle for Widget embedded into Active X.
1383 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1384 if (activeXNativeParentHandle.isValid())
1385 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1386 if (isTipLabel || isAlphaWidget)
1387 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1388#endif
1389 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1390 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1391 }
1392
1393}
1394
1395/*!
1396 Destroys the widget.
1397
1398 All this widget's children are deleted first. The application
1399 exits if this widget is the main widget.
1400*/
1401
1402QWidget::~QWidget()
1403{
1404 Q_D(QWidget);
1405 d->data.in_destructor = true;
1406
1407#if defined (QT_CHECK_STATE)
1408 if (Q_UNLIKELY(paintingActive()))
1409 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1410#endif
1411
1412#ifndef QT_NO_GESTURES
1413 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1414 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1415 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1416 manager->cleanupCachedGestures(this, *it);
1417 }
1418 d->gestureContext.clear();
1419#endif
1420
1421#ifndef QT_NO_ACTION
1422 // remove all actions from this widget
1423 for (auto action : qAsConst(d->actions)) {
1424 QActionPrivate *apriv = action->d_func();
1425 apriv->associatedObjects.removeAll(this);
1426 }
1427 d->actions.clear();
1428#endif
1429
1430#ifndef QT_NO_SHORTCUT
1431 // Remove all shortcuts grabbed by this
1432 // widget, unless application is closing
1433 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1434 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1435#endif
1436
1437 // delete layout while we still are a valid widget
1438 delete d->layout;
1439 d->layout = nullptr;
1440 // Remove myself from focus list
1441
1442 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1443 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1444
1445 if (d->focus_next != this) {
1446 d->focus_next->d_func()->focus_prev = d->focus_prev;
1447 d->focus_prev->d_func()->focus_next = d->focus_next;
1448 d->focus_next = d->focus_prev = nullptr;
1449 }
1450
1451
1452 QT_TRY {
1453#if QT_CONFIG(graphicsview)
1454 const QWidget* w = this;
1455 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1456 w = w->d_func()->extra->focus_proxy;
1457 QWidget *window = w->window();
1458 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1459 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1460#endif
1461 clearFocus();
1462 } QT_CATCH(...) {
1463 // swallow this problem because we are in a destructor
1464 }
1465
1466 d->setDirtyOpaqueRegion();
1467
1468 if (isWindow() && isVisible() && internalWinId()) {
1469 QT_TRY {
1470 d->close_helper(QWidgetPrivate::CloseNoEvent);
1471 } QT_CATCH(...) {
1472 // if we're out of memory, at least hide the window.
1473 QT_TRY {
1474 hide();
1475 } QT_CATCH(...) {
1476 // and if that also doesn't work, then give up
1477 }
1478 }
1479 } else if (isVisible()) {
1480 qApp->d_func()->sendSyntheticEnterLeave(this);
1481 }
1482
1483 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1484 repaintManager->removeDirtyWidget(this);
1485 if (testAttribute(Qt::WA_StaticContents))
1486 repaintManager->removeStaticWidget(this);
1487 }
1488
1489 delete d->needsFlush;
1490 d->needsFlush = nullptr;
1491
1492 // The next 20 lines are duplicated from QObject, but required here
1493 // since QWidget deletes is children itself
1494 bool blocked = d->blockSig;
1495 d->blockSig = 0; // unblock signals so we always emit destroyed()
1496
1497 if (d->isSignalConnected(0)) {
1498 QT_TRY {
1499 emit destroyed(this);
1500 } QT_CATCH(...) {
1501 // all the signal/slots connections are still in place - if we don't
1502 // quit now, we will crash pretty soon.
1503 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1504 QT_RETHROW;
1505 }
1506 }
1507
1508 if (d->declarativeData) {
1509 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1510 if (QAbstractDeclarativeData::destroyed)
1511 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1512 d->declarativeData = nullptr; // don't activate again in ~QObject
1513 d->wasDeleted = false;
1514 }
1515
1516 d->blockSig = blocked;
1517
1518 if (!d->children.isEmpty())
1519 d->deleteChildren();
1520
1521 QCoreApplication::removePostedEvents(this);
1522
1523 QT_TRY {
1524 destroy(); // platform-dependent cleanup
1525 } QT_CATCH(...) {
1526 // if this fails we can't do anything about it but at least we are not allowed to throw.
1527 }
1528 --QWidgetPrivate::instanceCounter;
1529
1530 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1531 QWidgetPrivate::allWidgets->remove(this);
1532
1533 QT_TRY {
1534 QEvent e(QEvent::Destroy);
1535 QCoreApplication::sendEvent(this, &e);
1536 } QT_CATCH(const std::exception&) {
1537 // if this fails we can't do anything about it but at least we are not allowed to throw.
1538 }
1539
1540#if QT_CONFIG(graphicseffect)
1541 delete d->graphicsEffect;
1542#endif
1543}
1544
1545int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1546int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1547
1548void QWidgetPrivate::setWinId(WId id) // set widget identifier
1549{
1550 Q_Q(QWidget);
1551 if (mapper && data.winid) {
1552 mapper->remove(data.winid);
1553 }
1554
1555 const WId oldWinId = data.winid;
1556
1557 data.winid = id;
1558 if (mapper && id) {
1559 mapper->insert(data.winid, q);
1560 }
1561
1562 if(oldWinId != id) {
1563 QEvent e(QEvent::WinIdChange);
1564 QCoreApplication::sendEvent(q, &e);
1565 }
1566}
1567
1568void QWidgetPrivate::createTLExtra()
1569{
1570 if (!extra)
1571 createExtra();
1572 if (!extra->topextra) {
1573 extra->topextra = qt_make_unique<QTLWExtra>();
1574 QTLWExtra* x = extra->topextra.get();
1575 x->backingStore = nullptr;
1576 x->sharedPainter = nullptr;
1577 x->incw = x->inch = 0;
1578 x->basew = x->baseh = 0;
1579 x->frameStrut.setCoords(0, 0, 0, 0);
1580 x->normalGeometry = QRect(0,0,-1,-1);
1581 x->savedFlags = { };
1582 x->opacity = 255;
1583 x->posIncludesFrame = 0;
1584 x->sizeAdjusted = false;
1585 x->embedded = 0;
1586 x->window = nullptr;
1587 x->initialScreen = nullptr;
1588
1589#ifdef QWIDGET_EXTRA_DEBUG
1590 static int count = 0;
1591 qDebug() << "tlextra" << ++count;
1592#endif
1593 }
1594}
1595
1596/*!
1597 \internal
1598 Creates the widget extra data.
1599*/
1600
1601void QWidgetPrivate::createExtra()
1602{
1603 if (!extra) { // if not exists
1604 extra = qt_make_unique<QWExtra>();
1605 extra->glContext = nullptr;
1606#if QT_CONFIG(graphicsview)
1607 extra->proxyWidget = nullptr;
1608#endif
1609 extra->minw = 0;
1610 extra->minh = 0;
1611 extra->maxw = QWIDGETSIZE_MAX;
1612 extra->maxh = QWIDGETSIZE_MAX;
1613 extra->customDpiX = 0;
1614 extra->customDpiY = 0;
1615 extra->explicitMinSize = 0;
1616 extra->explicitMaxSize = 0;
1617 extra->autoFillBackground = 0;
1618 extra->nativeChildrenForced = 0;
1619 extra->inRenderWithPainter = 0;
1620 extra->hasWindowContainer = false;
1621 extra->hasMask = 0;
1622 createSysExtra();
1623#ifdef QWIDGET_EXTRA_DEBUG
1624 static int count = 0;
1625 qDebug() << "extra" << ++count;
1626#endif
1627 }
1628}
1629
1630void QWidgetPrivate::createSysExtra()
1631{
1632}
1633
1634/*!
1635 \internal
1636 Deletes the widget extra data.
1637*/
1638
1639void QWidgetPrivate::deleteExtra()
1640{
1641 if (extra) { // if exists
1642 deleteSysExtra();
1643#ifndef QT_NO_STYLE_STYLESHEET
1644 // dereference the stylesheet style
1645 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1646 proxy->deref();
1647#endif
1648 if (extra->topextra) {
1649 deleteTLSysExtra();
1650 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1651 }
1652 // extra->xic destroyed in QWidget::destroy()
1653 extra.reset();
1654 }
1655}
1656
1657void QWidgetPrivate::deleteSysExtra()
1658{
1659}
1660
1661static void deleteBackingStore(QWidgetPrivate *d)
1662{
1663 QTLWExtra *topData = d->topData();
1664
1665 delete topData->backingStore;
1666 topData->backingStore = nullptr;
1667}
1668
1669void QWidgetPrivate::deleteTLSysExtra()
1670{
1671 if (extra && extra->topextra) {
1672 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1673 //needs to be deleted first.
1674
1675 extra->topextra->repaintManager.reset(nullptr);
1676 deleteBackingStore(this);
1677#ifndef QT_NO_OPENGL
1678 extra->topextra->widgetTextures.clear();
1679 extra->topextra->shareContext.reset();
1680#endif
1681
1682 //the toplevel might have a context with a "qglcontext associated with it. We need to
1683 //delete the qglcontext before we delete the qplatformopenglcontext.
1684 //One unfortunate thing about this is that we potentially create a glContext just to
1685 //delete it straight afterwards.
1686 if (extra->topextra->window) {
1687 extra->topextra->window->destroy();
1688 }
1689 delete extra->topextra->window;
1690 extra->topextra->window = nullptr;
1691
1692 }
1693}
1694
1695/*
1696 Returns \c region of widgets above this which overlap with
1697 \a rect, which is in parent's coordinate system (same as crect).
1698*/
1699
1700QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1701{
1702 Q_Q(const QWidget);
1703
1704 const QWidget *w = q;
1705 QRect r = rect;
1706 QPoint p;
1707 QRegion region;
1708 while (w) {
1709 if (w->isWindow())
1710 break;
1711 QWidgetPrivate *pd = w->parentWidget()->d_func();
1712 bool above = false;
1713 for (int i = 0; i < pd->children.size(); ++i) {
1714 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1715 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1716 continue;
1717 if (!above) {
1718 above = (sibling == w);
1719 continue;
1720 }
1721
1722 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1723 if (qRectIntersects(siblingRect, r)) {
1724 const auto &siblingExtra = sibling->d_func()->extra;
1725 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1726 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1727 continue;
1728 }
1729 region += siblingRect.translated(-p);
1730 if (breakAfterFirst)
1731 break;
1732 }
1733 }
1734 w = w->parentWidget();
1735 r.translate(pd->data.crect.topLeft());
1736 p += pd->data.crect.topLeft();
1737 }
1738 return region;
1739}
1740
1741void QWidgetPrivate::syncBackingStore()
1742{
1743 if (shouldPaintOnScreen()) {
1744 paintOnScreen(dirty);
1745 dirty = QRegion();
1746 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1747 repaintManager->sync();
1748 }
1749}
1750
1751void QWidgetPrivate::syncBackingStore(const QRegion &region)
1752{
1753 if (shouldPaintOnScreen())
1754 paintOnScreen(region);
1755 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1756 repaintManager->sync(q_func(), region);
1757 }
1758}
1759
1760void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1761{
1762 if (data.in_destructor)
1763 return;
1764
1765 if (shouldDiscardSyncRequest())
1766 return;
1767
1768 Q_Q(QWidget);
1769 if (q->testAttribute(Qt::WA_StaticContents)) {
1770 if (!extra)
1771 createExtra();
1772 extra->staticContentsSize = data.crect.size();
1773 }
1774
1775 QPaintEngine *engine = q->paintEngine();
1776
1777 // QGLWidget does not support partial updates if:
1778 // 1) The context is double buffered
1779 // 2) The context is single buffered and auto-fill background is enabled.
1780 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1781 || engine->type() == QPaintEngine::OpenGL2))
1782 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1783 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1784
1785 toBePainted &= clipRect();
1786 clipToEffectiveMask(toBePainted);
1787 if (toBePainted.isEmpty())
1788 return; // Nothing to repaint.
1789
1790 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1791
1792 if (Q_UNLIKELY(q->paintingActive()))
1793 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1794}
1795
1796void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1797{
1798 Q_Q(QWidget);
1799
1800 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1801 return; // nothing we can do
1802
1803 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1804 return; // nothing to do
1805
1806 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1807 if (enable)
1808 q->update();
1809
1810 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1811 for (int i = 0; i < children.size(); ++i) {
1812 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1813 if (w && !w->isWindow() && !w->testAttribute(attribute))
1814 w->d_func()->setUpdatesEnabled_helper(enable);
1815 }
1816}
1817
1818/*!
1819 \internal
1820
1821 Propagate this widget's palette to all children, except style sheet
1822 widgets, and windows that don't enable window propagation (palettes don't
1823 normally propagate to windows).
1824*/
1825void QWidgetPrivate::propagatePaletteChange()
1826{
1827 Q_Q(QWidget);
1828 // Propagate a new inherited mask to all children.
1829#if QT_CONFIG(graphicsview)
1830 if (!q->parentWidget() && extra && extra->proxyWidget) {
1831 QGraphicsProxyWidget *p = extra->proxyWidget;
1832 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1833 } else
1834#endif // QT_CONFIG(graphicsview)
1835 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1836 inheritedPaletteResolveMask = 0;
1837 }
1838
1839 directPaletteResolveMask = data.pal.resolveMask();
1840 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1841
1842 const bool useStyleSheetPropagationInWidgetStyles =
1843 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1844
1845 QEvent pc(QEvent::PaletteChange);
1846 QCoreApplication::sendEvent(q, &pc);
1847 for (int i = 0; i < children.size(); ++i) {
1848 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1849 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1850 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1851 QWidgetPrivate *wd = w->d_func();
1852 wd->inheritedPaletteResolveMask = mask;
1853 wd->resolvePalette();
1854 }
1855 }
1856}
1857
1858/*
1859 Returns the widget's clipping rectangle.
1860*/
1861QRect QWidgetPrivate::clipRect() const
1862{
1863 Q_Q(const QWidget);
1864 const QWidget * w = q;
1865 if (!w->isVisible())
1866 return QRect();
1867 QRect r = effectiveRectFor(q->rect());
1868 int ox = 0;
1869 int oy = 0;
1870 while (w
1871 && w->isVisible()
1872 && !w->isWindow()
1873 && w->parentWidget()) {
1874 ox -= w->x();
1875 oy -= w->y();
1876 w = w->parentWidget();
1877 r &= QRect(ox, oy, w->width(), w->height());
1878 }
1879 return r;
1880}
1881
1882/*
1883 Returns the widget's clipping region (without siblings).
1884*/
1885QRegion QWidgetPrivate::clipRegion() const
1886{
1887 Q_Q(const QWidget);
1888 if (!q->isVisible())
1889 return QRegion();
1890 QRegion r(q->rect());
1891 const QWidget * w = q;
1892 const QWidget *ignoreUpTo;
1893 int ox = 0;
1894 int oy = 0;
1895 while (w
1896 && w->isVisible()
1897 && !w->isWindow()
1898 && w->parentWidget()) {
1899 ox -= w->x();
1900 oy -= w->y();
1901 ignoreUpTo = w;
1902 w = w->parentWidget();
1903 r &= QRegion(ox, oy, w->width(), w->height());
1904
1905 int i = 0;
1906 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1907 ;
1908 for ( ; i < w->d_func()->children.size(); ++i) {
1909 if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1910 if(sibling->isVisible() && !sibling->isWindow()) {
1911 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1912 sibling->width(), sibling->height());
1913 if (qRectIntersects(siblingRect, q->rect()))
1914 r -= QRegion(siblingRect);
1915 }
1916 }
1917 }
1918 }
1919 return r;
1920}
1921
1922void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1923{
1924// Transform the system clip region from device-independent pixels to device pixels
1925 QTransform scaleTransform;
1926 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1927
1928 paintEngine->d_func()->baseSystemClip = region;
1929 paintEngine->d_func()->setSystemTransform(scaleTransform);
1930
1931}
1932
1933#if QT_CONFIG(graphicseffect)
1934void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1935{
1936 Q_Q(QWidget);
1937 QWidget *w = q;
1938 do {
1939 if (w->graphicsEffect()) {
1940 QWidgetEffectSourcePrivate *sourced =
1941 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1942 if (!sourced->updateDueToGraphicsEffect)
1943 w->graphicsEffect()->source()->d_func()->invalidateCache();
1944 }
1945 w = w->parentWidget();
1946 } while (w);
1947}
1948#endif // QT_CONFIG(graphicseffect)
1949
1950void QWidgetPrivate::setDirtyOpaqueRegion()
1951{
1952 Q_Q(QWidget);
1953
1954 dirtyOpaqueChildren = true;
1955
1956#if QT_CONFIG(graphicseffect)
1957 invalidateGraphicsEffectsRecursively();
1958#endif // QT_CONFIG(graphicseffect)
1959
1960 if (q->isWindow())
1961 return;
1962
1963 QWidget *parent = q->parentWidget();
1964 if (!parent)
1965 return;
1966
1967 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1968 QWidgetPrivate *pd = parent->d_func();
1969 if (!pd->dirtyOpaqueChildren)
1970 pd->setDirtyOpaqueRegion();
1971}
1972
1973const QRegion &QWidgetPrivate::getOpaqueChildren() const
1974{
1975 if (!dirtyOpaqueChildren)
1976 return opaqueChildren;
1977
1978 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
1979 that->opaqueChildren = QRegion();
1980
1981 for (int i = 0; i < children.size(); ++i) {
1982 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1983 if (!child || !child->isVisible() || child->isWindow())
1984 continue;
1985
1986 const QPoint offset = child->geometry().topLeft();
1987 QWidgetPrivate *childd = child->d_func();
1988 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
1989 if (childd->extra && childd->extra->hasMask)
1990 r &= childd->extra->mask;
1991 if (r.isEmpty())
1992 continue;
1993 r.translate(offset);
1994 that->opaqueChildren += r;
1995 }
1996
1997 that->opaqueChildren &= q_func()->rect();
1998 that->dirtyOpaqueChildren = false;
1999
2000 return that->opaqueChildren;
2001}
2002
2003void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2004{
2005 if (children.isEmpty() || clipRect.isEmpty())
2006 return;
2007
2008 const QRegion &r = getOpaqueChildren();
2009 if (!r.isEmpty())
2010 source -= (r & clipRect);
2011}
2012
2013//subtract any relatives that are higher up than me --- this is too expensive !!!
2014void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2015 bool alsoNonOpaque) const
2016{
2017 Q_Q(const QWidget);
2018 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2019 if (disableSubtractOpaqueSiblings || q->isWindow())
2020 return;
2021
2022 QRect clipBoundingRect;
2023 bool dirtyClipBoundingRect = true;
2024
2025 QRegion parentClip;
2026 bool dirtyParentClip = true;
2027
2028 QPoint parentOffset = data.crect.topLeft();
2029
2030 const QWidget *w = q;
2031
2032 while (w) {
2033 if (w->isWindow())
2034 break;
2035 QWidgetPrivate *pd = w->parentWidget()->d_func();
2036 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2037 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2038 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2039 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2040 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2041 continue;
2042
2043 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2044 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2045 continue;
2046
2047 if (dirtyClipBoundingRect) {
2048 clipBoundingRect = sourceRegion.boundingRect();
2049 dirtyClipBoundingRect = false;
2050 }
2051
2052 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2053 continue;
2054
2055 if (dirtyParentClip) {
2056 parentClip = sourceRegion.translated(parentOffset);
2057 dirtyParentClip = false;
2058 }
2059
2060 const QPoint siblingPos(sibling->data->crect.topLeft());
2061 const QRect siblingClipRect(sibling->d_func()->clipRect());
2062 QRegion siblingDirty(parentClip);
2063 siblingDirty &= (siblingClipRect.translated(siblingPos));
2064 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2065 && !sibling->d_func()->graphicsEffect;
2066 if (hasMask)
2067 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2068 if (siblingDirty.isEmpty())
2069 continue;
2070
2071 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2072 if (hasMask) {
2073 siblingDirty.translate(-parentOffset);
2074 sourceRegion -= siblingDirty;
2075 } else {
2076 sourceRegion -= siblingGeometry.translated(-parentOffset);
2077 }
2078 } else {
2079 if (hasDirtySiblingsAbove)
2080 *hasDirtySiblingsAbove = true;
2081 if (sibling->d_func()->children.isEmpty())
2082 continue;
2083 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2084 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2085 sourceRegion -= opaqueSiblingChildren;
2086 }
2087 if (sourceRegion.isEmpty())
2088 return;
2089
2090 dirtyClipBoundingRect = true;
2091 dirtyParentClip = true;
2092 }
2093
2094 w = w->parentWidget();
2095 parentOffset += pd->data.crect.topLeft();
2096 dirtyParentClip = true;
2097 }
2098}
2099
2100void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2101{
2102 Q_Q(const QWidget);
2103
2104 const QWidget *w = q;
2105 QPoint offset;
2106
2107#if QT_CONFIG(graphicseffect)
2108 if (graphicsEffect) {
2109 w = q->parentWidget();
2110 offset -= data.crect.topLeft();
2111 }
2112#endif // QT_CONFIG(graphicseffect)
2113
2114 while (w) {
2115 const QWidgetPrivate *wd = w->d_func();
2116 if (wd->extra && wd->extra->hasMask)
2117 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2118 if (w->isWindow())
2119 return;
2120 offset -= wd->data.crect.topLeft();
2121 w = w->parentWidget();
2122 }
2123}
2124
2125bool QWidgetPrivate::shouldPaintOnScreen() const
2126{
2127#if defined(QT_NO_BACKINGSTORE)
2128 return true;
2129#else
2130 Q_Q(const QWidget);
2131 if (q->testAttribute(Qt::WA_PaintOnScreen)
2132 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2133 return true;
2134 }
2135
2136 return false;
2137#endif
2138}
2139
2140void QWidgetPrivate::updateIsOpaque()
2141{
2142 // hw: todo: only needed if opacity actually changed
2143 setDirtyOpaqueRegion();
2144
2145#if QT_CONFIG(graphicseffect)
2146 if (graphicsEffect) {
2147 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2148 setOpaque(false);
2149 return;
2150 }
2151#endif // QT_CONFIG(graphicseffect)
2152
2153 Q_Q(QWidget);
2154 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2155 setOpaque(true);
2156 return;
2157 }
2158
2159 const QPalette &pal = q->palette();
2160
2161 if (q->autoFillBackground()) {
2162 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2163 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2164 setOpaque(true);
2165 return;
2166 }
2167 }
2168
2169 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2170 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2171 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2172 setOpaque(true);
2173 return;
2174 }
2175 }
2176 setOpaque(false);
2177}
2178
2179void QWidgetPrivate::setOpaque(bool opaque)
2180{
2181 if (isOpaque != opaque) {
2182 isOpaque = opaque;
2183 updateIsTranslucent();
2184 }
2185}
2186
2187void QWidgetPrivate::updateIsTranslucent()
2188{
2189 Q_Q(QWidget);
2190 if (QWindow *window = q->windowHandle()) {
2191 QSurfaceFormat format = window->format();
2192 const int oldAlpha = format.alphaBufferSize();
2193 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2194 if (oldAlpha != newAlpha) {
2195 format.setAlphaBufferSize(newAlpha);
2196 window->setFormat(format);
2197 }
2198 }
2199}
2200
2201static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2202{
2203 Q_ASSERT(painter);
2204
2205 if (brush.style() == Qt::TexturePattern) {
2206 const QRect rect(rgn.boundingRect());
2207 painter->setClipRegion(rgn);
2208 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2209 } else if (brush.gradient()
2210 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2211 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2212 painter->save();
2213 painter->setClipRegion(rgn);
2214 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2215 painter->restore();
2216 } else {
2217 for (const QRect &rect : rgn)
2218 painter->fillRect(rect, brush);
2219 }
2220}
2221
2222bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2223{
2224#if QT_CONFIG(scrollarea)
2225 Q_Q(const QWidget);
2226 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2227 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2228 return false;
2229 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2230 if (scrollArea && scrollArea->viewport() == q) {
2231 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2232 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2233 painter->setBrushOrigin(-priv->contentsOffset());
2234 }
2235#endif // QT_CONFIG(scrollarea)
2236 return true;
2237}
2238
2239void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2240{
2241 Q_Q(const QWidget);
2242
2243 bool brushOriginSet = false;
2244 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2245
2246 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2247 const QBrush bg = q->palette().brush(QPalette::Window);
2248 if (!brushOriginSet)
2249 brushOriginSet = updateBrushOrigin(painter, bg);
2250 if (!(flags & DontSetCompositionMode)) {
2251 //copy alpha straight in
2252 QPainter::CompositionMode oldMode = painter->compositionMode();
2253 painter->setCompositionMode(QPainter::CompositionMode_Source);
2254 fillRegion(painter, rgn, bg);
2255 painter->setCompositionMode(oldMode);
2256 } else {
2257 fillRegion(painter, rgn, bg);
2258 }
2259 }
2260
2261 if (q->autoFillBackground()) {
2262 if (!brushOriginSet)
2263 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2264 fillRegion(painter, rgn, autoFillBrush);
2265 }
2266
2267 if (q->testAttribute(Qt::WA_StyledBackground)) {
2268 painter->setClipRegion(rgn);
2269 QStyleOption opt;
2270 opt.initFrom(q);
2271 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2272 }
2273}
2274
2275/*
2276 \internal
2277 This function is called when a widget is hidden or destroyed.
2278 It resets some application global pointers that should only refer active,
2279 visible widgets.
2280*/
2281
2282extern QWidget *qt_button_down;
2283
2284void QWidgetPrivate::deactivateWidgetCleanup()
2285{
2286 Q_Q(QWidget);
2287 // If this was the active application window, reset it
2288 if (QApplication::activeWindow() == q)
2289 QApplication::setActiveWindow(nullptr);
2290 // If the is the active mouse press widget, reset it
2291 if (q == qt_button_down)
2292 qt_button_down = nullptr;
2293}
2294
2295
2296/*!
2297 Returns a pointer to the widget with window identifer/handle \a
2298 id.
2299
2300 The window identifier type depends on the underlying window
2301 system, see \c qwindowdefs.h for the actual definition. If there
2302 is no widget with this identifier, \nullptr is returned.
2303*/
2304
2305QWidget *QWidget::find(WId id)
2306{
2307 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2308}
2309
2310
2311
2312/*!
2313 \fn WId QWidget::internalWinId() const
2314 \internal
2315 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2316
2317*/
2318
2319/*!
2320 \fn WId QWidget::winId() const
2321
2322 Returns the window system identifier of the widget.
2323
2324 Portable in principle, but if you use it you are probably about to
2325 do something non-portable. Be careful.
2326
2327 If a widget is non-native (alien) and winId() is invoked on it, that widget
2328 will be provided a native handle.
2329
2330 This value may change at run-time. An event with type QEvent::WinIdChange
2331 will be sent to the widget following a change in window system identifier.
2332
2333 \sa find()
2334*/
2335WId QWidget::winId() const
2336{
2337 if (!data->in_destructor
2338 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2339 {
2340#ifdef ALIEN_DEBUG
2341 qDebug() << "QWidget::winId: creating native window for" << this;
2342#endif
2343 QWidget *that = const_cast<QWidget*>(this);
2344 that->setAttribute(Qt::WA_NativeWindow);
2345 that->d_func()->createWinId();
2346 return that->data->winid;
2347 }
2348 return data->winid;
2349}
2350
2351void QWidgetPrivate::createWinId()
2352{
2353 Q_Q(QWidget);
2354
2355#ifdef ALIEN_DEBUG
2356 qDebug() << "QWidgetPrivate::createWinId for" << q;
2357#endif
2358 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2359 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2360 if (!q->isWindow()) {
2361 QWidget *parent = q->parentWidget();
2362 QWidgetPrivate *pd = parent->d_func();
2363 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2364 parent->setAttribute(Qt::WA_NativeWindow);
2365 if (!parent->internalWinId()) {
2366 pd->createWinId();
2367 }
2368
2369 for (int i = 0; i < pd->children.size(); ++i) {
2370 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2371 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2372 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2373 w->create();
2374 }
2375 }
2376 } else {
2377 q->create();
2378 }
2379 }
2380}
2381
2382/*!
2383\internal
2384Ensures that the widget is set on the screen point is on. This is handy getting a correct
2385size hint before a resize in e.g QMenu and QToolTip.
2386Returns if the screen was changed.
2387*/
2388
2389bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2390{
2391 Q_Q(QWidget);
2392 if (!q->isWindow())
2393 return false;
2394 // Find the screen for pos and make the widget understand it is on that screen.
2395 return setScreen(QGuiApplication::screenAt(pos));
2396}
2397
2398/*!
2399\internal
2400Ensures that the widget's QWindow is set to be on the given \a screen.
2401Returns true if the screen was changed.
2402*/
2403
2404bool QWidgetPrivate::setScreen(QScreen *screen)
2405{
2406 Q_Q(QWidget);
2407 if (!screen || !q->isWindow())
2408 return false;
2409 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2410 if (currentScreen != screen) {
2411 topData()->initialScreen = screen;
2412 if (windowHandle())
2413 windowHandle()->setScreen(screen);
2414 return true;
2415 }
2416 return false;
2417}
2418
2419/*!
2420\internal
2421Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2422
2423*/
2424
2425void QWidget::createWinId()
2426{
2427 Q_D(QWidget);
2428#ifdef ALIEN_DEBUG
2429 qDebug() << "QWidget::createWinId" << this;
2430#endif
2431// qWarning("QWidget::createWinId is obsolete, please fix your code.");
2432 d->createWinId();
2433}
2434
2435/*!
2436 \since 4.4
2437
2438 Returns the effective window system identifier of the widget, i.e. the
2439 native parent's window system identifier.
2440
2441 If the widget is native, this function returns the native widget ID.
2442 Otherwise, the window ID of the first native parent widget, i.e., the
2443 top-level widget that contains this widget, is returned.
2444
2445 \note We recommend that you do not store this value as it is likely to
2446 change at run-time.
2447
2448 \sa nativeParentWidget()
2449*/
2450WId QWidget::effectiveWinId() const
2451{
2452 const WId id = internalWinId();
2453 if (id || !testAttribute(Qt::WA_WState_Created))
2454 return id;
2455 if (const QWidget *realParent = nativeParentWidget())
2456 return realParent->internalWinId();
2457 return 0;
2458}
2459
2460/*!
2461 If this is a native widget, return the associated QWindow.
2462 Otherwise return null.
2463
2464 Native widgets include toplevel widgets, QGLWidget, and child widgets
2465 on which winId() was called.
2466
2467 \since 5.0
2468
2469 \sa winId(), screen()
2470*/
2471QWindow *QWidget::windowHandle() const
2472{
2473 Q_D(const QWidget);
2474 return d->windowHandle();
2475}
2476
2477/*!
2478 Returns the screen the widget is on.
2479
2480 \since 5.14
2481
2482 \sa windowHandle()
2483*/
2484QScreen *QWidget::screen() const
2485{
2486 Q_D(const QWidget);
2487 if (auto associatedScreen = d->associatedScreen())
2488 return associatedScreen;
2489 if (auto topLevel = window()) {
2490 if (auto topData = qt_widget_private(topLevel)->topData()) {
2491 if (topData->initialScreen)
2492 return topData->initialScreen;
2493 }
2494 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2495 return screenByPos;
2496 }
2497 return QGuiApplication::primaryScreen();
2498}
2499
2500/*!
2501 Sets the screen on which the widget should be shown to \a screen.
2502
2503 Setting the screen only makes sense for windows. If necessary, the widget's
2504 window will get recreated on \a screen.
2505
2506 \note If the screen is part of a virtual desktop of multiple screens,
2507 the window will not move automatically to \a screen. To place the
2508 window relative to the screen, use the screen's topLeft() position.
2509
2510 \sa QWindow::setScreen()
2511*/
2512void QWidget::setScreen(QScreen *screen)
2513{
2514 Q_D(QWidget);
2515 d->setScreen(screen);
2516}
2517
2518#ifndef QT_NO_STYLE_STYLESHEET
2519
2520/*!
2521 \property QWidget::styleSheet
2522 \brief the widget's style sheet
2523 \since 4.2
2524
2525 The style sheet contains a textual description of customizations to the
2526 widget's style, as described in the \l{Qt Style Sheets} document.
2527
2528 Since Qt 4.5, Qt style sheets fully supports \macos.
2529
2530 \warning Qt style sheets are currently not supported for custom QStyle
2531 subclasses. We plan to address this in some future release.
2532
2533 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2534*/
2535QString QWidget::styleSheet() const
2536{
2537 Q_D(const QWidget);
2538 if (!d->extra)
2539 return QString();
2540 return d->extra->styleSheet;
2541}
2542
2543void QWidget::setStyleSheet(const QString& styleSheet)
2544{
2545 Q_D(QWidget);
2546 if (data->in_destructor)
2547 return;
2548 d->createExtra();
2549
2550 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2551 d->extra->styleSheet = styleSheet;
2552 if (styleSheet.isEmpty()) { // stylesheet removed
2553 if (!proxy)
2554 return;
2555
2556 d->inheritStyle();
2557 return;
2558 }
2559
2560 if (proxy) { // style sheet update
2561 if (d->polished)
2562 proxy->repolish(this);
2563 return;
2564 }
2565
2566 if (testAttribute(Qt::WA_SetStyle)) {
2567 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2568 } else {
2569 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2570 }
2571}
2572
2573#endif // QT_NO_STYLE_STYLESHEET
2574
2575/*!
2576 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2577*/
2578
2579QStyle *QWidget::style() const
2580{
2581 Q_D(const QWidget);
2582
2583 if (d->extra && d->extra->style)
2584 return d->extra->style;
2585 return QApplication::style();
2586}
2587
2588/*!
2589 Sets the widget's GUI style to \a style. The ownership of the style
2590 object is not transferred.
2591
2592 If no style is set, the widget uses the application's style,
2593 QApplication::style() instead.
2594
2595 Setting a widget's style has no effect on existing or future child
2596 widgets.
2597
2598 \warning This function is particularly useful for demonstration
2599 purposes, where you want to show Qt's styling capabilities. Real
2600 applications should avoid it and use one consistent GUI style
2601 instead.
2602
2603 \warning Qt style sheets are currently not supported for custom QStyle
2604 subclasses. We plan to address this in some future release.
2605
2606 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2607*/
2608
2609void QWidget::setStyle(QStyle *style)
2610{
2611 Q_D(QWidget);
2612 setAttribute(Qt::WA_SetStyle, style != nullptr);
2613 d->createExtra();
2614#ifndef QT_NO_STYLE_STYLESHEET
2615 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2616 //if for some reason someone try to set a QStyleSheetStyle, ref it
2617 //(this may happen for exemple in QButtonDialogBox which propagates its style)
2618 styleSheetStyle->ref();
2619 d->setStyle_helper(style, false);
2620 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2621 // if we have an application stylesheet or have a proxy already, propagate
2622 d->setStyle_helper(new QStyleSheetStyle(style), true);
2623 } else
2624#endif
2625 d->setStyle_helper(style, false);
2626}
2627
2628void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2629{
2630 Q_Q(QWidget);
2631 QStyle *oldStyle = q->style();
2632
2633 createExtra();
2634
2635#ifndef QT_NO_STYLE_STYLESHEET
2636 QPointer<QStyle> origStyle = extra->style;
2637#endif
2638 extra->style = newStyle;
2639
2640 // repolish
2641 if (polished && q->windowType() != Qt::Desktop) {
2642 oldStyle->unpolish(q);
2643 q->style()->polish(q);
2644 }
2645
2646 if (propagate) {
2647 // We copy the list because the order may be modified
2648 const QObjectList childrenList = children;
2649 for (int i = 0; i < childrenList.size(); ++i) {
2650 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2651 if (c)
2652 c->d_func()->inheritStyle();
2653 }
2654 }
2655
2656#ifndef QT_NO_STYLE_STYLESHEET
2657 if (!qt_styleSheet(newStyle)) {
2658 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2659 cssStyle->clearWidgetFont(q);
2660 }
2661 }
2662#endif
2663
2664 QEvent e(QEvent::StyleChange);
2665 QCoreApplication::sendEvent(q, &e);
2666
2667#ifndef QT_NO_STYLE_STYLESHEET
2668 // dereference the old stylesheet style
2669 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2670 proxy->deref();
2671#endif
2672}
2673
2674// Inherits style from the current parent and propagates it as necessary
2675void QWidgetPrivate::inheritStyle()
2676{
2677#ifndef QT_NO_STYLE_STYLESHEET
2678 Q_Q(QWidget);
2679
2680 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2681
2682 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2683
2684 if (!q->styleSheet().isEmpty()) {
2685 Q_ASSERT(proxy);
2686 proxy->repolish(q);
2687 return;
2688 }
2689
2690 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2691 QWidget *parent = q->parentWidget();
2692 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2693 // If we have stylesheet on app or parent has stylesheet style, we need
2694 // to be running a proxy
2695 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2696 QStyle *newStyle = parentStyle;
2697 if (q->testAttribute(Qt::WA_SetStyle))
2698 newStyle = new QStyleSheetStyle(origStyle);
2699 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2700 newProxy->ref();
2701
2702 setStyle_helper(newStyle, true);
2703 return;
2704 }
2705
2706 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2707 // we just need our original style back
2708 if (origStyle == extraStyle) // is it any different?
2709 return;
2710
2711 // We could have inherited the proxy from our parent (which has a custom style)
2712 // In such a case we need to start following the application style (i.e revert
2713 // the propagation behavior of QStyleSheetStyle)
2714 if (!q->testAttribute(Qt::WA_SetStyle))
2715 origStyle = nullptr;
2716
2717 setStyle_helper(origStyle, true);
2718#endif // QT_NO_STYLE_STYLESHEET
2719}
2720
2721
2722/*!
2723 \fn bool QWidget::isWindow() const
2724
2725 Returns \c true if the widget is an independent window, otherwise
2726 returns \c false.
2727
2728 A window is a widget that isn't visually the child of any other
2729 widget and that usually has a frame and a
2730 \l{QWidget::setWindowTitle()}{window title}.
2731
2732 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2733 It will then be grouped with its parent and deleted when the
2734 parent is deleted, minimized when the parent is minimized etc. If
2735 supported by the window manager, it will also have a common
2736 taskbar entry with its parent.
2737
2738 QDialog and QMainWindow widgets are by default windows, even if a
2739 parent widget is specified in the constructor. This behavior is
2740 specified by the Qt::Window flag.
2741
2742 \sa window(), isModal(), parentWidget()
2743*/
2744
2745/*!
2746 \property QWidget::modal
2747 \brief whether the widget is a modal widget
2748
2749 This property only makes sense for windows. A modal widget
2750 prevents widgets in all other windows from getting any input.
2751
2752 By default, this property is \c false.
2753
2754 \sa isWindow(), windowModality, QDialog
2755*/
2756
2757/*!
2758 \property QWidget::windowModality
2759 \brief which windows are blocked by the modal widget
2760 \since 4.1
2761
2762 This property only makes sense for windows. A modal widget
2763 prevents widgets in other windows from getting input. The value of
2764 this property controls which windows are blocked when the widget
2765 is visible. Changing this property while the window is visible has
2766 no effect; you must hide() the widget first, then show() it again.
2767
2768 By default, this property is Qt::NonModal.
2769
2770 \sa isWindow(), QWidget::modal, QDialog
2771*/
2772
2773Qt::WindowModality QWidget::windowModality() const
2774{
2775 return static_cast<Qt::WindowModality>(data->window_modality);
2776}
2777
2778void QWidget::setWindowModality(Qt::WindowModality windowModality)
2779{
2780 data->window_modality = windowModality;
2781 // setModal_sys() will be called by setAttribute()
2782 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2783 setAttribute(Qt::WA_SetWindowModality, true);
2784}
2785
2786void QWidgetPrivate::setModal_sys()
2787{
2788 Q_Q(QWidget);
2789 if (q->windowHandle())
2790 q->windowHandle()->setModality(q->windowModality());
2791}
2792
2793/*!
2794 \fn bool QWidget::underMouse() const
2795
2796 Returns \c true if the widget is under the mouse cursor; otherwise
2797 returns \c false.
2798
2799 This value is not updated properly during drag and drop
2800 operations.
2801
2802 \sa enterEvent(), leaveEvent()
2803*/
2804
2805/*!
2806 \property QWidget::minimized
2807 \brief whether this widget is minimized (iconified)
2808
2809 This property is only relevant for windows.
2810
2811 By default, this property is \c false.
2812
2813 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2814*/
2815bool QWidget::isMinimized() const
2816{ return data->window_state & Qt::WindowMinimized; }
2817
2818/*!
2819 Shows the widget minimized, as an icon.
2820
2821 Calling this function only affects \l{isWindow()}{windows}.
2822
2823 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2824 isMinimized()
2825*/
2826void QWidget::showMinimized()
2827{
2828 bool isMin = isMinimized();
2829 if (isMin && isVisible())
2830 return;
2831
2832 ensurePolished();
2833
2834 if (!isMin)
2835 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2836 setVisible(true);
2837}
2838
2839/*!
2840 \property QWidget::maximized
2841 \brief whether this widget is maximized
2842
2843 This property is only relevant for windows.
2844
2845 \note Due to limitations on some window systems, this does not always
2846 report the expected results (e.g., if the user on X11 maximizes the
2847 window via the window manager, Qt has no way of distinguishing this
2848 from any other resize). This is expected to improve as window manager
2849 protocols evolve.
2850
2851 By default, this property is \c false.
2852
2853 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2854*/
2855bool QWidget::isMaximized() const
2856{ return data->window_state & Qt::WindowMaximized; }
2857
2858
2859
2860/*!
2861 Returns the current window state. The window state is a OR'ed
2862 combination of Qt::WindowState: Qt::WindowMinimized,
2863 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2864
2865 \sa Qt::WindowState, setWindowState()
2866 */
2867Qt::WindowStates QWidget::windowState() const
2868{
2869 return Qt::WindowStates(data->window_state);
2870}
2871
2872/*!\internal
2873
2874 The function sets the window state on child widgets similar to
2875 setWindowState(). The difference is that the window state changed
2876 event has the isOverride() flag set. It exists mainly to keep
2877 QWorkspace working.
2878 */
2879void QWidget::overrideWindowState(Qt::WindowStates newstate)
2880{
2881 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2882 data->window_state = newstate;
2883 QCoreApplication::sendEvent(this, &e);
2884}
2885
2886/*!
2887 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2888
2889 Sets the window state to \a windowState. The window state is a OR'ed
2890 combination of Qt::WindowState: Qt::WindowMinimized,
2891 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2892
2893 If the window is not visible (i.e. isVisible() returns \c false), the
2894 window state will take effect when show() is called. For visible
2895 windows, the change is immediate. For example, to toggle between
2896 full-screen and normal mode, use the following code:
2897
2898 \snippet code/src_gui_kernel_qwidget.cpp 0
2899
2900 In order to restore and activate a minimized window (while
2901 preserving its maximized and/or full-screen state), use the following:
2902
2903 \snippet code/src_gui_kernel_qwidget.cpp 1
2904
2905 Calling this function will hide the widget. You must call show() to make
2906 the widget visible again.
2907
2908 \note On some window systems Qt::WindowActive is not immediate, and may be
2909 ignored in certain cases.
2910
2911 When the window state changes, the widget receives a changeEvent()
2912 of type QEvent::WindowStateChange.
2913
2914 \sa Qt::WindowState, windowState()
2915*/
2916void QWidget::setWindowState(Qt::WindowStates newstate)
2917{
2918 Q_D(QWidget);
2919 Qt::WindowStates oldstate = windowState();
2920 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2921 newstate.setFlag(Qt::WindowActive, false);
2922 if (oldstate == newstate)
2923 return;
2924 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2925 create();
2926
2927 data->window_state = newstate;
2928 data->in_set_window_state = 1;
2929 if (isWindow()) {
2930 // Ensure the initial size is valid, since we store it as normalGeometry below.
2931 if (!testAttribute(Qt::WA_Resized) && !isVisible())
2932 adjustSize();
2933
2934 d->createTLExtra();
2935 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2936 d->topData()->normalGeometry = geometry();
2937
2938 Q_ASSERT(windowHandle());
2939 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2940 }
2941 data->in_set_window_state = 0;
2942
2943 if (newstate & Qt::WindowActive)
2944 activateWindow();
2945
2946 QWindowStateChangeEvent e(oldstate);
2947 QCoreApplication::sendEvent(this, &e);
2948}
2949
2950/*!
2951 \property QWidget::fullScreen
2952 \brief whether the widget is shown in full screen mode
2953
2954 A widget in full screen mode occupies the whole screen area and does not
2955 display window decorations, such as a title bar.
2956
2957 By default, this property is \c false.
2958
2959 \sa windowState(), minimized, maximized
2960*/
2961bool QWidget::isFullScreen() const
2962{ return data->window_state & Qt::WindowFullScreen; }
2963
2964/*!
2965 Shows the widget in full-screen mode.
2966
2967 Calling this function only affects \l{isWindow()}{windows}.
2968
2969 To return from full-screen mode, call showNormal().
2970
2971 Full-screen mode works fine under Windows, but has certain
2972 problems under X. These problems are due to limitations of the
2973 ICCCM protocol that specifies the communication between X11
2974 clients and the window manager. ICCCM simply does not understand
2975 the concept of non-decorated full-screen windows. Therefore, the
2976 best we can do is to request a borderless window and place and
2977 resize it to fill the entire screen. Depending on the window
2978 manager, this may or may not work. The borderless window is
2979 requested using MOTIF hints, which are at least partially
2980 supported by virtually all modern window managers.
2981
2982 An alternative would be to bypass the window manager entirely and
2983 create a window with the Qt::X11BypassWindowManagerHint flag. This
2984 has other severe problems though, like totally broken keyboard focus
2985 and very strange effects on desktop changes or when the user raises
2986 other windows.
2987
2988 X11 window managers that follow modern post-ICCCM specifications
2989 support full-screen mode properly.
2990
2991 \sa showNormal(), showMaximized(), show(), hide(), isVisible()
2992*/
2993void QWidget::showFullScreen()
2994{
2995 ensurePolished();
2996
2997 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
2998 | Qt::WindowFullScreen);
2999 setVisible(true);
3000#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3001 // activating it here before libscreen activates it causes problems
3002 activateWindow();
3003#endif
3004}
3005
3006/*!
3007 Shows the widget maximized.
3008
3009 Calling this function only affects \l{isWindow()}{windows}.
3010
3011 On X11, this function may not work properly with certain window
3012 managers. See the \l{Window Geometry} documentation for an explanation.
3013
3014 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3015*/
3016void QWidget::showMaximized()
3017{
3018 ensurePolished();
3019
3020 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3021 | Qt::WindowMaximized);
3022 setVisible(true);
3023}
3024
3025/*!
3026 Restores the widget after it has been maximized or minimized.
3027
3028 Calling this function only affects \l{isWindow()}{windows}.
3029
3030 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3031*/
3032void QWidget::showNormal()
3033{
3034 ensurePolished();
3035
3036 setWindowState(windowState() & ~(Qt::WindowMinimized
3037 | Qt::WindowMaximized
3038 | Qt::WindowFullScreen));
3039 setVisible(true);
3040}
3041
3042/*!
3043 Returns \c true if this widget would become enabled if \a ancestor is
3044 enabled; otherwise returns \c false.
3045
3046
3047
3048 This is the case if neither the widget itself nor every parent up
3049 to but excluding \a ancestor has been explicitly disabled.
3050
3051 isEnabledTo(0) returns false if this widget or any if its ancestors
3052 was explicitly disabled.
3053
3054 The word ancestor here means a parent widget within the same window.
3055
3056 Therefore isEnabledTo(0) stops at this widget's window, unlike
3057 isEnabled() which also takes parent windows into considerations.
3058
3059 \sa setEnabled(), enabled
3060*/
3061
3062bool QWidget::isEnabledTo(const QWidget *ancestor) const
3063{
3064 const QWidget * w = this;
3065 while (!w->testAttribute(Qt::WA_ForceDisabled)
3066 && !w->isWindow()
3067 && w->parentWidget()
3068 && w->parentWidget() != ancestor)
3069 w = w->parentWidget();
3070 return !w->testAttribute(Qt::WA_ForceDisabled);
3071}
3072
3073#ifndef QT_NO_ACTION
3074/*!
3075 Appends the action \a action to this widget's list of actions.
3076
3077 All QWidgets have a list of \l{QAction}s, however they can be
3078 represented graphically in many different ways. The default use of
3079 the QAction list (as returned by actions()) is to create a context
3080 QMenu.
3081
3082 A QWidget should only have one of each action and adding an action
3083 it already has will not cause the same action to be in the widget twice.
3084
3085 The ownership of \a action is not transferred to this QWidget.
3086
3087 \sa removeAction(), insertAction(), actions(), QMenu
3088*/
3089void QWidget::addAction(QAction *action)
3090{
3091 insertAction(nullptr, action);
3092}
3093
3094/*!
3095 Appends the actions \a actions to this widget's list of actions.
3096
3097 \sa removeAction(), QMenu, addAction()
3098*/
3099void QWidget::addActions(const QList<QAction *> &actions)
3100{
3101 for(int i = 0; i < actions.count(); i++)
3102 insertAction(nullptr, actions.at(i));
3103}
3104
3105/*!
3106 Inserts the action \a action to this widget's list of actions,
3107 before the action \a before. It appends the action if \a before is \nullptr or
3108 \a before is not a valid action for this widget.
3109
3110 A QWidget should only have one of each action.
3111
3112 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3113*/
3114void QWidget::insertAction(QAction *before, QAction *action)
3115{
3116 if (Q_UNLIKELY(!action)) {
3117 qWarning("QWidget::insertAction: Attempt to insert null action");
3118 return;
3119 }
3120
3121 Q_D(QWidget);
3122 if(d->actions.contains(action))
3123 removeAction(action);
3124
3125 int pos = d->actions.indexOf(before);
3126 if (pos < 0) {
3127 before = nullptr;
3128 pos = d->actions.size();
3129 }
3130 d->actions.insert(pos, action);
3131
3132 QActionPrivate *apriv = action->d_func();
3133 apriv->associatedObjects.append(this);
3134
3135 QActionEvent e(QEvent::ActionAdded, action, before);
3136 QCoreApplication::sendEvent(this, &e);
3137}
3138
3139/*!
3140 Inserts the actions \a actions to this widget's list of actions,
3141 before the action \a before. It appends the action if \a before is \nullptr or
3142 \a before is not a valid action for this widget.
3143
3144 A QWidget can have at most one of each action.
3145
3146 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3147*/
3148void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3149{
3150 for(int i = 0; i < actions.count(); ++i)
3151 insertAction(before, actions.at(i));
3152}
3153
3154/*!
3155 Removes the action \a action from this widget's list of actions.
3156 \sa insertAction(), actions(), insertAction()
3157*/
3158void QWidget::removeAction(QAction *action)
3159{
3160 if (!action)
3161 return;
3162
3163 Q_D(QWidget);
3164
3165 QActionPrivate *apriv = action->d_func();
3166 apriv->associatedObjects.removeAll(this);
3167
3168 if (d->actions.removeAll(action)) {
3169 QActionEvent e(QEvent::ActionRemoved, action);
3170 QCoreApplication::sendEvent(this, &e);
3171 }
3172}
3173
3174/*!
3175 Returns the (possibly empty) list of this widget's actions.
3176
3177 \sa contextMenuPolicy, insertAction(), removeAction()
3178*/
3179QList<QAction*> QWidget::actions() const
3180{
3181 Q_D(const QWidget);
3182 return d->actions;
3183}
3184#endif // QT_NO_ACTION
3185
3186/*!
3187 \property QWidget::enabled
3188 \brief whether the widget is enabled
3189
3190 In general an enabled widget handles keyboard and mouse events; a disabled
3191 widget does not. An exception is made with \l{QAbstractButton}.
3192
3193 Some widgets display themselves differently when they are
3194 disabled. For example a button might draw its label grayed out. If
3195 your widget needs to know when it becomes enabled or disabled, you
3196 can use the changeEvent() with type QEvent::EnabledChange.
3197
3198 Disabling a widget implicitly disables all its children. Enabling
3199 respectively enables all child widgets unless they have been
3200 explicitly disabled. It it not possible to explicitly enable a child
3201 widget which is not a window while its parent widget remains disabled.
3202
3203 By default, this property is \c true.
3204
3205 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3206*/
3207void QWidget::setEnabled(bool enable)
3208{
3209 Q_D(QWidget);
3210 setAttribute(Qt::WA_ForceDisabled, !enable);
3211 d->setEnabled_helper(enable);
3212}
3213
3214void QWidgetPrivate::setEnabled_helper(bool enable)
3215{
3216 Q_Q(QWidget);
3217
3218 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3219 return; // nothing we can do
3220
3221 if (enable != q->testAttribute(Qt::WA_Disabled))
3222 return; // nothing to do
3223
3224 q->setAttribute(Qt::WA_Disabled, !enable);
3225 updateSystemBackground();
3226
3227 if (!enable && q->window()->focusWidget() == q) {
3228 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3229 if (!parentIsEnabled || !q->focusNextChild())
3230 q->clearFocus();
3231 }
3232
3233 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3234 for (int i = 0; i < children.size(); ++i) {
3235 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3236 if (w && !w->testAttribute(attribute))
3237 w->d_func()->setEnabled_helper(enable);
3238 }
3239#ifndef QT_NO_CURSOR
3240 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3241 // enforce the windows behavior of clearing the cursor on
3242 // disabled widgets
3243 qt_qpa_set_cursor(q, false);
3244 }
3245#endif
3246#ifndef QT_NO_IM
3247 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3248 QWidget *focusWidget = effectiveFocusWidget();
3249
3250 if (enable) {
3251 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3252 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3253 } else {
3254 QGuiApplication::inputMethod()->commit();
3255 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3256 }
3257 }
3258#endif //QT_NO_IM
3259 QEvent e(QEvent::EnabledChange);
3260 QCoreApplication::sendEvent(q, &e);
3261}
3262
3263/*!
3264 \property QWidget::acceptDrops
3265 \brief whether drop events are enabled for this widget
3266
3267 Setting this property to true announces to the system that this
3268 widget \e may be able to accept drop events.
3269
3270 If the widget is the desktop (windowType() == Qt::Desktop), this may
3271 fail if another application is using the desktop; you can call
3272 acceptDrops() to test if this occurs.
3273
3274 \warning Do not modify this property in a drag and drop event handler.
3275
3276 By default, this property is \c false.
3277
3278 \sa {Drag and Drop}
3279*/
3280bool QWidget::acceptDrops() const
3281{
3282 return testAttribute(Qt::WA_AcceptDrops);
3283}
3284
3285void QWidget::setAcceptDrops(bool on)
3286{
3287 setAttribute(Qt::WA_AcceptDrops, on);
3288
3289}
3290
3291/*!
3292 Disables widget input events if \a disable is true; otherwise
3293 enables input events.
3294
3295 See the \l enabled documentation for more information.
3296
3297 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3298*/
3299void QWidget::setDisabled(bool disable)
3300{
3301 setEnabled(!disable);
3302}
3303
3304/*!
3305 \property QWidget::frameGeometry
3306 \brief geometry of the widget relative to its parent including any
3307 window frame
3308
3309 See the \l{Window Geometry} documentation for an overview of geometry
3310 issues with windows.
3311
3312 By default, this property contains a value that depends on the user's
3313 platform and screen geometry.
3314
3315 \sa geometry(), x(), y(), pos()
3316*/
3317QRect QWidget::frameGeometry() const
3318{
3319 Q_D(const QWidget);
3320 if (isWindow() && ! (windowType() == Qt::Popup)) {
3321 QRect fs = d->frameStrut();
3322 return QRect(data->crect.x() - fs.left(),
3323 data->crect.y() - fs.top(),
3324 data->crect.width() + fs.left() + fs.right(),
3325 data->crect.height() + fs.top() + fs.bottom());
3326 }
3327 return data->crect;
3328}
3329
3330/*!
3331 \property QWidget::x
3332
3333 \brief the x coordinate of the widget relative to its parent including
3334 any window frame
3335
3336 See the \l{Window Geometry} documentation for an overview of geometry
3337 issues with windows.
3338
3339 By default, this property has a value of 0.
3340
3341 \sa frameGeometry, y, pos
3342*/
3343int QWidget::x() const
3344{
3345 Q_D(const QWidget);
3346 if (isWindow() && ! (windowType() == Qt::Popup))
3347 return data->crect.x() - d->frameStrut().left();
3348 return data->crect.x();
3349}
3350
3351/*!
3352 \property QWidget::y
3353 \brief the y coordinate of the widget relative to its parent and
3354 including any window frame
3355
3356 See the \l{Window Geometry} documentation for an overview of geometry
3357 issues with windows.
3358
3359 By default, this property has a value of 0.
3360
3361 \sa frameGeometry, x, pos
3362*/
3363int QWidget::y() const
3364{
3365 Q_D(const QWidget);
3366 if (isWindow() && ! (windowType() == Qt::Popup))
3367 return data->crect.y() - d->frameStrut().top();
3368 return data->crect.y();
3369}
3370
3371/*!
3372 \property QWidget::pos
3373 \brief the position of the widget within its parent widget
3374
3375 If the widget is a window, the position is that of the widget on
3376 the desktop, including its frame.
3377
3378 When changing the position, the widget, if visible, receives a
3379 move event (moveEvent()) immediately. If the widget is not
3380 currently visible, it is guaranteed to receive an event before it
3381 is shown.
3382
3383 By default, this property contains a position that refers to the
3384 origin.
3385
3386 \warning Calling move() or setGeometry() inside moveEvent() can
3387 lead to infinite recursion.
3388
3389 See the \l{Window Geometry} documentation for an overview of geometry
3390 issues with windows.
3391
3392 \sa frameGeometry, size, x(), y()
3393*/
3394QPoint QWidget::pos() const
3395{
3396 Q_D(const QWidget);
3397 QPoint result = data->crect.topLeft();
3398 if (isWindow() && ! (windowType() == Qt::Popup))
3399 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3400 result -= d->frameStrut().topLeft();
3401 return result;
3402}
3403
3404/*!
3405 \property QWidget::geometry
3406 \brief the geometry of the widget relative to its parent and
3407 excluding the window frame
3408
3409 When changing the geometry, the widget, if visible, receives a
3410 move event (moveEvent()) and/or a resize event (resizeEvent())
3411 immediately. If the widget is not currently visible, it is
3412 guaranteed to receive appropriate events before it is shown.
3413
3414 The size component is adjusted if it lies outside the range
3415 defined by minimumSize() and maximumSize().
3416
3417 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3418 can lead to infinite recursion.
3419
3420 See the \l{Window Geometry} documentation for an overview of geometry
3421 issues with windows.
3422
3423 By default, this property contains a value that depends on the user's
3424 platform and screen geometry.
3425
3426 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3427 resizeEvent(), minimumSize(), maximumSize()
3428*/
3429
3430/*!
3431 \property QWidget::normalGeometry
3432
3433 \brief the geometry of the widget as it will appear when shown as
3434 a normal (not maximized or full screen) top-level widget
3435
3436 For child widgets this property always holds an empty rectangle.
3437
3438 By default, this property contains an empty rectangle.
3439
3440 \sa QWidget::windowState(), QWidget::geometry
3441*/
3442
3443/*!
3444 \property QWidget::size
3445 \brief the size of the widget excluding any window frame
3446
3447 If the widget is visible when it is being resized, it receives a resize event
3448 (resizeEvent()) immediately. If the widget is not currently
3449 visible, it is guaranteed to receive an event before it is shown.
3450
3451 The size is adjusted if it lies outside the range defined by
3452 minimumSize() and maximumSize().
3453
3454 By default, this property contains a value that depends on the user's
3455 platform and screen geometry.
3456
3457 \warning Calling resize() or setGeometry() inside resizeEvent() can
3458 lead to infinite recursion.
3459
3460 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3461 appear on screen. This also applies to windows.
3462
3463 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3464*/
3465
3466/*!
3467 \property QWidget::width
3468 \brief the width of the widget excluding any window frame
3469
3470 See the \l{Window Geometry} documentation for an overview of geometry
3471 issues with windows.
3472
3473 \note Do not use this function to find the width of a screen on
3474 a multi-screen desktop. See QScreen for details.
3475
3476 By default, this property contains a value that depends on the user's
3477 platform and screen geometry.
3478
3479 \sa geometry, height, size
3480*/
3481
3482/*!
3483 \property QWidget::height
3484 \brief the height of the widget excluding any window frame
3485
3486 See the \l{Window Geometry} documentation for an overview of geometry
3487 issues with windows.
3488
3489 By default, this property contains a value that depends on the user's
3490 platform and \l{screen geometry}{QScreen::geometry}.
3491
3492 \sa geometry, width, size
3493*/
3494
3495/*!
3496 \property QWidget::rect
3497 \brief the internal geometry of the widget excluding any window
3498 frame
3499
3500 The rect property equals QRect(0, 0, width(), height()).
3501
3502 See the \l{Window Geometry} documentation for an overview of geometry
3503 issues with windows.
3504
3505 By default, this property contains a value that depends on the user's
3506 platform and screen geometry.
3507
3508 \sa size
3509*/
3510
3511
3512QRect QWidget::normalGeometry() const
3513{
3514 Q_D(const QWidget);
3515 if (!d->extra || !d->extra->topextra)
3516 return QRect();
3517
3518 if (!isMaximized() && !isFullScreen())
3519 return geometry();
3520
3521 return d->topData()->normalGeometry;
3522}
3523
3524
3525/*!
3526 \property QWidget::childrenRect
3527 \brief the bounding rectangle of the widget's children
3528
3529 Hidden children are excluded.
3530
3531 By default, for a widget with no children, this property contains a
3532 rectangle with zero width and height located at the origin.
3533
3534 \sa childrenRegion(), geometry()
3535*/
3536
3537QRect QWidget::childrenRect() const
3538{
3539 Q_D(const QWidget);
3540 QRect r(0, 0, 0, 0);
3541 for (int i = 0; i < d->children.size(); ++i) {
3542 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3543 if (w && !w->isWindow() && !w->isHidden())
3544 r |= w->geometry();
3545 }
3546 return r;
3547}
3548
3549/*!
3550 \property QWidget::childrenRegion
3551 \brief the combined region occupied by the widget's children
3552
3553 Hidden children are excluded.
3554
3555 By default, for a widget with no children, this property contains an
3556 empty region.
3557
3558 \sa childrenRect(), geometry(), mask()
3559*/
3560
3561QRegion QWidget::childrenRegion() const
3562{
3563 Q_D(const QWidget);
3564 QRegion r;
3565 for (int i = 0; i < d->children.size(); ++i) {
3566 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3567 if (w && !w->isWindow() && !w->isHidden()) {
3568 QRegion mask = w->mask();
3569 if (mask.isEmpty())
3570 r |= w->geometry();
3571 else
3572 r |= mask.translated(w->pos());
3573 }
3574 }
3575 return r;
3576}
3577
3578
3579/*!
3580 \property QWidget::minimumSize
3581 \brief the widget's minimum size
3582
3583 The widget cannot be resized to a smaller size than the minimum
3584 widget size. The widget's size is forced to the minimum size if
3585 the current size is smaller.
3586
3587 The minimum size set by this function will override the minimum size
3588 defined by QLayout. In order to unset the minimum size, use a
3589 value of \c{QSize(0, 0)}.
3590
3591 By default, this property contains a size with zero width and height.
3592
3593 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3594*/
3595
3596QSize QWidget::minimumSize() const
3597{
3598 Q_D(const QWidget);
3599 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3600}
3601
3602/*!
3603 \property QWidget::maximumSize
3604 \brief the widget's maximum size in pixels
3605
3606 The widget cannot be resized to a larger size than the maximum
3607 widget size.
3608
3609 By default, this property contains a size in which both width and height
3610 have values of 16777215.
3611
3612 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3613 of widgets.
3614
3615 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3616*/
3617
3618QSize QWidget::maximumSize() const
3619{
3620 Q_D(const QWidget);
3621 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3622 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3623}
3624
3625
3626/*!
3627 \property QWidget::minimumWidth
3628 \brief the widget's minimum width in pixels
3629
3630 This property corresponds to the width held by the \l minimumSize property.
3631
3632 By default, this property has a value of 0.
3633
3634 \sa minimumSize, minimumHeight
3635*/
3636
3637/*!
3638 \property QWidget::minimumHeight
3639 \brief the widget's minimum height in pixels
3640
3641 This property corresponds to the height held by the \l minimumSize property.
3642
3643 By default, this property has a value of 0.
3644
3645 \sa minimumSize, minimumWidth
3646*/
3647
3648/*!
3649 \property QWidget::maximumWidth
3650 \brief the widget's maximum width in pixels
3651
3652 This property corresponds to the width held by the \l maximumSize property.
3653
3654 By default, this property contains a value of 16777215.
3655
3656 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3657 of widgets.
3658
3659 \sa maximumSize, maximumHeight
3660*/
3661
3662/*!
3663 \property QWidget::maximumHeight
3664 \brief the widget's maximum height in pixels
3665
3666 This property corresponds to the height held by the \l maximumSize property.
3667
3668 By default, this property contains a value of 16777215.
3669
3670 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3671 of widgets.
3672
3673 \sa maximumSize, maximumWidth
3674*/
3675
3676/*!
3677 \property QWidget::sizeIncrement
3678 \brief the size increment of the widget
3679
3680 When the user resizes the window, the size will move in steps of
3681 sizeIncrement().width() pixels horizontally and
3682 sizeIncrement.height() pixels vertically, with baseSize() as the
3683 basis. Preferred widget sizes are for non-negative integers \e i
3684 and \e j:
3685 \snippet code/src_gui_kernel_qwidget.cpp 2
3686
3687 Note that while you can set the size increment for all widgets, it
3688 only affects windows.
3689
3690 By default, this property contains a size with zero width and height.
3691
3692 \warning The size increment has no effect under Windows, and may
3693 be disregarded by the window manager on X11.
3694
3695 \sa size, minimumSize, maximumSize
3696*/
3697QSize QWidget::sizeIncrement() const
3698{
3699 Q_D(const QWidget);
3700 return (d->extra && d->extra->topextra)
3701 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3702 : QSize(0, 0);
3703}
3704
3705/*!
3706 \property QWidget::baseSize
3707 \brief the base size of the widget
3708
3709 The base size is used to calculate a proper widget size if the
3710 widget defines sizeIncrement().
3711
3712 By default, for a newly-created widget, this property contains a size with
3713 zero width and height.
3714
3715 \sa setSizeIncrement()
3716*/
3717
3718QSize QWidget::baseSize() const
3719{
3720 Q_D(const QWidget);
3721 return (d->extra && d->extra->topextra)
3722 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3723 : QSize(0, 0);
3724}
3725
3726bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3727{
3728 Q_Q(QWidget);
3729
3730 int mw = minw, mh = minh;
3731 if (mw == QWIDGETSIZE_MAX)
3732 mw = 0;
3733 if (mh == QWIDGETSIZE_MAX)
3734 mh = 0;
3735 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3736 qWarning("QWidget::setMinimumSize: (%s/%s) "
3737 "The largest allowed size is (%d,%d)",
3738 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3739 QWIDGETSIZE_MAX);
3740 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3741 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3742 }
3743 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3744 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3745 "are not possible",
3746 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3747 minw = mw = qMax(minw, 0);
3748 minh = mh = qMax(minh, 0);
3749 }
3750 createExtra();
3751 if (extra->minw == mw && extra->minh == mh)
3752 return false;
3753 extra->minw = mw;
3754 extra->minh = mh;
3755 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3756 return true;
3757}
3758
3759void QWidgetPrivate::setConstraints_sys()
3760{
3761 Q_Q(QWidget);
3762 if (extra && q->windowHandle()) {
3763 QWindow *win = q->windowHandle();
3764 QWindowPrivate *winp = qt_window_private(win);
3765
3766 winp->minimumSize = QSize(extra->minw, extra->minh);
3767 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3768
3769 if (extra->topextra) {
3770 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3771 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3772 }
3773
3774 if (winp->platformWindow) {
3775 fixPosIncludesFrame();
3776 winp->platformWindow->propagateSizeHints();
3777 }
3778 }
3779}
3780
3781/*!
3782 \overload
3783
3784 This function corresponds to setMinimumSize(QSize(minw, minh)).
3785 Sets the minimum width to \a minw and the minimum height to \a
3786 minh.
3787*/
3788
3789void QWidget::setMinimumSize(int minw, int minh)
3790{
3791 Q_D(QWidget);
3792 if (!d->setMinimumSize_helper(minw, minh))
3793 return;
3794
3795 if (isWindow())
3796 d->setConstraints_sys();
3797 if (minw > width() || minh > height()) {
3798 bool resized = testAttribute(Qt::WA_Resized);
3799 bool maximized = isMaximized();
3800 resize(qMax(minw,width()), qMax(minh,height()));
3801 setAttribute(Qt::WA_Resized, resized); //not a user resize
3802 if (maximized)
3803 data->window_state = data->window_state | Qt::WindowMaximized;
3804 }
3805#if QT_CONFIG(graphicsview)
3806 if (d->extra) {
3807 if (d->extra->proxyWidget)
3808 d->extra->proxyWidget->setMinimumSize(minw, minh);
3809 }
3810#endif
3811 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3812}
3813
3814bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3815{
3816 Q_Q(QWidget);
3817 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3818 qWarning("QWidget::setMaximumSize: (%s/%s) "
3819 "The largest allowed size is (%d,%d)",
3820 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3821 QWIDGETSIZE_MAX);
3822 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
3823 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
3824 }
3825 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
3826 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
3827 "are not possible",
3828 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
3829 maxw = qMax(maxw, 0);
3830 maxh = qMax(maxh, 0);
3831 }
3832 createExtra();
3833 if (extra->maxw == maxw && extra->maxh == maxh)
3834 return false;
3835 extra->maxw = maxw;
3836 extra->maxh = maxh;
3837 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
3838 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
3839 return true;
3840}
3841
3842/*!
3843 \overload
3844
3845 This function corresponds to setMaximumSize(QSize(\a maxw, \a
3846 maxh)). Sets the maximum width to \a maxw and the maximum height
3847 to \a maxh.
3848*/
3849void QWidget::setMaximumSize(int maxw, int maxh)
3850{
3851 Q_D(QWidget);
3852 if (!d->setMaximumSize_helper(maxw, maxh))
3853 return;
3854
3855 if (isWindow())
3856 d->setConstraints_sys();
3857 if (maxw < width() || maxh < height()) {
3858 bool resized = testAttribute(Qt::WA_Resized);
3859 resize(qMin(maxw,width()), qMin(maxh,height()));
3860 setAttribute(Qt::WA_Resized, resized); //not a user resize
3861 }
3862
3863#if QT_CONFIG(graphicsview)
3864 if (d->extra) {
3865 if (d->extra->proxyWidget)
3866 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
3867 }
3868#endif
3869
3870 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3871}
3872
3873/*!
3874 \overload
3875
3876 Sets the x (width) size increment to \a w and the y (height) size
3877 increment to \a h.
3878*/
3879void QWidget::setSizeIncrement(int w, int h)
3880{
3881 Q_D(QWidget);
3882 d->createTLExtra();
3883 QTLWExtra* x = d->topData();
3884 if (x->incw == w && x->inch == h)
3885 return;
3886 x->incw = w;
3887 x->inch = h;
3888 if (isWindow())
3889 d->setConstraints_sys();
3890}
3891
3892/*!
3893 \overload
3894
3895 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
3896 the widgets base size to width \a basew and height \a baseh.
3897*/
3898void QWidget::setBaseSize(int basew, int baseh)
3899{
3900 Q_D(QWidget);
3901 d->createTLExtra();
3902 QTLWExtra* x = d->topData();
3903 if (x->basew == basew && x->baseh == baseh)
3904 return;
3905 x->basew = basew;
3906 x->baseh = baseh;
3907 if (isWindow())
3908 d->setConstraints_sys();
3909}
3910
3911/*!
3912 Sets both the minimum and maximum sizes of the widget to \a s,
3913 thereby preventing it from ever growing or shrinking.
3914
3915 This will override the default size constraints set by QLayout.
3916
3917 To remove constraints, set the size to QWIDGETSIZE_MAX.
3918
3919 Alternatively, if you want the widget to have a
3920 fixed size based on its contents, you can call
3921 QLayout::setSizeConstraint(QLayout::SetFixedSize);
3922
3923 \sa maximumSize, minimumSize
3924*/
3925
3926void QWidget::setFixedSize(const QSize & s)
3927{
3928 setFixedSize(s.width(), s.height());
3929}
3930
3931
3932/*!
3933 \fn void QWidget::setFixedSize(int w, int h)
3934 \overload
3935
3936 Sets the width of the widget to \a w and the height to \a h.
3937*/
3938
3939void QWidget::setFixedSize(int w, int h)
3940{
3941 Q_D(QWidget);
3942 bool minSizeSet = d->setMinimumSize_helper(w, h);
3943 bool maxSizeSet = d->setMaximumSize_helper(w, h);
3944 if (!minSizeSet && !maxSizeSet)
3945 return;
3946
3947 if (isWindow())
3948 d->setConstraints_sys();
3949 else
3950 d->updateGeometry_helper(true);
3951
3952 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
3953 resize(w, h);
3954}
3955
3956void QWidget::setMinimumWidth(int w)
3957{
3958 Q_D(QWidget);
3959 d->createExtra();
3960 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
3961 setMinimumSize(w, minimumSize().height());
3962 d->extra->explicitMinSize = expl;
3963}
3964
3965void QWidget::setMinimumHeight(int h)
3966{
3967 Q_D(QWidget);
3968 d->createExtra();
3969 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
3970 setMinimumSize(minimumSize().width(), h);
3971 d->extra->explicitMinSize = expl;
3972}
3973
3974void QWidget::setMaximumWidth(int w)
3975{
3976 Q_D(QWidget);
3977 d->createExtra();
3978 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
3979 setMaximumSize(w, maximumSize().height());
3980 d->extra->explicitMaxSize = expl;
3981}
3982
3983void QWidget::setMaximumHeight(int h)
3984{
3985 Q_D(QWidget);
3986 d->createExtra();
3987 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
3988 setMaximumSize(maximumSize().width(), h);
3989 d->extra->explicitMaxSize = expl;
3990}
3991
3992/*!
3993 Sets both the minimum and maximum width of the widget to \a w
3994 without changing the heights. Provided for convenience.
3995
3996 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
3997*/
3998
3999void QWidget::setFixedWidth(int w)
4000{
4001 Q_D(QWidget);
4002 d->createExtra();
4003 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4004 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4005 setMinimumSize(w, minimumSize().height());
4006 setMaximumSize(w, maximumSize().height());
4007 d->extra->explicitMinSize = explMin;
4008 d->extra->explicitMaxSize = explMax;
4009}
4010
4011
4012/*!
4013 Sets both the minimum and maximum heights of the widget to \a h
4014 without changing the widths. Provided for convenience.
4015
4016 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4017*/
4018
4019void QWidget::setFixedHeight(int h)
4020{
4021 Q_D(QWidget);
4022 d->createExtra();
4023 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4024 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4025 setMinimumSize(minimumSize().width(), h);
4026 setMaximumSize(maximumSize().width(), h);
4027 d->extra->explicitMinSize = explMin;
4028 d->extra->explicitMaxSize = explMax;
4029}
4030
4031
4032/*!
4033 Translates the widget coordinate \a pos to the coordinate system
4034 of \a parent. The \a parent must not be \nullptr and must be a parent
4035 of the calling widget.
4036
4037 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4038 \since 6.0
4039*/
4040
4041QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4042{
4043 QPointF p = pos;
4044 if (parent) {
4045 const QWidget * w = this;
4046 while (w != parent) {
4047 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPointF &pos)",
4048 "parent must be in parent hierarchy");
4049 p = w->mapToParent(p);
4050 w = w->parentWidget();
4051 }
4052 }
4053 return p;
4054}
4055
4056/*!
4057 \overload
4058*/
4059QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4060{
4061 return mapTo(parent, QPointF(pos)).toPoint();
4062}
4063
4064/*!
4065 Translates the widget coordinate \a pos from the coordinate system
4066 of \a parent to this widget's coordinate system. The \a parent
4067 must not be \nullptr and must be a parent of the calling widget.
4068
4069 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4070 \since 6.0
4071*/
4072
4073QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4074{
4075 QPointF p(pos);
4076 if (parent) {
4077 const QWidget * w = this;
4078 while (w != parent) {
4079 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4080 "parent must be in parent hierarchy");
4081
4082 p = w->mapFromParent(p);
4083 w = w->parentWidget();
4084 }
4085 }
4086 return p;
4087}
4088
4089/*!
4090 \overload
4091*/
4092QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4093{
4094 return mapFrom(parent, QPointF(pos)).toPoint();
4095}
4096
4097/*!
4098 Translates the widget coordinate \a pos to a coordinate in the
4099 parent widget.
4100
4101 Same as mapToGlobal() if the widget has no parent.
4102
4103 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4104 \since 6.0
4105*/
4106
4107QPointF QWidget::mapToParent(const QPointF &pos) const
4108{
4109 return pos + QPointF(data->crect.topLeft());
4110}
4111
4112/*!
4113 \overload
4114*/
4115QPoint QWidget::mapToParent(const QPoint &pos) const
4116{
4117 return pos + data->crect.topLeft();
4118}
4119
4120/*!
4121 Translates the parent widget coordinate \a pos to widget
4122 coordinates.
4123
4124 Same as mapFromGlobal() if the widget has no parent.
4125
4126 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4127 \since 6.0
4128*/
4129
4130QPointF QWidget::mapFromParent(const QPointF &pos) const
4131{
4132 return pos - QPointF(data->crect.topLeft());
4133}
4134
4135/*!
4136 \overload
4137*/
4138QPoint QWidget::mapFromParent(const QPoint &pos) const
4139{
4140 return pos - data->crect.topLeft();
4141}
4142
4143
4144/*!
4145 Returns the window for this widget, i.e. the next ancestor widget
4146 that has (or could have) a window-system frame.
4147
4148 If the widget is a window, the widget itself is returned.
4149
4150 Typical usage is changing the window title:
4151
4152 \snippet code/src_gui_kernel_qwidget.cpp 3
4153
4154 \sa isWindow()
4155*/
4156
4157QWidget *QWidget::window() const
4158{
4159 QWidget *w = const_cast<QWidget *>(this);
4160 QWidget *p = w->parentWidget();
4161 while (!w->isWindow() && p) {
4162 w = p;
4163 p = p->parentWidget();
4164 }
4165 return w;
4166}
4167
4168/*!
4169 \since 4.4
4170
4171 Returns the native parent for this widget, i.e. the next ancestor widget
4172 that has a system identifier, or \nullptr if it does not have any native
4173 parent.
4174
4175 \sa effectiveWinId()
4176*/
4177QWidget *QWidget::nativeParentWidget() const
4178{
4179 QWidget *parent = parentWidget();
4180 while (parent && !parent->internalWinId())
4181 parent = parent->parentWidget();
4182 return parent;
4183}
4184
4185/*! \fn QWidget *QWidget::topLevelWidget() const
4186 \obsolete
4187
4188 Use window() instead.
4189*/
4190
4191
4192
4193/*!
4194 Returns the background role of the widget.
4195
4196 The background role defines the brush from the widget's \l palette that
4197 is used to render the background.
4198
4199 If no explicit background role is set, the widget inherts its parent
4200 widget's background role.
4201
4202 \sa setBackgroundRole(), foregroundRole()
4203 */
4204QPalette::ColorRole QWidget::backgroundRole() const
4205{
4206
4207 const QWidget *w = this;
4208 do {
4209 QPalette::ColorRole role = w->d_func()->bg_role;
4210 if (role != QPalette::NoRole)
4211 return role;
4212 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4213 break;
4214 w = w->parentWidget();
4215 } while (w);
4216 return QPalette::Window;
4217}
4218
4219/*!
4220 Sets the background role of the widget to \a role.
4221
4222 The background role defines the brush from the widget's \l palette that
4223 is used to render the background.
4224
4225 If \a role is QPalette::NoRole, then the widget inherits its
4226 parent's background role.
4227
4228 Note that styles are free to choose any color from the palette.
4229 You can modify the palette or set a style sheet if you don't
4230 achieve the result you want with setBackgroundRole().
4231
4232 \sa backgroundRole(), foregroundRole()
4233 */
4234
4235void QWidget::setBackgroundRole(QPalette::ColorRole role)
4236{
4237 Q_D(QWidget);
4238 d->bg_role = role;
4239 d->updateSystemBackground();
4240 d->propagatePaletteChange();
4241 d->updateIsOpaque();
4242}
4243
4244/*!
4245 Returns the foreground role.
4246
4247 The foreground role defines the color from the widget's \l palette that
4248 is used to draw the foreground.
4249
4250 If no explicit foreground role is set, the function returns a role
4251 that contrasts with the background role.
4252
4253 \sa setForegroundRole(), backgroundRole()
4254 */
4255QPalette::ColorRole QWidget::foregroundRole() const
4256{
4257 Q_D(const QWidget);
4258 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4259 if (rl != QPalette::NoRole)
4260 return rl;
4261 QPalette::ColorRole role = QPalette::WindowText;
4262 switch (backgroundRole()) {
4263 case QPalette::Button:
4264 role = QPalette::ButtonText;
4265 break;
4266 case QPalette::Base:
4267 role = QPalette::Text;
4268 break;
4269 case QPalette::Dark:
4270 case QPalette::Shadow:
4271 role = QPalette::Light;
4272 break;
4273 case QPalette::Highlight:
4274 role = QPalette::HighlightedText;
4275 break;
4276 case QPalette::ToolTipBase:
4277 role = QPalette::ToolTipText;
4278 break;
4279 default:
4280 ;
4281 }
4282 return role;
4283}
4284
4285/*!
4286 Sets the foreground role of the widget to \a role.
4287
4288 The foreground role defines the color from the widget's \l palette that
4289 is used to draw the foreground.
4290
4291 If \a role is QPalette::NoRole, the widget uses a foreground role
4292 that contrasts with the background role.
4293
4294 Note that styles are free to choose any color from the palette.
4295 You can modify the palette or set a style sheet if you don't
4296 achieve the result you want with setForegroundRole().
4297
4298 \sa foregroundRole(), backgroundRole()
4299 */
4300void QWidget::setForegroundRole(QPalette::ColorRole role)
4301{
4302 Q_D(QWidget);
4303 d->fg_role = role;
4304 d->updateSystemBackground();
4305 d->propagatePaletteChange();
4306}
4307
4308/*!
4309 \property QWidget::palette
4310 \brief the widget's palette
4311
4312 This property describes the widget's palette. The palette is used by the
4313 widget's style when rendering standard components, and is available as a
4314 means to ensure that custom widgets can maintain consistency with the
4315 native platform's look and feel. It's common that different platforms, or
4316 different styles, have different palettes.
4317
4318 When you assign a new palette to a widget, the color roles from this
4319 palette are combined with the widget's default palette to form the
4320 widget's final palette. The palette entry for the widget's background role
4321 is used to fill the widget's background (see QWidget::autoFillBackground),
4322 and the foreground role initializes QPainter's pen.
4323
4324 The default depends on the system environment. QApplication maintains a
4325 system/theme palette which serves as a default for all widgets. There may
4326 also be special palette defaults for certain types of widgets (e.g., on
4327 Windows Vista, all classes that derive from QMenuBar have a special
4328 default palette). You can also define default palettes for widgets
4329 yourself by passing a custom palette and the name of a widget to
4330 QApplication::setPalette(). Finally, the style always has the option of
4331 polishing the palette as it's assigned (see QStyle::polish()).
4332
4333 QWidget propagates explicit palette roles from parent to child. If you
4334 assign a brush or color to a specific role on a palette and assign that
4335 palette to a widget, that role will propagate to all the widget's
4336 children, overriding any system defaults for that role. Note that palettes
4337 by default don't propagate to windows (see isWindow()) unless the
4338 Qt::WA_WindowPropagation attribute is enabled.
4339
4340 QWidget's palette propagation is similar to its font propagation.
4341
4342 The current style, which is used to render the content of all standard Qt
4343 widgets, is free to choose colors and brushes from the widget palette, or
4344 in some cases, to ignore the palette (partially, or completely). In
4345 particular, certain styles like GTK style, Mac style, and Windows Vista
4346 style, depend on third party APIs to render the content of widgets,
4347 and these styles typically do not follow the palette. Because of this,
4348 assigning roles to a widget's palette is not guaranteed to change the
4349 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4350
4351 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4352 When using style sheets, the palette of a widget can be customized using
4353 the "color", "background-color", "selection-color",
4354 "selection-background-color" and "alternate-background-color".
4355
4356 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4357*/
4358const QPalette &QWidget::palette() const
4359{
4360 if (!isEnabled()) {
4361 data->pal.setCurrentColorGroup(QPalette::Disabled);
4362 } else if ((!isVisible() || isActiveWindow())
4363#if defined(Q_OS_WIN)
4364 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4365#endif
4366 ) {
4367 data->pal.setCurrentColorGroup(QPalette::Active);
4368 } else {
4369 data->pal.setCurrentColorGroup(QPalette::Inactive);
4370 }
4371 return data->pal;
4372}
4373
4374void QWidget::setPalette(const QPalette &palette)
4375{
4376 Q_D(QWidget);
4377 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4378
4379 // Determine which palette is inherited from this widget's ancestors and
4380 // QApplication::palette, resolve this against \a palette (attributes from
4381 // the inherited palette are copied over this widget's palette). Then
4382 // propagate this palette to this widget's children.
4383 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4384 QPalette resolvedPalette = palette.resolve(naturalPalette);
4385 d->setPalette_helper(resolvedPalette);
4386}
4387
4388/*!
4389 \internal
4390
4391 Returns the palette that the widget \a w inherits from its ancestors and
4392 QApplication::palette. \a inheritedMask is the combination of the widget's
4393 ancestors palette request masks (i.e., which attributes from the parent
4394 widget's palette are implicitly imposed on this widget by the user). Note
4395 that this font does not take into account the palette set on \a w itself.
4396*/
4397QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4398{
4399 Q_Q(const QWidget);
4400
4401 const bool useStyleSheetPropagationInWidgetStyles =
4402 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4403
4404 QPalette naturalPalette = QApplication::palette(q);
4405 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4406 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4407#if QT_CONFIG(graphicsview)
4408 || (extra && extra->proxyWidget)
4409#endif // QT_CONFIG(graphicsview)
4410 )) {
4411 if (QWidget *p = q->parentWidget()) {
4412 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4413 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4414 QPalette inheritedPalette = p->palette();
4415 inheritedPalette.setResolveMask(inheritedMask);
4416 naturalPalette = inheritedPalette.resolve(naturalPalette);
4417 } else {
4418 naturalPalette = p->palette();
4419 }
4420 }
4421 }
4422#if QT_CONFIG(graphicsview)
4423 else if (extra && extra->proxyWidget) {
4424 QPalette inheritedPalette = extra->proxyWidget->palette();
4425 inheritedPalette.setResolveMask(inheritedMask);
4426 naturalPalette = inheritedPalette.resolve(naturalPalette);
4427 }
4428#endif // QT_CONFIG(graphicsview)
4429 }
4430 naturalPalette.setResolveMask(0);
4431 return naturalPalette;
4432}
4433/*!
4434 \internal
4435
4436 Determine which palette is inherited from this widget's ancestors and
4437 QApplication::palette, resolve this against this widget's palette
4438 (attributes from the inherited palette are copied over this widget's
4439 palette). Then propagate this palette to this widget's children.
4440*/
4441void QWidgetPrivate::resolvePalette()
4442{
4443 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4444 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4445 setPalette_helper(resolvedPalette);
4446}
4447
4448void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4449{
4450 Q_Q(QWidget);
4451 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4452 return;
4453 data.pal = palette;
4454 updateSystemBackground();
4455 propagatePaletteChange();
4456 updateIsOpaque();
4457 q->update();
4458 updateIsOpaque();
4459}
4460
4461void QWidgetPrivate::updateSystemBackground()
4462{
4463}
4464
4465/*!
4466 \property QWidget::font
4467 \brief the font currently set for the widget
4468
4469 This property describes the widget's requested font. The font is used by
4470 the widget's style when rendering standard components, and is available as
4471 a means to ensure that custom widgets can maintain consistency with the
4472 native platform's look and feel. It's common that different platforms, or
4473 different styles, define different fonts for an application.
4474
4475 When you assign a new font to a widget, the properties from this font are
4476 combined with the widget's default font to form the widget's final
4477 font. You can call fontInfo() to get a copy of the widget's final
4478 font. The final font is also used to initialize QPainter's font.
4479
4480 The default depends on the system environment. QApplication maintains a
4481 system/theme font which serves as a default for all widgets. There may
4482 also be special font defaults for certain types of widgets. You can also
4483 define default fonts for widgets yourself by passing a custom font and the
4484 name of a widget to QApplication::setFont(). Finally, the font is matched
4485 against Qt's font database to find the best match.
4486
4487 QWidget propagates explicit font properties from parent to child. If you
4488 change a specific property on a font and assign that font to a widget,
4489 that property will propagate to all the widget's children, overriding any
4490 system defaults for that property. Note that fonts by default don't
4491 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4492 attribute is enabled.
4493
4494 QWidget's font propagation is similar to its palette propagation.
4495
4496 The current style, which is used to render the content of all standard Qt
4497 widgets, is free to choose to use the widget font, or in some cases, to
4498 ignore it (partially, or completely). In particular, certain styles like
4499 GTK style, Mac style, and Windows Vista style, apply special
4500 modifications to the widget font to match the platform's native look and
4501 feel. Because of this, assigning properties to a widget's font is not
4502 guaranteed to change the appearance of the widget. Instead, you may choose
4503 to apply a \l styleSheet.
4504
4505 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4506 style sheets will take precedence if the settings conflict.
4507
4508 \sa fontInfo(), fontMetrics()
4509*/
4510
4511void QWidget::setFont(const QFont &font)
4512{
4513 Q_D(QWidget);
4514
4515#ifndef QT_NO_STYLE_STYLESHEET
4516 const QStyleSheetStyle* style;
4517 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4518 style->saveWidgetFont(this, font);
4519#endif
4520
4521 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4522
4523 // Determine which font is inherited from this widget's ancestors and
4524 // QApplication::font, resolve this against \a font (attributes from the
4525 // inherited font are copied over). Then propagate this font to this
4526 // widget's children.
4527 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4528 QFont resolvedFont = font.resolve(naturalFont);
4529 d->setFont_helper(resolvedFont);
4530}
4531
4532/*
4533 \internal
4534
4535 Returns the font that the widget \a w inherits from its ancestors and
4536 QApplication::font. \a inheritedMask is the combination of the widget's
4537 ancestors font request masks (i.e., which attributes from the parent
4538 widget's font are implicitly imposed on this widget by the user). Note
4539 that this font does not take into account the font set on \a w itself.
4540
4541 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4542 is applied, fonts are not propagated anymore
4543*/
4544QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4545{
4546 Q_Q(const QWidget);
4547
4548 const bool useStyleSheetPropagationInWidgetStyles =
4549 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4550
4551 QFont naturalFont = QApplication::font(q);
4552 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4553 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4554#if QT_CONFIG(graphicsview)
4555 || (extra && extra->proxyWidget)
4556#endif // QT_CONFIG(graphicsview)
4557 )) {
4558 if (QWidget *p = q->parentWidget()) {
4559 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4560 if (!naturalFont.isCopyOf(QApplication::font())) {
4561 if (inheritedMask != 0) {
4562 QFont inheritedFont = p->font();
4563 inheritedFont.setResolveMask(inheritedMask);
4564 naturalFont = inheritedFont.resolve(naturalFont);
4565 } // else nothing to do (naturalFont = naturalFont)
4566 } else {
4567 naturalFont = p->font();
4568 }
4569 }
4570 }
4571#if QT_CONFIG(graphicsview)
4572 else if (extra && extra->proxyWidget) {
4573 if (inheritedMask != 0) {
4574 QFont inheritedFont = extra->proxyWidget->font();
4575 inheritedFont.setResolveMask(inheritedMask);
4576 naturalFont = inheritedFont.resolve(naturalFont);
4577 } // else nothing to do (naturalFont = naturalFont)
4578 }
4579#endif // QT_CONFIG(graphicsview)
4580 }
4581 naturalFont.setResolveMask(0);
4582 return naturalFont;
4583}
4584
4585/*!
4586 \internal
4587
4588 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4589*/
4590QFont QWidgetPrivate::localFont() const
4591{
4592 QFont localfont = data.fnt;
4593 localfont.setResolveMask(directFontResolveMask);
4594 return localfont;
4595}
4596
4597/*!
4598 \internal
4599
4600 Determine which font is implicitly imposed on this widget by its ancestors
4601 and QApplication::font, resolve this against its own font (attributes from
4602 the implicit font are copied over). Then propagate this font to this
4603 widget's children.
4604*/
4605void QWidgetPrivate::resolveFont()
4606{
4607 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4608 QFont resolvedFont = localFont().resolve(naturalFont);
4609 setFont_helper(resolvedFont);
4610}
4611
4612/*!
4613 \internal
4614
4615 Assign \a font to this widget, and propagate it to all children, except
4616 style sheet widgets (handled differently) and windows that don't enable
4617 window propagation. \a implicitMask is the union of all ancestor widgets'
4618 font request masks, and determines which attributes from this widget's
4619 font should propagate.
4620*/
4621void QWidgetPrivate::updateFont(const QFont &font)
4622{
4623 Q_Q(QWidget);
4624#ifndef QT_NO_STYLE_STYLESHEET
4625 const QStyleSheetStyle* cssStyle;
4626 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4627 const bool useStyleSheetPropagationInWidgetStyles =
4628 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4629#endif
4630
4631 data.fnt = QFont(font, q);
4632
4633 // Combine new mask with natural mask and propagate to children.
4634#if QT_CONFIG(graphicsview)
4635 if (!q->parentWidget() && extra && extra->proxyWidget) {
4636 QGraphicsProxyWidget *p = extra->proxyWidget;
4637 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4638 } else
4639#endif // QT_CONFIG(graphicsview)
4640 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4641 inheritedFontResolveMask = 0;
4642 }
4643 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4644 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4645 // isn't all weak information, but save the original mask to be able to let new changes on the
4646 // parent widget font propagate correctly.
4647 directFontResolveMask = data.fnt.resolveMask();
4648 data.fnt.setResolveMask(newMask);
4649
4650 for (int i = 0; i < children.size(); ++i) {
4651 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4652 if (w) {
4653 if (0) {
4654#ifndef QT_NO_STYLE_STYLESHEET
4655 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4656 // Style sheets follow a different font propagation scheme.
4657 if (cssStyle)
4658 cssStyle->updateStyleSheetFont(w);
4659#endif
4660 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4661 // Propagate font changes.
4662 QWidgetPrivate *wd = w->d_func();
4663 wd->inheritedFontResolveMask = newMask;
4664 wd->resolveFont();
4665 }
4666 }
4667 }
4668
4669#ifndef QT_NO_STYLE_STYLESHEET
4670 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4671 cssStyle->updateStyleSheetFont(q);
4672 }
4673#endif
4674
4675 QEvent e(QEvent::FontChange);
4676 QCoreApplication::sendEvent(q, &e);
4677}
4678
4679void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4680{
4681 Q_Q(QWidget);
4682
4683 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4684 return;
4685 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4686 if (!children.isEmpty()) {
4687 for (int i = 0; i < children.size(); ++i) {
4688 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4689 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4690 w->d_func()->setLayoutDirection_helper(direction);
4691 }
4692 }
4693 QEvent e(QEvent::LayoutDirectionChange);
4694 QCoreApplication::sendEvent(q, &e);
4695}
4696
4697void QWidgetPrivate::resolveLayoutDirection()
4698{
4699 Q_Q(const QWidget);
4700 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4701 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4702}
4703
4704/*!
4705 \property QWidget::layoutDirection
4706
4707 \brief the layout direction for this widget
4708
4709 By default, this property is set to Qt::LeftToRight.
4710
4711 When the layout direction is set on a widget, it will propagate to
4712 the widget's children, but not to a child that is a window and not
4713 to a child for which setLayoutDirection() has been explicitly
4714 called. Also, child widgets added \e after setLayoutDirection()
4715 has been called for the parent do not inherit the parent's layout
4716 direction.
4717
4718 This method no longer affects text layout direction since Qt 4.7.
4719
4720 \sa QApplication::layoutDirection
4721*/
4722void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4723{
4724 Q_D(QWidget);
4725
4726 if (direction == Qt::LayoutDirectionAuto) {
4727 unsetLayoutDirection();
4728 return;
4729 }
4730
4731 setAttribute(Qt::WA_SetLayoutDirection);
4732 d->setLayoutDirection_helper(direction);
4733}
4734
4735Qt::LayoutDirection QWidget::layoutDirection() const
4736{
4737 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4738}
4739
4740void QWidget::unsetLayoutDirection()
4741{
4742 Q_D(QWidget);
4743 setAttribute(Qt::WA_SetLayoutDirection, false);
4744 d->resolveLayoutDirection();
4745}
4746
4747/*!
4748 \fn QFontMetrics QWidget::fontMetrics() const
4749
4750 Returns the font metrics for the widget's current font.
4751 Equivalent to \c QFontMetrics(widget->font()).
4752
4753 \sa font(), fontInfo(), setFont()
4754*/
4755
4756/*!
4757 \fn QFontInfo QWidget::fontInfo() const
4758
4759 Returns the font info for the widget's current font.
4760 Equivalent to \c QFontInfo(widget->font()).
4761
4762 \sa font(), fontMetrics(), setFont()
4763*/
4764
4765
4766/*!
4767 \property QWidget::cursor
4768 \brief the cursor shape for this widget
4769
4770 The mouse cursor will assume this shape when it's over this
4771 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4772
4773 An editor widget might use an I-beam cursor:
4774 \snippet code/src_gui_kernel_qwidget.cpp 6
4775
4776 If no cursor has been set, or after a call to unsetCursor(), the
4777 parent's cursor is used.
4778
4779 By default, this property contains a cursor with the Qt::ArrowCursor
4780 shape.
4781
4782 Some underlying window implementations will reset the cursor if it
4783 leaves a widget even if the mouse is grabbed. If you want to have
4784 a cursor set for all widgets, even when outside the window, consider
4785 QGuiApplication::setOverrideCursor().
4786
4787 \sa QGuiApplication::setOverrideCursor()
4788*/
4789
4790#ifndef QT_NO_CURSOR
4791QCursor QWidget::cursor() const
4792{
4793 Q_D(const QWidget);
4794 if (testAttribute(Qt::WA_SetCursor))
4795 return (d->extra && d->extra->curs)
4796 ? *d->extra->curs
4797 : QCursor(Qt::ArrowCursor);
4798 if (isWindow() || !parentWidget())
4799 return QCursor(Qt::ArrowCursor);
4800 return parentWidget()->cursor();
4801}
4802
4803void QWidget::setCursor(const QCursor &cursor)
4804{
4805 Q_D(QWidget);
4806 if (cursor.shape() != Qt::ArrowCursor
4807 || (d->extra && d->extra->curs))
4808 {
4809 d->createExtra();
4810 d->extra->curs = qt_make_unique<QCursor>(cursor);
4811 }
4812 setAttribute(Qt::WA_SetCursor);
4813 d->setCursor_sys(cursor);
4814
4815 QEvent event(QEvent::CursorChange);
4816 QCoreApplication::sendEvent(this, &event);
4817}
4818
4819void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4820{
4821 Q_UNUSED(cursor);
4822 Q_Q(QWidget);
4823 qt_qpa_set_cursor(q, false);
4824}
4825
4826void QWidget::unsetCursor()
4827{
4828 Q_D(QWidget);
4829 if (d->extra)
4830 d->extra->curs.reset();
4831 if (!isWindow())
4832 setAttribute(Qt::WA_SetCursor, false);
4833 d->unsetCursor_sys();
4834
4835 QEvent event(QEvent::CursorChange);
4836 QCoreApplication::sendEvent(this, &event);
4837}
4838
4839void QWidgetPrivate::unsetCursor_sys()
4840{
4841 Q_Q(QWidget);
4842 qt_qpa_set_cursor(q, false);
4843}
4844
4845static inline void applyCursor(QWidget *w, const QCursor &c)
4846{
4847 if (QWindow *window = w->windowHandle())
4848 window->setCursor(c);
4849}
4850
4851static inline void unsetCursor(QWidget *w)
4852{
4853 if (QWindow *window = w->windowHandle())
4854 window->unsetCursor();
4855}
4856
4857void qt_qpa_set_cursor(QWidget *w, bool force)
4858{
4859 if (!w->testAttribute(Qt::WA_WState_Created))
4860 return;
4861
4862 static QPointer<QWidget> lastUnderMouse = nullptr;
4863 if (force) {
4864 lastUnderMouse = w;
4865 } else if (lastUnderMouse) {
4866 const WId lastWinId = lastUnderMouse->effectiveWinId();
4867 const WId winId = w->effectiveWinId();
4868 if (lastWinId && lastWinId == winId)
4869 w = lastUnderMouse;
4870 } else if (!w->internalWinId()) {
4871 return; // The mouse is not under this widget, and it's not native, so don't change it.
4872 }
4873
4874 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
4875 && !w->testAttribute(Qt::WA_SetCursor))
4876 w = w->parentWidget();
4877
4878 QWidget *nativeParent = w;
4879 if (!w->internalWinId())
4880 nativeParent = w->nativeParentWidget();
4881 if (!nativeParent || !nativeParent->internalWinId())
4882 return;
4883
4884 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
4885 if (w->isEnabled())
4886 applyCursor(nativeParent, w->cursor());
4887 else
4888 // Enforce the windows behavior of clearing the cursor on
4889 // disabled widgets.
4890 unsetCursor(nativeParent);
4891 } else {
4892 unsetCursor(nativeParent);
4893 }
4894}
4895#endif
4896
4897/*!
4898 \enum QWidget::RenderFlag
4899
4900 This enum describes how to render the widget when calling QWidget::render().
4901
4902 \value DrawWindowBackground If you enable this option, the widget's background
4903 is rendered into the target even if autoFillBackground is not set. By default,
4904 this option is enabled.
4905
4906 \value DrawChildren If you enable this option, the widget's children
4907 are rendered recursively into the target. By default, this option is enabled.
4908
4909 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
4910 is ignored when rendering into the target. By default, this option is disabled.
4911
4912 \since 4.3
4913*/
4914
4915/*!
4916 \since 4.3
4917
4918 Renders the \a sourceRegion of this widget into the \a target
4919 using \a renderFlags to determine how to render. Rendering
4920 starts at \a targetOffset in the \a target. For example:
4921
4922 \snippet code/src_gui_kernel_qwidget.cpp 7
4923
4924 If \a sourceRegion is a null region, this function will use QWidget::rect() as
4925 the region, i.e. the entire widget.
4926
4927 Ensure that you call QPainter::end() for the \a target device's
4928 active painter (if any) before rendering. For example:
4929
4930 \snippet code/src_gui_kernel_qwidget.cpp 8
4931
4932 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
4933 instead.
4934*/
4935void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
4936 const QRegion &sourceRegion, RenderFlags renderFlags)
4937{
4938 QPainter p(target);
4939 render(&p, targetOffset, sourceRegion, renderFlags);
4940}
4941
4942/*!
4943 \overload
4944
4945 Renders the widget into the \a painter's QPainter::device().
4946
4947 Transformations and settings applied to the \a painter will be used
4948 when rendering.
4949
4950 \note The \a painter must be active. On \macos the widget will be
4951 rendered into a QPixmap and then drawn by the \a painter.
4952
4953 \sa QPainter::device()
4954*/
4955void QWidget::render(QPainter *painter, const QPoint &targetOffset,
4956 const QRegion &sourceRegion, RenderFlags renderFlags)
4957{
4958 if (Q_UNLIKELY(!painter)) {
4959 qWarning("QWidget::render: Null pointer to painter");
4960 return;
4961 }
4962
4963 if (Q_UNLIKELY(!painter->isActive())) {
4964 qWarning("QWidget::render: Cannot render with an inactive painter");
4965 return;
4966 }
4967
4968 const qreal opacity = painter->opacity();
4969 if (qFuzzyIsNull(opacity))
4970 return; // Fully transparent.
4971
4972 Q_D(QWidget);
4973 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
4974 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
4975 : sourceRegion;
4976 if (toBePainted.isEmpty())
4977 return;
4978
4979 if (!d->extra)
4980 d->createExtra();
4981 d->extra->inRenderWithPainter = true;
4982
4983 QPaintEngine *engine = painter->paintEngine();
4984 Q_ASSERT(engine);
4985 QPaintEnginePrivate *enginePriv = engine->d_func();
4986 Q_ASSERT(enginePriv);
4987 QPaintDevice *target = engine->paintDevice();
4988 Q_ASSERT(target);
4989
4990 // Render via a pixmap when dealing with non-opaque painters or printers.
4991 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
4992 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
4993 d->extra->inRenderWithPainter = inRenderWithPainter;
4994 return;
4995 }
4996
4997 // Set new shared painter.
4998 QPainter *oldPainter = d->sharedPainter();
4999 d->setSharedPainter(painter);
5000
5001 // Save current system clip, viewport and transform,
5002 const QTransform oldTransform = enginePriv->systemTransform;
5003 const QRegion oldSystemClip = enginePriv->systemClip;
5004 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5005 const QRegion oldSystemViewport = enginePriv->systemViewport;
5006
5007 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5008 if (painter->hasClipping()) {
5009 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5010 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5011 } else {
5012 enginePriv->setSystemViewport(oldSystemClip);
5013 }
5014
5015 d->render(target, targetOffset, toBePainted, renderFlags);
5016
5017 // Restore system clip, viewport and transform.
5018 enginePriv->baseSystemClip = oldBaseClip;
5019 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5020 enginePriv->systemStateChanged();
5021
5022 // Restore shared painter.
5023 d->setSharedPainter(oldPainter);
5024
5025 d->extra->inRenderWithPainter = inRenderWithPainter;
5026}
5027
5028static void sendResizeEvents(QWidget *target)
5029{
5030 QResizeEvent e(target->size(), QSize());
5031 QCoreApplication::sendEvent(target, &e);
5032
5033 const QObjectList children = target->children();
5034 for (int i = 0; i < children.size(); ++i) {
5035 if (!children.at(i)->isWidgetType())
5036 continue;
5037 QWidget *child = static_cast<QWidget*>(children.at(i));
5038 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5039 sendResizeEvents(child);
5040 }
5041}
5042
5043/*!
5044 \since 5.0
5045
5046 Renders the widget into a pixmap restricted by the
5047 given \a rectangle. If the widget has any children, then
5048 they are also painted in the appropriate positions.
5049
5050 If a rectangle with an invalid size is specified (the default),
5051 the entire widget is painted.
5052
5053 \sa render(), QPixmap
5054*/
5055QPixmap QWidget::grab(const QRect &rectangle)
5056{
5057 Q_D(QWidget);
5058 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5059 sendResizeEvents(this);
5060
5061 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5062
5063 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5064 QRect r(rectangle);
5065 if (r.width() < 0 || r.height() < 0) {
5066 // For grabbing widgets that haven't been shown yet,
5067 // we trigger the layouting mechanism to determine the widget's size.
5068 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5069 r.setTopLeft(rectangle.topLeft());
5070 }
5071
5072 if (!r.intersects(rect()))
5073 return QPixmap();
5074
5075 const qreal dpr = devicePixelRatio();
5076 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5077 res.setDevicePixelRatio(dpr);
5078 if (!d->isOpaque)
5079 res.fill(Qt::transparent);
5080 d->render(&res, QPoint(), QRegion(r), renderFlags);
5081
5082 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5083 return res;
5084}
5085
5086/*!
5087 \brief The graphicsEffect function returns a pointer to the
5088 widget's graphics effect.
5089
5090 If the widget has no graphics effect, \nullptr is returned.
5091
5092 \since 4.6
5093
5094 \sa setGraphicsEffect()
5095*/
5096#if QT_CONFIG(graphicseffect)
5097QGraphicsEffect *QWidget::graphicsEffect() const
5098{
5099 Q_D(const QWidget);
5100 return d->graphicsEffect;
5101}
5102#endif // QT_CONFIG(graphicseffect)
5103
5104/*!
5105
5106 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5107
5108 Sets \a effect as the widget's effect. If there already is an effect installed
5109 on this widget, QWidget will delete the existing effect before installing
5110 the new \a effect.
5111
5112 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5113 the effect from the widget and install it on this widget.
5114
5115 QWidget takes ownership of \a effect.
5116
5117 \note This function will apply the effect on itself and all its children.
5118
5119 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5120 QOpenGLWidget and QQuickWidget.
5121
5122 \since 4.6
5123
5124 \sa graphicsEffect()
5125*/
5126#if QT_CONFIG(graphicseffect)
5127void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5128{
5129 Q_D(QWidget);
5130 if (d->graphicsEffect == effect)
5131 return;
5132
5133 if (d->graphicsEffect) {
5134 d->invalidateBackingStore(rect());
5135 delete d->graphicsEffect;
5136 d->graphicsEffect = nullptr;
5137 }
5138
5139 if (effect) {
5140 // Set new effect.
5141 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5142 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5143 d->graphicsEffect = effect;
5144 effect->d_func()->setGraphicsEffectSource(source);
5145 update();
5146 }
5147
5148 d->updateIsOpaque();
5149}
5150#endif // QT_CONFIG(graphicseffect)
5151
5152bool QWidgetPrivate::isAboutToShow() const
5153{
5154 if (data.in_show)
5155 return true;
5156
5157 Q_Q(const QWidget);
5158 if (q->isHidden())
5159 return false;
5160
5161 // The widget will be shown if any of its ancestors are about to show.
5162 QWidget *parent = q->parentWidget();
5163 return parent ? parent->d_func()->isAboutToShow() : false;
5164}
5165
5166QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5167{
5168 Q_Q(QWidget);
5169 const bool isVisible = q->isVisible();
5170
5171 // Make sure the widget is laid out correctly.
5172 if (!isVisible && !isAboutToShow()) {
5173 QWidget *topLevel = q->window();
5174 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5175 topLevel->ensurePolished();
5176
5177 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5178 // they're not explicitly hidden.
5179 QWidget *widget = q;
5180 QWidgetList hiddenWidgets;
5181 while (widget) {
5182 if (widget->isHidden()) {
5183 widget->setAttribute(Qt::WA_WState_Hidden, false);
5184 hiddenWidgets.append(widget);
5185 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5186 widget->d_func()->updateGeometry_helper(true);
5187 }
5188 widget = widget->parentWidget();
5189 }
5190
5191 // Activate top-level layout.
5192 if (topLevel->d_func()->layout)
5193 topLevel->d_func()->layout->activate();
5194
5195 // Adjust size if necessary.
5196 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5197 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5198 && !topLevel->testAttribute(Qt::WA_Resized)) {
5199 topLevel->adjustSize();
5200 topLevel->setAttribute(Qt::WA_Resized, false);
5201 }
5202
5203 // Activate child layouts.
5204 topLevel->d_func()->activateChildLayoutsRecursively();
5205
5206 // We're not cheating with WA_WState_Hidden anymore.
5207 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5208 QWidget *widget = hiddenWidgets.at(i);
5209 widget->setAttribute(Qt::WA_WState_Hidden);
5210 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5211 widget->parentWidget()->d_func()->layout->invalidate();
5212 }
5213 } else if (isVisible) {
5214 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5215 }
5216
5217 // Calculate the region to be painted.
5218 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5219 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5220 toBePainted &= extra->mask;
5221 return toBePainted;
5222}
5223
5224void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5225 QWidget::RenderFlags renderFlags)
5226{
5227 Q_ASSERT(painter);
5228 Q_ASSERT(!toBePainted.isEmpty());
5229
5230 Q_Q(QWidget);
5231 const QTransform originalTransform = painter->worldTransform();
5232 const bool useDeviceCoordinates = originalTransform.isScaling();
5233 if (!useDeviceCoordinates) {
5234 // Render via a pixmap.
5235 const QRect rect = toBePainted.boundingRect();
5236 const QSize size = rect.size();
5237 if (size.isNull())
5238 return;
5239
5240 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5241 QPixmap pixmap(size * pixmapDevicePixelRatio);
5242 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5243
5244 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5245 pixmap.fill(Qt::transparent);
5246 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5247
5248 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5249 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5250
5251 painter->drawPixmap(targetOffset, pixmap);
5252
5253 if (restore)
5254 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5255
5256 } else {
5257 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5258 QTransform transform = originalTransform;
5259 transform.translate(targetOffset.x(), targetOffset.y());
5260
5261 QPaintDevice *device = painter->device();
5262 Q_ASSERT(device);
5263
5264 // Calculate device rect.
5265 const QRectF rect(toBePainted.boundingRect());
5266 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5267 deviceRect &= QRect(0, 0, device->width(), device->height());
5268
5269 QPixmap pixmap(deviceRect.size());
5270 pixmap.fill(Qt::transparent);
5271
5272 // Create a pixmap device coordinate painter.
5273 QPainter pixmapPainter(&pixmap);
5274 pixmapPainter.setRenderHints(painter->renderHints());
5275 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5276 pixmapPainter.setTransform(transform);
5277
5278 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5279 pixmapPainter.end();
5280
5281 // And then draw the pixmap.
5282 painter->setTransform(QTransform());
5283 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5284 painter->setTransform(originalTransform);
5285 }
5286}
5287
5288void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5289 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5290{
5291 if (rgn.isEmpty())
5292 return;
5293
5294 Q_Q(QWidget);
5295
5296 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5297 << "into paint device" << pdev << "with" << flags;
5298
5299 const bool asRoot = flags & DrawAsRoot;
5300 bool onScreen = shouldPaintOnScreen();
5301
5302#if QT_CONFIG(graphicseffect)
5303 if (graphicsEffect && graphicsEffect->isEnabled()) {
5304 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5305 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5306 (source->d_func());
5307 if (!sourced->context) {
5308 QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, repaintManager);
5309 sourced->context = &context;
5310 if (!sharedPainter) {
5311 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), rgn.translated(offset));
5312 QPainter p(pdev);
5313 p.translate(offset);
5314 context.painter = &p;
5315 graphicsEffect->draw(&p);
5316 setSystemClip(pdev->paintEngine(), 1, QRegion());
5317 } else {
5318 context.painter = sharedPainter;
5319 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5320 sourced->invalidateCache();
5321 sourced->lastEffectTransform = sharedPainter->worldTransform();
5322 }
5323 sharedPainter->save();
5324 sharedPainter->translate(offset);
5325 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), rgn.translated(offset));
5326 graphicsEffect->draw(sharedPainter);
5327 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5328 sharedPainter->restore();
5329 }
5330 sourced->context = nullptr;
5331
5332 if (repaintManager)
5333 repaintManager->markNeedsFlush(q, rgn, offset);
5334
5335 return;
5336 }
5337 }
5338#endif // QT_CONFIG(graphicseffect)
5339
5340 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5341 const bool recursive = flags & DrawRecursive;
5342 const bool alsoInvisible = flags & DrawInvisible;
5343
5344 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5345
5346 QRegion toBePainted(rgn);
5347 if (asRoot && !alsoInvisible)
5348 toBePainted &= clipRect(); //(rgn & visibleRegion());
5349 if (!(flags & DontSubtractOpaqueChildren))
5350 subtractOpaqueChildren(toBePainted, q->rect());
5351
5352 if (!toBePainted.isEmpty()) {
5353 if (!onScreen || alsoOnScreen) {
5354 //update the "in paint event" flag
5355 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5356 qWarning("QWidget::repaint: Recursive repaint detected");
5357 q->setAttribute(Qt::WA_WState_InPaintEvent);
5358
5359 //clip away the new area
5360 QPaintEngine *paintEngine = pdev->paintEngine();
5361 if (paintEngine) {
5362 setRedirected(pdev, -offset);
5363
5364 if (sharedPainter)
5365 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5366 else
5367 paintEngine->d_func()->systemRect = q->data->crect;
5368
5369 //paint the background
5370 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5371 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5372#ifndef QT_NO_OPENGL
5373 beginBackingStorePainting();
5374#endif
5375 QPainter p(q);
5376 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5377#ifndef QT_NO_OPENGL
5378 endBackingStorePainting();
5379#endif
5380 }
5381
5382 if (!sharedPainter)
5383 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5384
5385 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5386#ifndef QT_NO_OPENGL
5387 beginBackingStorePainting();
5388#endif
5389 QPainter p(q);
5390 QColor tint = q->palette().window().color();
5391 tint.setAlphaF(.6f);
5392 p.fillRect(toBePainted.boundingRect(), tint);
5393#ifndef QT_NO_OPENGL
5394 endBackingStorePainting();
5395#endif
5396 }
5397 }
5398
5399#if 0
5400 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5401 qDebug() << "clipping to" << toBePainted << "location == " << offset
5402 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5403#endif
5404
5405 bool skipPaintEvent = false;
5406#ifndef QT_NO_OPENGL
5407 if (renderToTexture) {
5408 // This widget renders into a texture which is composed later. We just need to
5409 // punch a hole in the backingstore, so the texture will be visible.
5410 beginBackingStorePainting();
5411 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5412 QPainter p(q);
5413 p.setCompositionMode(QPainter::CompositionMode_Source);
5414 p.fillRect(q->rect(), Qt::transparent);
5415 } else if (!repaintManager) {
5416 // We are not drawing to a backingstore: fall back to QImage
5417 QImage img = grabFramebuffer();
5418 // grabFramebuffer() always sets the format to RGB32
5419 // regardless of whether it is transparent or not.
5420 if (img.format() == QImage::Format_RGB32)
5421 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5422 QPainter p(q);
5423 p.drawImage(q->rect(), img);
5424 skipPaintEvent = true;
5425 }
5426 endBackingStorePainting();
5427 if (renderToTextureReallyDirty)
5428 renderToTextureReallyDirty = 0;
5429 else
5430 skipPaintEvent = true;
5431 }
5432#endif // QT_NO_OPENGL
5433
5434 if (!skipPaintEvent) {
5435 //actually send the paint event
5436 sendPaintEvent(toBePainted);
5437 }
5438
5439 if (repaintManager)
5440 repaintManager->markNeedsFlush(q, toBePainted, offset);
5441
5442 //restore
5443 if (paintEngine) {
5444 restoreRedirected();
5445 if (!sharedPainter)
5446 paintEngine->d_func()->systemRect = QRect();
5447 else
5448 paintEngine->d_func()->currentClipDevice = nullptr;
5449
5450 setSystemClip(pdev->paintEngine(), 1, QRegion());
5451 }
5452 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5453 if (Q_UNLIKELY(q->paintingActive()))
5454 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5455
5456 if (paintEngine && paintEngine->autoDestruct()) {
5457 delete paintEngine;
5458 }
5459 } else if (q->isWindow()) {
5460 QPaintEngine *engine = pdev->paintEngine();
5461 if (engine) {
5462 QPainter p(pdev);
5463 p.setClipRegion(toBePainted);
5464 const QBrush bg = q->palette().brush(QPalette::Window);
5465 if (bg.style() == Qt::TexturePattern)
5466 p.drawTiledPixmap(q->rect(), bg.texture());
5467 else
5468 p.fillRect(q->rect(), bg);
5469
5470 if (engine->autoDestruct())
5471 delete engine;
5472 }
5473 }
5474 }
5475
5476 if (recursive && !children.isEmpty()) {
5477 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5478 sharedPainter, repaintManager);
5479 }
5480}
5481
5482void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5483{
5484 Q_Q(QWidget);
5485 QPaintEvent e(toBePainted);
5486 QCoreApplication::sendSpontaneousEvent(q, &e);
5487
5488#ifndef QT_NO_OPENGL
5489 if (renderToTexture)
5490 resolveSamples();
5491#endif // QT_NO_OPENGL
5492}
5493
5494void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5495 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5496{
5497 if (Q_UNLIKELY(!target)) {
5498 qWarning("QWidget::render: null pointer to paint device");
5499 return;
5500 }
5501
5502 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5503 QRegion paintRegion = !inRenderWithPainter
5504 ? prepareToRender(sourceRegion, renderFlags)
5505 : sourceRegion;
5506 if (paintRegion.isEmpty())
5507 return;
5508
5509 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5510
5511 // Use the target's shared painter if set (typically set when doing
5512 // "other->render(widget);" in the widget's paintEvent.
5513 if (target->devType() == QInternal::Widget) {
5514 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5515 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5516 QPainter *targetPainter = targetPrivate->sharedPainter();
5517 if (targetPainter && targetPainter->isActive())
5518 setSharedPainter(targetPainter);
5519 }
5520 }
5521
5522 // Use the target's redirected device if set and adjust offset and paint
5523 // region accordingly. This is typically the case when people call render
5524 // from the paintEvent.
5525 QPoint offset = targetOffset;
5526 offset -= paintRegion.boundingRect().topLeft();
5527 QPoint redirectionOffset;
5528 QPaintDevice *redirected = nullptr;
5529
5530 if (target->devType() == QInternal::Widget)
5531 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5532
5533 if (redirected) {
5534 target = redirected;
5535 offset -= redirectionOffset;
5536 }
5537
5538 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5539 if (QPaintEngine *targetEngine = target->paintEngine()) {
5540 const QRegion targetSystemClip = targetEngine->systemClip();
5541 if (!targetSystemClip.isEmpty())
5542 paintRegion &= targetSystemClip.translated(-offset);
5543 }
5544 }
5545
5546 // Set backingstore flags.
5547 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5548 if (renderFlags & QWidget::DrawWindowBackground)
5549 flags |= DrawAsRoot;
5550
5551 if (renderFlags & QWidget::DrawChildren)
5552 flags |= DrawRecursive;
5553 else
5554 flags |= DontSubtractOpaqueChildren;
5555
5556 flags |= DontSetCompositionMode;
5557
5558 // Render via backingstore.
5559 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5560
5561 // Restore shared painter.
5562 if (oldSharedPainter)
5563 setSharedPainter(oldSharedPainter);
5564}
5565
5566void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5567 const QPoint &offset, DrawWidgetFlags flags
5568 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5569{
5570 QWidget *w = nullptr;
5571 QRect boundingRect;
5572 bool dirtyBoundingRect = true;
5573 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5574 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5575
5576 do {
5577 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5578 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5579 && !(excludeNativeChildren && x->internalWinId())) {
5580 if (dirtyBoundingRect) {
5581 boundingRect = rgn.boundingRect();
5582 dirtyBoundingRect = false;
5583 }
5584
5585 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5586 w = x;
5587 break;
5588 }
5589 }
5590 --index;
5591 } while (index >= 0);
5592
5593 if (!w)
5594 return;
5595
5596 QWidgetPrivate *wd = w->d_func();
5597 const QPoint widgetPos(w->data->crect.topLeft());
5598 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5599 if (index > 0) {
5600 QRegion wr(rgn);
5601 if (wd->isOpaque)
5602 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5603 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5604 sharedPainter, repaintManager);
5605 }
5606
5607 if (w->updatesEnabled()
5608#if QT_CONFIG(graphicsview)
5609 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5610#endif // QT_CONFIG(graphicsview)
5611 ) {
5612 QRegion wRegion(rgn);
5613 wRegion &= wd->effectiveRectFor(w->data->crect);
5614 wRegion.translate(-widgetPos);
5615 if (hasMask)
5616 wRegion &= wd->extra->mask;
5617 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5618 }
5619}
5620
5621#if QT_CONFIG(graphicseffect)
5622QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5623{
5624 if (system != Qt::DeviceCoordinates)
5625 return m_widget->rect();
5626
5627 if (Q_UNLIKELY(!context)) {
5628 // Device coordinates without context not yet supported.
5629 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5630 return QRectF();
5631 }
5632
5633 return context->painter->worldTransform().mapRect(m_widget->rect());
5634}
5635
5636void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5637{
5638 if (!context || context->painter != painter) {
5639 m_widget->render(painter);
5640 return;
5641 }
5642
5643 // The region saved in the context is neither clipped to the rect
5644 // nor the mask, so we have to clip it here before calling drawWidget.
5645 QRegion toBePainted = context->rgn;
5646 toBePainted &= m_widget->rect();
5647 QWidgetPrivate *wd = qt_widget_private(m_widget);
5648 if (wd->extra && wd->extra->hasMask)
5649 toBePainted &= wd->extra->mask;
5650
5651 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5652 context->sharedPainter, context->repaintManager);
5653}
5654
5655QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5656 QGraphicsEffect::PixmapPadMode mode) const
5657{
5658 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5659 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5660 // Device coordinates without context not yet supported.
5661 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5662 return QPixmap();
5663 }
5664
5665 QPoint pixmapOffset;
5666 QRectF sourceRect = m_widget->rect();
5667
5668 if (deviceCoordinates) {
5669 const QTransform &painterTransform = context->painter->worldTransform();
5670 sourceRect = painterTransform.mapRect(sourceRect);
5671 pixmapOffset = painterTransform.map(pixmapOffset);
5672 }
5673
5674 QRect effectRect;
5675
5676 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5677 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5678 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5679 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5680 else
5681 effectRect = sourceRect.toAlignedRect();
5682
5683 if (offset)
5684 *offset = effectRect.topLeft();
5685
5686 pixmapOffset -= effectRect.topLeft();
5687
5688 qreal dpr(1.0);
5689 if (const auto *paintDevice = context->painter->device())
5690 dpr = paintDevice->devicePixelRatio();
5691 else
5692 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5693 QPixmap pixmap(effectRect.size() * dpr);
5694 pixmap.setDevicePixelRatio(dpr);
5695
5696 pixmap.fill(Qt::transparent);
5697 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5698 return pixmap;
5699}
5700#endif // QT_CONFIG(graphicseffect)
5701
5702#if QT_CONFIG(graphicsview)
5703/*!
5704 \internal
5705
5706 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5707 widget and its ancestors. The search starts at \a origin (inclusive).
5708 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5709 embedded widget was found.
5710*/
5711QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5712{
5713 if (origin) {
5714 const auto &extra = origin->d_func()->extra;
5715 if (extra && extra->proxyWidget)
5716 return extra->proxyWidget;
5717 return nearestGraphicsProxyWidget(origin->parentWidget());
5718 }
5719 return nullptr;
5720}
5721#endif
5722
5723/*!
5724 \property QWidget::locale
5725 \brief the widget's locale
5726 \since 4.3
5727
5728 As long as no special locale has been set, this is either
5729 the parent's locale or (if this widget is a top level widget),
5730 the default locale.
5731
5732 If the widget displays dates or numbers, these should be formatted
5733 using the widget's locale.
5734
5735 \sa QLocale, QLocale::setDefault()
5736*/
5737
5738void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5739{
5740 Q_Q(QWidget);
5741 if (locale == loc && !forceUpdate)
5742 return;
5743
5744 locale = loc;
5745
5746 if (!children.isEmpty()) {
5747 for (int i = 0; i < children.size(); ++i) {
5748 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5749 if (!w)
5750 continue;
5751 if (w->testAttribute(Qt::WA_SetLocale))
5752 continue;
5753 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5754 continue;
5755 w->d_func()->setLocale_helper(loc, forceUpdate);
5756 }
5757 }
5758 QEvent e(QEvent::LocaleChange);
5759 QCoreApplication::sendEvent(q, &e);
5760}
5761
5762void QWidget::setLocale(const QLocale &locale)
5763{
5764 Q_D(QWidget);
5765
5766 setAttribute(Qt::WA_SetLocale);
5767 d->setLocale_helper(locale);
5768}
5769
5770QLocale QWidget::locale() const
5771{
5772 Q_D(const QWidget);
5773
5774 return d->locale;
5775}
5776
5777void QWidgetPrivate::resolveLocale()
5778{
5779 Q_Q(const QWidget);
5780
5781 if (!q->testAttribute(Qt::WA_SetLocale)) {
5782 QWidget *parent = q->parentWidget();
5783 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5784 ? QLocale() : parent->locale());
5785 }
5786}
5787
5788void QWidget::unsetLocale()
5789{
5790 Q_D(QWidget);
5791 setAttribute(Qt::WA_SetLocale, false);
5792 d->resolveLocale();
5793}
5794
5795/*!
5796 \property QWidget::windowTitle
5797 \brief the window title (caption)
5798
5799 This property only makes sense for top-level widgets, such as
5800 windows and dialogs. If no caption has been set, the title is based of the
5801 \l windowFilePath. If neither of these is set, then the title is
5802 an empty string.
5803
5804 If you use the \l windowModified mechanism, the window title must
5805 contain a "[*]" placeholder, which indicates where the '*' should
5806 appear. Normally, it should appear right after the file name
5807 (e.g., "document1.txt[*] - Text Editor"). If the \l
5808 windowModified property is \c false (the default), the placeholder
5809 is simply removed.
5810
5811 On some desktop platforms (including Windows and Unix), the application name
5812 (from QGuiApplication::applicationDisplayName) is added at the end of the
5813 window title, if set. This is done by the QPA plugin, so it is shown to the
5814 user, but isn't part of the windowTitle string.
5815
5816 \sa windowIcon, windowModified, windowFilePath
5817*/
5818QString QWidget::windowTitle() const
5819{
5820 Q_D(const QWidget);
5821 if (d->extra && d->extra->topextra) {
5822 if (!d->extra->topextra->caption.isEmpty())
5823 return d->extra->topextra->caption;
5824 if (!d->extra->topextra->filePath.isEmpty())
5825 return QFileInfo(d->extra->topextra->filePath).fileName() + QLatin1String("[*]");
5826 }
5827 return QString();
5828}
5829
5830/*!
5831 Returns a modified window title with the [*] place holder
5832 replaced according to the rules described in QWidget::setWindowTitle
5833
5834 This function assumes that "[*]" can be quoted by another
5835 "[*]", so it will replace two place holders by one and
5836 a single last one by either "*" or nothing depending on
5837 the modified flag.
5838
5839 \internal
5840*/
5841QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
5842{
5843 Q_ASSERT(widget);
5844
5845 QString cap = title;
5846 if (cap.isEmpty())
5847 return cap;
5848
5849 QLatin1String placeHolder("[*]");
5850 int index = cap.indexOf(placeHolder);
5851
5852 // here the magic begins
5853 while (index != -1) {
5854 index += placeHolder.size();
5855 int count = 1;
5856 while (cap.indexOf(placeHolder, index) == index) {
5857 ++count;
5858 index += placeHolder.size();
5859 }
5860
5861 if (count%2) { // odd number of [*] -> replace last one
5862 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
5863 if (widget->isWindowModified()
5864 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
5865 cap.replace(lastIndex, 3, QWidget::tr("*"));
5866 else
5867 cap.remove(lastIndex, 3);
5868 }
5869
5870 index = cap.indexOf(placeHolder, index);
5871 }
5872
5873 cap.replace(QLatin1String("[*][*]"), placeHolder);
5874
5875 return cap;
5876}
5877
5878void QWidgetPrivate::setWindowTitle_helper(const QString &title)
5879{
5880 Q_Q(QWidget);
5881 if (q->testAttribute(Qt::WA_WState_Created))
5882 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
5883}
5884
5885void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
5886{
5887 Q_Q(QWidget);
5888 if (!q->isWindow())
5889 return;
5890
5891 if (QWindow *window = q->windowHandle())
5892 window->setTitle(caption);
5893
5894}
5895
5896void QWidgetPrivate::setWindowIconText_helper(const QString &title)
5897{
5898 Q_Q(QWidget);
5899 if (q->testAttribute(Qt::WA_WState_Created))
5900 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
5901}
5902
5903void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
5904{
5905#if QT_CONFIG(xcb)
5906 Q_Q(QWidget);
5907 // ### The QWidget property is deprecated, but the XCB window function is not.
5908 // It should remain available for the rare application that needs it.
5909 if (QWindow *window = q->windowHandle()) {
5910 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
5911 xcbWindow->setWindowIconText(iconText);
5912 }
5913#else
5914 Q_UNUSED(iconText);
5915#endif
5916}
5917
5918/*!
5919 \fn void QWidget::windowIconTextChanged(const QString &iconText)
5920
5921 This signal is emitted when the window's icon text has changed, with the
5922 new \a iconText as an argument.
5923
5924 \since 5.2
5925 \obsolete
5926
5927 This signal is deprecated.
5928*/
5929
5930void QWidget::setWindowIconText(const QString &iconText)
5931{
5932 if (QWidget::windowIconText() == iconText)
5933 return;
5934
5935 Q_D(QWidget);
5936 d->topData()->iconText = iconText;
5937 d->setWindowIconText_helper(iconText);
5938
5939 QEvent e(QEvent::IconTextChange);
5940 QCoreApplication::sendEvent(this, &e);
5941
5942 emit windowIconTextChanged(iconText);
5943}
5944
5945/*!
5946 \fn void QWidget::windowTitleChanged(const QString &title)
5947
5948 This signal is emitted when the window's title has changed, with the
5949 new \a title as an argument.
5950
5951 \since 5.2
5952*/
5953
5954void QWidget::setWindowTitle(const QString &title)
5955{
5956 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
5957 return;
5958
5959 Q_D(QWidget);
5960 d->topData()->caption = title;
5961 d->setWindowTitle_helper(title);
5962
5963 QEvent e(QEvent::WindowTitleChange);
5964 QCoreApplication::sendEvent(this, &e);
5965
5966 emit windowTitleChanged(title);
5967}
5968
5969
5970/*!
5971 \property QWidget::windowIcon
5972 \brief the widget's icon
5973
5974 This property only makes sense for windows. If no icon
5975 has been set, windowIcon() returns the application icon
5976 (QApplication::windowIcon()).
5977
5978 \note On \macos, window icons represent the active document,
5979 and will not be displayed unless a file path has also been
5980 set using setWindowFilePath.
5981
5982 \sa windowTitle, setWindowFilePath
5983*/
5984QIcon QWidget::windowIcon() const
5985{
5986 const QWidget *w = this;
5987 while (w) {
5988 const QWidgetPrivate *d = w->d_func();
5989 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
5990 return *d->extra->topextra->icon;
5991 w = w->parentWidget();
5992 }
5993 return QApplication::windowIcon();
5994}
5995
5996void QWidgetPrivate::setWindowIcon_helper()
5997{
5998 Q_Q(QWidget);
5999 QEvent e(QEvent::WindowIconChange);
6000
6001 // Do not send the event if the widget is a top level.
6002 // In that case, setWindowIcon_sys does it, and event propagation from
6003 // QWidgetWindow to the top level QWidget ensures that the event reaches
6004 // the top level anyhow
6005 if (!q->windowHandle())
6006 QCoreApplication::sendEvent(q, &e);
6007 for (int i = 0; i < children.size(); ++i) {
6008 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6009 if (w && !w->isWindow())
6010 QCoreApplication::sendEvent(w, &e);
6011 }
6012}
6013
6014/*!
6015 \fn void QWidget::windowIconChanged(const QIcon &icon)
6016
6017 This signal is emitted when the window's icon has changed, with the
6018 new \a icon as an argument.
6019
6020 \since 5.2
6021*/
6022
6023void QWidget::setWindowIcon(const QIcon &icon)
6024{
6025 Q_D(QWidget);
6026
6027 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6028 d->createTLExtra();
6029
6030 if (!d->extra->topextra->icon)
6031 d->extra->topextra->icon = qt_make_unique<QIcon>(icon);
6032 else
6033 *d->extra->topextra->icon = icon;
6034
6035 d->setWindowIcon_sys();
6036 d->setWindowIcon_helper();
6037
6038 emit windowIconChanged(icon);
6039}
6040
6041void QWidgetPrivate::setWindowIcon_sys()
6042{
6043 Q_Q(QWidget);
6044 if (QWindow *window = q->windowHandle())
6045 window->setIcon(q->windowIcon());
6046}
6047
6048/*!
6049 \property QWidget::windowIconText
6050 \brief the text to be displayed on the icon of a minimized window
6051
6052 This property only makes sense for windows. If no icon
6053 text has been set, this accessor returns an empty string.
6054 It is only implemented on the X11 platform, and only certain
6055 window managers use this window property.
6056
6057 \obsolete
6058 This property is deprecated.
6059
6060 \sa windowIcon, windowTitle
6061*/
6062
6063QString QWidget::windowIconText() const
6064{
6065 Q_D(const QWidget);
6066 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6067}
6068
6069/*!
6070 \property QWidget::windowFilePath
6071 \since 4.4
6072 \brief the file path associated with a widget
6073
6074 This property only makes sense for windows. It associates a file path with
6075 a window. If you set the file path, but have not set the window title, Qt
6076 sets the window title to the file name of the specified path, obtained using
6077 QFileInfo::fileName().
6078
6079 If the window title is set at any point, then the window title takes precedence and
6080 will be shown instead of the file path string.
6081
6082 Additionally, on \macos, this has an added benefit that it sets the
6083 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6084 for the window, assuming that the file path exists.
6085
6086 If no file path is set, this property contains an empty string.
6087
6088 By default, this property contains an empty string.
6089
6090 \sa windowTitle, windowIcon
6091*/
6092
6093QString QWidget::windowFilePath() const
6094{
6095 Q_D(const QWidget);
6096 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6097}
6098
6099void QWidget::setWindowFilePath(const QString &filePath)
6100{
6101 if (filePath == windowFilePath())
6102 return;
6103
6104 Q_D(QWidget);
6105
6106 d->createTLExtra();
6107 d->extra->topextra->filePath = filePath;
6108 d->setWindowFilePath_helper(filePath);
6109}
6110
6111void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6112{
6113 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6114#ifdef Q_OS_MAC
6115 setWindowTitle_helper(QFileInfo(filePath).fileName());
6116#else
6117 Q_Q(QWidget);
6118 Q_UNUSED(filePath);
6119 setWindowTitle_helper(q->windowTitle());
6120#endif
6121 }
6122#ifdef Q_OS_MAC
6123 setWindowFilePath_sys(filePath);
6124#endif
6125}
6126
6127void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6128{
6129 Q_Q(QWidget);
6130 if (!q->isWindow())
6131 return;
6132
6133 if (QWindow *window = q->windowHandle())
6134 window->setFilePath(filePath);
6135}
6136
6137/*!
6138 Returns the window's role, or an empty string.
6139
6140 \sa windowIcon, windowTitle
6141*/
6142
6143QString QWidget::windowRole() const
6144{
6145 Q_D(const QWidget);
6146 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6147}
6148
6149/*!
6150 Sets the window's role to \a role. This only makes sense for
6151 windows on X11.
6152*/
6153void QWidget::setWindowRole(const QString &role)
6154{
6155#if QT_CONFIG(xcb)
6156 Q_D(QWidget);
6157 d->createTLExtra();
6158 d->topData()->role = role;
6159 if (windowHandle()) {
6160 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6161 xcbWindow->setWindowRole(role);
6162 }
6163#else
6164 Q_UNUSED(role);
6165#endif
6166}
6167
6168/*!
6169 \property QWidget::mouseTracking
6170 \brief whether mouse tracking is enabled for the widget
6171
6172 If mouse tracking is disabled (the default), the widget only
6173 receives mouse move events when at least one mouse button is
6174 pressed while the mouse is being moved.
6175
6176 If mouse tracking is enabled, the widget receives mouse move
6177 events even if no buttons are pressed.
6178
6179 \sa mouseMoveEvent()
6180*/
6181
6182/*!
6183 \property QWidget::tabletTracking
6184 \brief whether tablet tracking is enabled for the widget
6185 \since 5.9
6186
6187 If tablet tracking is disabled (the default), the widget only
6188 receives tablet move events when the stylus is in contact with
6189 the tablet, or at least one stylus button is pressed,
6190 while the stylus is being moved.
6191
6192 If tablet tracking is enabled, the widget receives tablet move
6193 events even while hovering in proximity. This is useful for
6194 monitoring position as well as the auxiliary properties such
6195 as rotation and tilt, and providing feedback in the UI.
6196
6197 \sa tabletEvent()
6198*/
6199
6200
6201/*!
6202 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6203 function resets this widget to have no focus proxy.
6204
6205 Some widgets can "have focus", but create a child widget, such as
6206 QLineEdit, to actually handle the focus. In this case, the widget
6207 can set the line edit to be its focus proxy.
6208
6209 setFocusProxy() sets the widget which will actually get focus when
6210 "this widget" gets it. If there is a focus proxy, setFocus() and
6211 hasFocus() operate on the focus proxy. If "this widget" is the focus
6212 widget, then setFocusProxy() moves focus to the new focus proxy.
6213
6214 \sa focusProxy()
6215*/
6216
6217void QWidget::setFocusProxy(QWidget * w)
6218{
6219 Q_D(QWidget);
6220 if (!w && !d->extra)
6221 return;
6222
6223 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6224 if (Q_UNLIKELY(fp == this)) {
6225 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6226 return;
6227 }
6228 }
6229
6230 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6231
6232 d->createExtra();
6233 d->extra->focus_proxy = w;
6234
6235 if (moveFocusToProxy)
6236 setFocus(Qt::OtherFocusReason);
6237}
6238
6239
6240/*!
6241 Returns the focus proxy, or \nullptr if there is no focus proxy.
6242
6243 \sa setFocusProxy()
6244*/
6245
6246QWidget *QWidget::focusProxy() const
6247{
6248 Q_D(const QWidget);
6249 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6250}
6251
6252
6253/*!
6254 \property QWidget::focus
6255 \brief whether this widget (or its focus proxy) has the keyboard
6256 input focus
6257
6258 By default, this property is \c false.
6259
6260 \note Obtaining the value of this property for a widget is effectively equivalent
6261 to checking whether QApplication::focusWidget() refers to the widget.
6262
6263 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6264*/
6265bool QWidget::hasFocus() const
6266{
6267 const QWidget* w = this;
6268 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6269 w = w->d_func()->extra->focus_proxy;
6270#if QT_CONFIG(graphicsview)
6271 if (QWidget *window = w->window()) {
6272 const auto &e = window->d_func()->extra;
6273 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6274 return true;
6275 }
6276#endif // QT_CONFIG(graphicsview)
6277 return (QApplication::focusWidget() == w);
6278}
6279
6280/*!
6281 Gives the keyboard input focus to this widget (or its focus
6282 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6283 be passed into any focus event sent from this function, it is used
6284 to give an explanation of what caused the widget to get focus.
6285 If the window is not active, the widget will be given the focus when
6286 the window becomes active.
6287
6288 First, a focus about to change event is sent to the focus widget (if any) to
6289 tell it that it is about to lose the focus. Then focus is changed, a
6290 focus out event is sent to the previous focus item and a focus in event is sent
6291 to the new item to tell it that it just received the focus.
6292 (Nothing happens if the focus in and focus out widgets are the
6293 same.)
6294
6295 \note On embedded platforms, setFocus() will not cause an input panel
6296 to be opened by the input method. If you want this to happen, you
6297 have to send a QEvent::RequestSoftwareInputPanel event to the
6298 widget yourself.
6299
6300 setFocus() gives focus to a widget regardless of its focus policy,
6301 but does not clear any keyboard grab (see grabKeyboard()).
6302
6303 Be aware that if the widget is hidden, it will not accept focus
6304 until it is shown.
6305
6306 \warning If you call setFocus() in a function which may itself be
6307 called from focusOutEvent() or focusInEvent(), you may get an
6308 infinite recursion.
6309
6310 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6311 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6312 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6313*/
6314
6315void QWidget::setFocus(Qt::FocusReason reason)
6316{
6317 if (!isEnabled())
6318 return;
6319
6320 QWidget *f = d_func()->deepestFocusProxy();
6321 if (!f)
6322 f = this;
6323
6324 if (QApplication::focusWidget() == f)
6325 return;
6326
6327#if QT_CONFIG(graphicsview)
6328 QWidget *previousProxyFocus = nullptr;
6329 if (const auto &topData = window()->d_func()->extra) {
6330 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6331 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6332 if (previousProxyFocus && previousProxyFocus->focusProxy())
6333 previousProxyFocus = previousProxyFocus->focusProxy();
6334 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6335 return;
6336 }
6337 }
6338#endif
6339
6340#if QT_CONFIG(graphicsview)
6341 // Update proxy state
6342 if (const auto &topData = window()->d_func()->extra) {
6343 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6344 f->d_func()->updateFocusChild();
6345 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6346 topData->proxyWidget->setFocus(reason);
6347 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6348 }
6349 }
6350#endif
6351
6352 if (f->isActiveWindow()) {
6353 QWidget *prev = QApplicationPrivate::focus_widget;
6354 if (prev) {
6355 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6356 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6357 QGuiApplication::inputMethod()->commit();
6358 }
6359
6360 if (reason != Qt::NoFocusReason) {
6361 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6362 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6363 }
6364 }
6365
6366 f->d_func()->updateFocusChild();
6367
6368 QApplicationPrivate::setFocusWidget(f, reason);
6369#ifndef QT_NO_ACCESSIBILITY
6370 // menus update the focus manually and this would create bogus events
6371 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6372 {
6373 QAccessibleEvent event(f, QAccessible::Focus);
6374 QAccessible::updateAccessibility(&event);
6375 }
6376#endif
6377#if QT_CONFIG(graphicsview)
6378 if (const auto &topData = window()->d_func()->extra) {
6379 if (topData->proxyWidget) {
6380 if (previousProxyFocus && previousProxyFocus != f) {
6381 // Send event to self
6382 QFocusEvent event(QEvent::FocusOut, reason);
6383 QPointer<QWidget> that = previousProxyFocus;
6384 QCoreApplication::sendEvent(previousProxyFocus, &event);
6385 if (that)
6386 QCoreApplication::sendEvent(that->style(), &event);
6387 }
6388 if (!isHidden()) {
6389#if QT_CONFIG(graphicsview)
6390 // Update proxy state
6391 if (const auto &topData = window()->d_func()->extra)
6392 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6393 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6394#endif
6395 // Send event to self
6396 QFocusEvent event(QEvent::FocusIn, reason);
6397 QPointer<QWidget> that = f;
6398 QCoreApplication::sendEvent(f, &event);
6399 if (that)
6400 QCoreApplication::sendEvent(that->style(), &event);
6401 }
6402 }
6403 }
6404#endif
6405 } else {
6406 f->d_func()->updateFocusChild();
6407 }
6408}
6409
6410
6411/*!\internal
6412 * A focus proxy can have its own focus proxy, which can have its own
6413 * proxy, and so on. This helper function returns the widget that sits
6414 * at the bottom of the proxy chain, and therefore the one that should
6415 * normally get focus if this widget receives a focus request.
6416 */
6417QWidget *QWidgetPrivate::deepestFocusProxy() const
6418{
6419 Q_Q(const QWidget);
6420
6421 QWidget *focusProxy = q->focusProxy();
6422 if (!focusProxy)
6423 return nullptr;
6424
6425 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6426 focusProxy = nextFocusProxy;
6427
6428 return focusProxy;
6429}
6430
6431static inline bool isEmbedded(const QWindow *w)
6432{
6433 const auto platformWindow = w->handle();
6434 return platformWindow && platformWindow->isEmbedded();
6435}
6436
6437void QWidgetPrivate::setFocus_sys()
6438{
6439 Q_Q(QWidget);
6440 // Embedded native widget may have taken the focus; get it back to toplevel
6441 // if that is the case (QTBUG-25852)
6442 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6443 // unless the application is embedded (QTBUG-71991).
6444 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6445 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6446 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6447 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6448 || isEmbedded(nativeWindow))) {
6449 nativeWindow->requestActivate();
6450 }
6451 }
6452}
6453
6454// updates focus_child on parent widgets to point into this widget
6455void QWidgetPrivate::updateFocusChild()
6456{
6457 Q_Q(QWidget);
6458
6459 QWidget *w = q;
6460 if (q->isHidden()) {
6461 while (w && w->isHidden()) {
6462 w->d_func()->focus_child = q;
6463 w = w->isWindow() ? nullptr : w->parentWidget();
6464 }
6465 } else {
6466 while (w) {
6467 w->d_func()->focus_child = q;
6468 w = w->isWindow() ? nullptr : w->parentWidget();
6469 }
6470 }
6471
6472 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6473 if (extra->window)
6474 emit extra->window->focusObjectChanged(q);
6475 }
6476}
6477
6478/*!
6479 \fn void QWidget::setFocus()
6480 \overload
6481
6482 Gives the keyboard input focus to this widget (or its focus
6483 proxy) if this widget or one of its parents is the
6484 \l{isActiveWindow()}{active window}.
6485*/
6486
6487/*!
6488 Takes keyboard input focus from the widget.
6489
6490 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6491 lost the focus.
6492
6493 This widget must enable focus setting in order to get the keyboard
6494 input focus, i.e. it must call setFocusPolicy().
6495
6496 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6497 setFocusPolicy(), QApplication::focusWidget()
6498*/
6499
6500void QWidget::clearFocus()
6501{
6502 if (hasFocus()) {
6503 if (testAttribute(Qt::WA_InputMethodEnabled))
6504 QGuiApplication::inputMethod()->commit();
6505
6506 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6507 QCoreApplication::sendEvent(this, &focusAboutToChange);
6508 }
6509
6510 QWidget *w = this;
6511 while (w) {
6512 // Just like setFocus(), we update (clear) the focus_child of our parents
6513 if (w->d_func()->focus_child == this)
6514 w->d_func()->focus_child = nullptr;
6515 w = w->parentWidget();
6516 }
6517
6518 // Since we've unconditionally cleared the focus_child of our parents, we need
6519 // to report this to the rest of Qt. Note that the focus_child is not the same
6520 // thing as the application's focusWidget, which is why this piece of code is
6521 // not inside the hasFocus() block below.
6522 if (QTLWExtra *extra = window()->d_func()->maybeTopData()) {
6523 if (extra->window)
6524 emit extra->window->focusObjectChanged(extra->window->focusObject());
6525 }
6526
6527#if QT_CONFIG(graphicsview)
6528 const auto &topData = d_func()->extra;
6529 if (topData && topData->proxyWidget)
6530 topData->proxyWidget->clearFocus();
6531#endif
6532
6533 if (hasFocus()) {
6534 // Update proxy state
6535 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6536#ifndef QT_NO_ACCESSIBILITY
6537 QAccessibleEvent event(this, QAccessible::Focus);
6538 QAccessible::updateAccessibility(&event);
6539#endif
6540 }
6541}
6542
6543
6544/*!
6545 \fn bool QWidget::focusNextChild()
6546
6547 Finds a new widget to give the keyboard focus to, as appropriate
6548 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6549 false if it can't.
6550
6551 \sa focusPreviousChild()
6552*/
6553
6554/*!
6555 \fn bool QWidget::focusPreviousChild()
6556
6557 Finds a new widget to give the keyboard focus to, as appropriate
6558 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6559 or false if it can't.
6560
6561 \sa focusNextChild()
6562*/
6563
6564/*!
6565 Finds a new widget to give the keyboard focus to, as appropriate
6566 for Tab and Shift+Tab, and returns \c true if it can find a new
6567 widget, or false if it can't.
6568
6569 If \a next is true, this function searches forward, if \a next
6570 is false, it searches backward.
6571
6572 Sometimes, you will want to reimplement this function. For
6573 example, a web browser might reimplement it to move its "current
6574 active link" forward or backward, and call
6575 focusNextPrevChild() only when it reaches the last or
6576 first link on the "page".
6577
6578 Child widgets call focusNextPrevChild() on their parent widgets,
6579 but only the window that contains the child widgets decides where
6580 to redirect focus. By reimplementing this function for an object,
6581 you thus gain control of focus traversal for all child widgets.
6582
6583 \sa focusNextChild(), focusPreviousChild()
6584*/
6585
6586bool QWidget::focusNextPrevChild(bool next)
6587{
6588 QWidget* p = parentWidget();
6589 bool isSubWindow = (windowType() == Qt::SubWindow);
6590 if (!isWindow() && !isSubWindow && p)
6591 return p->focusNextPrevChild(next);
6592#if QT_CONFIG(graphicsview)
6593 Q_D(QWidget);
6594 if (d->extra && d->extra->proxyWidget)
6595 return d->extra->proxyWidget->focusNextPrevChild(next);
6596#endif
6597
6598 bool wrappingOccurred = false;
6599 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6600 &wrappingOccurred);
6601 if (!w) return false;
6602
6603 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6604
6605 /* If we are about to wrap the focus chain, give the platform
6606 * implementation a chance to alter the wrapping behavior. This is
6607 * especially needed when the window is embedded in a window created by
6608 * another process.
6609 */
6610 if (wrappingOccurred) {
6611 QWindow *window = windowHandle();
6612 if (window != nullptr) {
6613 QWindowPrivate *winp = qt_window_private(window);
6614
6615 if (winp->platformWindow != nullptr) {
6616 QFocusEvent event(QEvent::FocusIn, reason);
6617 event.ignore();
6618 winp->platformWindow->windowEvent(&event);
6619 if (event.isAccepted()) return true;
6620 }
6621 }
6622 }
6623
6624 w->setFocus(reason);
6625 return true;
6626}
6627
6628/*!
6629 Returns the last child of this widget that setFocus had been
6630 called on. For top level widgets this is the widget that will get
6631 focus in case this window gets activated
6632
6633 This is not the same as QApplication::focusWidget(), which returns
6634 the focus widget in the currently active window.
6635*/
6636
6637QWidget *QWidget::focusWidget() const
6638{
6639 return const_cast<QWidget *>(d_func()->focus_child);
6640}
6641
6642/*!
6643 Returns the next widget in this widget's focus chain.
6644
6645 \sa previousInFocusChain()
6646*/
6647QWidget *QWidget::nextInFocusChain() const
6648{
6649 return const_cast<QWidget *>(d_func()->focus_next);
6650}
6651
6652/*!
6653 \brief The previousInFocusChain function returns the previous
6654 widget in this widget's focus chain.
6655
6656 \sa nextInFocusChain()
6657
6658 \since 4.6
6659*/
6660QWidget *QWidget::previousInFocusChain() const
6661{
6662 return const_cast<QWidget *>(d_func()->focus_prev);
6663}
6664
6665/*!
6666 \property QWidget::isActiveWindow
6667 \brief whether this widget's window is the active window
6668
6669 The active window is the window that contains the widget that has
6670 keyboard focus (The window may still have focus if it has no
6671 widgets or none of its widgets accepts keyboard focus).
6672
6673 When popup windows are visible, this property is \c true for both the
6674 active window \e and for the popup.
6675
6676 By default, this property is \c false.
6677
6678 \sa activateWindow(), QApplication::activeWindow()
6679*/
6680bool QWidget::isActiveWindow() const
6681{
6682 QWidget *tlw = window();
6683 if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6684 return true;
6685
6686#if QT_CONFIG(graphicsview)
6687 if (const auto &tlwExtra = tlw->d_func()->extra) {
6688 if (isVisible() && tlwExtra->proxyWidget)
6689 return tlwExtra->proxyWidget->isActiveWindow();
6690 }
6691#endif
6692
6693 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6694 if(tlw->windowType() == Qt::Tool &&
6695 !tlw->isModal() &&
6696 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6697 return true;
6698 QWidget *w = QApplication::activeWindow();
6699 while(w && tlw->windowType() == Qt::Tool &&
6700 !w->isModal() && w->parentWidget()) {
6701 w = w->parentWidget()->window();
6702 if(w == tlw)
6703 return true;
6704 }
6705 }
6706
6707 // Check for an active window container
6708 if (QWindow *ww = QGuiApplication::focusWindow()) {
6709 while (ww) {
6710 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6711 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6712 if (qwc && qwc->topLevelWidget() == tlw)
6713 return true;
6714 ww = ww->parent();
6715 }
6716 }
6717
6718 // Check if platform adaptation thinks the window is active. This is necessary for
6719 // example in case of ActiveQt servers that are embedded into another application.
6720 // Those are separate processes that are not part of the parent application Qt window/widget
6721 // hierarchy, so they need to rely on native methods to determine if they are part of the
6722 // active window.
6723 if (const QWindow *w = tlw->windowHandle()) {
6724 if (w->handle())
6725 return w->handle()->isActive();
6726 }
6727
6728 return false;
6729}
6730
6731/*!
6732 Puts the \a second widget after the \a first widget in the focus order.
6733
6734 It effectively removes the \a second widget from its focus chain and
6735 inserts it after the \a first widget.
6736
6737 Note that since the tab order of the \a second widget is changed, you
6738 should order a chain like this:
6739
6740 \snippet code/src_gui_kernel_qwidget.cpp 9
6741
6742 \e not like this:
6743
6744 \snippet code/src_gui_kernel_qwidget.cpp 10
6745
6746 If \a first or \a second has a focus proxy, setTabOrder()
6747 correctly substitutes the proxy.
6748
6749 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
6750 a compound widget. When setting a tab order between one or two compound widgets, the
6751 local tab order inside each will be preserved. This means that if both widgets are
6752 compound widgets, the resulting tab order will be from the last child inside
6753 \a first, to the first child inside \a second.
6754
6755 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6756*/
6757void QWidget::setTabOrder(QWidget* first, QWidget *second)
6758{
6759 if (!first || !second || first == second
6760 || first->focusPolicy() == Qt::NoFocus
6761 || second->focusPolicy() == Qt::NoFocus)
6762 return;
6763
6764 if (Q_UNLIKELY(first->window() != second->window())) {
6765 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
6766 return;
6767 }
6768
6769 auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild)
6770 {
6771 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
6772 // determines the last focus child for a widget, taking proxies and compound widgets into account.
6773 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
6774 // 'lastFocusChild' will be set to the target itself.
6775 lastFocusChild = target;
6776
6777 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
6778 if (!focusProxy || !target->isAncestorOf(focusProxy))
6779 return;
6780
6781 lastFocusChild = focusProxy;
6782
6783 for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
6784 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
6785 focusNext = focusNext->d_func()->focus_next) {
6786 if (focusNext->focusPolicy() != Qt::NoFocus)
6787 lastFocusChild = focusNext;
6788 }
6789 };
6790 auto setPrev = [](QWidget *w, QWidget *prev)
6791 {
6792 w->d_func()->focus_prev = prev;
6793 };
6794 auto setNext = [](QWidget *w, QWidget *next)
6795 {
6796 w->d_func()->focus_next = next;
6797 };
6798
6799 // remove the second widget from the chain
6800 QWidget *lastFocusChildOfSecond;
6801 determineLastFocusChild(second, lastFocusChildOfSecond);
6802 {
6803 QWidget *oldPrev = second->d_func()->focus_prev;
6804 QWidget *prevWithFocus = oldPrev;
6805 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
6806 prevWithFocus = prevWithFocus->d_func()->focus_prev;
6807 // only widgets between first and second -> all is fine
6808 if (prevWithFocus == first)
6809 return;
6810 QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
6811 setPrev(oldNext, oldPrev);
6812 setNext(oldPrev, oldNext);
6813 }
6814
6815 // insert the second widget into the chain
6816 QWidget *lastFocusChildOfFirst;
6817 determineLastFocusChild(first, lastFocusChildOfFirst);
6818 {
6819 QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
6820 setPrev(second, lastFocusChildOfFirst);
6821 setNext(lastFocusChildOfFirst, second);
6822 setPrev(oldNext, lastFocusChildOfSecond);
6823 setNext(lastFocusChildOfSecond, oldNext);
6824 }
6825}
6826
6827/*!\internal
6828
6829 Moves the relevant subwidgets of this widget from the \a oldtlw's
6830 tab chain to that of the new parent, if there's anything to move and
6831 we're really moving
6832
6833 This function is called from QWidget::reparent() *after* the widget
6834 has been reparented.
6835
6836 \sa reparent()
6837*/
6838
6839void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
6840{
6841 Q_Q(QWidget);
6842 if (oldtlw == q->window())
6843 return; // nothing to do
6844
6845 if(focus_child)
6846 focus_child->clearFocus();
6847
6848 // separate the focus chain into new (children of myself) and old (the rest)
6849 QWidget *firstOld = nullptr;
6850 //QWidget *firstNew = q; //invariant
6851 QWidget *o = nullptr; // last in the old list
6852 QWidget *n = q; // last in the new list
6853
6854 bool prevWasNew = true;
6855 QWidget *w = focus_next;
6856
6857 //Note: for efficiency, we do not maintain the list invariant inside the loop
6858 //we append items to the relevant list, and we optimize by not changing pointers
6859 //when subsequent items are going into the same list.
6860 while (w != q) {
6861 bool currentIsNew = q->isAncestorOf(w);
6862 if (currentIsNew) {
6863 if (!prevWasNew) {
6864 //prev was old -- append to new list
6865 n->d_func()->focus_next = w;
6866 w->d_func()->focus_prev = n;
6867 }
6868 n = w;
6869 } else {
6870 if (prevWasNew) {
6871 //prev was new -- append to old list, if there is one
6872 if (o) {
6873 o->d_func()->focus_next = w;
6874 w->d_func()->focus_prev = o;
6875 } else {
6876 // "create" the old list
6877 firstOld = w;
6878 }
6879 }
6880 o = w;
6881 }
6882 w = w->d_func()->focus_next;
6883 prevWasNew = currentIsNew;
6884 }
6885
6886 //repair the old list:
6887 if (firstOld) {
6888 o->d_func()->focus_next = firstOld;
6889 firstOld->d_func()->focus_prev = o;
6890 }
6891
6892 if (!q->isWindow()) {
6893 QWidget *topLevel = q->window();
6894 //insert new chain into toplevel's chain
6895
6896 QWidget *prev = topLevel->d_func()->focus_prev;
6897
6898 topLevel->d_func()->focus_prev = n;
6899 prev->d_func()->focus_next = q;
6900
6901 focus_prev = prev;
6902 n->d_func()->focus_next = topLevel;
6903 } else {
6904 //repair the new list
6905 n->d_func()->focus_next = q;
6906 focus_prev = n;
6907 }
6908
6909}
6910
6911/*!
6912 \property QWidget::frameSize
6913 \brief the size of the widget including any window frame
6914
6915 By default, this property contains a value that depends on the user's
6916 platform and screen geometry.
6917*/
6918QSize QWidget::frameSize() const
6919{
6920 Q_D(const QWidget);
6921 if (isWindow() && !(windowType() == Qt::Popup)) {
6922 QRect fs = d->frameStrut();
6923 return QSize(data->crect.width() + fs.left() + fs.right(),
6924 data->crect.height() + fs.top() + fs.bottom());
6925 }
6926 return data->crect.size();
6927}
6928
6929/*! \fn void QWidget::move(int x, int y)
6930
6931 \overload
6932
6933 This corresponds to move(QPoint(\a x, \a y)).
6934*/
6935
6936void QWidget::move(const QPoint &p)
6937{
6938 Q_D(QWidget);
6939 setAttribute(Qt::WA_Moved);
6940 if (testAttribute(Qt::WA_WState_Created)) {
6941 if (isWindow())
6942 d->topData()->posIncludesFrame = false;
6943 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
6944 p.y() + geometry().y() - QWidget::y(),
6945 width(), height(), true);
6946 d->setDirtyOpaqueRegion();
6947 } else {
6948 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
6949 if (isWindow())
6950 d->topData()->posIncludesFrame = true;
6951 data->crect.moveTopLeft(p); // no frame yet
6952 setAttribute(Qt::WA_PendingMoveEvent);
6953 }
6954
6955 if (d->extra && d->extra->hasWindowContainer)
6956 QWindowContainer::parentWasMoved(this);
6957}
6958
6959// move() was invoked with Qt::WA_WState_Created not set (frame geometry
6960// unknown), that is, crect has a position including the frame.
6961// If we can determine the frame strut, fix that and clear the flag.
6962// FIXME: This does not play well with window states other than
6963// Qt::WindowNoState, as we depend on calling setGeometry() on the
6964// platform window after fixing up the position so that the new
6965// geometry is reflected in the platform window, but when the frame
6966// comes in after the window has been shown (e.g. maximized), we're
6967// not in a position to do that kind of fixup.
6968void QWidgetPrivate::fixPosIncludesFrame()
6969{
6970 Q_Q(QWidget);
6971 if (QTLWExtra *te = maybeTopData()) {
6972 if (te->posIncludesFrame) {
6973 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
6974 // example, in QGraphicsProxyWidget).
6975 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
6976 te->posIncludesFrame = 0;
6977 } else {
6978 if (q->windowHandle() && q->windowHandle()->handle()) {
6979 updateFrameStrut();
6980 if (!q->data->fstrut_dirty) {
6981 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
6982 te->posIncludesFrame = 0;
6983 }
6984 } // windowHandle()
6985 } // !WA_DontShowOnScreen
6986 } // posIncludesFrame
6987 } // QTLWExtra
6988}
6989
6990/*! \fn void QWidget::resize(int w, int h)
6991 \overload
6992
6993 This corresponds to resize(QSize(\a w, \a h)).
6994*/
6995
6996void QWidget::resize(const QSize &s)
6997{
6998 Q_D(QWidget);
6999 setAttribute(Qt::WA_Resized);
7000 if (testAttribute(Qt::WA_WState_Created)) {
7001 d->fixPosIncludesFrame();
7002 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7003 d->setDirtyOpaqueRegion();
7004 } else {
7005 const auto oldRect = data->crect;
7006 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7007 if (oldRect != data->crect)
7008 setAttribute(Qt::WA_PendingResizeEvent);
7009 }
7010}
7011
7012void QWidget::setGeometry(const QRect &r)
7013{
7014 Q_D(QWidget);
7015 setAttribute(Qt::WA_Resized);
7016 setAttribute(Qt::WA_Moved);
7017 if (isWindow())
7018 d->topData()->posIncludesFrame = 0;
7019 if (testAttribute(Qt::WA_WState_Created)) {
7020 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7021 d->setDirtyOpaqueRegion();
7022 } else {
7023 const auto oldRect = data->crect;
7024 data->crect.setTopLeft(r.topLeft());
7025 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7026 if (oldRect != data->crect) {
7027 setAttribute(Qt::WA_PendingMoveEvent);
7028 setAttribute(Qt::WA_PendingResizeEvent);
7029 }
7030 }
7031
7032 if (d->extra && d->extra->hasWindowContainer)
7033 QWindowContainer::parentWasMoved(this);
7034}
7035
7036void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7037{
7038 Q_Q(QWidget);
7039 if (extra) { // any size restrictions?
7040 w = qMin(w,extra->maxw);
7041 h = qMin(h,extra->maxh);
7042 w = qMax(w,extra->minw);
7043 h = qMax(h,extra->minh);
7044 }
7045
7046 if (q->isWindow() && q->windowHandle()) {
7047 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7048 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7049 x = 0;
7050 y = 0;
7051 w = q->windowHandle()->width();
7052 h = q->windowHandle()->height();
7053 }
7054 }
7055
7056 QPoint oldp = q->geometry().topLeft();
7057 QSize olds = q->size();
7058 QRect r(x, y, w, h);
7059
7060 bool isResize = olds != r.size();
7061 if (!isMove)
7062 isMove = oldp != r.topLeft();
7063
7064
7065 // We only care about stuff that changes the geometry, or may
7066 // cause the window manager to change its state
7067 if (r.size() == olds && oldp == r.topLeft())
7068 return;
7069
7070 if (!data.in_set_window_state) {
7071 q->data->window_state &= ~Qt::WindowMaximized;
7072 q->data->window_state &= ~Qt::WindowFullScreen;
7073 if (q->isWindow())
7074 topData()->normalGeometry = QRect(0, 0, -1, -1);
7075 }
7076
7077 QPoint oldPos = q->pos();
7078 data.crect = r;
7079
7080 bool needsShow = false;
7081
7082 if (q->isWindow() || q->windowHandle()) {
7083 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7084 q->setAttribute(Qt::WA_OutsideWSRange, true);
7085 if (q->isVisible())
7086 hide_sys();
7087 data.crect = QRect(x, y, w, h);
7088 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7089 q->setAttribute(Qt::WA_OutsideWSRange, false);
7090 needsShow = true;
7091 }
7092 }
7093
7094 if (q->isVisible()) {
7095 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7096 if (QWindow *win = q->windowHandle()) {
7097 if (q->isWindow()) {
7098 if (isResize && !isMove)
7099 win->resize(w, h);
7100 else if (isMove && !isResize)
7101 win->setPosition(x, y);
7102 else
7103 win->setGeometry(q->geometry());
7104 } else {
7105 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7106 win->setGeometry(QRect(posInNativeParent,r.size()));
7107 }
7108
7109 if (needsShow)
7110 show_sys();
7111 }
7112
7113 if (!q->isWindow()) {
7114 if (renderToTexture) {
7115 QRegion updateRegion(q->geometry());
7116 updateRegion += QRect(oldPos, olds);
7117 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7118 } else if (isMove && !isResize) {
7119 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7120 } else {
7121 invalidateBackingStore_resizeHelper(oldPos, olds);
7122 }
7123 }
7124 }
7125
7126 if (isMove) {
7127 QMoveEvent e(q->pos(), oldPos);
7128 QCoreApplication::sendEvent(q, &e);
7129 }
7130 if (isResize) {
7131 QResizeEvent e(r.size(), olds);
7132 QCoreApplication::sendEvent(q, &e);
7133 if (q->windowHandle())
7134 q->update();
7135 }
7136 } else { // not visible
7137 if (isMove && q->pos() != oldPos)
7138 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7139 if (isResize)
7140 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7141 }
7142
7143}
7144
7145/*!
7146 \since 4.2
7147 Saves the current geometry and state for top-level widgets.
7148
7149 To save the geometry when the window closes, you can
7150 implement a close event like this:
7151
7152 \snippet code/src_gui_kernel_qwidget.cpp 11
7153
7154 See the \l{Window Geometry} documentation for an overview of geometry
7155 issues with windows.
7156
7157 Use QMainWindow::saveState() to save the geometry and the state of
7158 toolbars and dock widgets.
7159
7160 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7161*/
7162QByteArray QWidget::saveGeometry() const
7163{
7164 QByteArray array;
7165 QDataStream stream(&array, QIODevice::WriteOnly);
7166 stream.setVersion(QDataStream::Qt_4_0);
7167 const quint32 magicNumber = 0x1D9D0CB;
7168 // Version history:
7169 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7170 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7171 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7172 quint16 majorVersion = 3;
7173 quint16 minorVersion = 0;
7174 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7175 stream << magicNumber
7176 << majorVersion
7177 << minorVersion
7178 << frameGeometry()
7179 << normalGeometry()
7180 << qint32(screenNumber)
7181 << quint8(windowState() & Qt::WindowMaximized)
7182 << quint8(windowState() & Qt::WindowFullScreen)
7183 << qint32(screen()->geometry().width()) // added in 2.0
7184 << geometry(); // added in 3.0
7185 return array;
7186}
7187
7188static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7189 int frameHeight)
7190{
7191 if (!restoredGeometry->intersects(availableGeometry)) {
7192 restoredGeometry->moveBottom(qMin(restoredGeometry->bottom(), availableGeometry.bottom()));
7193 restoredGeometry->moveLeft(qMax(restoredGeometry->left(), availableGeometry.left()));
7194 restoredGeometry->moveRight(qMin(restoredGeometry->right(), availableGeometry.right()));
7195 }
7196 restoredGeometry->moveTop(qMax(restoredGeometry->top(), availableGeometry.top() + frameHeight));
7197}
7198
7199/*!
7200 \since 4.2
7201
7202 Restores the geometry and state of top-level widgets stored in the
7203 byte array \a geometry. Returns \c true on success; otherwise
7204 returns \c false.
7205
7206 If the restored geometry is off-screen, it will be modified to be
7207 inside the available screen geometry.
7208
7209 To restore geometry saved using QSettings, you can use code like
7210 this:
7211
7212 \snippet code/src_gui_kernel_qwidget.cpp 12
7213
7214 See the \l{Window Geometry} documentation for an overview of geometry
7215 issues with windows.
7216
7217 Use QMainWindow::restoreState() to restore the geometry and the
7218 state of toolbars and dock widgets.
7219
7220 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7221*/
7222bool QWidget::restoreGeometry(const QByteArray &geometry)
7223{
7224 if (geometry.size() < 4)
7225 return false;
7226 QDataStream stream(geometry);
7227 stream.setVersion(QDataStream::Qt_4_0);
7228
7229 const quint32 magicNumber = 0x1D9D0CB;
7230 quint32 storedMagicNumber;
7231 stream >> storedMagicNumber;
7232 if (storedMagicNumber != magicNumber)
7233 return false;
7234
7235 const quint16 currentMajorVersion = 3;
7236 quint16 majorVersion = 0;
7237 quint16 minorVersion = 0;
7238
7239 stream >> majorVersion >> minorVersion;
7240
7241 if (majorVersion > currentMajorVersion)
7242 return false;
7243 // (Allow all minor versions.)
7244
7245 QRect restoredFrameGeometry;
7246 QRect restoredGeometry;
7247 QRect restoredNormalGeometry;
7248 qint32 restoredScreenNumber;
7249 quint8 maximized;
7250 quint8 fullScreen;
7251 qint32 restoredScreenWidth = 0;
7252
7253 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7254 >> restoredNormalGeometry
7255 >> restoredScreenNumber
7256 >> maximized
7257 >> fullScreen;
7258
7259 if (majorVersion > 1)
7260 stream >> restoredScreenWidth;
7261 if (majorVersion > 2)
7262 stream >> restoredGeometry;
7263
7264 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7265
7266 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7267 restoredScreenNumber = 0;
7268 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7269 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7270 // Sanity check bailing out when large variations of screen sizes occur due to
7271 // high DPI scaling or different levels of DPI awareness.
7272 if (restoredScreenWidth) {
7273 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7274 if (factor < 0.8 || factor > 1.25)
7275 return false;
7276 } else {
7277 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7278 // unless the size will be adapted by maximized or fullscreen.
7279 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7280 return false;
7281 }
7282
7283 const int frameHeight = 20;
7284
7285 if (!restoredNormalGeometry.isValid())
7286 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7287 if (!restoredNormalGeometry.isValid()) {
7288 // use the widget's adjustedSize if the sizeHint() doesn't help
7289 restoredNormalGeometry.setSize(restoredNormalGeometry
7290 .size()
7291 .expandedTo(d_func()->adjustedSize()));
7292 }
7293
7294 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7295 : QRect();
7296
7297 // Modify the restored geometry if we are about to restore to coordinates
7298 // that would make the window "lost". This happens if:
7299 // - The restored geometry is completely oustside the available geometry
7300 // - The title bar is outside the available geometry.
7301
7302 checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7303 checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7304
7305 if (maximized || fullScreen) {
7306 // set geometry before setting the window state to make
7307 // sure the window is maximized to the right screen.
7308 Qt::WindowStates ws = windowState();
7309#ifndef Q_OS_WIN
7310 setGeometry(restoredNormalGeometry);
7311#else
7312 if (ws & Qt::WindowFullScreen) {
7313 // Full screen is not a real window state on Windows.
7314 move(availableGeometry.topLeft());
7315 } else if (ws & Qt::WindowMaximized) {
7316 // Setting a geometry on an already maximized window causes this to be
7317 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7318 // Move the window in normal state if needed.
7319 if (restoredScreen != screen()) {
7320 setWindowState(Qt::WindowNoState);
7321 setGeometry(restoredNormalGeometry);
7322 }
7323 } else {
7324 setGeometry(restoredNormalGeometry);
7325 }
7326#endif // Q_OS_WIN
7327 if (maximized)
7328 ws |= Qt::WindowMaximized;
7329 if (fullScreen)
7330 ws |= Qt::WindowFullScreen;
7331 setWindowState(ws);
7332 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7333 } else {
7334 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7335 if (majorVersion > 2)
7336 setGeometry(restoredGeometry);
7337 else
7338 setGeometry(restoredNormalGeometry);
7339 }
7340 return true;
7341}
7342
7343/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7344 \overload
7345
7346 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7347*/
7348
7349/*!
7350 Sets the margins around the contents of the widget to have the sizes
7351 \a left, \a top, \a right, and \a bottom. The margins are used by
7352 the layout system, and may be used by subclasses to specify the area
7353 to draw in (e.g. excluding the frame).
7354
7355 Changing the margins will trigger a resizeEvent().
7356
7357 \sa contentsRect(), contentsMargins()
7358*/
7359void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7360{
7361 Q_D(QWidget);
7362 if (left == d->leftmargin && top == d->topmargin
7363 && right == d->rightmargin && bottom == d->bottommargin)
7364 return;
7365 d->leftmargin = left;
7366 d->topmargin = top;
7367 d->rightmargin = right;
7368 d->bottommargin = bottom;
7369
7370 d->updateContentsRect();
7371}
7372
7373/*!
7374 \overload
7375 \since 4.6
7376
7377 \brief The setContentsMargins function sets the margins around the
7378 widget's contents.
7379
7380 Sets the margins around the contents of the widget to have the
7381 sizes determined by \a margins. The margins are
7382 used by the layout system, and may be used by subclasses to
7383 specify the area to draw in (e.g. excluding the frame).
7384
7385 Changing the margins will trigger a resizeEvent().
7386
7387 \sa contentsRect(), contentsMargins()
7388*/
7389void QWidget::setContentsMargins(const QMargins &margins)
7390{
7391 setContentsMargins(margins.left(), margins.top(),
7392 margins.right(), margins.bottom());
7393}
7394
7395void QWidgetPrivate::updateContentsRect()
7396{
7397 Q_Q(QWidget);
7398
7399 if (layout)
7400 layout->update(); //force activate; will do updateGeometry
7401 else
7402 q->updateGeometry();
7403
7404 if (q->isVisible()) {
7405 q->update();
7406 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7407 QCoreApplication::sendEvent(q, &e);
7408 } else {
7409 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7410 }
7411
7412 QEvent e(QEvent::ContentsRectChange);
7413 QCoreApplication::sendEvent(q, &e);
7414}
7415
7416/*!
7417 \since 4.6
7418
7419 \brief The contentsMargins function returns the widget's contents margins.
7420
7421 \sa setContentsMargins(), contentsRect()
7422 */
7423QMargins QWidget::contentsMargins() const
7424{
7425 Q_D(const QWidget);
7426 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7427 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7428 userMargins | d->safeAreaMargins() : userMargins;
7429}
7430
7431/*!
7432 Returns the area inside the widget's margins.
7433
7434 \sa setContentsMargins(), contentsMargins()
7435*/
7436QRect QWidget::contentsRect() const
7437{
7438 return rect() - contentsMargins();
7439}
7440
7441QMargins QWidgetPrivate::safeAreaMargins() const
7442{
7443 Q_Q(const QWidget);
7444 QWidget *nativeWidget = q->window();
7445 if (!nativeWidget->windowHandle())
7446 return QMargins();
7447
7448 QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7449 if (!platformWindow)
7450 return QMargins();
7451
7452 QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7453
7454 if (!q->isWindow()) {
7455 // In theory the native parent widget already has a contents rect reflecting
7456 // the safe area of that widget, but we can't be sure that the widget or child
7457 // widgets of that widget have respected the contents rect when setting their
7458 // geometry, so we need to manually compute the safe area.
7459
7460 // Unless the native widget doesn't have any margins, in which case there's
7461 // nothing for us to compute.
7462 if (safeAreaMargins.isNull())
7463 return QMargins();
7464
7465 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7466 // set, then we know that the layout has already taken care of placing us inside the
7467 // safe area, by taking the contents rect of its parent widget into account.
7468 const QWidget *assumedSafeWidget = nullptr;
7469 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7470 QWidget *parentWidget = w->parentWidget();
7471 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7472 continue; // Layout not going to help us
7473
7474 QLayout *layout = parentWidget->layout();
7475 if (!layout)
7476 continue;
7477
7478 if (layout->geometry().isNull())
7479 continue; // Layout hasn't been activated yet
7480
7481 if (layout->indexOf(w) < 0)
7482 continue; // Widget is not in layout
7483
7484 assumedSafeWidget = w;
7485 break;
7486 }
7487
7488#if !defined(QT_DEBUG)
7489 if (assumedSafeWidget) {
7490 // We found a layout that we assume will take care of keeping us within the safe area
7491 // For debug builds we still map the safe area using the fallback logic, so that we
7492 // can detect any misbehaving layouts.
7493 return QMargins();
7494 }
7495#endif
7496
7497 // In all other cases we need to map the safe area of the native parent to the widget.
7498 // This depends on the widget being positioned and sized already, which means the initial
7499 // layout will be wrong, but the layout will then adjust itself.
7500 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7501 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7502 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7503 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7504
7505 // Margins should never be negative
7506 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7507 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7508
7509 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7510 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7511 qWarning() << layout << "is laying out" << assumedSafeWidget
7512 << "outside of the contents rect of" << layout->parentWidget();
7513 return QMargins(); // Return empty margin to visually highlight the error
7514 }
7515 }
7516
7517 return safeAreaMargins;
7518}
7519
7520/*!
7521 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7522
7523 This signal is emitted when the widget's \l contextMenuPolicy is
7524 Qt::CustomContextMenu, and the user has requested a context menu on
7525 the widget. The position \a pos is the position of the context menu
7526 event that the widget receives. Normally this is in widget
7527 coordinates. The exception to this rule is QAbstractScrollArea and
7528 its subclasses that map the context menu event to coordinates of the
7529 \l{QAbstractScrollArea::viewport()}{viewport()}.
7530
7531
7532 \sa mapToGlobal(), QMenu, contextMenuPolicy
7533*/
7534
7535
7536/*!
7537 \property QWidget::contextMenuPolicy
7538 \brief how the widget shows a context menu
7539
7540 The default value of this property is Qt::DefaultContextMenu,
7541 which means the contextMenuEvent() handler is called. Other values
7542 are Qt::NoContextMenu, Qt::PreventContextMenu,
7543 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7544 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7545 emitted.
7546
7547 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7548*/
7549
7550Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7551{
7552 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7553}
7554
7555void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7556{
7557 data->context_menu_policy = (uint) policy;
7558}
7559
7560/*!
7561 \property QWidget::focusPolicy
7562 \brief the way the widget accepts keyboard focus
7563
7564 The policy is Qt::TabFocus if the widget accepts keyboard
7565 focus by tabbing, Qt::ClickFocus if the widget accepts
7566 focus by clicking, Qt::StrongFocus if it accepts both, and
7567 Qt::NoFocus (the default) if it does not accept focus at
7568 all.
7569
7570 You must enable keyboard focus for a widget if it processes
7571 keyboard events. This is normally done from the widget's
7572 constructor. For instance, the QLineEdit constructor calls
7573 setFocusPolicy(Qt::StrongFocus).
7574
7575 If the widget has a focus proxy, then the focus policy will
7576 be propagated to it.
7577
7578 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7579*/
7580
7581
7582Qt::FocusPolicy QWidget::focusPolicy() const
7583{
7584 return (Qt::FocusPolicy)data->focus_policy;
7585}
7586
7587void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7588{
7589 data->focus_policy = (uint) policy;
7590 Q_D(QWidget);
7591 if (d->extra && d->extra->focus_proxy)
7592 d->extra->focus_proxy->setFocusPolicy(policy);
7593}
7594
7595/*!
7596 \property QWidget::updatesEnabled
7597 \brief whether updates are enabled
7598
7599 An updates enabled widget receives paint events and has a system
7600 background; a disabled widget does not. This also implies that
7601 calling update() and repaint() has no effect if updates are
7602 disabled.
7603
7604 By default, this property is \c true.
7605
7606 setUpdatesEnabled() is normally used to disable updates for a
7607 short period of time, for instance to avoid screen flicker during
7608 large changes. In Qt, widgets normally do not generate screen
7609 flicker, but on X11 the server might erase regions on the screen
7610 when widgets get hidden before they can be replaced by other
7611 widgets. Disabling updates solves this.
7612
7613 Example:
7614 \snippet code/src_gui_kernel_qwidget.cpp 13
7615
7616 Disabling a widget implicitly disables all its children. Enabling a widget
7617 enables all child widgets \e except top-level widgets or those that
7618 have been explicitly disabled. Re-enabling updates implicitly calls
7619 update() on the widget.
7620
7621 \sa paintEvent()
7622*/
7623void QWidget::setUpdatesEnabled(bool enable)
7624{
7625 Q_D(QWidget);
7626 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7627 d->setUpdatesEnabled_helper(enable);
7628}
7629
7630/*!
7631 Shows the widget and its child widgets.
7632
7633 This is equivalent to calling showFullScreen(), showMaximized(), or setVisible(true),
7634 depending on the platform's default behavior for the window flags.
7635
7636 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7637 showNormal(), isVisible(), windowFlags()
7638*/
7639void QWidget::show()
7640{
7641 Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
7642 if (defaultState == Qt::WindowFullScreen)
7643 showFullScreen();
7644 else if (defaultState == Qt::WindowMaximized)
7645 showMaximized();
7646 else
7647 setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7648}
7649
7650/*! \internal
7651
7652 Makes the widget visible in the isVisible() meaning of the word.
7653 It is only called for toplevels or widgets with visible parents.
7654 */
7655void QWidgetPrivate::show_recursive()
7656{
7657 Q_Q(QWidget);
7658 // polish if necessary
7659
7660 if (!q->testAttribute(Qt::WA_WState_Created))
7661 createRecursively();
7662 q->ensurePolished();
7663
7664 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7665 q->parentWidget()->d_func()->layout->activate();
7666 // activate our layout before we and our children become visible
7667 if (layout)
7668 layout->activate();
7669
7670 show_helper();
7671}
7672
7673void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7674{
7675 Q_Q(QWidget);
7676
7677 disableUpdates = disableUpdates && q->updatesEnabled();
7678 if (disableUpdates)
7679 q->setAttribute(Qt::WA_UpdatesDisabled);
7680
7681 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7682 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7683 QCoreApplication::sendEvent(q, &e);
7684 q->setAttribute(Qt::WA_PendingMoveEvent, false);
7685 }
7686
7687 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7688 QResizeEvent e(data.crect.size(), QSize());
7689 QCoreApplication::sendEvent(q, &e);
7690 q->setAttribute(Qt::WA_PendingResizeEvent, false);
7691 }
7692
7693 if (disableUpdates)
7694 q->setAttribute(Qt::WA_UpdatesDisabled, false);
7695
7696 if (!recursive)
7697 return;
7698
7699 for (int i = 0; i < children.size(); ++i) {
7700 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
7701 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7702 }
7703}
7704
7705void QWidgetPrivate::activateChildLayoutsRecursively()
7706{
7707 sendPendingMoveAndResizeEvents(false, true);
7708
7709 for (int i = 0; i < children.size(); ++i) {
7710 QWidget *child = qobject_cast<QWidget *>(children.at(i));
7711 if (!child || child->isHidden() || child->isWindow())
7712 continue;
7713
7714 child->ensurePolished();
7715
7716 // Activate child's layout
7717 QWidgetPrivate *childPrivate = child->d_func();
7718 if (childPrivate->layout)
7719 childPrivate->layout->activate();
7720
7721 // Pretend we're visible.
7722 const bool wasVisible = child->isVisible();
7723 if (!wasVisible)
7724 child->setAttribute(Qt::WA_WState_Visible);
7725
7726 // Do the same for all my children.
7727 childPrivate->activateChildLayoutsRecursively();
7728
7729 // We're not cheating anymore.
7730 if (!wasVisible)
7731 child->setAttribute(Qt::WA_WState_Visible, false);
7732 }
7733}
7734
7735void QWidgetPrivate::show_helper()
7736{
7737 Q_Q(QWidget);
7738 data.in_show = true; // qws optimization
7739 // make sure we receive pending move and resize events
7740 sendPendingMoveAndResizeEvents();
7741
7742 // become visible before showing all children
7743 q->setAttribute(Qt::WA_WState_Visible);
7744
7745 // finally show all children recursively
7746 showChildren(false);
7747
7748
7749
7750 const bool isWindow = q->isWindow();
7751#if QT_CONFIG(graphicsview)
7752 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
7753#else
7754 bool isEmbedded = false;
7755#endif
7756
7757 // popup handling: new popups and tools need to be raised, and
7758 // existing popups must be closed. Also propagate the current
7759 // windows's KeyboardFocusChange status.
7760 if (isWindow && !isEmbedded) {
7761 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
7762 q->raise();
7763 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
7764 q->setAttribute(Qt::WA_KeyboardFocusChange);
7765 } else {
7766 while (QApplication::activePopupWidget()) {
7767 if (!QApplication::activePopupWidget()->close())
7768 break;
7769 }
7770 }
7771 }
7772
7773 // Automatic embedding of child windows of widgets already embedded into
7774 // QGraphicsProxyWidget when they are shown the first time.
7775#if QT_CONFIG(graphicsview)
7776 if (isWindow) {
7777 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
7778 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
7779 if (ancestorProxy) {
7780 isEmbedded = true;
7781 ancestorProxy->d_func()->embedSubWindow(q);
7782 }
7783 }
7784 }
7785#else
7786 Q_UNUSED(isEmbedded);
7787#endif
7788
7789 // send the show event before showing the window
7790 QShowEvent showEvent;
7791 QCoreApplication::sendEvent(q, &showEvent);
7792
7793 show_sys();
7794
7795 if (!isEmbedded && q->windowType() == Qt::Popup)
7796 qApp->d_func()->openPopup(q);
7797
7798#ifndef QT_NO_ACCESSIBILITY
7799 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
7800 QAccessibleEvent event(q, QAccessible::ObjectShow);
7801 QAccessible::updateAccessibility(&event);
7802 }
7803#endif
7804
7805 if (QApplicationPrivate::hidden_focus_widget == q) {
7806 QApplicationPrivate::hidden_focus_widget = nullptr;
7807 q->setFocus(Qt::OtherFocusReason);
7808 }
7809
7810 // Process events when showing a Qt::SplashScreen widget before the event loop
7811 // is spinnning; otherwise it might not show up on particular platforms.
7812 // This makes QSplashScreen behave the same on all platforms.
7813 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
7814 QCoreApplication::processEvents();
7815
7816 data.in_show = false; // reset qws optimization
7817}
7818
7819void QWidgetPrivate::show_sys()
7820{
7821 Q_Q(QWidget);
7822
7823 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7824
7825 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7826 invalidateBackingStore(q->rect());
7827 q->setAttribute(Qt::WA_Mapped);
7828 // add our window the modal window list (native dialogs)
7829 if (window && q->isWindow()
7830#if QT_CONFIG(graphicsview)
7831 && (!extra || !extra->proxyWidget)
7832#endif
7833 && q->windowModality() != Qt::NonModal) {
7834 QGuiApplicationPrivate::showModalWindow(window);
7835 }
7836 return;
7837 }
7838
7839 if (renderToTexture && !q->isWindow())
7840 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
7841 else
7842 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
7843
7844 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
7845 || q->testAttribute(Qt::WA_OutsideWSRange)) {
7846 return;
7847 }
7848
7849 if (window) {
7850 if (q->isWindow())
7851 fixPosIncludesFrame();
7852 QRect geomRect = q->geometry();
7853 if (!q->isWindow()) {
7854 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
7855 geomRect.moveTopLeft(topLeftOfWindow);
7856 }
7857 const QRect windowRect = window->geometry();
7858 if (windowRect != geomRect) {
7859 if (q->testAttribute(Qt::WA_Moved)
7860 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
7861 window->setGeometry(geomRect);
7862 else
7863 window->resize(geomRect.size());
7864 }
7865
7866#ifndef QT_NO_CURSOR
7867 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
7868#endif
7869 invalidateBackingStore(q->rect());
7870 window->setNativeWindowVisibility(true);
7871 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
7872 if (window->isTopLevel()) {
7873 const QPoint crectTopLeft = q->data->crect.topLeft();
7874 const QPoint windowTopLeft = window->geometry().topLeft();
7875 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
7876 q->data->crect.moveTopLeft(windowTopLeft);
7877 }
7878 }
7879}
7880
7881/*!
7882 Hides the widget. This function is equivalent to
7883 setVisible(false).
7884
7885
7886 \note If you are working with QDialog or its subclasses and you invoke
7887 the show() function after this function, the dialog will be displayed in
7888 its original position.
7889
7890 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
7891*/
7892void QWidget::hide()
7893{
7894 setVisible(false);
7895}
7896
7897/*!\internal
7898 */
7899void QWidgetPrivate::hide_helper()
7900{
7901 Q_Q(QWidget);
7902
7903 bool isEmbedded = false;
7904#if QT_CONFIG(graphicsview)
7905 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
7906#else
7907 Q_UNUSED(isEmbedded);
7908#endif
7909
7910 if (!isEmbedded && (q->windowType() == Qt::Popup))
7911 qApp->d_func()->closePopup(q);
7912
7913 q->setAttribute(Qt::WA_Mapped, false);
7914 hide_sys();
7915
7916 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
7917
7918 if (wasVisible) {
7919 q->setAttribute(Qt::WA_WState_Visible, false);
7920
7921 }
7922
7923 QHideEvent hideEvent;
7924 QCoreApplication::sendEvent(q, &hideEvent);
7925 hideChildren(false);
7926
7927 // next bit tries to move the focus if the focus widget is now
7928 // hidden.
7929 if (wasVisible) {
7930 qApp->d_func()->sendSyntheticEnterLeave(q);
7931 QWidget *fw = QApplication::focusWidget();
7932 while (fw && !fw->isWindow()) {
7933 if (fw == q) {
7934 q->focusNextPrevChild(true);
7935 break;
7936 }
7937 fw = fw->parentWidget();
7938 }
7939 }
7940
7941 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
7942 repaintManager->removeDirtyWidget(q);
7943
7944#ifndef QT_NO_ACCESSIBILITY
7945 if (wasVisible) {
7946 QAccessibleEvent event(q, QAccessible::ObjectHide);
7947 QAccessible::updateAccessibility(&event);
7948 }
7949#endif
7950}
7951
7952void QWidgetPrivate::hide_sys()
7953{
7954 Q_Q(QWidget);
7955
7956 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7957
7958 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7959 q->setAttribute(Qt::WA_Mapped, false);
7960 // remove our window from the modal window list (native dialogs)
7961 if (window && q->isWindow()
7962#if QT_CONFIG(graphicsview)
7963 && (!extra || !extra->proxyWidget)
7964#endif
7965 && q->windowModality() != Qt::NonModal) {
7966 QGuiApplicationPrivate::hideModalWindow(window);
7967 }
7968 // do not return here, if window non-zero, we must hide it
7969 }
7970
7971 deactivateWidgetCleanup();
7972
7973 if (!q->isWindow()) {
7974 QWidget *p = q->parentWidget();
7975 if (p &&p->isVisible()) {
7976 if (renderToTexture)
7977 p->d_func()->invalidateBackingStore(q->geometry());
7978 else
7979 invalidateBackingStore(q->rect());
7980 }
7981 } else {
7982 invalidateBackingStore(q->rect());
7983 }
7984
7985 if (window)
7986 window->setNativeWindowVisibility(false);
7987}
7988
7989/*!
7990 \fn bool QWidget::isHidden() const
7991
7992 Returns \c true if the widget is hidden, otherwise returns \c false.
7993
7994 A hidden widget will only become visible when show() is called on
7995 it. It will not be automatically shown when the parent is shown.
7996
7997 To check visibility, use !isVisible() instead (notice the exclamation mark).
7998
7999 isHidden() implies !isVisible(), but a widget can be not visible
8000 and not hidden at the same time. This is the case for widgets that are children of
8001 widgets that are not visible.
8002
8003
8004 Widgets are hidden if:
8005 \list
8006 \li they were created as independent windows,
8007 \li they were created as children of visible widgets,
8008 \li hide() or setVisible(false) was called.
8009 \endlist
8010*/
8011
8012void QWidget::setVisible(bool visible)
8013{
8014 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8015 return;
8016
8017 // Remember that setVisible was called explicitly
8018 setAttribute(Qt::WA_WState_ExplicitShowHide);
8019
8020 Q_D(QWidget);
8021 d->setVisible(visible);
8022}
8023
8024// This method is called from QWidgetWindow in response to QWindow::setVisible,
8025// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8026// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8027void QWidgetPrivate::setVisible(bool visible)
8028{
8029 Q_Q(QWidget);
8030 if (visible) { // show
8031 // Designer uses a trick to make grabWidget work without showing
8032 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8033 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8034 q->parentWidget()->window()->d_func()->createRecursively();
8035
8036 //create toplevels but not children of non-visible parents
8037 QWidget *pw = q->parentWidget();
8038 if (!q->testAttribute(Qt::WA_WState_Created)
8039 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8040 q->create();
8041 }
8042
8043 bool wasResized = q->testAttribute(Qt::WA_Resized);
8044 Qt::WindowStates initialWindowState = q->windowState();
8045
8046 // polish if necessary
8047 q->ensurePolished();
8048
8049 // whether we need to inform the parent widget immediately
8050 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8051 // we are no longer hidden
8052 q->setAttribute(Qt::WA_WState_Hidden, false);
8053
8054 if (needUpdateGeometry)
8055 updateGeometry_helper(true);
8056
8057 // activate our layout before we and our children become visible
8058 if (layout)
8059 layout->activate();
8060
8061 if (!q->isWindow()) {
8062 QWidget *parent = q->parentWidget();
8063 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8064 parent->d_func()->layout->activate();
8065 if (parent->isWindow())
8066 break;
8067 parent = parent->parentWidget();
8068 }
8069 if (parent)
8070 parent->d_func()->setDirtyOpaqueRegion();
8071 }
8072
8073 // adjust size if necessary
8074 if (!wasResized
8075 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8076 if (q->isWindow()) {
8077 q->adjustSize();
8078 if (q->windowState() != initialWindowState)
8079 q->setWindowState(initialWindowState);
8080 } else {
8081 q->adjustSize();
8082 }
8083 q->setAttribute(Qt::WA_Resized, false);
8084 }
8085
8086 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8087
8088 if (q->isWindow() || q->parentWidget()->isVisible()) {
8089 show_helper();
8090
8091 qApp->d_func()->sendSyntheticEnterLeave(q);
8092 }
8093
8094 QEvent showToParentEvent(QEvent::ShowToParent);
8095 QCoreApplication::sendEvent(q, &showToParentEvent);
8096 } else { // hide
8097 if (QApplicationPrivate::hidden_focus_widget == q)
8098 QApplicationPrivate::hidden_focus_widget = nullptr;
8099
8100 // hw: The test on getOpaqueRegion() needs to be more intelligent
8101 // currently it doesn't work if the widget is hidden (the region will
8102 // be clipped). The real check should be testing the cached region
8103 // (and dirty flag) directly.
8104 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8105 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8106
8107 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8108 q->setAttribute(Qt::WA_WState_Hidden);
8109 if (q->testAttribute(Qt::WA_WState_Created))
8110 hide_helper();
8111 }
8112
8113 // invalidate layout similar to updateGeometry()
8114 if (!q->isWindow() && q->parentWidget()) {
8115 if (q->parentWidget()->d_func()->layout)
8116 q->parentWidget()->d_func()->layout->invalidate();
8117 else if (q->parentWidget()->isVisible())
8118 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8119 }
8120
8121 QEvent hideToParentEvent(QEvent::HideToParent);
8122 QCoreApplication::sendEvent(q, &hideToParentEvent);
8123 }
8124}
8125
8126/*!
8127 Convenience function, equivalent to setVisible(!\a hidden).
8128*/
8129void QWidget::setHidden(bool hidden)
8130{
8131 setVisible(!hidden);
8132}
8133
8134void QWidgetPrivate::_q_showIfNotHidden()
8135{
8136 Q_Q(QWidget);
8137 if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
8138 q->setVisible(true);
8139}
8140
8141void QWidgetPrivate::showChildren(bool spontaneous)
8142{
8143 QList<QObject*> childList = children;
8144 for (int i = 0; i < childList.size(); ++i) {
8145 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8146 if (widget && widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8147 widget->setAttribute(Qt::WA_WState_Hidden, false);
8148 if (!widget
8149 || widget->isWindow()
8150 || widget->testAttribute(Qt::WA_WState_Hidden))
8151 continue;
8152 if (spontaneous) {
8153 widget->setAttribute(Qt::WA_Mapped);
8154 widget->d_func()->showChildren(true);
8155 QShowEvent e;
8156 QApplication::sendSpontaneousEvent(widget, &e);
8157 } else {
8158 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8159 widget->d_func()->show_recursive();
8160 else
8161 widget->show();
8162 }
8163 }
8164}
8165
8166void QWidgetPrivate::hideChildren(bool spontaneous)
8167{
8168 QList<QObject*> childList = children;
8169 for (int i = 0; i < childList.size(); ++i) {
8170 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8171 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8172 continue;
8173
8174 if (spontaneous)
8175 widget->setAttribute(Qt::WA_Mapped, false);
8176 else
8177 widget->setAttribute(Qt::WA_WState_Visible, false);
8178 widget->d_func()->hideChildren(spontaneous);
8179 QHideEvent e;
8180 if (spontaneous) {
8181 QApplication::sendSpontaneousEvent(widget, &e);
8182 } else {
8183 QCoreApplication::sendEvent(widget, &e);
8184 if (widget->internalWinId()
8185 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8186 // hide_sys() on an ancestor won't have any affect on this
8187 // widget, so it needs an explicit hide_sys() of its own
8188 widget->d_func()->hide_sys();
8189 }
8190 }
8191 qApp->d_func()->sendSyntheticEnterLeave(widget);
8192#ifndef QT_NO_ACCESSIBILITY
8193 if (!spontaneous) {
8194 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8195 QAccessible::updateAccessibility(&event);
8196 }
8197#endif
8198 }
8199}
8200
8201bool QWidgetPrivate::close_helper(CloseMode mode)
8202{
8203 if (data.is_closing)
8204 return true;
8205
8206 Q_Q(QWidget);
8207 data.is_closing = 1;
8208
8209 QPointer<QWidget> that = q;
8210 QPointer<QWidget> parentWidget = (q->parentWidget() && !QObjectPrivate::get(q->parentWidget())->wasDeleted) ? q->parentWidget() : nullptr;
8211
8212 bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
8213 if (mode != CloseNoEvent) {
8214 QCloseEvent e;
8215 if (mode == CloseWithSpontaneousEvent)
8216 QApplication::sendSpontaneousEvent(q, &e);
8217 else
8218 QCoreApplication::sendEvent(q, &e);
8219 if (!that.isNull() && !e.isAccepted()) {
8220 data.is_closing = 0;
8221 return false;
8222 }
8223 }
8224
8225 if (!that.isNull() && !q->isHidden())
8226 q->hide();
8227
8228 // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
8229 quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
8230
8231 if (quitOnClose) {
8232 /* if there is no non-withdrawn primary window left (except
8233 the ones without QuitOnClose), we emit the lastWindowClosed
8234 signal */
8235 QWidgetList list = QApplication::topLevelWidgets();
8236 bool lastWindowClosed = true;
8237 for (int i = 0; i < list.size(); ++i) {
8238 QWidget *w = list.at(i);
8239 if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
8240 continue;
8241 lastWindowClosed = false;
8242 break;
8243 }
8244 if (lastWindowClosed) {
8245 QGuiApplicationPrivate::emitLastWindowClosed();
8246 QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
8247 applicationPrivate->maybeQuit();
8248 }
8249 }
8250
8251
8252 if (!that.isNull()) {
8253 data.is_closing = 0;
8254 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8255 q->setAttribute(Qt::WA_DeleteOnClose, false);
8256 q->deleteLater();
8257 }
8258 }
8259 return true;
8260}
8261
8262
8263/*!
8264 Closes this widget. Returns \c true if the widget was closed;
8265 otherwise returns \c false.
8266
8267 First it sends the widget a QCloseEvent. The widget is
8268 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8269 the close event. If it \l{QEvent::ignore()}{ignores}
8270 the event, nothing happens. The default
8271 implementation of QWidget::closeEvent() accepts the close event.
8272
8273 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8274 is also deleted. A close events is delivered to the widget no
8275 matter if the widget is visible or not.
8276
8277 The \l QApplication::lastWindowClosed() signal is emitted when the
8278 last visible primary window (i.e. window with no parent) with the
8279 Qt::WA_QuitOnClose attribute set is closed. By default this
8280 attribute is set for all widgets except transient windows such as
8281 splash screens, tool windows, and popup menus.
8282
8283*/
8284
8285bool QWidget::close()
8286{
8287 return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
8288}
8289
8290/*!
8291 \property QWidget::visible
8292 \brief whether the widget is visible
8293
8294 Calling setVisible(true) or show() sets the widget to visible
8295 status if all its parent widgets up to the window are visible. If
8296 an ancestor is not visible, the widget won't become visible until
8297 all its ancestors are shown. If its size or position has changed,
8298 Qt guarantees that a widget gets move and resize events just
8299 before it is shown. If the widget has not been resized yet, Qt
8300 will adjust the widget's size to a useful default using
8301 adjustSize().
8302
8303 Calling setVisible(false) or hide() hides a widget explicitly. An
8304 explicitly hidden widget will never become visible, even if all
8305 its ancestors become visible, unless you show it.
8306
8307 A widget receives show and hide events when its visibility status
8308 changes. Between a hide and a show event, there is no need to
8309 waste CPU cycles preparing or displaying information to the user.
8310 A video application, for example, might simply stop generating new
8311 frames.
8312
8313 A widget that happens to be obscured by other windows on the
8314 screen is considered to be visible. The same applies to iconified
8315 windows and windows that exist on another virtual
8316 desktop (on platforms that support this concept). A widget
8317 receives spontaneous show and hide events when its mapping status
8318 is changed by the window system, e.g. a spontaneous hide event
8319 when the user minimizes the window, and a spontaneous show event
8320 when the window is restored again.
8321
8322 You almost never have to reimplement the setVisible() function. If
8323 you need to change some settings before a widget is shown, use
8324 showEvent() instead. If you need to do some delayed initialization
8325 use the Polish event delivered to the event() function.
8326
8327 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8328 showEvent(), hideEvent()
8329*/
8330
8331
8332/*!
8333 Returns \c true if this widget would become visible if \a ancestor is
8334 shown; otherwise returns \c false.
8335
8336 The true case occurs if neither the widget itself nor any parent
8337 up to but excluding \a ancestor has been explicitly hidden.
8338
8339 This function will still return true if the widget is obscured by
8340 other windows on the screen, but could be physically visible if it
8341 or they were to be moved.
8342
8343 isVisibleTo(0) is identical to isVisible().
8344
8345 \sa show(), hide(), isVisible()
8346*/
8347
8348bool QWidget::isVisibleTo(const QWidget *ancestor) const
8349{
8350 if (!ancestor)
8351 return isVisible();
8352 const QWidget * w = this;
8353 while (!w->isHidden()
8354 && !w->isWindow()
8355 && w->parentWidget()
8356 && w->parentWidget() != ancestor)
8357 w = w->parentWidget();
8358 return !w->isHidden();
8359}
8360
8361
8362/*!
8363 Returns the unobscured region where paint events can occur.
8364
8365 For visible widgets, this is an approximation of the area not
8366 covered by other widgets; otherwise, this is an empty region.
8367
8368 The repaint() function calls this function if necessary, so in
8369 general you do not need to call it.
8370
8371*/
8372QRegion QWidget::visibleRegion() const
8373{
8374 Q_D(const QWidget);
8375
8376 QRect clipRect = d->clipRect();
8377 if (clipRect.isEmpty())
8378 return QRegion();
8379 QRegion r(clipRect);
8380 d->subtractOpaqueChildren(r, clipRect);
8381 d->subtractOpaqueSiblings(r);
8382 return r;
8383}
8384
8385
8386QSize QWidgetPrivate::adjustedSize() const
8387{
8388 Q_Q(const QWidget);
8389
8390 QSize s = q->sizeHint();
8391
8392 if (q->isWindow()) {
8393 Qt::Orientations exp;
8394 if (layout) {
8395 if (layout->hasHeightForWidth())
8396 s.setHeight(layout->totalHeightForWidth(s.width()));
8397 exp = layout->expandingDirections();
8398 } else
8399 {
8400 if (q->sizePolicy().hasHeightForWidth())
8401 s.setHeight(q->heightForWidth(s.width()));
8402 exp = q->sizePolicy().expandingDirections();
8403 }
8404 if (exp & Qt::Horizontal)
8405 s.setWidth(qMax(s.width(), 200));
8406 if (exp & Qt::Vertical)
8407 s.setHeight(qMax(s.height(), 100));
8408
8409 QRect screen;
8410 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8411 screen = screenAtPoint->geometry();
8412 else
8413 screen = QGuiApplication::primaryScreen()->geometry();
8414
8415 s.setWidth(qMin(s.width(), screen.width()*2/3));
8416 s.setHeight(qMin(s.height(), screen.height()*2/3));
8417
8418 if (QTLWExtra *extra = maybeTopData())
8419 extra->sizeAdjusted = true;
8420 }
8421
8422 if (!s.isValid()) {
8423 QRect r = q->childrenRect(); // get children rectangle
8424 if (r.isNull())
8425 return s;
8426 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8427 }
8428
8429 return s;
8430}
8431
8432/*!
8433 Adjusts the size of the widget to fit its contents.
8434
8435 This function uses sizeHint() if it is valid, i.e., the size hint's width
8436 and height are \>= 0. Otherwise, it sets the size to the children
8437 rectangle that covers all child widgets (the union of all child widget
8438 rectangles).
8439
8440 For windows, the screen size is also taken into account. If the sizeHint()
8441 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8442 {expanding}, the window will be at least (200, 100). The maximum size of
8443 a window is 2/3 of the screen's width and height.
8444
8445 \sa sizeHint(), childrenRect()
8446*/
8447
8448void QWidget::adjustSize()
8449{
8450 Q_D(QWidget);
8451 ensurePolished();
8452 QSize s = d->adjustedSize();
8453
8454 if (d->layout)
8455 d->layout->activate();
8456
8457 if (s.isValid())
8458 resize(s);
8459}
8460
8461
8462/*!
8463 \property QWidget::sizeHint
8464 \brief the recommended size for the widget
8465
8466 If the value of this property is an invalid size, no size is
8467 recommended.
8468
8469 The default implementation of sizeHint() returns an invalid size
8470 if there is no layout for this widget, and returns the layout's
8471 preferred size otherwise.
8472
8473 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8474 setMinimumSize(), updateGeometry()
8475*/
8476
8477QSize QWidget::sizeHint() const
8478{
8479 Q_D(const QWidget);
8480 if (d->layout)
8481 return d->layout->totalSizeHint();
8482 return QSize(-1, -1);
8483}
8484
8485/*!
8486 \property QWidget::minimumSizeHint
8487 \brief the recommended minimum size for the widget
8488
8489 If the value of this property is an invalid size, no minimum size
8490 is recommended.
8491
8492 The default implementation of minimumSizeHint() returns an invalid
8493 size if there is no layout for this widget, and returns the
8494 layout's minimum size otherwise. Most built-in widgets reimplement
8495 minimumSizeHint().
8496
8497 \l QLayout will never resize a widget to a size smaller than the
8498 minimum size hint unless minimumSize() is set or the size policy is
8499 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8500 size hint will be ignored.
8501
8502 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8503*/
8504QSize QWidget::minimumSizeHint() const
8505{
8506 Q_D(const QWidget);
8507 if (d->layout)
8508 return d->layout->totalMinimumSize();
8509 return QSize(-1, -1);
8510}
8511
8512
8513/*!
8514 \fn QWidget *QWidget::parentWidget() const
8515
8516 Returns the parent of this widget, or \nullptr if it does not have any
8517 parent widget.
8518*/
8519
8520
8521/*!
8522 Returns \c true if this widget is a parent, (or grandparent and so on
8523 to any level), of the given \a child, and both widgets are within
8524 the same window; otherwise returns \c false.
8525*/
8526
8527bool QWidget::isAncestorOf(const QWidget *child) const
8528{
8529 while (child) {
8530 if (child == this)
8531 return true;
8532 if (child->isWindow())
8533 return false;
8534 child = child->parentWidget();
8535 }
8536 return false;
8537}
8538
8539/*****************************************************************************
8540 QWidget event handling
8541 *****************************************************************************/
8542
8543/*!
8544 This is the main event handler; it handles event \a event. You can
8545 reimplement this function in a subclass, but we recommend using
8546 one of the specialized event handlers instead.
8547
8548 Key press and release events are treated differently from other
8549 events. event() checks for Tab and Shift+Tab and tries to move the
8550 focus appropriately. If there is no widget to move the focus to
8551 (or the key press is not Tab or Shift+Tab), event() calls
8552 keyPressEvent().
8553
8554 Mouse and tablet event handling is also slightly special: only
8555 when the widget is \l enabled, event() will call the specialized
8556 handlers such as mousePressEvent(); otherwise it will discard the
8557 event.
8558
8559 This function returns \c true if the event was recognized, otherwise
8560 it returns \c false. If the recognized event was accepted (see \l
8561 QEvent::accepted), any further processing such as event
8562 propagation to the parent widget stops.
8563
8564 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8565 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8566 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8567 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8568 QObject::event(), QObject::timerEvent()
8569*/
8570
8571bool QWidget::event(QEvent *event)
8572{
8573 Q_D(QWidget);
8574
8575 // ignore mouse and key events when disabled
8576 if (!isEnabled()) {
8577 switch(event->type()) {
8578 case QEvent::TabletPress:
8579 case QEvent::TabletRelease:
8580 case QEvent::TabletMove:
8581 case QEvent::MouseButtonPress:
8582 case QEvent::MouseButtonRelease:
8583 case QEvent::MouseButtonDblClick:
8584 case QEvent::MouseMove:
8585 case QEvent::TouchBegin:
8586 case QEvent::TouchUpdate:
8587 case QEvent::TouchEnd:
8588 case QEvent::TouchCancel:
8589 case QEvent::ContextMenu:
8590 case QEvent::KeyPress:
8591 case QEvent::KeyRelease:
8592#if QT_CONFIG(wheelevent)
8593 case QEvent::Wheel:
8594#endif
8595 return false;
8596 default:
8597 break;
8598 }
8599 }
8600 switch (event->type()) {
8601 case QEvent::PlatformSurface: {
8602 // Sync up QWidget's view of whether or not the widget has been created
8603 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8604 case QPlatformSurfaceEvent::SurfaceCreated:
8605 if (!testAttribute(Qt::WA_WState_Created))
8606 create();
8607 break;
8608 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8609 if (testAttribute(Qt::WA_WState_Created)) {
8610 // Child windows have already been destroyed by QWindow,
8611 // so we skip them here.
8612 destroy(false, false);
8613 }
8614 break;
8615 }
8616 break;
8617 }
8618 case QEvent::MouseMove:
8619 mouseMoveEvent((QMouseEvent*)event);
8620 break;
8621
8622 case QEvent::MouseButtonPress:
8623 mousePressEvent((QMouseEvent*)event);
8624 break;
8625
8626 case QEvent::MouseButtonRelease:
8627 mouseReleaseEvent((QMouseEvent*)event);
8628 break;
8629
8630 case QEvent::MouseButtonDblClick:
8631 mouseDoubleClickEvent((QMouseEvent*)event);
8632 break;
8633#if QT_CONFIG(wheelevent)
8634 case QEvent::Wheel:
8635 wheelEvent((QWheelEvent*)event);
8636 break;
8637#endif
8638#if QT_CONFIG(tabletevent)
8639 case QEvent::TabletMove:
8640 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
8641 break;
8642 Q_FALLTHROUGH();
8643 case QEvent::TabletPress:
8644 case QEvent::TabletRelease:
8645 tabletEvent((QTabletEvent*)event);
8646 break;
8647#endif
8648 case QEvent::KeyPress: {
8649 QKeyEvent *k = (QKeyEvent *)event;
8650 bool res = false;
8651 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
8652 if (k->key() == Qt::Key_Backtab
8653 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
8654 res = focusNextPrevChild(false);
8655 else if (k->key() == Qt::Key_Tab)
8656 res = focusNextPrevChild(true);
8657 if (res)
8658 break;
8659 }
8660 keyPressEvent(k);
8661#ifdef QT_KEYPAD_NAVIGATION
8662 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
8663 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
8664 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
8665 if (k->key() == Qt::Key_Up)
8666 res = focusNextPrevChild(false);
8667 else if (k->key() == Qt::Key_Down)
8668 res = focusNextPrevChild(true);
8669 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
8670 if (k->key() == Qt::Key_Up)
8671 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
8672 else if (k->key() == Qt::Key_Right)
8673 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
8674 else if (k->key() == Qt::Key_Down)
8675 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
8676 else if (k->key() == Qt::Key_Left)
8677 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
8678 }
8679 if (res) {
8680 k->accept();
8681 break;
8682 }
8683 }
8684#endif
8685#if QT_CONFIG(whatsthis)
8686 if (!k->isAccepted()
8687 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
8688 && d->whatsThis.size()) {
8689 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
8690 k->accept();
8691 }
8692#endif
8693 }
8694 break;
8695
8696 case QEvent::KeyRelease:
8697 keyReleaseEvent((QKeyEvent*)event);
8698 Q_FALLTHROUGH();
8699 case QEvent::ShortcutOverride:
8700 break;
8701
8702 case QEvent::InputMethod:
8703 inputMethodEvent((QInputMethodEvent *) event);
8704 break;
8705
8706 case QEvent::InputMethodQuery:
8707 if (testAttribute(Qt::WA_InputMethodEnabled)) {
8708 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
8709 Qt::InputMethodQueries queries = query->queries();
8710 for (uint i = 0; i < 32; ++i) {
8711 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
8712 if (q) {
8713 QVariant v = inputMethodQuery(q);
8714 if (q == Qt::ImEnabled && !v.isValid() && isEnabled())
8715 v = QVariant(true); // special case for Qt4 compatibility
8716 query->setValue(q, v);
8717 }
8718 }
8719 query->accept();
8720 }
8721 break;
8722
8723 case QEvent::PolishRequest:
8724 ensurePolished();
8725 break;
8726
8727 case QEvent::Polish: {
8728 style()->polish(this);
8729 setAttribute(Qt::WA_WState_Polished);
8730 if (!QApplication::font(this).isCopyOf(QApplication::font()))
8731 d->resolveFont();
8732 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
8733 d->resolvePalette();
8734 }
8735 break;
8736
8737 case QEvent::ApplicationWindowIconChange:
8738 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
8739 d->setWindowIcon_sys();
8740 d->setWindowIcon_helper();
8741 }
8742 break;
8743 case QEvent::FocusIn:
8744 focusInEvent((QFocusEvent*)event);
8745 d->updateWidgetTransform(event);
8746 break;
8747
8748 case QEvent::FocusOut:
8749 focusOutEvent((QFocusEvent*)event);
8750 break;
8751
8752 case QEvent::Enter:
8753#if QT_CONFIG(statustip)
8754 if (d->statusTip.size()) {
8755 QStatusTipEvent tip(d->statusTip);
8756 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8757 }
8758#endif
8759 enterEvent(static_cast<QEnterEvent*>(event));
8760 break;
8761
8762 case QEvent::Leave:
8763#if QT_CONFIG(statustip)
8764 if (d->statusTip.size()) {
8765 QString empty;
8766 QStatusTipEvent tip(empty);
8767 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8768 }
8769#endif
8770 leaveEvent(event);
8771 break;
8772
8773 case QEvent::HoverEnter:
8774 case QEvent::HoverLeave:
8775 update();
8776 break;
8777
8778 case QEvent::Paint:
8779 // At this point the event has to be delivered, regardless
8780 // whether the widget isVisible() or not because it
8781 // already went through the filters
8782 paintEvent((QPaintEvent*)event);
8783 break;
8784
8785 case QEvent::Move:
8786 moveEvent((QMoveEvent*)event);
8787 d->updateWidgetTransform(event);
8788 break;
8789
8790 case QEvent::Resize:
8791 resizeEvent((QResizeEvent*)event);
8792 d->updateWidgetTransform(event);
8793 break;
8794
8795 case QEvent::Close:
8796 closeEvent((QCloseEvent *)event);
8797 break;
8798
8799#ifndef QT_NO_CONTEXTMENU
8800 case QEvent::ContextMenu:
8801 switch (data->context_menu_policy) {
8802 case Qt::PreventContextMenu:
8803 break;
8804 case Qt::DefaultContextMenu:
8805 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
8806 break;
8807 case Qt::CustomContextMenu:
8808 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
8809 break;
8810#if QT_CONFIG(menu)
8811 case Qt::ActionsContextMenu:
8812 if (d->actions.count()) {
8813 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
8814 nullptr, this);
8815 break;
8816 }
8817 Q_FALLTHROUGH();
8818#endif
8819 default:
8820 event->ignore();
8821 break;
8822 }
8823 break;
8824#endif // QT_NO_CONTEXTMENU
8825
8826#if QT_CONFIG(draganddrop)
8827 case QEvent::Drop:
8828 dropEvent((QDropEvent*) event);
8829 break;
8830
8831 case QEvent::DragEnter:
8832 dragEnterEvent((QDragEnterEvent*) event);
8833 break;
8834
8835 case QEvent::DragMove:
8836 dragMoveEvent((QDragMoveEvent*) event);
8837 break;
8838
8839 case QEvent::DragLeave:
8840 dragLeaveEvent((QDragLeaveEvent*) event);
8841 break;
8842#endif
8843
8844 case QEvent::Show:
8845 showEvent((QShowEvent*) event);
8846 break;
8847
8848 case QEvent::Hide:
8849 hideEvent((QHideEvent*) event);
8850 break;
8851
8852 case QEvent::ShowWindowRequest:
8853 if (!isHidden())
8854 d->show_sys();
8855 break;
8856
8857 case QEvent::ApplicationFontChange:
8858 d->resolveFont();
8859 break;
8860 case QEvent::ApplicationPaletteChange:
8861 if (!(windowType() == Qt::Desktop))
8862 d->resolvePalette();
8863 break;
8864
8865 case QEvent::ToolBarChange:
8866 case QEvent::ActivationChange:
8867 case QEvent::EnabledChange:
8868 case QEvent::FontChange:
8869 case QEvent::StyleChange:
8870 case QEvent::PaletteChange:
8871 case QEvent::WindowTitleChange:
8872 case QEvent::IconTextChange:
8873 case QEvent::ModifiedChange:
8874 case QEvent::MouseTrackingChange:
8875 case QEvent::TabletTrackingChange:
8876 case QEvent::ParentChange:
8877 case QEvent::LocaleChange:
8878 case QEvent::MacSizeChange:
8879 case QEvent::ContentsRectChange:
8880 case QEvent::ThemeChange:
8881 case QEvent::ReadOnlyChange:
8882 changeEvent(event);
8883 break;
8884
8885 case QEvent::WindowStateChange: {
8886 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
8887 if (wasMinimized != isMinimized()) {
8888 QWidget *widget = const_cast<QWidget *>(this);
8889 if (wasMinimized) {
8890 // Always send the spontaneous events here, otherwise it can break the application!
8891 if (!d->childrenShownByExpose) {
8892 // Show widgets only when they are not yet shown by the expose event
8893 d->showChildren(true);
8894 QShowEvent showEvent;
8895 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
8896 }
8897 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
8898 } else {
8899 QHideEvent hideEvent;
8900 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
8901 d->hideChildren(true);
8902 d->childrenHiddenByWState = true;
8903 }
8904 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
8905 }
8906 changeEvent(event);
8907 }
8908 break;
8909
8910 case QEvent::WindowActivate:
8911 case QEvent::WindowDeactivate: {
8912 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
8913 update();
8914 QList<QObject*> childList = d->children;
8915 for (int i = 0; i < childList.size(); ++i) {
8916 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
8917 if (w && w->isVisible() && !w->isWindow())
8918 QCoreApplication::sendEvent(w, event);
8919 }
8920 break; }
8921
8922 case QEvent::LanguageChange:
8923 changeEvent(event);
8924 {
8925 QList<QObject*> childList = d->children;
8926 for (int i = 0; i < childList.size(); ++i) {
8927 QObject *o = childList.at(i);
8928 if (o)
8929 QCoreApplication::sendEvent(o, event);
8930 }
8931 }
8932 update();
8933 break;
8934
8935 case QEvent::ApplicationLayoutDirectionChange:
8936 d->resolveLayoutDirection();
8937 break;
8938
8939 case QEvent::LayoutDirectionChange:
8940 if (d->layout)
8941 d->layout->invalidate();
8942 update();
8943 changeEvent(event);
8944 break;
8945 case QEvent::UpdateRequest:
8946 d->syncBackingStore();
8947 break;
8948 case QEvent::UpdateLater:
8949 update(static_cast<QUpdateLaterEvent*>(event)->region());
8950 break;
8951 case QEvent::StyleAnimationUpdate:
8952 if (isVisible() && !window()->isMinimized()) {
8953 event->accept();
8954 update();
8955 }
8956 break;
8957
8958 case QEvent::WindowBlocked:
8959 case QEvent::WindowUnblocked:
8960 if (!d->children.isEmpty()) {
8961 QWidget *modalWidget = QApplication::activeModalWidget();
8962 for (int i = 0; i < d->children.size(); ++i) {
8963 QObject *o = d->children.at(i);
8964 if (o && o != modalWidget && o->isWidgetType()) {
8965 QWidget *w = static_cast<QWidget *>(o);
8966 // do not forward the event to child windows; QApplication does this for us
8967 if (!w->isWindow())
8968 QCoreApplication::sendEvent(w, event);
8969 }
8970 }
8971 }
8972 break;
8973#if QT_CONFIG(tooltip)
8974 case QEvent::ToolTip:
8975 if (!d->toolTip.isEmpty())
8976 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
8977 else
8978 event->ignore();
8979 break;
8980#endif
8981#if QT_CONFIG(whatsthis)
8982 case QEvent::WhatsThis:
8983 if (d->whatsThis.size())
8984 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
8985 else
8986 event->ignore();
8987 break;
8988 case QEvent::QueryWhatsThis:
8989 if (d->whatsThis.isEmpty())
8990 event->ignore();
8991 break;
8992#endif
8993 case QEvent::EmbeddingControl:
8994 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
8995 data->fstrut_dirty = false;
8996 break;
8997#ifndef QT_NO_ACTION
8998 case QEvent::ActionAdded:
8999 case QEvent::ActionRemoved:
9000 case QEvent::ActionChanged:
9001 actionEvent((QActionEvent*)event);
9002 break;
9003#endif
9004
9005 case QEvent::KeyboardLayoutChange:
9006 {
9007 changeEvent(event);
9008
9009 // inform children of the change
9010 QList<QObject*> childList = d->children;
9011 for (int i = 0; i < childList.size(); ++i) {
9012 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9013 if (w && w->isVisible() && !w->isWindow())
9014 QCoreApplication::sendEvent(w, event);
9015 }
9016 break;
9017 }
9018 case QEvent::TouchBegin:
9019 case QEvent::TouchUpdate:
9020 case QEvent::TouchEnd:
9021 case QEvent::TouchCancel:
9022 {
9023 event->ignore();
9024 break;
9025 }
9026#ifndef QT_NO_GESTURES
9027 case QEvent::Gesture:
9028 event->ignore();
9029 break;
9030#endif
9031 case QEvent::ScreenChangeInternal:
9032 if (const QTLWExtra *te = d->maybeTopData()) {
9033 const QWindow *win = te->window;
9034 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9035 }
9036 if (d->data.fnt.d->dpi != logicalDpiY())
9037 d->updateFont(d->data.fnt);
9038#ifndef QT_NO_OPENGL
9039 d->renderToTextureReallyDirty = 1;
9040#endif
9041 break;
9042#ifndef QT_NO_PROPERTIES
9043 case QEvent::DynamicPropertyChange: {
9044 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9045 if (propName.length() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9046 uint value = property(propName.constData()).toUInt();
9047 if (!d->extra)
9048 d->createExtra();
9049 const char axis = propName.at(12);
9050 if (axis == 'X')
9051 d->extra->customDpiX = value;
9052 else if (axis == 'Y')
9053 d->extra->customDpiY = value;
9054 d->updateFont(d->data.fnt);
9055 }
9056 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9057 windowHandle()->setProperty(propName, property(propName));
9058 Q_FALLTHROUGH();
9059 }
9060#endif
9061 default:
9062 return QObject::event(event);
9063 }
9064 return true;
9065}
9066
9067/*!
9068 This event handler can be reimplemented to handle state changes.
9069
9070 The state being changed in this event can be retrieved through the \a event
9071 supplied.
9072
9073 Change events include: QEvent::ToolBarChange,
9074 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9075 QEvent::StyleChange, QEvent::PaletteChange,
9076 QEvent::WindowTitleChange, QEvent::IconTextChange,
9077 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9078 QEvent::ParentChange, QEvent::WindowStateChange,
9079 QEvent::LanguageChange, QEvent::LocaleChange,
9080 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9081
9082*/
9083void QWidget::changeEvent(QEvent * event)
9084{
9085 switch(event->type()) {
9086 case QEvent::EnabledChange: {
9087 update();
9088#ifndef QT_NO_ACCESSIBILITY
9089 QAccessible::State s;
9090 s.disabled = true;
9091 QAccessibleStateChangeEvent event(this, s);
9092 QAccessible::updateAccessibility(&event);
9093#endif
9094 break;
9095 }
9096
9097 case QEvent::FontChange:
9098 case QEvent::StyleChange: {
9099 Q_D(QWidget);
9100 update();
9101 updateGeometry();
9102 if (d->layout)
9103 d->layout->invalidate();
9104 break;
9105 }
9106
9107 case QEvent::PaletteChange:
9108 update();
9109 break;
9110
9111 case QEvent::ThemeChange:
9112 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9113 && qApp && !QCoreApplication::closingDown()) {
9114 if (testAttribute(Qt::WA_WState_Polished))
9115 QApplication::style()->unpolish(this);
9116 if (testAttribute(Qt::WA_WState_Polished))
9117 QApplication::style()->polish(this);
9118 QEvent styleChangedEvent(QEvent::StyleChange);
9119 QCoreApplication::sendEvent(this, &styleChangedEvent);
9120 if (isVisible())
9121 update();
9122 }
9123 break;
9124
9125#ifdef Q_OS_MAC
9126 case QEvent::MacSizeChange:
9127 updateGeometry();
9128 break;
9129#endif
9130
9131 default:
9132 break;
9133 }
9134}
9135
9136/*!
9137 This event handler, for event \a event, can be reimplemented in a
9138 subclass to receive mouse move events for the widget.
9139
9140 If mouse tracking is switched off, mouse move events only occur if
9141 a mouse button is pressed while the mouse is being moved. If mouse
9142 tracking is switched on, mouse move events occur even if no mouse
9143 button is pressed.
9144
9145 QMouseEvent::pos() reports the position of the mouse cursor,
9146 relative to this widget. For press and release events, the
9147 position is usually the same as the position of the last mouse
9148 move event, but it might be different if the user's hand shakes.
9149 This is a feature of the underlying window system, not Qt.
9150
9151 If you want to show a tooltip immediately, while the mouse is
9152 moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9153 and show them as a tooltip), you must first enable mouse tracking
9154 as described above. Then, to ensure that the tooltip is updated
9155 immediately, you must call QToolTip::showText() instead of
9156 setToolTip() in your implementation of mouseMoveEvent().
9157
9158 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9159 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9160*/
9161
9162void QWidget::mouseMoveEvent(QMouseEvent *event)
9163{
9164 event->ignore();
9165}
9166
9167/*!
9168 This event handler, for event \a event, can be reimplemented in a
9169 subclass to receive mouse press events for the widget.
9170
9171 If you create new widgets in the mousePressEvent() the
9172 mouseReleaseEvent() may not end up where you expect, depending on
9173 the underlying window system (or X11 window manager), the widgets'
9174 location and maybe more.
9175
9176 The default implementation implements the closing of popup widgets
9177 when you click outside the window. For other widget types it does
9178 nothing.
9179
9180 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9181 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9182*/
9183
9184void QWidget::mousePressEvent(QMouseEvent *event)
9185{
9186 event->ignore();
9187 if ((windowType() == Qt::Popup)) {
9188 event->accept();
9189 QWidget* w;
9190 while ((w = QApplication::activePopupWidget()) && w != this){
9191 w->close();
9192 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9193 w->hide(); // hide at least
9194 }
9195 if (!rect().contains(event->position().toPoint())){
9196 close();
9197 }
9198 }
9199}
9200
9201/*!
9202 This event handler, for event \a event, can be reimplemented in a
9203 subclass to receive mouse release events for the widget.
9204
9205 \sa mousePressEvent(), mouseDoubleClickEvent(),
9206 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9207*/
9208
9209void QWidget::mouseReleaseEvent(QMouseEvent *event)
9210{
9211 event->ignore();
9212}
9213
9214/*!
9215 This event handler, for event \a event, can be reimplemented in a
9216 subclass to receive mouse double click events for the widget.
9217
9218 The default implementation calls mousePressEvent().
9219
9220 \note The widget will also receive mouse press and mouse release
9221 events in addition to the double click event. And if another widget
9222 that overlaps this widget disappears in response to press or
9223 release events, then this widget will only receive the double click
9224 event. It is up to the developer to ensure that the application
9225 interprets these events correctly.
9226
9227 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9228 event(), QMouseEvent
9229*/
9230
9231void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9232{
9233 mousePressEvent(event);
9234}
9235
9236#if QT_CONFIG(wheelevent)
9237/*!
9238 This event handler, for event \a event, can be reimplemented in a
9239 subclass to receive wheel events for the widget.
9240
9241 If you reimplement this handler, it is very important that you
9242 \l{QEvent}{ignore()} the event if you do not handle
9243 it, so that the widget's parent can interpret it.
9244
9245 The default implementation ignores the event.
9246
9247 \sa QEvent::ignore(), QEvent::accept(), event(),
9248 QWheelEvent
9249*/
9250
9251void QWidget::wheelEvent(QWheelEvent *event)
9252{
9253 event->ignore();
9254}
9255#endif // QT_CONFIG(wheelevent)
9256
9257#if QT_CONFIG(tabletevent)
9258/*!
9259 This event handler, for event \a event, can be reimplemented in a
9260 subclass to receive tablet events for the widget.
9261
9262 If you reimplement this handler, it is very important that you
9263 \l{QEvent}{ignore()} the event if you do not handle
9264 it, so that the widget's parent can interpret it.
9265
9266 The default implementation ignores the event.
9267
9268 If tablet tracking is switched off, tablet move events only occur if the
9269 stylus is in contact with the tablet, or at least one stylus button is
9270 pressed, while the stylus is being moved. If tablet tracking is switched on,
9271 tablet move events occur even while the stylus is hovering in proximity of
9272 the tablet, with no buttons pressed.
9273
9274 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9275 QTabletEvent
9276*/
9277
9278void QWidget::tabletEvent(QTabletEvent *event)
9279{
9280 event->ignore();
9281}
9282#endif // QT_CONFIG(tabletevent)
9283
9284/*!
9285 This event handler, for event \a event, can be reimplemented in a
9286 subclass to receive key press events for the widget.
9287
9288 A widget must call setFocusPolicy() to accept focus initially and
9289 have focus in order to receive a key press event.
9290
9291 If you reimplement this handler, it is very important that you
9292 call the base class implementation if you do not act upon the key.
9293
9294 The default implementation closes popup widgets if the user
9295 presses the key sequence for QKeySequence::Cancel (typically the
9296 Escape key). Otherwise the event is ignored, so that the widget's
9297 parent can interpret it.
9298
9299 Note that QKeyEvent starts with isAccepted() == true, so you do not
9300 need to call QKeyEvent::accept() - just do not call the base class
9301 implementation if you act upon the key.
9302
9303 \sa keyReleaseEvent(), setFocusPolicy(),
9304 focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
9305*/
9306
9307void QWidget::keyPressEvent(QKeyEvent *event)
9308{
9309#ifndef QT_NO_SHORTCUT
9310 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9311 event->accept();
9312 close();
9313 } else
9314#endif
9315 {
9316 event->ignore();
9317 }
9318}
9319
9320/*!
9321 This event handler, for event \a event, can be reimplemented in a
9322 subclass to receive key release events for the widget.
9323
9324 A widget must \l{setFocusPolicy()}{accept focus}
9325 initially and \l{hasFocus()}{have focus} in order to
9326 receive a key release event.
9327
9328 If you reimplement this handler, it is very important that you
9329 call the base class implementation if you do not act upon the key.
9330
9331 The default implementation ignores the event, so that the widget's
9332 parent can interpret it.
9333
9334 Note that QKeyEvent starts with isAccepted() == true, so you do not
9335 need to call QKeyEvent::accept() - just do not call the base class
9336 implementation if you act upon the key.
9337
9338 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9339 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9340*/
9341
9342void QWidget::keyReleaseEvent(QKeyEvent *event)
9343{
9344 event->ignore();
9345}
9346
9347/*!
9348 \fn void QWidget::focusInEvent(QFocusEvent *event)
9349
9350 This event handler can be reimplemented in a subclass to receive
9351 keyboard focus events (focus received) for the widget. The event
9352 is passed in the \a event parameter
9353
9354 A widget normally must setFocusPolicy() to something other than
9355 Qt::NoFocus in order to receive focus events. (Note that the
9356 application programmer can call setFocus() on any widget, even
9357 those that do not normally accept focus.)
9358
9359 The default implementation updates the widget (except for windows
9360 that do not specify a focusPolicy()).
9361
9362 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9363 keyReleaseEvent(), event(), QFocusEvent
9364*/
9365
9366void QWidget::focusInEvent(QFocusEvent *)
9367{
9368 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9369 update();
9370 }
9371}
9372
9373/*!
9374 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9375
9376 This event handler can be reimplemented in a subclass to receive
9377 keyboard focus events (focus lost) for the widget. The events is
9378 passed in the \a event parameter.
9379
9380 A widget normally must setFocusPolicy() to something other than
9381 Qt::NoFocus in order to receive focus events. (Note that the
9382 application programmer can call setFocus() on any widget, even
9383 those that do not normally accept focus.)
9384
9385 The default implementation updates the widget (except for windows
9386 that do not specify a focusPolicy()).
9387
9388 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9389 keyReleaseEvent(), event(), QFocusEvent
9390*/
9391
9392void QWidget::focusOutEvent(QFocusEvent *)
9393{
9394 if (focusPolicy() != Qt::NoFocus || !isWindow())
9395 update();
9396
9397#if !defined(QT_PLATFORM_UIKIT)
9398 // FIXME: revisit autoSIP logic, QTBUG-42906
9399 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9400 QGuiApplication::inputMethod()->hide();
9401#endif
9402}
9403
9404/*!
9405 \fn void QWidget::enterEvent(QEnterEvent *event)
9406
9407 This event handler can be reimplemented in a subclass to receive
9408 widget enter events which are passed in the \a event parameter.
9409
9410 An event is sent to the widget when the mouse cursor enters the
9411 widget.
9412
9413 \sa leaveEvent(), mouseMoveEvent(), event()
9414*/
9415
9416void QWidget::enterEvent(QEnterEvent *)
9417{
9418}
9419
9420/*!
9421 \fn void QWidget::leaveEvent(QEvent *event)
9422
9423 This event handler can be reimplemented in a subclass to receive
9424 widget leave events which are passed in the \a event parameter.
9425
9426 A leave event is sent to the widget when the mouse cursor leaves
9427 the widget.
9428
9429 \sa enterEvent(), mouseMoveEvent(), event()
9430*/
9431
9432void QWidget::leaveEvent(QEvent *)
9433{
9434}
9435
9436/*!
9437 \fn void QWidget::paintEvent(QPaintEvent *event)
9438
9439 This event handler can be reimplemented in a subclass to receive paint
9440 events passed in \a event.
9441
9442 A paint event is a request to repaint all or part of a widget. It can
9443 happen for one of the following reasons:
9444
9445 \list
9446 \li repaint() or update() was invoked,
9447 \li the widget was obscured and has now been uncovered, or
9448 \li many other reasons.
9449 \endlist
9450
9451 Many widgets can simply repaint their entire surface when asked to, but
9452 some slow widgets need to optimize by painting only the requested region:
9453 QPaintEvent::region(). This speed optimization does not change the result,
9454 as painting is clipped to that region during event processing. QListView
9455 and QTableView do this, for example.
9456
9457 Qt also tries to speed up painting by merging multiple paint events into
9458 one. When update() is called several times or the window system sends
9459 several paint events, Qt merges these events into one event with a larger
9460 region (see QRegion::united()). The repaint() function does not permit this
9461 optimization, so we suggest using update() whenever possible.
9462
9463 When the paint event occurs, the update region has normally been erased, so
9464 you are painting on the widget's background.
9465
9466 The background can be set using setBackgroundRole() and setPalette().
9467
9468 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9469 is no need to write double-buffering code in paintEvent() to avoid flicker.
9470
9471 \note Generally, you should refrain from calling update() or repaint()
9472 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9473 children inside a paintEvent() results in undefined behavior; the child may
9474 or may not get a paint event.
9475
9476 \warning If you are using a custom paint engine without Qt's backingstore,
9477 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9478 never be called; the backingstore will be used instead.
9479
9480 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9481 {Analog Clock Example}
9482*/
9483
9484void QWidget::paintEvent(QPaintEvent *)
9485{
9486}
9487
9488
9489/*!
9490 \fn void QWidget::moveEvent(QMoveEvent *event)
9491
9492 This event handler can be reimplemented in a subclass to receive
9493 widget move events which are passed in the \a event parameter.
9494 When the widget receives this event, it is already at the new
9495 position.
9496
9497 The old position is accessible through QMoveEvent::oldPos().
9498
9499 \sa resizeEvent(), event(), move(), QMoveEvent
9500*/
9501
9502void QWidget::moveEvent(QMoveEvent *)
9503{
9504}
9505
9506
9507/*!
9508 This event handler can be reimplemented in a subclass to receive
9509 widget resize events which are passed in the \a event parameter.
9510 When resizeEvent() is called, the widget already has its new
9511 geometry. The old size is accessible through
9512 QResizeEvent::oldSize().
9513
9514 The widget will be erased and receive a paint event immediately
9515 after processing the resize event. No drawing need be (or should
9516 be) done inside this handler.
9517
9518
9519 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9520 {Scribble Example}
9521*/
9522
9523void QWidget::resizeEvent(QResizeEvent * /* event */)
9524{
9525}
9526
9527#ifndef QT_NO_ACTION
9528/*!
9529 \fn void QWidget::actionEvent(QActionEvent *event)
9530
9531 This event handler is called with the given \a event whenever the
9532 widget's actions are changed.
9533
9534 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9535*/
9536void QWidget::actionEvent(QActionEvent *)
9537{
9538
9539}
9540#endif
9541
9542/*!
9543 This event handler is called with the given \a event when Qt receives a window
9544 close request for a top-level widget from the window system.
9545
9546 By default, the event is accepted and the widget is closed. You can reimplement
9547 this function to change the way the widget responds to window close requests.
9548 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9549 on all events.
9550
9551 Main window applications typically use reimplementations of this function to check
9552 whether the user's work has been saved and ask for permission before closing.
9553 For example, the \l{Application Example} uses a helper function to determine whether
9554 or not to close the window:
9555
9556 \snippet mainwindows/application/mainwindow.cpp 3
9557 \snippet mainwindows/application/mainwindow.cpp 4
9558
9559 \sa event(), hide(), close(), QCloseEvent, {Application Example}
9560*/
9561
9562void QWidget::closeEvent(QCloseEvent *event)
9563{
9564 event->accept();
9565}
9566
9567#ifndef QT_NO_CONTEXTMENU
9568/*!
9569 This event handler, for event \a event, can be reimplemented in a
9570 subclass to receive widget context menu events.
9571
9572 The handler is called when the widget's \l contextMenuPolicy is
9573 Qt::DefaultContextMenu.
9574
9575 The default implementation ignores the context event.
9576 See the \l QContextMenuEvent documentation for more details.
9577
9578 \sa event(), QContextMenuEvent, customContextMenuRequested()
9579*/
9580
9581void QWidget::contextMenuEvent(QContextMenuEvent *event)
9582{
9583 event->ignore();
9584}
9585#endif // QT_NO_CONTEXTMENU
9586
9587
9588/*!
9589 This event handler, for event \a event, can be reimplemented in a
9590 subclass to receive Input Method composition events. This handler
9591 is called when the state of the input method changes.
9592
9593 Note that when creating custom text editing widgets, the
9594 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9595 (using the setAttribute() function) in order to receive input
9596 method events.
9597
9598 The default implementation calls event->ignore(), which rejects the
9599 Input Method event. See the \l QInputMethodEvent documentation for more
9600 details.
9601
9602 \sa event(), QInputMethodEvent
9603*/
9604void QWidget::inputMethodEvent(QInputMethodEvent *event)
9605{
9606 event->ignore();
9607}
9608
9609/*!
9610 This method is only relevant for input widgets. It is used by the
9611 input method to query a set of properties of the widget to be
9612 able to support complex input method operations as support for
9613 surrounding text and reconversions.
9614
9615 \a query specifies which property is queried.
9616
9617 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9618*/
9619QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9620{
9621 switch(query) {
9622 case Qt::ImCursorRectangle:
9623 return QRect(width()/2, 0, 1, height());
9624 case Qt::ImFont:
9625 return font();
9626 case Qt::ImAnchorPosition:
9627 // Fallback.
9628 return inputMethodQuery(Qt::ImCursorPosition);
9629 case Qt::ImHints:
9630 return (int)inputMethodHints();
9631 case Qt::ImInputItemClipRectangle:
9632 return d_func()->clipRect();
9633 default:
9634 return QVariant();
9635 }
9636}
9637
9638/*!
9639 \property QWidget::inputMethodHints
9640 \brief What input method specific hints the widget has.
9641
9642 This is only relevant for input widgets. It is used by
9643 the input method to retrieve hints as to how the input method
9644 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9645 is set, the input method may change its visual components to reflect
9646 that only numbers can be entered.
9647
9648 \warning Some widgets require certain flags in order to work as
9649 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9650 instead of \c{w->setInputMethodHints(f)}.
9651
9652 \note The flags are only hints, so the particular input method
9653 implementation is free to ignore them. If you want to be
9654 sure that a certain type of characters are entered,
9655 you should also set a QValidator on the widget.
9656
9657 The default value is Qt::ImhNone.
9658
9659 \since 4.6
9660
9661 \sa inputMethodQuery()
9662*/
9663Qt::InputMethodHints QWidget::inputMethodHints() const
9664{
9665#ifndef QT_NO_IM
9666 const QWidgetPrivate *priv = d_func();
9667 while (priv->inheritsInputMethodHints) {
9668 priv = priv->q_func()->parentWidget()->d_func();
9669 Q_ASSERT(priv);
9670 }
9671 return priv->imHints;
9672#else //QT_NO_IM
9673 return 0;
9674#endif //QT_NO_IM
9675}
9676
9677void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
9678{
9679#ifndef QT_NO_IM
9680 Q_D(QWidget);
9681 if (d->imHints == hints)
9682 return;
9683 d->imHints = hints;
9684 if (this == QGuiApplication::focusObject())
9685 QGuiApplication::inputMethod()->update(Qt::ImHints);
9686#else
9687 Q_UNUSED(hints);
9688#endif //QT_NO_IM
9689}
9690
9691
9692#if QT_CONFIG(draganddrop)
9693
9694/*!
9695 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
9696
9697 This event handler is called when a drag is in progress and the
9698 mouse enters this widget. The event is passed in the \a event parameter.
9699
9700 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
9701 move events}.
9702
9703 See the \l{dnd.html}{Drag-and-drop documentation} for an
9704 overview of how to provide drag-and-drop in your application.
9705
9706 \sa QDrag, QDragEnterEvent
9707*/
9708void QWidget::dragEnterEvent(QDragEnterEvent *)
9709{
9710}
9711
9712/*!
9713 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
9714
9715 This event handler is called if a drag is in progress, and when
9716 any of the following conditions occur: the cursor enters this widget,
9717 the cursor moves within this widget, or a modifier key is pressed on
9718 the keyboard while this widget has the focus. The event is passed
9719 in the \a event parameter.
9720
9721 See the \l{dnd.html}{Drag-and-drop documentation} for an
9722 overview of how to provide drag-and-drop in your application.
9723
9724 \sa QDrag, QDragMoveEvent
9725*/
9726void QWidget::dragMoveEvent(QDragMoveEvent *)
9727{
9728}
9729
9730/*!
9731 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
9732
9733 This event handler is called when a drag is in progress and the
9734 mouse leaves this widget. The event is passed in the \a event
9735 parameter.
9736
9737 See the \l{dnd.html}{Drag-and-drop documentation} for an
9738 overview of how to provide drag-and-drop in your application.
9739
9740 \sa QDrag, QDragLeaveEvent
9741*/
9742void QWidget::dragLeaveEvent(QDragLeaveEvent *)
9743{
9744}
9745
9746/*!
9747 \fn void QWidget::dropEvent(QDropEvent *event)
9748
9749 This event handler is called when the drag is dropped on this
9750 widget. The event is passed in the \a event parameter.
9751
9752 See the \l{dnd.html}{Drag-and-drop documentation} for an
9753 overview of how to provide drag-and-drop in your application.
9754
9755 \sa QDrag, QDropEvent
9756*/
9757void QWidget::dropEvent(QDropEvent *)
9758{
9759}
9760
9761#endif // QT_CONFIG(draganddrop)
9762
9763/*!
9764 \fn void QWidget::showEvent(QShowEvent *event)
9765
9766 This event handler can be reimplemented in a subclass to receive
9767 widget show events which are passed in the \a event parameter.
9768
9769 Non-spontaneous show events are sent to widgets immediately
9770 before they are shown. The spontaneous show events of windows are
9771 delivered afterwards.
9772
9773 Note: A widget receives spontaneous show and hide events when its
9774 mapping status is changed by the window system, e.g. a spontaneous
9775 hide event when the user minimizes the window, and a spontaneous
9776 show event when the window is restored again. After receiving a
9777 spontaneous hide event, a widget is still considered visible in
9778 the sense of isVisible().
9779
9780 \sa visible, event(), QShowEvent
9781*/
9782void QWidget::showEvent(QShowEvent *)
9783{
9784}
9785
9786/*!
9787 \fn void QWidget::hideEvent(QHideEvent *event)
9788
9789 This event handler can be reimplemented in a subclass to receive
9790 widget hide events. The event is passed in the \a event parameter.
9791
9792 Hide events are sent to widgets immediately after they have been
9793 hidden.
9794
9795 Note: A widget receives spontaneous show and hide events when its
9796 mapping status is changed by the window system, e.g. a spontaneous
9797 hide event when the user minimizes the window, and a spontaneous
9798 show event when the window is restored again. After receiving a
9799 spontaneous hide event, a widget is still considered visible in
9800 the sense of isVisible().
9801
9802 \sa visible, event(), QHideEvent
9803*/
9804void QWidget::hideEvent(QHideEvent *)
9805{
9806}
9807
9808/*!
9809 This special event handler can be reimplemented in a subclass to
9810 receive native platform events identified by \a eventType
9811 which are passed in the \a message parameter.
9812
9813 In your reimplementation of this function, if you want to stop the
9814 event being handled by Qt, return true and set \a result. The \a result
9815 parameter has meaning only on Windows. If you return false, this native
9816 event is passed back to Qt, which translates the event into a Qt event
9817 and sends it to the widget.
9818
9819 \note Events are only delivered to this event handler if the widget
9820 has a native window handle.
9821
9822 \note This function superseedes the event filter functions
9823 x11Event(), winEvent() and macEvent() of Qt 4.
9824
9825 \sa QAbstractNativeEventFilter
9826
9827 \table
9828 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
9829 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
9830 \row \li macOS \li "NSEvent" \li NSEvent * \li
9831 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
9832 \endtable
9833*/
9834
9835bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
9836{
9837 Q_UNUSED(eventType);
9838 Q_UNUSED(message);
9839 Q_UNUSED(result);
9840 return false;
9841}
9842
9843/*!
9844 Ensures that the widget and its children have been polished by
9845 QStyle (i.e., have a proper font and palette).
9846
9847 QWidget calls this function after it has been fully constructed
9848 but before it is shown the very first time. You can call this
9849 function if you want to ensure that the widget is polished before
9850 doing an operation, e.g., the correct font size might be needed in
9851 the widget's sizeHint() reimplementation. Note that this function
9852 \e is called from the default implementation of sizeHint().
9853
9854 Polishing is useful for final initialization that must happen after
9855 all constructors (from base classes as well as from subclasses)
9856 have been called.
9857
9858 If you need to change some settings when a widget is polished,
9859 reimplement event() and handle the QEvent::Polish event type.
9860
9861 \b{Note:} The function is declared const so that it can be called from
9862 other const functions (e.g., sizeHint()).
9863
9864 \sa event()
9865*/
9866void QWidget::ensurePolished() const
9867{
9868 Q_D(const QWidget);
9869
9870 const QMetaObject *m = metaObject();
9871 if (m == d->polished)
9872 return;
9873 d->polished = m;
9874
9875 QEvent e(QEvent::Polish);
9876 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
9877
9878 // polish children after 'this'
9879 QList<QObject*> children = d->children;
9880 for (int i = 0; i < children.size(); ++i) {
9881 QObject *o = children.at(i);
9882 if(!o->isWidgetType())
9883 continue;
9884 if (QWidget *w = qobject_cast<QWidget *>(o))
9885 w->ensurePolished();
9886 }
9887
9888 if (d->parent && d->sendChildEvents) {
9889 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
9890 QCoreApplication::sendEvent(d->parent, &e);
9891 }
9892}
9893
9894/*!
9895 Returns the mask currently set on a widget. If no mask is set the
9896 return value will be an empty region.
9897
9898 \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
9899*/
9900QRegion QWidget::mask() const
9901{
9902 Q_D(const QWidget);
9903 return d->extra ? d->extra->mask : QRegion();
9904}
9905
9906/*!
9907 Returns the layout manager that is installed on this widget, or \nullptr
9908 if no layout manager is installed.
9909
9910 The layout manager sets the geometry of the widget's children
9911 that have been added to the layout.
9912
9913 \sa setLayout(), sizePolicy(), {Layout Management}
9914*/
9915QLayout *QWidget::layout() const
9916{
9917 return d_func()->layout;
9918}
9919
9920
9921/*!
9922 \fn void QWidget::setLayout(QLayout *layout)
9923
9924 Sets the layout manager for this widget to \a layout.
9925
9926 If there already is a layout manager installed on this widget,
9927 QWidget won't let you install another. You must first delete the
9928 existing layout manager (returned by layout()) before you can
9929 call setLayout() with the new layout.
9930
9931 If \a layout is the layout manager on a different widget, setLayout()
9932 will reparent the layout and make it the layout manager for this widget.
9933
9934 Example:
9935
9936 \snippet layouts/layouts.cpp 24
9937
9938 An alternative to calling this function is to pass this widget to
9939 the layout's constructor.
9940
9941 The QWidget will take ownership of \a layout.
9942
9943 \sa layout(), {Layout Management}
9944*/
9945
9946void QWidget::setLayout(QLayout *l)
9947{
9948 if (Q_UNLIKELY(!l)) {
9949 qWarning("QWidget::setLayout: Cannot set layout to 0");
9950 return;
9951 }
9952 if (layout()) {
9953 if (Q_UNLIKELY(layout() != l))
9954 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
9955 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
9956 objectName().toLocal8Bit().data());
9957 return;
9958 }
9959
9960 QObject *oldParent = l->parent();
9961 if (oldParent && oldParent != this) {
9962 if (oldParent->isWidgetType()) {
9963 // Steal the layout off a widget parent. Takes effect when
9964 // morphing laid-out container widgets in Designer.
9965 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
9966 oldParentWidget->takeLayout();
9967 } else {
9968 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
9969 l->objectName().toLocal8Bit().data(), metaObject()->className(),
9970 objectName().toLocal8Bit().data());
9971 return;
9972 }
9973 }
9974
9975 Q_D(QWidget);
9976 l->d_func()->topLevel = true;
9977 d->layout = l;
9978 if (oldParent != this) {
9979 l->setParent(this);
9980 l->d_func()->reparentChildWidgets(this);
9981 l->invalidate();
9982 }
9983
9984 if (isWindow() && d->maybeTopData())
9985 d->topData()->sizeAdjusted = false;
9986}
9987
9988/*!
9989 \fn QLayout *QWidget::takeLayout()
9990
9991 Remove the layout from the widget.
9992 \since 4.5
9993*/
9994
9995QLayout *QWidget::takeLayout()
9996{
9997 Q_D(QWidget);
9998 QLayout *l = layout();
9999 if (!l)
10000 return nullptr;
10001 d->layout = nullptr;
10002 l->setParent(nullptr);
10003 return l;
10004}
10005
10006/*!
10007 \property QWidget::sizePolicy
10008 \brief the default layout behavior of the widget
10009
10010 If there is a QLayout that manages this widget's children, the
10011 size policy specified by that layout is used. If there is no such
10012 QLayout, the result of this function is used.
10013
10014 The default policy is Preferred/Preferred, which means that the
10015 widget can be freely resized, but prefers to be the size
10016 sizeHint() returns. Button-like widgets set the size policy to
10017 specify that they may stretch horizontally, but are fixed
10018 vertically. The same applies to lineedit controls (such as
10019 QLineEdit, QSpinBox or an editable QComboBox) and other
10020 horizontally orientated widgets (such as QProgressBar).
10021 QToolButton's are normally square, so they allow growth in both
10022 directions. Widgets that support different directions (such as
10023 QSlider, QScrollBar or QHeader) specify stretching in the
10024 respective direction only. Widgets that can provide scroll bars
10025 (usually subclasses of QScrollArea) tend to specify that they can
10026 use additional space, and that they can make do with less than
10027 sizeHint().
10028
10029 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10030*/
10031QSizePolicy QWidget::sizePolicy() const
10032{
10033 Q_D(const QWidget);
10034 return d->size_policy;
10035}
10036
10037void QWidget::setSizePolicy(QSizePolicy policy)
10038{
10039 Q_D(QWidget);
10040 setAttribute(Qt::WA_WState_OwnSizePolicy);
10041 if (policy == d->size_policy)
10042 return;
10043
10044 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10045 d->retainSizeWhenHiddenChanged = 1;
10046
10047 d->size_policy = policy;
10048
10049#if QT_CONFIG(graphicsview)
10050 if (const auto &extra = d->extra) {
10051 if (extra->proxyWidget)
10052 extra->proxyWidget->setSizePolicy(policy);
10053 }
10054#endif
10055
10056 updateGeometry();
10057 d->retainSizeWhenHiddenChanged = 0;
10058
10059 if (isWindow() && d->maybeTopData())
10060 d->topData()->sizeAdjusted = false;
10061}
10062
10063/*!
10064 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10065 \overload
10066
10067 Sets the size policy of the widget to \a horizontal and \a
10068 vertical, with standard stretch and no height-for-width.
10069
10070 \sa QSizePolicy::QSizePolicy()
10071*/
10072
10073/*!
10074 Returns the preferred height for this widget, given the width \a w.
10075
10076 If this widget has a layout, the default implementation returns
10077 the layout's preferred height. if there is no layout, the default
10078 implementation returns -1 indicating that the preferred height
10079 does not depend on the width.
10080*/
10081
10082int QWidget::heightForWidth(int w) const
10083{
10084 if (layout() && layout()->hasHeightForWidth())
10085 return layout()->totalHeightForWidth(w);
10086 return -1;
10087}
10088
10089
10090/*!
10091 \since 5.0
10092
10093 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10094*/
10095bool QWidget::hasHeightForWidth() const
10096{
10097 Q_D(const QWidget);
10098 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10099}
10100
10101/*!
10102 \fn QWidget *QWidget::childAt(int x, int y) const
10103
10104 Returns the visible child widget at the position (\a{x}, \a{y})
10105 in the widget's coordinate system. If there is no visible child
10106 widget at the specified position, the function returns \nullptr.
10107*/
10108
10109/*!
10110 \overload
10111
10112 Returns the visible child widget at point \a p in the widget's own
10113 coordinate system.
10114*/
10115
10116QWidget *QWidget::childAt(const QPoint &p) const
10117{
10118 return d_func()->childAt_helper(p, false);
10119}
10120
10121QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
10122{
10123 if (children.isEmpty())
10124 return nullptr;
10125
10126 if (!pointInsideRectAndMask(p))
10127 return nullptr;
10128 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10129}
10130
10131QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor) const
10132{
10133 for (int i = children.size() - 1; i >= 0; --i) {
10134 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10135 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10136 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10137 continue;
10138 }
10139
10140 // Map the point 'p' from parent coordinates to child coordinates.
10141 QPoint childPoint = p;
10142 childPoint -= child->data->crect.topLeft();
10143
10144 // Check if the point hits the child.
10145 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10146 continue;
10147
10148 // Do the same for the child's descendants.
10149 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10150 return w;
10151
10152 // We have found our target; namely the child at position 'p'.
10153 return child;
10154 }
10155 return nullptr;
10156}
10157
10158void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10159{
10160 Q_Q(QWidget);
10161 if (widgetItem)
10162 widgetItem->invalidateSizeCache();
10163 QWidget *parent;
10164 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10165 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10166
10167 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10168 if (parent->d_func()->layout)
10169 parent->d_func()->layout->invalidate();
10170 else if (parent->isVisible())
10171 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10172 }
10173 }
10174}
10175
10176/*!
10177 Notifies the layout system that this widget has changed and may
10178 need to change geometry.
10179
10180 Call this function if the sizeHint() or sizePolicy() have changed.
10181
10182 For explicitly hidden widgets, updateGeometry() is a no-op. The
10183 layout system will be notified as soon as the widget is shown.
10184*/
10185
10186void QWidget::updateGeometry()
10187{
10188 Q_D(QWidget);
10189 d->updateGeometry_helper(false);
10190}
10191
10192/*! \property QWidget::windowFlags
10193
10194 Window flags are a combination of a type (e.g. Qt::Dialog) and
10195 zero or more hints to the window system (e.g.
10196 Qt::FramelessWindowHint).
10197
10198 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10199 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10200 0) on the desktop. If the widget is a window and becomes a
10201 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10202 relative to its parent widget.
10203
10204 \note This function calls setParent() when changing the flags for
10205 a window, causing the widget to be hidden. You must call show() to make
10206 the widget visible again..
10207
10208 \sa windowType(), setWindowFlag(), {Window Flags Example}
10209*/
10210void QWidget::setWindowFlags(Qt::WindowFlags flags)
10211{
10212 Q_D(QWidget);
10213 d->setWindowFlags(flags);
10214}
10215
10216/*!
10217 \since 5.9
10218
10219 Sets the window flag \a flag on this widget if \a on is true;
10220 otherwise clears the flag.
10221
10222 \sa setWindowFlags(), windowFlags(), windowType()
10223*/
10224void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10225{
10226 Q_D(QWidget);
10227 if (on)
10228 d->setWindowFlags(data->window_flags | flag);
10229 else
10230 d->setWindowFlags(data->window_flags & ~flag);
10231}
10232
10233/*! \internal
10234
10235 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10236*/
10237void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10238{
10239 Q_Q(QWidget);
10240 if (q->data->window_flags == flags)
10241 return;
10242
10243 if ((q->data->window_flags | flags) & Qt::Window) {
10244 // the old type was a window and/or the new type is a window
10245 QPoint oldPos = q->pos();
10246 bool visible = q->isVisible();
10247 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10248 q->setParent(q->parentWidget(), flags);
10249
10250 // if both types are windows or neither of them are, we restore
10251 // the old position
10252 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10253 q->move(oldPos);
10254 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10255 adjustQuitOnCloseAttribute();
10256 } else {
10257 q->data->window_flags = flags;
10258 }
10259}
10260
10261/*!
10262 Sets the window flags for the widget to \a flags,
10263 \e without telling the window system.
10264
10265 \warning Do not call this function unless you really know what
10266 you're doing.
10267
10268 \sa setWindowFlags()
10269*/
10270void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10271{
10272 data->window_flags = flags;
10273}
10274
10275/*!
10276 \fn Qt::WindowType QWidget::windowType() const
10277
10278 Returns the window type of this widget. This is identical to
10279 windowFlags() & Qt::WindowType_Mask.
10280
10281 \sa windowFlags
10282*/
10283
10284/*!
10285 Sets the parent of the widget to \a parent, and resets the window
10286 flags. The widget is moved to position (0, 0) in its new parent.
10287
10288 If the new parent widget is in a different window, the
10289 reparented widget and its children are appended to the end of the
10290 \l{setFocusPolicy()}{tab chain} of the new parent
10291 widget, in the same internal order as before. If one of the moved
10292 widgets had keyboard focus, setParent() calls clearFocus() for that
10293 widget.
10294
10295 If the new parent widget is in the same window as the
10296 old parent, setting the parent doesn't change the tab order or
10297 keyboard focus.
10298
10299 If the "new" parent widget is the old parent widget, this function
10300 does nothing.
10301
10302 \note The widget becomes invisible as part of changing its parent,
10303 even if it was previously visible. You must call show() to make the
10304 widget visible again.
10305
10306 \warning It is very unlikely that you will ever need this
10307 function. If you have a widget that changes its content
10308 dynamically, it is far easier to use \l QStackedWidget.
10309
10310 \sa setWindowFlags()
10311*/
10312void QWidget::setParent(QWidget *parent)
10313{
10314 if (parent == parentWidget())
10315 return;
10316 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10317}
10318
10319#ifndef QT_NO_OPENGL
10320static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget)
10321{
10322 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10323 if (d->renderToTexture) {
10324 QEvent e(QEvent::WindowChangeInternal);
10325 QCoreApplication::sendEvent(widget, &e);
10326 }
10327
10328 for (int i = 0; i < d->children.size(); ++i) {
10329 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10330 if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
10331 sendWindowChangeToTextureChildrenRecursively(w);
10332 }
10333}
10334#endif
10335
10336/*!
10337 \overload
10338
10339 This function also takes widget flags, \a f as an argument.
10340*/
10341
10342void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10343{
10344 Q_D(QWidget);
10345 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10346#ifdef QT_DEBUG
10347 const auto checkForParentChildLoops = qScopeGuard([&](){
10348 int depth = 0;
10349 auto p = parentWidget();
10350 while (p) {
10351 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10352 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10353 "this is undefined behavior",
10354 this, metaObject()->className(), qPrintable(objectName()));
10355 }
10356 p = p->parentWidget();
10357 }
10358 });
10359#endif
10360
10361 bool resized = testAttribute(Qt::WA_Resized);
10362 bool wasCreated = testAttribute(Qt::WA_WState_Created);
10363 QWidget *oldtlw = window();
10364
10365 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10366 d->data.fstrut_dirty = true;
10367
10368 QWidget *desktopWidget = nullptr;
10369 if (parent && parent->windowType() == Qt::Desktop)
10370 desktopWidget = parent;
10371 bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
10372
10373 if (newParent && parent && !desktopWidget) {
10374 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10375 parent->d_func()->enforceNativeChildren();
10376 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10377 setAttribute(Qt::WA_NativeWindow);
10378 }
10379
10380 if (wasCreated) {
10381 if (!testAttribute(Qt::WA_WState_Hidden)) {
10382 hide();
10383 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10384 }
10385 if (newParent) {
10386 QEvent e(QEvent::ParentAboutToChange);
10387 QCoreApplication::sendEvent(this, &e);
10388 }
10389 }
10390 if (newParent && isAncestorOf(focusWidget()))
10391 focusWidget()->clearFocus();
10392
10393 d->setParent_sys(parent, f);
10394
10395 if (desktopWidget)
10396 parent = nullptr;
10397
10398#ifndef QT_NO_OPENGL
10399 if (d->textureChildSeen && parent) {
10400 // set the textureChildSeen flag up the whole parent chain
10401 QWidgetPrivate::get(parent)->setTextureChildSeen();
10402 }
10403#endif
10404
10405 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10406 if (newParent)
10407 oldPaintManager->removeDirtyWidget(this);
10408 // Move the widget and all its static children from
10409 // the old backing store to the new one.
10410 oldPaintManager->moveStaticWidgets(this);
10411 }
10412
10413 d->reparentFocusWidgets(oldtlw);
10414 setAttribute(Qt::WA_Resized, resized);
10415
10416 const bool useStyleSheetPropagationInWidgetStyles =
10417 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10418
10419 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10420 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10421 // if the parent has a font set or inherited, then propagate the mask to the new child
10422 if (parent) {
10423 const auto pd = parent->d_func();
10424 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10425 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10426 }
10427 d->resolveFont();
10428 d->resolvePalette();
10429 }
10430 d->resolveLayoutDirection();
10431 d->resolveLocale();
10432
10433 // Note: GL widgets under WGL or EGL will always need a ParentChange
10434 // event to handle recreation/rebinding of the GL context, hence the
10435 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10436 // platforms).
10437 if (newParent
10438#if QT_CONFIG(opengles2)
10439 || (f & Qt::MSWindowsOwnDC)
10440#endif
10441 ) {
10442 // propagate enabled updates enabled state to non-windows
10443 if (!isWindow()) {
10444 if (!testAttribute(Qt::WA_ForceDisabled))
10445 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10446 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10447 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10448 }
10449 d->inheritStyle();
10450
10451 // send and post remaining QObject events
10452 if (parent && d->sendChildEvents) {
10453 QChildEvent e(QEvent::ChildAdded, this);
10454 QCoreApplication::sendEvent(parent, &e);
10455 }
10456
10457 if (parent && d->sendChildEvents && d->polished) {
10458 QChildEvent e(QEvent::ChildPolished, this);
10459 QCoreApplication::sendEvent(parent, &e);
10460 }
10461
10462 QEvent e(QEvent::ParentChange);
10463 QCoreApplication::sendEvent(this, &e);
10464 }
10465#ifndef QT_NO_OPENGL
10466 //renderToTexture widgets also need to know when their top-level window changes
10467 if (d->textureChildSeen && oldtlw != window()) {
10468 sendWindowChangeToTextureChildrenRecursively(this);
10469 }
10470#endif
10471
10472 if (!wasCreated) {
10473 if (isWindow() || parentWidget()->isVisible())
10474 setAttribute(Qt::WA_WState_Hidden, true);
10475 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10476 setAttribute(Qt::WA_WState_Hidden, false);
10477 }
10478
10479 d->updateIsOpaque();
10480
10481#if QT_CONFIG(graphicsview)
10482 // Embed the widget into a proxy if the parent is embedded.
10483 // ### Doesn't handle reparenting out of an embedded widget.
10484 if (oldtlw->graphicsProxyWidget()) {
10485 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10486 ancestorProxy->d_func()->unembedSubWindow(this);
10487 }
10488 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10489 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10490 ancestorProxy->d_func()->embedSubWindow(this);
10491 }
10492#endif
10493
10494 if (d->extra && d->extra->hasWindowContainer)
10495 QWindowContainer::parentWasChanged(this);
10496}
10497
10498void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10499{
10500 Q_Q(QWidget);
10501
10502 Qt::WindowFlags oldFlags = data.window_flags;
10503 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10504
10505 QScreen *targetScreen = nullptr;
10506 // Handle a request to move the widget to a particular screen
10507 if (newparent && newparent->windowType() == Qt::Desktop) {
10508 // make sure the widget is created on the same screen as the
10509 // programmer specified desktop widget
10510 targetScreen = newparent->screen();
10511 newparent = nullptr;
10512 }
10513
10514 setWinId(0);
10515
10516 if (parent != newparent) {
10517 QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
10518 if (q->windowHandle()) {
10519 q->windowHandle()->setFlags(f);
10520 QWidget *parentWithWindow =
10521 newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
10522 if (parentWithWindow) {
10523 QWidget *topLevel = parentWithWindow->window();
10524 if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
10525 q->windowHandle()->setTransientParent(topLevel->windowHandle());
10526 q->windowHandle()->setParent(nullptr);
10527 } else {
10528 q->windowHandle()->setTransientParent(nullptr);
10529 q->windowHandle()->setParent(parentWithWindow->windowHandle());
10530 }
10531 } else {
10532 q->windowHandle()->setTransientParent(nullptr);
10533 q->windowHandle()->setParent(nullptr);
10534 }
10535 }
10536 }
10537
10538 if (!newparent) {
10539 f |= Qt::Window;
10540 if (parent)
10541 targetScreen = q->parentWidget()->window()->screen();
10542 }
10543
10544 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
10545
10546 // Reparenting toplevel to child
10547 if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
10548 if (extra && extra->hasWindowContainer)
10549 QWindowContainer::toplevelAboutToBeDestroyed(q);
10550
10551 QWindow *newParentWindow = newparent->windowHandle();
10552 if (!newParentWindow)
10553 if (QWidget *npw = newparent->nativeParentWidget())
10554 newParentWindow = npw->windowHandle();
10555
10556 Q_FOREACH (QObject *child, q->windowHandle()->children()) {
10557 QWindow *childWindow = qobject_cast<QWindow *>(child);
10558 if (!childWindow)
10559 continue;
10560
10561 QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(childWindow);
10562 QWidget *childWidget = childWW ? childWW->widget() : nullptr;
10563 if (!childWW || (childWidget && childWidget->testAttribute(Qt::WA_NativeWindow)))
10564 childWindow->setParent(newParentWindow);
10565 }
10566 q->destroy();
10567 }
10568
10569 adjustFlags(f, q);
10570 data.window_flags = f;
10571 q->setAttribute(Qt::WA_WState_Created, false);
10572 q->setAttribute(Qt::WA_WState_Visible, false);
10573 q->setAttribute(Qt::WA_WState_Hidden, false);
10574
10575 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
10576 q->createWinId();
10577
10578 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
10579 q->setAttribute(Qt::WA_WState_Hidden);
10580 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
10581
10582 // move the window to the selected screen
10583 if (!newparent && targetScreen) {
10584 // only if it is already created
10585 if (q->testAttribute(Qt::WA_WState_Created))
10586 q->windowHandle()->setScreen(targetScreen);
10587 else
10588 topData()->initialScreen = targetScreen;
10589 }
10590}
10591
10592/*!
10593 Scrolls the widget including its children \a dx pixels to the
10594 right and \a dy downward. Both \a dx and \a dy may be negative.
10595
10596 After scrolling, the widgets will receive paint events for
10597 the areas that need to be repainted. For widgets that Qt knows to
10598 be opaque, this is only the newly exposed parts.
10599 For example, if an opaque widget is scrolled 8 pixels to the left,
10600 only an 8-pixel wide stripe at the right edge needs updating.
10601
10602 Since widgets propagate the contents of their parents by default,
10603 you need to set the \l autoFillBackground property, or use
10604 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
10605 a widget opaque.
10606
10607 For widgets that use contents propagation, a scroll will cause an
10608 update of the entire scroll area.
10609
10610 \sa {Transparency and Double Buffering}
10611*/
10612
10613void QWidget::scroll(int dx, int dy)
10614{
10615 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10616 return;
10617 if (dx == 0 && dy == 0)
10618 return;
10619 Q_D(QWidget);
10620#if QT_CONFIG(graphicsview)
10621 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10622 // Graphics View maintains its own dirty region as a list of rects;
10623 // until we can connect item updates directly to the view, we must
10624 // separately add a translated dirty region.
10625 for (const QRect &rect : d->dirty)
10626 proxy->update(rect.translated(dx, dy));
10627 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
10628 return;
10629 }
10630#endif
10631 d->setDirtyOpaqueRegion();
10632 d->scroll_sys(dx, dy);
10633}
10634
10635void QWidgetPrivate::scroll_sys(int dx, int dy)
10636{
10637 Q_Q(QWidget);
10638 scrollChildren(dx, dy);
10639 scrollRect(q->rect(), dx, dy);
10640}
10641
10642/*!
10643 \overload
10644
10645 This version only scrolls \a r and does not move the children of
10646 the widget.
10647
10648 If \a r is empty or invalid, the result is undefined.
10649
10650 \sa QScrollArea
10651*/
10652void QWidget::scroll(int dx, int dy, const QRect &r)
10653{
10654
10655 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10656 return;
10657 if (dx == 0 && dy == 0)
10658 return;
10659 Q_D(QWidget);
10660#if QT_CONFIG(graphicsview)
10661 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10662 // Graphics View maintains its own dirty region as a list of rects;
10663 // until we can connect item updates directly to the view, we must
10664 // separately add a translated dirty region.
10665 if (!d->dirty.isEmpty()) {
10666 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
10667 proxy->update(rect);
10668 }
10669 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
10670 return;
10671 }
10672#endif
10673 d->scroll_sys(dx, dy, r);
10674}
10675
10676void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
10677{
10678 scrollRect(r, dx, dy);
10679}
10680
10681/*!
10682 Repaints the widget directly by calling paintEvent() immediately,
10683 unless updates are disabled or the widget is hidden.
10684
10685 We suggest only using repaint() if you need an immediate repaint,
10686 for example during animation. In almost all circumstances update()
10687 is better, as it permits Qt to optimize for speed and minimize
10688 flicker.
10689
10690 \warning If you call repaint() in a function which may itself be
10691 called from paintEvent(), you may get infinite recursion. The
10692 update() function never causes recursion.
10693
10694 \sa update(), paintEvent(), setUpdatesEnabled()
10695*/
10696
10697void QWidget::repaint()
10698{
10699 repaint(rect());
10700}
10701
10702/*! \overload
10703
10704 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
10705 the widget.
10706
10707 If \a w is negative, it is replaced with \c{width() - x}, and if
10708 \a h is negative, it is replaced width \c{height() - y}.
10709*/
10710void QWidget::repaint(int x, int y, int w, int h)
10711{
10712 if (x > data->crect.width() || y > data->crect.height())
10713 return;
10714
10715 if (w < 0)
10716 w = data->crect.width() - x;
10717 if (h < 0)
10718 h = data->crect.height() - y;
10719
10720 repaint(QRect(x, y, w, h));
10721}
10722
10723/*! \overload
10724
10725 This version repaints a rectangle \a rect inside the widget.
10726*/
10727void QWidget::repaint(const QRect &rect)
10728{
10729 Q_D(QWidget);
10730 d->repaint(rect);
10731}
10732
10733/*!
10734 \overload
10735
10736 This version repaints a region \a rgn inside the widget.
10737*/
10738void QWidget::repaint(const QRegion &rgn)
10739{
10740 Q_D(QWidget);
10741 d->repaint(rgn);
10742}
10743
10744template <typename T>
10745void QWidgetPrivate::repaint(T r)
10746{
10747 Q_Q(QWidget);
10748
10749 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
10750 return;
10751
10752 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10753 if (tlwExtra && tlwExtra->backingStore)
10754 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
10755}
10756
10757/*!
10758 Updates the widget unless updates are disabled or the widget is
10759 hidden.
10760
10761 This function does not cause an immediate repaint; instead it
10762 schedules a paint event for processing when Qt returns to the main
10763 event loop. This permits Qt to optimize for more speed and less
10764 flicker than a call to repaint() does.
10765
10766 Calling update() several times normally results in just one
10767 paintEvent() call.
10768
10769 Qt normally erases the widget's area before the paintEvent() call.
10770 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
10771 responsible for painting all its pixels with an opaque color.
10772
10773 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
10774*/
10775void QWidget::update()
10776{
10777 update(rect());
10778}
10779
10780/*! \fn void QWidget::update(int x, int y, int w, int h)
10781 \overload
10782
10783 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
10784 the widget.
10785*/
10786
10787/*!
10788 \overload
10789
10790 This version updates a rectangle \a rect inside the widget.
10791*/
10792void QWidget::update(const QRect &rect)
10793{
10794 Q_D(QWidget);
10795 d->update(rect);
10796}
10797
10798/*!
10799 \overload
10800
10801 This version repaints a region \a rgn inside the widget.
10802*/
10803void QWidget::update(const QRegion &rgn)
10804{
10805 Q_D(QWidget);
10806 d->update(rgn);
10807}
10808
10809template <typename T>
10810void QWidgetPrivate::update(T r)
10811{
10812 Q_Q(QWidget);
10813
10814 if (!q->isVisible() || !q->updatesEnabled())
10815 return;
10816
10817 T clipped = r & q->rect();
10818
10819 if (clipped.isEmpty())
10820 return;
10821
10822 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
10823 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
10824 return;
10825 }
10826
10827 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10828 if (tlwExtra && tlwExtra->backingStore)
10829 tlwExtra->repaintManager->markDirty(clipped, q);
10830}
10831
10832 /*!
10833 \internal
10834
10835 This just sets the corresponding attribute bit to 1 or 0
10836 */
10837static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
10838 QWidgetPrivate *d)
10839{
10840 if (attribute < int(8*sizeof(uint))) {
10841 if (on)
10842 data->widget_attributes |= (1<<attribute);
10843 else
10844 data->widget_attributes &= ~(1<<attribute);
10845 } else {
10846 const int x = attribute - 8*sizeof(uint);
10847 const int int_off = x / (8*sizeof(uint));
10848 if (on)
10849 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
10850 else
10851 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
10852 }
10853}
10854
10855#ifdef Q_OS_MAC
10856void QWidgetPrivate::macUpdateSizeAttribute()
10857{
10858 Q_Q(QWidget);
10859 QEvent event(QEvent::MacSizeChange);
10860 QCoreApplication::sendEvent(q, &event);
10861 for (int i = 0; i < children.size(); ++i) {
10862 QWidget *w = qobject_cast<QWidget *>(children.at(i));
10863 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
10864 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
10865 && !w->testAttribute(Qt::WA_MacSmallSize)
10866 && !w->testAttribute(Qt::WA_MacNormalSize))
10867 w->d_func()->macUpdateSizeAttribute();
10868 }
10869 resolveFont();
10870}
10871#endif
10872
10873/*!
10874 Sets the attribute \a attribute on this widget if \a on is true;
10875 otherwise clears the attribute.
10876
10877 \sa testAttribute()
10878*/
10879void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
10880{
10881 if (testAttribute(attribute) == on)
10882 return;
10883
10884 Q_D(QWidget);
10885 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
10886 "QWidget::setAttribute(WidgetAttribute, bool): "
10887 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
10888#ifdef Q_OS_WIN
10889 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
10890 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
10891 // see ::paintEngine for details
10892 paintEngine();
10893 if (d->noPaintOnScreen)
10894 return;
10895 }
10896#endif
10897
10898 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
10899 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
10900 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
10901 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
10902 return;
10903 }
10904
10905 setAttribute_internal(attribute, on, data, d);
10906
10907 switch (attribute) {
10908
10909#if QT_CONFIG(draganddrop)
10910 case Qt::WA_AcceptDrops: {
10911 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
10912 setAttribute(Qt::WA_DropSiteRegistered, true);
10913 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
10914 setAttribute(Qt::WA_DropSiteRegistered, false);
10915 QEvent e(QEvent::AcceptDropsChange);
10916 QCoreApplication::sendEvent(this, &e);
10917 break;
10918 }
10919 case Qt::WA_DropSiteRegistered: {
10920 for (int i = 0; i < d->children.size(); ++i) {
10921 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10922 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
10923 w->setAttribute(Qt::WA_DropSiteRegistered, on);
10924 }
10925 break;
10926 }
10927#endif
10928
10929 case Qt::WA_NoChildEventsForParent:
10930 d->sendChildEvents = !on;
10931 break;
10932 case Qt::WA_NoChildEventsFromChildren:
10933 d->receiveChildEvents = !on;
10934 break;
10935 case Qt::WA_MacNormalSize:
10936 case Qt::WA_MacSmallSize:
10937 case Qt::WA_MacMiniSize:
10938#ifdef Q_OS_MAC
10939 {
10940 // We can only have one of these set at a time
10941 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
10942 Qt::WA_MacMiniSize };
10943 for (int i = 0; i < 3; ++i) {
10944 if (MacSizes[i] != attribute)
10945 setAttribute_internal(MacSizes[i], false, data, d);
10946 }
10947 d->macUpdateSizeAttribute();
10948 }
10949#endif
10950 break;
10951 case Qt::WA_ShowModal:
10952 if (!on) {
10953 // reset modality type to NonModal when clearing WA_ShowModal
10954 data->window_modality = Qt::NonModal;
10955 } else if (data->window_modality == Qt::NonModal) {
10956 // determine the modality type if it hasn't been set prior
10957 // to setting WA_ShowModal. set the default to WindowModal
10958 // if we are the child of a group leader; otherwise use
10959 // ApplicationModal.
10960 QWidget *w = parentWidget();
10961 if (w)
10962 w = w->window();
10963 while (w && !w->testAttribute(Qt::WA_GroupLeader)) {
10964 w = w->parentWidget();
10965 if (w)
10966 w = w->window();
10967 }
10968 data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader))
10969 ? Qt::WindowModal
10970 : Qt::ApplicationModal;
10971 // Some window managers do not allow us to enter modality after the
10972 // window is visible.The window must be hidden before changing the
10973 // windowModality property and then reshown.
10974 }
10975 if (testAttribute(Qt::WA_WState_Created)) {
10976 // don't call setModal_sys() before create()
10977 d->setModal_sys();
10978 }
10979 break;
10980 case Qt::WA_MouseTracking: {
10981 QEvent e(QEvent::MouseTrackingChange);
10982 QCoreApplication::sendEvent(this, &e);
10983 break; }
10984 case Qt::WA_TabletTracking: {
10985 QEvent e(QEvent::TabletTrackingChange);
10986 QCoreApplication::sendEvent(this, &e);
10987 break; }
10988 case Qt::WA_NativeWindow: {
10989 d->createTLExtra();
10990 if (on)
10991 d->createTLSysExtra();
10992#ifndef QT_NO_IM
10993 QWidget *focusWidget = d->effectiveFocusWidget();
10994 if (on && !internalWinId() && this == QGuiApplication::focusObject()
10995 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
10996 QGuiApplication::inputMethod()->commit();
10997 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
10998 }
10999 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11000 parentWidget()->d_func()->enforceNativeChildren();
11001 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11002 d->createWinId();
11003 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11004 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11005 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11006 }
11007#endif //QT_NO_IM
11008 break;
11009 }
11010 case Qt::WA_PaintOnScreen:
11011 d->updateIsOpaque();
11012 Q_FALLTHROUGH();
11013 case Qt::WA_OpaquePaintEvent:
11014 d->updateIsOpaque();
11015 break;
11016 case Qt::WA_NoSystemBackground:
11017 d->updateIsOpaque();
11018 Q_FALLTHROUGH();
11019 case Qt::WA_UpdatesDisabled:
11020 d->updateSystemBackground();
11021 break;
11022 case Qt::WA_TransparentForMouseEvents:
11023 break;
11024 case Qt::WA_InputMethodEnabled: {
11025#ifndef QT_NO_IM
11026 if (QGuiApplication::focusObject() == this) {
11027 if (!on)
11028 QGuiApplication::inputMethod()->commit();
11029 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11030 }
11031#endif //QT_NO_IM
11032 break;
11033 }
11034 case Qt::WA_WindowPropagation:
11035 d->resolvePalette();
11036 d->resolveFont();
11037 d->resolveLocale();
11038 break;
11039 case Qt::WA_DontShowOnScreen: {
11040 if (on && isVisible()) {
11041 // Make sure we keep the current state and only hide the widget
11042 // from the desktop. show_sys will only update platform specific
11043 // attributes at this point.
11044 d->hide_sys();
11045 d->show_sys();
11046 }
11047 break;
11048 }
11049
11050 case Qt::WA_X11NetWmWindowTypeDesktop:
11051 case Qt::WA_X11NetWmWindowTypeDock:
11052 case Qt::WA_X11NetWmWindowTypeToolBar:
11053 case Qt::WA_X11NetWmWindowTypeMenu:
11054 case Qt::WA_X11NetWmWindowTypeUtility:
11055 case Qt::WA_X11NetWmWindowTypeSplash:
11056 case Qt::WA_X11NetWmWindowTypeDialog:
11057 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11058 case Qt::WA_X11NetWmWindowTypePopupMenu:
11059 case Qt::WA_X11NetWmWindowTypeToolTip:
11060 case Qt::WA_X11NetWmWindowTypeNotification:
11061 case Qt::WA_X11NetWmWindowTypeCombo:
11062 case Qt::WA_X11NetWmWindowTypeDND:
11063 d->setNetWmWindowTypes();
11064 break;
11065
11066 case Qt::WA_StaticContents:
11067 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11068 if (on)
11069 repaintManager->addStaticWidget(this);
11070 else
11071 repaintManager->removeStaticWidget(this);
11072 }
11073 break;
11074 case Qt::WA_TranslucentBackground:
11075 if (on)
11076 setAttribute(Qt::WA_NoSystemBackground);
11077 d->updateIsTranslucent();
11078
11079 break;
11080 case Qt::WA_AcceptTouchEvents:
11081 break;
11082 default:
11083 break;
11084 }
11085}
11086
11087/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11088
11089 Returns \c true if attribute \a attribute is set on this widget;
11090 otherwise returns \c false.
11091
11092 \sa setAttribute()
11093 */
11094bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11095{
11096 Q_D(const QWidget);
11097 const int x = attribute - 8*sizeof(uint);
11098 const int int_off = x / (8*sizeof(uint));
11099 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11100}
11101
11102/*!
11103 \property QWidget::windowOpacity
11104
11105 \brief The level of opacity for the window.
11106
11107 The valid range of opacity is from 1.0 (completely opaque) to
11108 0.0 (completely transparent).
11109
11110 By default the value of this property is 1.0.
11111
11112 This feature is available on Embedded Linux, \macos, Windows,
11113 and X11 platforms that support the Composite extension.
11114
11115 \note On X11 you need to have a composite manager running,
11116 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11117 supported by the window manager you are using.
11118
11119 \warning Changing this property from opaque to transparent might issue a
11120 paint event that needs to be processed before the window is displayed
11121 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11122 that semi-transparent windows update and resize significantly slower than
11123 opaque windows.
11124
11125 \sa setMask()
11126*/
11127qreal QWidget::windowOpacity() const
11128{
11129 Q_D(const QWidget);
11130 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11131}
11132
11133void QWidget::setWindowOpacity(qreal opacity)
11134{
11135 Q_D(QWidget);
11136 if (!isWindow())
11137 return;
11138
11139 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11140 QTLWExtra *extra = d->topData();
11141 extra->opacity = uint(opacity * 255);
11142 setAttribute(Qt::WA_WState_WindowOpacitySet);
11143 d->setWindowOpacity_sys(opacity);
11144
11145 if (!testAttribute(Qt::WA_WState_Created))
11146 return;
11147
11148#if QT_CONFIG(graphicsview)
11149 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11150 // Avoid invalidating the cache if set.
11151 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11152 proxy->update();
11153 else if (QGraphicsScene *scene = proxy->scene())
11154 scene->update(proxy->sceneBoundingRect());
11155 return;
11156 }
11157#endif
11158}
11159
11160void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11161{
11162 Q_Q(QWidget);
11163 if (q->windowHandle())
11164 q->windowHandle()->setOpacity(level);
11165}
11166
11167/*!
11168 \property QWidget::windowModified
11169 \brief whether the document shown in the window has unsaved changes
11170
11171 A modified window is a window whose content has changed but has
11172 not been saved to disk. This flag will have different effects
11173 varied by the platform. On \macos the close button will have a
11174 modified look; on other platforms, the window title will have an
11175 '*' (asterisk).
11176
11177 The window title must contain a "[*]" placeholder, which
11178 indicates where the '*' should appear. Normally, it should appear
11179 right after the file name (e.g., "document1.txt[*] - Text
11180 Editor"). If the window isn't modified, the placeholder is simply
11181 removed.
11182
11183 Note that if a widget is set as modified, all its ancestors will
11184 also be set as modified. However, if you call \c
11185 {setWindowModified(false)} on a widget, this will not propagate to
11186 its parent because other children of the parent might have been
11187 modified.
11188
11189 \sa windowTitle, {Application Example}, {SDI Example}, {MDI Example}
11190*/
11191bool QWidget::isWindowModified() const
11192{
11193 return testAttribute(Qt::WA_WindowModified);
11194}
11195
11196void QWidget::setWindowModified(bool mod)
11197{
11198 Q_D(QWidget);
11199 setAttribute(Qt::WA_WindowModified, mod);
11200
11201 d->setWindowModified_helper();
11202
11203 QEvent e(QEvent::ModifiedChange);
11204 QCoreApplication::sendEvent(this, &e);
11205}
11206
11207void QWidgetPrivate::setWindowModified_helper()
11208{
11209 Q_Q(QWidget);
11210 QWindow *window = q->windowHandle();
11211 if (!window)
11212 return;
11213 QPlatformWindow *platformWindow = window->handle();
11214 if (!platformWindow)
11215 return;
11216 bool on = q->testAttribute(Qt::WA_WindowModified);
11217 if (!platformWindow->setWindowModified(on)) {
11218 if (Q_UNLIKELY(on && !q->windowTitle().contains(QLatin1String("[*]"))))
11219 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11220 setWindowTitle_helper(q->windowTitle());
11221 setWindowIconText_helper(q->windowIconText());
11222 }
11223}
11224
11225#if QT_CONFIG(tooltip)
11226/*!
11227 \property QWidget::toolTip
11228
11229 \brief the widget's tooltip
11230
11231 Note that by default tooltips are only shown for widgets that are
11232 children of the active window. You can change this behavior by
11233 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11234 not on the widget with the tooltip.
11235
11236 If you want to control a tooltip's behavior, you can intercept the
11237 event() function and catch the QEvent::ToolTip event (e.g., if you
11238 want to customize the area for which the tooltip should be shown).
11239
11240 By default, this property contains an empty string.
11241
11242 \sa QToolTip, statusTip, whatsThis
11243*/
11244void QWidget::setToolTip(const QString &s)
11245{
11246 Q_D(QWidget);
11247 d->toolTip = s;
11248
11249 QEvent event(QEvent::ToolTipChange);
11250 QCoreApplication::sendEvent(this, &event);
11251}
11252
11253QString QWidget::toolTip() const
11254{
11255 Q_D(const QWidget);
11256 return d->toolTip;
11257}
11258
11259/*!
11260 \property QWidget::toolTipDuration
11261 \brief the widget's tooltip duration
11262 \since 5.2
11263
11264 Specifies how long time the tooltip will be displayed, in milliseconds.
11265 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11266
11267 \sa toolTip
11268*/
11269
11270void QWidget::setToolTipDuration(int msec)
11271{
11272 Q_D(QWidget);
11273 d->toolTipDuration = msec;
11274}
11275
11276int QWidget::toolTipDuration() const
11277{
11278 Q_D(const QWidget);
11279 return d->toolTipDuration;
11280}
11281
11282#endif // QT_CONFIG(tooltip)
11283
11284
11285#if QT_CONFIG(statustip)
11286/*!
11287 \property QWidget::statusTip
11288 \brief the widget's status tip
11289
11290 By default, this property contains an empty string.
11291
11292 \sa toolTip, whatsThis
11293*/
11294void QWidget::setStatusTip(const QString &s)
11295{
11296 Q_D(QWidget);
11297 d->statusTip = s;
11298}
11299
11300QString QWidget::statusTip() const
11301{
11302 Q_D(const QWidget);
11303 return d->statusTip;
11304}
11305#endif // QT_CONFIG(statustip)
11306
11307#if QT_CONFIG(whatsthis)
11308/*!
11309 \property QWidget::whatsThis
11310
11311 \brief the widget's What's This help text.
11312
11313 By default, this property contains an empty string.
11314
11315 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11316*/
11317void QWidget::setWhatsThis(const QString &s)
11318{
11319 Q_D(QWidget);
11320 d->whatsThis = s;
11321}
11322
11323QString QWidget::whatsThis() const
11324{
11325 Q_D(const QWidget);
11326 return d->whatsThis;
11327}
11328#endif // QT_CONFIG(whatsthis)
11329
11330#ifndef QT_NO_ACCESSIBILITY
11331/*!
11332 \property QWidget::accessibleName
11333
11334 \brief the widget's name as seen by assistive technologies
11335
11336 This is the primary name by which assistive technology such as screen readers
11337 announce this widget. For most widgets setting this property is not required.
11338 For example for QPushButton the button's text will be used.
11339
11340 It is important to set this property when the widget does not provide any
11341 text. For example a button that only contains an icon needs to set this
11342 property to work with screen readers.
11343 The name should be short and equivalent to the visual information conveyed
11344 by the widget.
11345
11346 This property has to be \l{Internationalization with Qt}{localized}.
11347
11348 By default, this property contains an empty string.
11349
11350 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11351*/
11352void QWidget::setAccessibleName(const QString &name)
11353{
11354 Q_D(QWidget);
11355 d->accessibleName = name;
11356 QAccessibleEvent event(this, QAccessible::NameChanged);
11357 QAccessible::updateAccessibility(&event);
11358}
11359
11360QString QWidget::accessibleName() const
11361{
11362 Q_D(const QWidget);
11363 return d->accessibleName;
11364}
11365
11366/*!
11367 \property QWidget::accessibleDescription
11368
11369 \brief the widget's description as seen by assistive technologies
11370
11371 The accessible description of a widget should convey what a widget does.
11372 While the \l accessibleName should be a short and consise string (e.g. \gui{Save}),
11373 the description should give more context, such as \gui{Saves the current document}.
11374
11375 This property has to be \l{Internationalization with Qt}{localized}.
11376
11377 By default, this property contains an empty string and Qt falls back
11378 to using the tool tip to provide this information.
11379
11380 \sa QWidget::accessibleName, QAccessibleInterface::text()
11381*/
11382void QWidget::setAccessibleDescription(const QString &description)
11383{
11384 Q_D(QWidget);
11385 d->accessibleDescription = description;
11386 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11387 QAccessible::updateAccessibility(&event);
11388}
11389
11390QString QWidget::accessibleDescription() const
11391{
11392 Q_D(const QWidget);
11393 return d->accessibleDescription;
11394}
11395#endif // QT_NO_ACCESSIBILITY
11396
11397#ifndef QT_NO_SHORTCUT
11398/*!
11399 Adds a shortcut to Qt's shortcut system that watches for the given
11400 \a key sequence in the given \a context. If the \a context is
11401 Qt::ApplicationShortcut, the shortcut applies to the application as a
11402 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11403 or to the window itself, Qt::WindowShortcut.
11404
11405 If the same \a key sequence has been grabbed by several widgets,
11406 when the \a key sequence occurs a QEvent::Shortcut event is sent
11407 to all the widgets to which it applies in a non-deterministic
11408 order, but with the ``ambiguous'' flag set to true.
11409
11410 \warning You should not normally need to use this function;
11411 instead create \l{QAction}s with the shortcut key sequences you
11412 require (if you also want equivalent menu options and toolbar
11413 buttons), or create \l{QShortcut}s if you just need key sequences.
11414 Both QAction and QShortcut handle all the event filtering for you,
11415 and provide signals which are triggered when the user triggers the
11416 key sequence, so are much easier to use than this low-level
11417 function.
11418
11419 \sa releaseShortcut(), setShortcutEnabled()
11420*/
11421int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11422{
11423 Q_ASSERT(qApp);
11424 if (key.isEmpty())
11425 return 0;
11426 setAttribute(Qt::WA_GrabbedShortcut);
11427 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11428}
11429
11430/*!
11431 Removes the shortcut with the given \a id from Qt's shortcut
11432 system. The widget will no longer receive QEvent::Shortcut events
11433 for the shortcut's key sequence (unless it has other shortcuts
11434 with the same key sequence).
11435
11436 \warning You should not normally need to use this function since
11437 Qt's shortcut system removes shortcuts automatically when their
11438 parent widget is destroyed. It is best to use QAction or
11439 QShortcut to handle shortcuts, since they are easier to use than
11440 this low-level function. Note also that this is an expensive
11441 operation.
11442
11443 \sa grabShortcut(), setShortcutEnabled()
11444*/
11445void QWidget::releaseShortcut(int id)
11446{
11447 Q_ASSERT(qApp);
11448 if (id)
11449 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11450}
11451
11452/*!
11453 If \a enable is true, the shortcut with the given \a id is
11454 enabled; otherwise the shortcut is disabled.
11455
11456 \warning You should not normally need to use this function since
11457 Qt's shortcut system enables/disables shortcuts automatically as
11458 widgets become hidden/visible and gain or lose focus. It is best
11459 to use QAction or QShortcut to handle shortcuts, since they are
11460 easier to use than this low-level function.
11461
11462 \sa grabShortcut(), releaseShortcut()
11463*/
11464void QWidget::setShortcutEnabled(int id, bool enable)
11465{
11466 Q_ASSERT(qApp);
11467 if (id)
11468 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11469}
11470
11471/*!
11472 \since 4.2
11473
11474 If \a enable is true, auto repeat of the shortcut with the
11475 given \a id is enabled; otherwise it is disabled.
11476
11477 \sa grabShortcut(), releaseShortcut()
11478*/
11479void QWidget::setShortcutAutoRepeat(int id, bool enable)
11480{
11481 Q_ASSERT(qApp);
11482 if (id)
11483 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
11484}
11485#endif // QT_NO_SHORTCUT
11486
11487/*!
11488 Updates the widget's micro focus.
11489*/
11490void QWidget::updateMicroFocus()
11491{
11492 // updating everything since this is currently called for any kind of state change
11493 if (this == QGuiApplication::focusObject())
11494 QGuiApplication::inputMethod()->update(Qt::ImQueryAll);
11495}
11496
11497/*!
11498 Raises this widget to the top of the parent widget's stack.
11499
11500 After this call the widget will be visually in front of any
11501 overlapping sibling widgets.
11502
11503 \note When using activateWindow(), you can call this function to
11504 ensure that the window is stacked on top.
11505
11506 \sa lower(), stackUnder()
11507*/
11508
11509void QWidget::raise()
11510{
11511 Q_D(QWidget);
11512 if (!isWindow()) {
11513 QWidget *p = parentWidget();
11514 const int parentChildCount = p->d_func()->children.size();
11515 if (parentChildCount < 2)
11516 return;
11517 const int from = p->d_func()->children.indexOf(this);
11518 Q_ASSERT(from >= 0);
11519 // Do nothing if the widget is already in correct stacking order _and_ created.
11520 if (from != parentChildCount -1)
11521 p->d_func()->children.move(from, parentChildCount - 1);
11522 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11523 create();
11524 else if (from == parentChildCount - 1)
11525 return;
11526
11527 QRegion region(rect());
11528 d->subtractOpaqueSiblings(region);
11529 d->invalidateBackingStore(region);
11530 }
11531 if (testAttribute(Qt::WA_WState_Created))
11532 d->raise_sys();
11533
11534 if (d->extra && d->extra->hasWindowContainer)
11535 QWindowContainer::parentWasRaised(this);
11536
11537 QEvent e(QEvent::ZOrderChange);
11538 QCoreApplication::sendEvent(this, &e);
11539}
11540
11541void QWidgetPrivate::raise_sys()
11542{
11543 Q_Q(QWidget);
11544 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11545 q->windowHandle()->raise();
11546 } else if (renderToTexture) {
11547 if (QWidget *p = q->parentWidget()) {
11548 setDirtyOpaqueRegion();
11549 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11550 }
11551 }
11552}
11553
11554/*!
11555 Lowers the widget to the bottom of the parent widget's stack.
11556
11557 After this call the widget will be visually behind (and therefore
11558 obscured by) any overlapping sibling widgets.
11559
11560 \sa raise(), stackUnder()
11561*/
11562
11563void QWidget::lower()
11564{
11565 Q_D(QWidget);
11566 if (!isWindow()) {
11567 QWidget *p = parentWidget();
11568 const int parentChildCount = p->d_func()->children.size();
11569 if (parentChildCount < 2)
11570 return;
11571 const int from = p->d_func()->children.indexOf(this);
11572 Q_ASSERT(from >= 0);
11573 // Do nothing if the widget is already in correct stacking order _and_ created.
11574 if (from != 0)
11575 p->d_func()->children.move(from, 0);
11576 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11577 create();
11578 else if (from == 0)
11579 return;
11580 }
11581 if (testAttribute(Qt::WA_WState_Created))
11582 d->lower_sys();
11583
11584 if (d->extra && d->extra->hasWindowContainer)
11585 QWindowContainer::parentWasLowered(this);
11586
11587 QEvent e(QEvent::ZOrderChange);
11588 QCoreApplication::sendEvent(this, &e);
11589}
11590
11591void QWidgetPrivate::lower_sys()
11592{
11593 Q_Q(QWidget);
11594 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11595 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
11596 q->windowHandle()->lower();
11597 } else if (QWidget *p = q->parentWidget()) {
11598 setDirtyOpaqueRegion();
11599 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11600 }
11601}
11602
11603/*!
11604 Places the widget under \a w in the parent widget's stack.
11605
11606 To make this work, the widget itself and \a w must be siblings.
11607
11608 \sa raise(), lower()
11609*/
11610void QWidget::stackUnder(QWidget* w)
11611{
11612 Q_D(QWidget);
11613 QWidget *p = parentWidget();
11614 if (!w || isWindow() || p != w->parentWidget() || this == w)
11615 return;
11616 if (p) {
11617 int from = p->d_func()->children.indexOf(this);
11618 int to = p->d_func()->children.indexOf(w);
11619 Q_ASSERT(from >= 0);
11620 Q_ASSERT(to >= 0);
11621 if (from < to)
11622 --to;
11623 // Do nothing if the widget is already in correct stacking order _and_ created.
11624 if (from != to)
11625 p->d_func()->children.move(from, to);
11626 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11627 create();
11628 else if (from == to)
11629 return;
11630 }
11631 if (testAttribute(Qt::WA_WState_Created))
11632 d->stackUnder_sys(w);
11633
11634 QEvent e(QEvent::ZOrderChange);
11635 QCoreApplication::sendEvent(this, &e);
11636}
11637
11638void QWidgetPrivate::stackUnder_sys(QWidget*)
11639{
11640 Q_Q(QWidget);
11641 if (QWidget *p = q->parentWidget()) {
11642 setDirtyOpaqueRegion();
11643 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11644 }
11645}
11646
11647/*!
11648 \fn bool QWidget::isTopLevel() const
11649 \obsolete
11650
11651 Use isWindow() instead.
11652*/
11653
11654/*!
11655 \fn bool QWidget::isRightToLeft() const
11656 \internal
11657*/
11658
11659/*!
11660 \fn bool QWidget::isLeftToRight() const
11661 \internal
11662*/
11663
11664/*!
11665 \macro QWIDGETSIZE_MAX
11666 \relates QWidget
11667
11668 Defines the maximum size for a QWidget object.
11669
11670 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
11671 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
11672
11673 \sa QWidget::setMaximumSize()
11674*/
11675
11676/*!
11677 \fn QWidget::setupUi(QWidget *widget)
11678
11679 Sets up the user interface for the specified \a widget.
11680
11681 \note This function is available with widgets that derive from user
11682 interface descriptions created using \l{uic}.
11683
11684 \sa {Using a Designer UI File in Your Application}
11685*/
11686
11687QRect QWidgetPrivate::frameStrut() const
11688{
11689 Q_Q(const QWidget);
11690 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(Qt::WA_DontShowOnScreen)) {
11691 // x2 = x1 + w - 1, so w/h = 1
11692 return QRect(0, 0, 1, 1);
11693 }
11694
11695 if (data.fstrut_dirty
11696 // ### Fix properly for 4.3
11697 && q->isVisible()
11698 && q->testAttribute(Qt::WA_WState_Created))
11699 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
11700
11701 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
11702}
11703
11704void QWidgetPrivate::updateFrameStrut()
11705{
11706 Q_Q(QWidget);
11707 if (q->data->fstrut_dirty) {
11708 if (QTLWExtra *te = maybeTopData()) {
11709 if (te->window && te->window->handle()) {
11710 const QMargins margins = te->window->frameMargins();
11711 if (!margins.isNull()) {
11712 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
11713 q->data->fstrut_dirty = false;
11714 }
11715 }
11716 }
11717 }
11718}
11719
11720#ifdef QT_KEYPAD_NAVIGATION
11721/*!
11722 \internal
11723
11724 Changes the focus from the current focusWidget to a widget in
11725 the \a direction.
11726
11727 Returns \c true, if there was a widget in that direction
11728*/
11729bool QWidgetPrivate::navigateToDirection(Direction direction)
11730{
11731 QWidget *targetWidget = widgetInNavigationDirection(direction);
11732 if (targetWidget)
11733 targetWidget->setFocus();
11734 return (targetWidget != 0);
11735}
11736
11737/*!
11738 \internal
11739
11740 Searches for a widget that is positioned in the \a direction, starting
11741 from the current focusWidget.
11742
11743 Returns the pointer to a found widget or \nullptr, if there was no widget
11744 in that direction.
11745*/
11746QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
11747{
11748 const QWidget *sourceWidget = QApplication::focusWidget();
11749 if (!sourceWidget)
11750 return nullptr;
11751 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
11752 const int sourceX =
11753 (direction == DirectionNorth || direction == DirectionSouth) ?
11754 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
11755 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
11756 const int sourceY =
11757 (direction == DirectionEast || direction == DirectionWest) ?
11758 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
11759 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
11760 const QPoint sourcePoint(sourceX, sourceY);
11761 const QPoint sourceCenter = sourceRect.center();
11762 const QWidget *sourceWindow = sourceWidget->window();
11763
11764 QWidget *targetWidget = nullptr;
11765 int shortestDistance = INT_MAX;
11766
11767 const auto targetCandidates = QApplication::allWidgets();
11768 for (QWidget *targetCandidate : targetCandidates) {
11769
11770 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
11771
11772 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
11773 // but the owner of the proxy cannot.
11774 // Additionally, empty widgets should be ignored.
11775 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
11776 continue;
11777
11778 // Only navigate to a target widget that...
11779 if ( targetCandidate != sourceWidget
11780 // ...takes the focus,
11781 && targetCandidate->focusPolicy() & Qt::TabFocus
11782 // ...is above if DirectionNorth,
11783 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
11784 // ...is on the right if DirectionEast,
11785 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
11786 // ...is below if DirectionSouth,
11787 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
11788 // ...is on the left if DirectionWest,
11789 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
11790 // ...is enabled,
11791 && targetCandidate->isEnabled()
11792 // ...is visible,
11793 && targetCandidate->isVisible()
11794 // ...is in the same window,
11795 && targetCandidate->window() == sourceWindow) {
11796 const int targetCandidateDistance = [](const QPoint &sourcePoint,
11797 const QRect &targetCandidateRect) {
11798 int dx = 0;
11799 int dy = 0;
11800 if (p.x() < r.left())
11801 dx = r.left() - p.x();
11802 else if (p.x() > r.right())
11803 dx = p.x() - r.right();
11804 if (p.y() < r.top())
11805 dy = r.top() - p.y();
11806 else if (p.y() > r.bottom())
11807 dy = p.y() - r.bottom();
11808 return dx + dy;
11809 }();
11810 if (targetCandidateDistance < shortestDistance) {
11811 shortestDistance = targetCandidateDistance;
11812 targetWidget = targetCandidate;
11813 }
11814 }
11815 }
11816 return targetWidget;
11817}
11818
11819/*!
11820 \internal
11821
11822 Tells us if it there is currently a reachable widget by keypad navigation in
11823 a certain \a orientation.
11824 If no navigation is possible, occurring key events in that \a orientation may
11825 be used to interact with the value in the focused widget, even though it
11826 currently has not the editFocus.
11827
11828 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
11829*/
11830bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
11831{
11832 return orientation == Qt::Horizontal?
11833 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
11834 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
11835 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
11836 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
11837}
11838/*!
11839 \internal
11840
11841 Checks, if the \a widget is inside a QTabWidget. If is is inside
11842 one, left/right key events will be used to switch between tabs in keypad
11843 navigation. If there is no QTabWidget, the horizontal key events can be used
11844to
11845 interact with the value in the focused widget, even though it currently has
11846 not the editFocus.
11847
11848 \sa QWidget::hasEditFocus()
11849*/
11850bool QWidgetPrivate::inTabWidget(QWidget *widget)
11851{
11852 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
11853 if (qobject_cast<const QTabWidget*>(tabWidget))
11854 return true;
11855 return false;
11856}
11857#endif
11858
11859/*!
11860 \since 5.0
11861 \internal
11862
11863 Sets the backing store to be the \a store specified.
11864 The QWidget will take ownership of the \a store.
11865*/
11866void QWidget::setBackingStore(QBackingStore *store)
11867{
11868 // ### createWinId() ??
11869
11870 if (!isTopLevel())
11871 return;
11872
11873 Q_D(QWidget);
11874
11875 QTLWExtra *topData = d->topData();
11876 if (topData->backingStore == store)
11877 return;
11878
11879 QBackingStore *oldStore = topData->backingStore;
11880 deleteBackingStore(d);
11881 topData->backingStore = store;
11882
11883 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11884 if (!repaintManager)
11885 return;
11886
11887 if (isTopLevel()) {
11888 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
11889 delete repaintManager->backingStore();
11890 repaintManager->setBackingStore(store);
11891 }
11892}
11893
11894/*!
11895 \since 5.0
11896
11897 Returns the QBackingStore this widget will be drawn into.
11898*/
11899QBackingStore *QWidget::backingStore() const
11900{
11901 Q_D(const QWidget);
11902 QTLWExtra *extra = d->maybeTopData();
11903 if (extra && extra->backingStore)
11904 return extra->backingStore;
11905
11906 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11907 return repaintManager ? repaintManager->backingStore() : nullptr;
11908}
11909
11910void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
11911{
11912 if (left)
11913 *left = (int)leftLayoutItemMargin;
11914 if (top)
11915 *top = (int)topLayoutItemMargin;
11916 if (right)
11917 *right = (int)rightLayoutItemMargin;
11918 if (bottom)
11919 *bottom = (int)bottomLayoutItemMargin;
11920}
11921
11922void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
11923{
11924 if (leftLayoutItemMargin == left
11925 && topLayoutItemMargin == top
11926 && rightLayoutItemMargin == right
11927 && bottomLayoutItemMargin == bottom)
11928 return;
11929
11930 Q_Q(QWidget);
11931 leftLayoutItemMargin = (signed char)left;
11932 topLayoutItemMargin = (signed char)top;
11933 rightLayoutItemMargin = (signed char)right;
11934 bottomLayoutItemMargin = (signed char)bottom;
11935 q->updateGeometry();
11936}
11937
11938void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
11939{
11940 Q_Q(QWidget);
11941 QStyleOption myOpt;
11942 if (!opt) {
11943 myOpt.initFrom(q);
11944 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
11945 opt = &myOpt;
11946 }
11947
11948 QRect liRect = q->style()->subElementRect(element, opt, q);
11949 if (liRect.isValid()) {
11950 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
11951 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
11952 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
11953 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
11954 } else {
11955 leftLayoutItemMargin = 0;
11956 topLayoutItemMargin = 0;
11957 rightLayoutItemMargin = 0;
11958 bottomLayoutItemMargin = 0;
11959 }
11960}
11961// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
11962void QWidgetPrivate::adjustQuitOnCloseAttribute()
11963{
11964 Q_Q(QWidget);
11965
11966 if (!q->parentWidget()) {
11967 Qt::WindowType type = q->windowType();
11968 if (type == Qt::Widget || type == Qt::SubWindow)
11969 type = Qt::Window;
11970 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
11971 q->setAttribute(Qt::WA_QuitOnClose, false);
11972 }
11973}
11974
11975QOpenGLContext *QWidgetPrivate::shareContext() const
11976{
11977#ifdef QT_NO_OPENGL
11978 return 0;
11979#else
11980 if (!extra || !extra->topextra || !extra->topextra->window)
11981 return nullptr;
11982
11983 if (!extra->topextra->shareContext) {
11984 auto ctx = qt_make_unique<QOpenGLContext>();
11985 ctx->setShareContext(qt_gl_global_share_context());
11986 ctx->setFormat(extra->topextra->window->format());
11987 ctx->setScreen(extra->topextra->window->screen());
11988 ctx->create();
11989 extra->topextra->shareContext = std::move(ctx);
11990 }
11991 return extra->topextra->shareContext.get();
11992#endif // QT_NO_OPENGL
11993}
11994
11995#ifndef QT_NO_OPENGL
11996void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
11997{
11998 QWidgetPrivate *wd = QWidgetPrivate::get(w);
11999 if (!wd->textureChildSeen)
12000 return;
12001 if (end)
12002 wd->endCompose();
12003 else
12004 wd->beginCompose();
12005 for (int i = 0; i < wd->children.size(); ++i) {
12006 w = qobject_cast<QWidget *>(wd->children.at(i));
12007 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12008 sendComposeStatus(w, end);
12009 }
12010}
12011#endif // QT_NO_OPENGL
12012
12013Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12014{
12015 return widget->data;
12016}
12017
12018Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12019{
12020 return widget->d_func();
12021}
12022
12023
12024#if QT_CONFIG(graphicsview)
12025/*!
12026 \since 4.5
12027
12028 Returns the proxy widget for the corresponding embedded widget in a graphics
12029 view; otherwise returns \nullptr.
12030
12031 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12032 QGraphicsScene::addWidget()
12033 */
12034QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12035{
12036 Q_D(const QWidget);
12037 if (d->extra) {
12038 return d->extra->proxyWidget;
12039 }
12040 return nullptr;
12041}
12042#endif
12043
12044#ifndef QT_NO_GESTURES
12045/*!
12046 Subscribes the widget to a given \a gesture with specific \a flags.
12047
12048 \sa ungrabGesture(), QGestureEvent
12049 \since 4.6
12050*/
12051void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12052{
12053 Q_D(QWidget);
12054 d->gestureContext.insert(gesture, flags);
12055 (void)QGestureManager::instance(); // create a gesture manager
12056}
12057
12058/*!
12059 Unsubscribes the widget from a given \a gesture type
12060
12061 \sa grabGesture(), QGestureEvent
12062 \since 4.6
12063*/
12064void QWidget::ungrabGesture(Qt::GestureType gesture)
12065{
12066 // if you modify this function, check the inlined version in ~QWidget, too
12067 Q_D(QWidget);
12068 if (d->gestureContext.remove(gesture)) {
12069 if (QGestureManager *manager = QGestureManager::instance())
12070 manager->cleanupCachedGestures(this, gesture);
12071 }
12072}
12073#endif // QT_NO_GESTURES
12074
12075/*!
12076 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12077
12078 Frees up window system resources. Destroys the widget window if \a
12079 destroyWindow is true.
12080
12081 destroy() calls itself recursively for all the child widgets,
12082 passing \a destroySubWindows for the \a destroyWindow parameter.
12083 To have more control over destruction of subwidgets, destroy
12084 subwidgets selectively first.
12085
12086 This function is usually called from the QWidget destructor.
12087*/
12088void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12089{
12090 Q_D(QWidget);
12091
12092 d->aboutToDestroy();
12093 if (!isWindow() && parentWidget())
12094 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12095 d->deactivateWidgetCleanup();
12096
12097 if ((windowType() == Qt::Popup) && qApp)
12098 qApp->d_func()->closePopup(this);
12099
12100 if (this == QApplicationPrivate::active_window)
12101 QApplication::setActiveWindow(nullptr);
12102 if (QWidget::mouseGrabber() == this)
12103 releaseMouse();
12104 if (QWidget::keyboardGrabber() == this)
12105 releaseKeyboard();
12106
12107 setAttribute(Qt::WA_WState_Created, false);
12108
12109 if (windowType() != Qt::Desktop) {
12110 if (destroySubWindows) {
12111 QObjectList childList(children());
12112 for (int i = 0; i < childList.size(); i++) {
12113 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12114 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12115 if (widget->windowHandle()) {
12116 widget->destroy();
12117 }
12118 }
12119 }
12120 }
12121 if (destroyWindow) {
12122 d->deleteTLSysExtra();
12123 } else {
12124 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12125 d->hide_sys();
12126 }
12127 }
12128
12129 d->setWinId(0);
12130 }
12131}
12132
12133/*!
12134 \fn QPaintEngine *QWidget::paintEngine() const
12135
12136 Returns the widget's paint engine.
12137
12138 Note that this function should not be called explicitly by the
12139 user, since it's meant for reimplementation purposes only. The
12140 function is called by Qt internally, and the default
12141 implementation may not always return a valid pointer.
12142*/
12143QPaintEngine *QWidget::paintEngine() const
12144{
12145 qWarning("QWidget::paintEngine: Should no longer be called");
12146
12147#ifdef Q_OS_WIN
12148 // We set this bit which is checked in setAttribute for
12149 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12150 //
12151 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12152 // Windows which would mean suddenly their widgets stop working.
12153 //
12154 // 2. Users set paint on screen and subclass paintEngine() to
12155 // return 0, in which case we have a "hole" in the backingstore
12156 // allowing use of GDI or DirectX directly.
12157 //
12158 // 1 is WRONG, but to minimize silent failures, we have set this
12159 // bit to ignore the setAttribute call. 2. needs to be
12160 // supported because its our only means of embedding native
12161 // graphics stuff.
12162 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12163#endif
12164
12165 return nullptr; //##### @@@
12166}
12167
12168// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12169static inline bool canMapPosition(QWindow *window)
12170{
12171 return window->handle() && !qt_window_private(window)->resizeEventPending;
12172}
12173
12174#if QT_CONFIG(graphicsview)
12175static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12176{
12177 QGraphicsProxyWidget *result = nullptr;
12178 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12179 if (d->extra)
12180 result = d->extra->proxyWidget;
12181 return result;
12182}
12183#endif // QT_CONFIG(graphicsview)
12184
12185struct MapToGlobalTransformResult {
12186 QTransform transform;
12187 QWindow *window;
12188};
12189
12190static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12191{
12192 MapToGlobalTransformResult result;
12193 result.window = nullptr;
12194 for ( ; w ; w = w->parentWidget()) {
12195#if QT_CONFIG(graphicsview)
12196 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12197 if (const QGraphicsScene *scene = qgpw->scene()) {
12198 const QList <QGraphicsView *> views = scene->views();
12199 if (!views.isEmpty()) {
12200 result.transform *= qgpw->sceneTransform();
12201 result.transform *= views.first()->viewportTransform();
12202 w = views.first()->viewport();
12203 }
12204 }
12205 }
12206#endif // QT_CONFIG(graphicsview)
12207 QWindow *window = w->windowHandle();
12208 if (window && canMapPosition(window)) {
12209 result.window = window;
12210 break;
12211 }
12212
12213 const QPoint topLeft = w->geometry().topLeft();
12214 result.transform.translate(topLeft.x(), topLeft.y());
12215 if (w->isWindow())
12216 break;
12217 }
12218 return result;
12219}
12220
12221/*!
12222 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12223
12224 Translates the widget coordinate \a pos to global screen
12225 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12226 the global coordinates of the top-left pixel of the widget.
12227
12228 \sa mapFromGlobal(), mapTo(), mapToParent()
12229 \since 6.0
12230*/
12231QPointF QWidget::mapToGlobal(const QPointF &pos) const
12232{
12233 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12234 const QPointF g = t.transform.map(pos);
12235 return t.window ? t.window->mapToGlobal(g) : g;
12236}
12237
12238/*!
12239 \overload
12240*/
12241QPoint QWidget::mapToGlobal(const QPoint &pos) const
12242{
12243 return mapToGlobal(QPointF(pos)).toPoint();
12244}
12245
12246/*!
12247 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12248
12249 Translates the global screen coordinate \a pos to widget
12250 coordinates.
12251
12252 \sa mapToGlobal(), mapFrom(), mapFromParent()
12253 \since 6.0
12254*/
12255QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12256{
12257 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12258 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12259 return t.transform.inverted().map(windowLocal);
12260}
12261
12262/*!
12263 \overload
12264*/
12265QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12266{
12267 return mapFromGlobal(QPointF(pos)).toPoint();
12268}
12269
12270QWidget *qt_pressGrab = nullptr;
12271QWidget *qt_mouseGrb = nullptr;
12272static bool mouseGrabWithCursor = false;
12273static QWidget *keyboardGrb = nullptr;
12274
12275static inline QWindow *grabberWindow(const QWidget *w)
12276{
12277 QWindow *window = w->windowHandle();
12278 if (!window)
12279 if (const QWidget *nativeParent = w->nativeParentWidget())
12280 window = nativeParent->windowHandle();
12281 return window;
12282}
12283
12284#ifndef QT_NO_CURSOR
12285static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12286#else
12287static void grabMouseForWidget(QWidget *widget)
12288#endif
12289{
12290 if (qt_mouseGrb)
12291 qt_mouseGrb->releaseMouse();
12292
12293 mouseGrabWithCursor = false;
12294 if (QWindow *window = grabberWindow(widget)) {
12295#ifndef QT_NO_CURSOR
12296 if (cursor) {
12297 mouseGrabWithCursor = true;
12298 QGuiApplication::setOverrideCursor(*cursor);
12299 }
12300#endif // !QT_NO_CURSOR
12301 window->setMouseGrabEnabled(true);
12302 }
12303
12304 qt_mouseGrb = widget;
12305 qt_pressGrab = nullptr;
12306}
12307
12308static void releaseMouseGrabOfWidget(QWidget *widget)
12309{
12310 if (qt_mouseGrb == widget) {
12311 if (QWindow *window = grabberWindow(widget)) {
12312#ifndef QT_NO_CURSOR
12313 if (mouseGrabWithCursor) {
12314 QGuiApplication::restoreOverrideCursor();
12315 mouseGrabWithCursor = false;
12316 }
12317#endif // !QT_NO_CURSOR
12318 window->setMouseGrabEnabled(false);
12319 }
12320 }
12321 qt_mouseGrb = nullptr;
12322}
12323
12324/*!
12325 \fn void QWidget::grabMouse()
12326
12327 Grabs the mouse input.
12328
12329 This widget receives all mouse events until releaseMouse() is
12330 called; other widgets get no mouse events at all. Keyboard
12331 events are not affected. Use grabKeyboard() if you want to grab
12332 that.
12333
12334 \warning Bugs in mouse-grabbing applications very often lock the
12335 terminal. Use this function with extreme caution, and consider
12336 using the \c -nograb command line option while debugging.
12337
12338 It is almost never necessary to grab the mouse when using Qt, as
12339 Qt grabs and releases it sensibly. In particular, Qt grabs the
12340 mouse when a mouse button is pressed and keeps it until the last
12341 button is released.
12342
12343 \note Only visible widgets can grab mouse input. If isVisible()
12344 returns \c false for a widget, that widget cannot call grabMouse().
12345
12346 \note On Windows, grabMouse() only works when the mouse is inside a window
12347 owned by the process.
12348 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12349
12350 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12351*/
12352void QWidget::grabMouse()
12353{
12354 grabMouseForWidget(this);
12355}
12356
12357/*!
12358 \fn void QWidget::grabMouse(const QCursor &cursor)
12359 \overload grabMouse()
12360
12361 Grabs the mouse input and changes the cursor shape.
12362
12363 The cursor will assume shape \a cursor (for as long as the mouse
12364 focus is grabbed) and this widget will be the only one to receive
12365 mouse events until releaseMouse() is called().
12366
12367 \warning Grabbing the mouse might lock the terminal.
12368
12369 \note See the note in QWidget::grabMouse().
12370
12371 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12372*/
12373#ifndef QT_NO_CURSOR
12374void QWidget::grabMouse(const QCursor &cursor)
12375{
12376 grabMouseForWidget(this, &cursor);
12377}
12378#endif
12379
12380bool QWidgetPrivate::stealMouseGrab(bool grab)
12381{
12382 // This is like a combination of grab/releaseMouse() but with error checking
12383 // and it has no effect on the result of mouseGrabber().
12384 Q_Q(QWidget);
12385 QWindow *window = grabberWindow(q);
12386 return window ? window->setMouseGrabEnabled(grab) : false;
12387}
12388
12389/*!
12390 \fn void QWidget::releaseMouse()
12391
12392 Releases the mouse grab.
12393
12394 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12395*/
12396void QWidget::releaseMouse()
12397{
12398 releaseMouseGrabOfWidget(this);
12399}
12400
12401/*!
12402 \fn void QWidget::grabKeyboard()
12403
12404 Grabs the keyboard input.
12405
12406 This widget receives all keyboard events until releaseKeyboard()
12407 is called; other widgets get no keyboard events at all. Mouse
12408 events are not affected. Use grabMouse() if you want to grab that.
12409
12410 The focus widget is not affected, except that it doesn't receive
12411 any keyboard events. setFocus() moves the focus as usual, but the
12412 new focus widget receives keyboard events only after
12413 releaseKeyboard() is called.
12414
12415 If a different widget is currently grabbing keyboard input, that
12416 widget's grab is released first.
12417
12418 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12419*/
12420void QWidget::grabKeyboard()
12421{
12422 if (keyboardGrb)
12423 keyboardGrb->releaseKeyboard();
12424 if (QWindow *window = grabberWindow(this))
12425 window->setKeyboardGrabEnabled(true);
12426 keyboardGrb = this;
12427}
12428
12429bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12430{
12431 // This is like a combination of grab/releaseKeyboard() but with error
12432 // checking and it has no effect on the result of keyboardGrabber().
12433 Q_Q(QWidget);
12434 QWindow *window = grabberWindow(q);
12435 return window ? window->setKeyboardGrabEnabled(grab) : false;
12436}
12437
12438/*!
12439 \fn void QWidget::releaseKeyboard()
12440
12441 Releases the keyboard grab.
12442
12443 \sa grabKeyboard(), grabMouse(), releaseMouse()
12444*/
12445void QWidget::releaseKeyboard()
12446{
12447 if (keyboardGrb == this) {
12448 if (QWindow *window = grabberWindow(this))
12449 window->setKeyboardGrabEnabled(false);
12450 keyboardGrb = nullptr;
12451 }
12452}
12453
12454/*!
12455 \fn QWidget *QWidget::mouseGrabber()
12456
12457 Returns the widget that is currently grabbing the mouse input.
12458
12459 If no widget in this application is currently grabbing the mouse,
12460 \nullptr is returned.
12461
12462 \sa grabMouse(), keyboardGrabber()
12463*/
12464QWidget *QWidget::mouseGrabber()
12465{
12466 if (qt_mouseGrb)
12467 return qt_mouseGrb;
12468 return qt_pressGrab;
12469}
12470
12471/*!
12472 \fn QWidget *QWidget::keyboardGrabber()
12473
12474 Returns the widget that is currently grabbing the keyboard input.
12475
12476 If no widget in this application is currently grabbing the
12477 keyboard, \nullptr is returned.
12478
12479 \sa grabMouse(), mouseGrabber()
12480*/
12481QWidget *QWidget::keyboardGrabber()
12482{
12483 return keyboardGrb;
12484}
12485
12486/*!
12487 \fn void QWidget::activateWindow()
12488
12489 Sets the top-level widget containing this widget to be the active
12490 window.
12491
12492 An active window is a visible top-level window that has the
12493 keyboard input focus.
12494
12495 This function performs the same operation as clicking the mouse on
12496 the title bar of a top-level window. On X11, the result depends on
12497 the Window Manager. If you want to ensure that the window is
12498 stacked on top as well you should also call raise(). Note that the
12499 window must be visible, otherwise activateWindow() has no effect.
12500
12501 On Windows, if you are calling this when the application is not
12502 currently the active one then it will not make it the active
12503 window. It will change the color of the taskbar entry to indicate
12504 that the window has changed in some way. This is because Microsoft
12505 does not allow an application to interrupt what the user is currently
12506 doing in another application.
12507
12508 \sa isActiveWindow(), window(), show(), QWindowsWindowFunctions::setWindowActivationBehavior()
12509*/
12510void QWidget::activateWindow()
12511{
12512 QWindow *const wnd = window()->windowHandle();
12513
12514 if (wnd)
12515 wnd->requestActivate();
12516}
12517
12518/*!
12519
12520 Internal implementation of the virtual QPaintDevice::metric()
12521 function.
12522
12523 \a m is the metric to get.
12524*/
12525int QWidget::metric(PaintDeviceMetric m) const
12526{
12527 QWindow *topLevelWindow = nullptr;
12528 QScreen *screen = nullptr;
12529 if (QWidget *topLevel = window()) {
12530 topLevelWindow = topLevel->windowHandle();
12531 if (topLevelWindow)
12532 screen = topLevelWindow->screen();
12533 }
12534 if (!screen && QGuiApplication::primaryScreen())
12535 screen = QGuiApplication::primaryScreen();
12536
12537 if (!screen) {
12538 if (m == PdmDpiX || m == PdmDpiY)
12539 return 72;
12540 return QPaintDevice::metric(m);
12541 }
12542 int val;
12543 if (m == PdmWidth) {
12544 val = data->crect.width();
12545 } else if (m == PdmWidthMM) {
12546 val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12547 } else if (m == PdmHeight) {
12548 val = data->crect.height();
12549 } else if (m == PdmHeightMM) {
12550 val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12551 } else if (m == PdmDepth) {
12552 return screen->depth();
12553 } else if (m == PdmDpiX) {
12554 for (const QWidget *p = this; p; p = p->parentWidget()) {
12555 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12556 return p->d_func()->extra->customDpiX;
12557 }
12558 return qRound(screen->logicalDotsPerInchX());
12559 } else if (m == PdmDpiY) {
12560 for (const QWidget *p = this; p; p = p->parentWidget()) {
12561 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12562 return p->d_func()->extra->customDpiY;
12563 }
12564 return qRound(screen->logicalDotsPerInchY());
12565 } else if (m == PdmPhysicalDpiX) {
12566 return qRound(screen->physicalDotsPerInchX());
12567 } else if (m == PdmPhysicalDpiY) {
12568 return qRound(screen->physicalDotsPerInchY());
12569 } else if (m == PdmDevicePixelRatio) {
12570 return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
12571 } else if (m == PdmDevicePixelRatioScaled) {
12572 return (QPaintDevice::devicePixelRatioFScale() *
12573 (topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio()));
12574 } else {
12575 val = QPaintDevice::metric(m);// XXX
12576 }
12577 return val;
12578}
12579
12580/*!
12581 Initializes the \a painter pen, background and font to the same as
12582 the given widget's. This function is called automatically when the
12583 painter is opened on a QWidget.
12584*/
12585void QWidget::initPainter(QPainter *painter) const
12586{
12587 const QPalette &pal = palette();
12588 painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1);
12589 painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
12590 QFont f(font(), const_cast<QWidget *>(this));
12591 painter->d_func()->state->deviceFont = f;
12592 painter->d_func()->state->font = f;
12593}
12594
12595/*!
12596 \internal
12597
12598 Do PaintDevice rendering with the specified \a offset.
12599*/
12600QPaintDevice *QWidget::redirected(QPoint *offset) const
12601{
12602 return d_func()->redirected(offset);
12603}
12604
12605/*!
12606 \internal
12607
12608 A painter that is shared among other instances of QPainter.
12609*/
12610QPainter *QWidget::sharedPainter() const
12611{
12612 // Someone sent a paint event directly to the widget
12613 if (!d_func()->redirectDev)
12614 return nullptr;
12615
12616 QPainter *sp = d_func()->sharedPainter();
12617 if (!sp || !sp->isActive())
12618 return nullptr;
12619
12620 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12621 return nullptr;
12622
12623 return sp;
12624}
12625
12626/*!
12627 \fn void QWidget::setMask(const QRegion &region)
12628 \overload
12629
12630 Causes only the parts of the widget which overlap \a region to be
12631 visible. If the region includes pixels outside the rect() of the
12632 widget, window system controls in that area may or may not be
12633 visible, depending on the platform.
12634
12635 Note that this effect can be slow if the region is particularly
12636 complex.
12637
12638 \sa windowOpacity
12639*/
12640void QWidget::setMask(const QRegion &newMask)
12641{
12642 Q_D(QWidget);
12643
12644 d->createExtra();
12645 if (newMask == d->extra->mask)
12646 return;
12647
12648#ifndef QT_NO_BACKINGSTORE
12649 const QRegion oldMask(d->extra->mask);
12650#endif
12651
12652 d->extra->mask = newMask;
12653 d->extra->hasMask = !newMask.isEmpty();
12654
12655 if (!testAttribute(Qt::WA_WState_Created))
12656 return;
12657
12658 d->setMask_sys(newMask);
12659
12660#ifndef QT_NO_BACKINGSTORE
12661 if (!isVisible())
12662 return;
12663
12664 if (!d->extra->hasMask) {
12665 // Mask was cleared; update newly exposed area.
12666 QRegion expose(rect());
12667 expose -= oldMask;
12668 if (!expose.isEmpty()) {
12669 d->setDirtyOpaqueRegion();
12670 update(expose);
12671 }
12672 return;
12673 }
12674
12675 if (!isWindow()) {
12676 // Update newly exposed area on the parent widget.
12677 QRegion parentExpose(rect());
12678 parentExpose -= newMask;
12679 if (!parentExpose.isEmpty()) {
12680 d->setDirtyOpaqueRegion();
12681 parentExpose.translate(data->crect.topLeft());
12682 parentWidget()->update(parentExpose);
12683 }
12684
12685 // Update newly exposed area on this widget
12686 if (!oldMask.isEmpty())
12687 update(newMask - oldMask);
12688 }
12689#endif
12690}
12691
12692void QWidgetPrivate::setMask_sys(const QRegion &region)
12693{
12694 Q_Q(QWidget);
12695 if (QWindow *window = q->windowHandle())
12696 window->setMask(region);
12697}
12698
12699/*!
12700 \fn void QWidget::setMask(const QBitmap &bitmap)
12701
12702 Causes only the pixels of the widget for which \a bitmap has a
12703 corresponding 1 bit to be visible. If the region includes pixels
12704 outside the rect() of the widget, window system controls in that
12705 area may or may not be visible, depending on the platform.
12706
12707 Note that this effect can be slow if the region is particularly
12708 complex.
12709
12710 The following code shows how an image with an alpha channel can be
12711 used to generate a mask for a widget:
12712
12713 \snippet widget-mask/main.cpp 0
12714
12715 The label shown by this code is masked using the image it contains,
12716 giving the appearance that an irregularly-shaped image is being drawn
12717 directly onto the screen.
12718
12719 Masked widgets receive mouse events only on their visible
12720 portions.
12721
12722 \sa clearMask(), windowOpacity(), {Shaped Clock Example}
12723*/
12724void QWidget::setMask(const QBitmap &bitmap)
12725{
12726 setMask(QRegion(bitmap));
12727}
12728
12729/*!
12730 \fn void QWidget::clearMask()
12731
12732 Removes any mask set by setMask().
12733
12734 \sa setMask()
12735*/
12736void QWidget::clearMask()
12737{
12738 Q_D(QWidget);
12739 if (!d->extra || !d->extra->hasMask)
12740 return;
12741 setMask(QRegion());
12742}
12743
12744void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
12745{
12746 Q_ASSERT(widgetAsObject->isWidgetType());
12747 Q_ASSERT(!newParent || newParent->isWidgetType());
12748 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
12749 widget->setParent(static_cast<QWidget*>(newParent));
12750}
12751
12752void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
12753{
12754#if QT_CONFIG(xcb)
12755 Q_Q(QWidget);
12756
12757 if (!q->windowHandle())
12758 return;
12759
12760 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
12761 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
12762 wmWindowType |= QXcbWindow::Desktop;
12763 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
12764 wmWindowType |= QXcbWindow::Dock;
12765 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
12766 wmWindowType |= QXcbWindow::Toolbar;
12767 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
12768 wmWindowType |= QXcbWindow::Menu;
12769 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
12770 wmWindowType |= QXcbWindow::Utility;
12771 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
12772 wmWindowType |= QXcbWindow::Splash;
12773 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
12774 wmWindowType |= QXcbWindow::Dialog;
12775 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
12776 wmWindowType |= QXcbWindow::DropDownMenu;
12777 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
12778 wmWindowType |= QXcbWindow::PopupMenu;
12779 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
12780 wmWindowType |= QXcbWindow::Tooltip;
12781 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
12782 wmWindowType |= QXcbWindow::Notification;
12783 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
12784 wmWindowType |= QXcbWindow::Combo;
12785 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
12786 wmWindowType |= QXcbWindow::Dnd;
12787
12788 if (wmWindowType == QXcbWindow::None && skipIfMissing)
12789 return;
12790
12791 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
12792 xcbWindow->setWindowType(wmWindowType);
12793#else
12794 Q_UNUSED(skipIfMissing);
12795#endif
12796}
12797
12798#ifndef QT_NO_DEBUG_STREAM
12799
12800static inline void formatWidgetAttributes(QDebug debug, const QWidget *widget)
12801{
12802 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
12803 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
12804 debug << ", attributes=[";
12805 int count = 0;
12806 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
12807 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
12808 if (count++)
12809 debug << ',';
12810 debug << me.valueToKey(a);
12811 }
12812 }
12813 debug << ']';
12814}
12815
12816QDebug operator<<(QDebug debug, const QWidget *widget)
12817{
12818 const QDebugStateSaver saver(debug);
12819 debug.nospace();
12820 if (widget) {
12821 debug << widget->metaObject()->className() << '(' << (const void *)widget;
12822 if (!widget->objectName().isEmpty())
12823 debug << ", name=" << widget->objectName();
12824 if (debug.verbosity() > 2) {
12825 const QRect geometry = widget->geometry();
12826 const QRect frameGeometry = widget->frameGeometry();
12827 if (widget->isVisible())
12828 debug << ", visible";
12829 if (!widget->isEnabled())
12830 debug << ", disabled";
12831 debug << ", states=" << widget->windowState()
12832 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
12833 formatWidgetAttributes(debug, widget);
12834 if (widget->isWindow())
12835 debug << ", window";
12836 debug << ", " << geometry.width() << 'x' << geometry.height()
12837 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
12838 if (frameGeometry != geometry) {
12839 const QMargins margins(geometry.x() - frameGeometry.x(),
12840 geometry.y() - frameGeometry.y(),
12841 frameGeometry.right() - geometry.right(),
12842 frameGeometry.bottom() - geometry.bottom());
12843 debug << ", margins=" << margins;
12844 }
12845 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
12846 if (const WId wid = widget->internalWinId())
12847 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
12848 }
12849 debug << ')';
12850 } else {
12851 debug << "QWidget(0x0)";
12852 }
12853 return debug;
12854}
12855#endif // !QT_NO_DEBUG_STREAM
12856
12857QT_END_NAMESPACE
12858
12859#include "moc_qwidget.cpp"
12860
12861