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 "qdesktopwidget_p.h"
46#include "qevent.h"
47#include "qlayout.h"
48#if QT_CONFIG(menu)
49#include "qmenu.h"
50#endif
51#include "qmetaobject.h"
52#include "qpixmap.h"
53#include "qpointer.h"
54#include "qstack.h"
55#include "qstyle.h"
56#include "qstylefactory.h"
57#include "qvariant.h"
58#include "qwidget.h"
59#include "qstyleoption.h"
60#include "qstylehints.h"
61#ifndef QT_NO_ACCESSIBILITY
62# include "qaccessible.h"
63#endif
64#if 0 // Used to be included in Qt4 for Q_WS_MAC
65# include "qt_mac_p.h"
66# include "qt_cocoa_helpers_mac_p.h"
67# include "qmainwindow.h"
68# include "qtoolbar.h"
69# include <private/qmainwindowlayout_p.h>
70#endif
71#include <qpa/qplatformwindow.h>
72#include "private/qwidgetwindow_p.h"
73#include "qpainter.h"
74#include "qtooltip.h"
75#if QT_CONFIG(whatsthis)
76#include "qwhatsthis.h"
77#endif
78#include "qdebug.h"
79#include "private/qstylesheetstyle_p.h"
80#include "private/qstyle_p.h"
81#include "qfileinfo.h"
82#include <QtGui/private/qhighdpiscaling_p.h>
83#include <QtGui/qinputmethod.h>
84#include <QtGui/qopenglcontext.h>
85#include <QtGui/private/qopenglcontext_p.h>
86#include <QtGui/qoffscreensurface.h>
87
88#if QT_CONFIG(graphicseffect)
89#include <private/qgraphicseffect_p.h>
90#endif
91#include <qbackingstore.h>
92#include <private/qwidgetbackingstore_p.h>
93#if 0 // Used to be included in Qt4 for Q_WS_MAC
94# include <private/qpaintengine_mac_p.h>
95#endif
96#include <private/qpaintengine_raster_p.h>
97
98#include "qwidget_p.h"
99#include <QtGui/private/qwindow_p.h>
100#include "qaction_p.h"
101#include "qlayout_p.h"
102#if QT_CONFIG(graphicsview)
103#include "QtWidgets/qgraphicsproxywidget.h"
104#include "QtWidgets/qgraphicsscene.h"
105#include "private/qgraphicsproxywidget_p.h"
106#endif
107#include "QtWidgets/qabstractscrollarea.h"
108#include "private/qabstractscrollarea_p.h"
109#include "private/qevent_p.h"
110
111#include "private/qgesturemanager_p.h"
112
113#ifdef QT_KEYPAD_NAVIGATION
114#if QT_CONFIG(tabwidget)
115#include "qtabwidget.h" // Needed in inTabWidget()
116#endif
117#endif // QT_KEYPAD_NAVIGATION
118
119#include "qwindowcontainer_p.h"
120
121#include <QtPlatformHeaders/qxcbwindowfunctions.h>
122
123// widget/widget data creation count
124//#define QWIDGET_EXTRA_DEBUG
125//#define ALIEN_DEBUG
126
127QT_BEGIN_NAMESPACE
128
129#if 0 // Used to be included in Qt4 for Q_WS_MAC
130bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false;
131#endif
132
133static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
134{
135 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
136 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
137}
138
139#if 0 // Used to be included in Qt4 for Q_WS_MAC
140# define QT_NO_PAINT_DEBUG
141#endif
142
143extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
144extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
145
146/*!
147 \internal
148 \class QWidgetBackingStoreTracker
149 \brief Class which allows tracking of which widgets are using a given backing store
150
151 QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer,
152 which maintains a list of the QWidgets which are currently using the backing
153 store. This list is modified via the registerWidget and unregisterWidget functions.
154 */
155
156QWidgetBackingStoreTracker::QWidgetBackingStoreTracker()
157 : m_ptr(0)
158{
159
160}
161
162QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker()
163{
164 delete m_ptr;
165}
166
167/*!
168 \internal
169 Destroy the contained QWidgetBackingStore, if not null, and clear the list of
170 widgets using the backing store, then create a new QWidgetBackingStore, providing
171 the QWidget.
172 */
173void QWidgetBackingStoreTracker::create(QWidget *widget)
174{
175 destroy();
176 m_ptr = new QWidgetBackingStore(widget);
177}
178
179/*!
180 \internal
181 Destroy the contained QWidgetBackingStore, if not null, and clear the list of
182 widgets using the backing store.
183 */
184void QWidgetBackingStoreTracker::destroy()
185{
186 delete m_ptr;
187 m_ptr = 0;
188 m_widgets.clear();
189}
190
191/*!
192 \internal
193 Add the widget to the list of widgets currently using the backing store.
194 If the widget was already in the list, this function is a no-op.
195 */
196void QWidgetBackingStoreTracker::registerWidget(QWidget *w)
197{
198 Q_ASSERT(m_ptr);
199 Q_ASSERT(w->internalWinId());
200 Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr);
201 m_widgets.insert(w);
202}
203
204/*!
205 \internal
206 Remove the widget from the list of widgets currently using the backing store.
207 If the widget was in the list, and removing it causes the list to be empty,
208 the backing store is deleted.
209 If the widget was not in the list, this function is a no-op.
210 */
211void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w)
212{
213 if (m_widgets.remove(w) && m_widgets.isEmpty()) {
214 delete m_ptr;
215 m_ptr = 0;
216 }
217}
218
219/*!
220 \internal
221 Recursively remove widget and all of its descendents.
222 */
223void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget)
224{
225 unregisterWidget(widget);
226 foreach (QObject *child, widget->children())
227 if (QWidget *childWidget = qobject_cast<QWidget *>(child))
228 unregisterWidgetSubtree(childWidget);
229}
230
231QWidgetPrivate::QWidgetPrivate(int version)
232 : QObjectPrivate(version)
233 , extra(0)
234 , focus_next(0)
235 , focus_prev(0)
236 , focus_child(0)
237 , layout(0)
238 , needsFlush(0)
239 , redirectDev(0)
240 , widgetItem(0)
241 , extraPaintEngine(0)
242 , polished(0)
243 , graphicsEffect(0)
244#if !defined(QT_NO_IM)
245 , imHints(Qt::ImhNone)
246#endif
247#ifndef QT_NO_TOOLTIP
248 , toolTipDuration(-1)
249#endif
250 , directFontResolveMask(0)
251 , inheritedFontResolveMask(0)
252 , inheritedPaletteResolveMask(0)
253 , leftmargin(0)
254 , topmargin(0)
255 , rightmargin(0)
256 , bottommargin(0)
257 , leftLayoutItemMargin(0)
258 , topLayoutItemMargin(0)
259 , rightLayoutItemMargin(0)
260 , bottomLayoutItemMargin(0)
261 , hd(0)
262 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
263 , fg_role(QPalette::NoRole)
264 , bg_role(QPalette::NoRole)
265 , dirtyOpaqueChildren(1)
266 , isOpaque(0)
267 , retainSizeWhenHiddenChanged(0)
268 , inDirtyList(0)
269 , isScrolled(0)
270 , isMoved(0)
271 , usesDoubleBufferedGLContext(0)
272 , mustHaveWindowHandle(0)
273 , renderToTexture(0)
274 , textureChildSeen(0)
275#ifndef QT_NO_IM
276 , inheritsInputMethodHints(0)
277#endif
278#ifndef QT_NO_OPENGL
279 , renderToTextureReallyDirty(1)
280 , renderToTextureComposeActive(0)
281#endif
282 , childrenHiddenByWState(0)
283 , childrenShownByExpose(0)
284#if defined(Q_OS_WIN)
285 , noPaintOnScreen(0)
286#endif
287#if 0 // Used to be included in Qt4 for Q_WS_X11
288 , picture(0)
289#elif 0 // Used to be included in Qt4 for Q_WS_WIN
290 #ifndef QT_NO_GESTURES
291 , nativeGesturePanEnabled(0)
292 #endif
293#elif 0 // Used to be included in Qt4 for Q_WS_MAC
294 , needWindowChange(0)
295 , window_event(0)
296 , qd_hd(0)
297#endif
298{
299 if (Q_UNLIKELY(!qApp)) {
300 qFatal("QWidget: Must construct a QApplication before a QWidget");
301 return;
302 }
303
304#ifdef QT_BUILD_INTERNAL
305 // Don't check the version parameter in internal builds.
306 // This allows incompatible versions to be loaded, possibly for testing.
307 Q_UNUSED(version);
308#else
309 if (Q_UNLIKELY(version != QObjectPrivateVersion))
310 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
311 version, QObjectPrivateVersion);
312#endif
313
314 isWidget = true;
315 memset(high_attributes, 0, sizeof(high_attributes));
316#if 0 // Used to be included in Qt4 for Q_WS_MAC
317 drawRectOriginalAdded = false;
318 originalDrawMethod = true;
319 changeMethods = false;
320 isInUnifiedToolbar = false;
321 unifiedSurface = 0;
322 toolbar_ancestor = 0;
323 flushRequested = false;
324 touchEventsEnabled = false;
325#endif
326#ifdef QWIDGET_EXTRA_DEBUG
327 static int count = 0;
328 qDebug() << "widgets" << ++count;
329#endif
330}
331
332
333QWidgetPrivate::~QWidgetPrivate()
334{
335 if (widgetItem)
336 widgetItem->wid = 0;
337
338 if (extra)
339 deleteExtra();
340}
341
342/*!
343 \internal
344*/
345void QWidgetPrivate::scrollChildren(int dx, int dy)
346{
347 Q_Q(QWidget);
348 if (q->children().size() > 0) { // scroll children
349 QPoint pd(dx, dy);
350 QObjectList childObjects = q->children();
351 for (int i = 0; i < childObjects.size(); ++i) { // move all children
352 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
353 if (w && !w->isWindow()) {
354 QPoint oldp = w->pos();
355 QRect r(w->pos() + pd, w->size());
356 w->data->crect = r;
357 if (w->testAttribute(Qt::WA_WState_Created))
358 w->d_func()->setWSGeometry();
359 w->d_func()->setDirtyOpaqueRegion();
360 QMoveEvent e(r.topLeft(), oldp);
361 QApplication::sendEvent(w, &e);
362 }
363 }
364 }
365}
366
367void QWidgetPrivate::setWSGeometry()
368{
369 Q_Q(QWidget);
370 if (QWindow *window = q->windowHandle())
371 window->setGeometry(data.crect);
372}
373
374void QWidgetPrivate::updateWidgetTransform(QEvent *event)
375{
376 Q_Q(QWidget);
377 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
378 QTransform t;
379 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
380 t.translate(p.x(), p.y());
381 QGuiApplication::inputMethod()->setInputItemTransform(t);
382 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
383 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
384 }
385}
386
387#ifdef QT_KEYPAD_NAVIGATION
388QPointer<QWidget> QWidgetPrivate::editingWidget;
389
390/*!
391 Returns \c true if this widget currently has edit focus; otherwise false.
392
393 This feature is only available in Qt for Embedded Linux.
394
395 \sa setEditFocus(), QApplication::keypadNavigationEnabled()
396*/
397bool QWidget::hasEditFocus() const
398{
399 const QWidget* w = this;
400 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
401 w = w->d_func()->extra->focus_proxy;
402 return QWidgetPrivate::editingWidget == w;
403}
404
405/*!
406 \fn void QWidget::setEditFocus(bool enable)
407
408 If \a enable is true, make this widget have edit focus, in which
409 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
410 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
411 change focus.
412
413 This feature is only available in Qt for Embedded Linux.
414
415 \sa hasEditFocus(), QApplication::keypadNavigationEnabled()
416*/
417void QWidget::setEditFocus(bool on)
418{
419 QWidget *f = this;
420 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
421 f = f->d_func()->extra->focus_proxy;
422
423 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
424 QWidgetPrivate::editingWidget->setEditFocus(false);
425
426 if (on && !f->hasFocus())
427 f->setFocus();
428
429 if ((!on && !QWidgetPrivate::editingWidget)
430 || (on && QWidgetPrivate::editingWidget == f)) {
431 return;
432 }
433
434 if (!on && QWidgetPrivate::editingWidget == f) {
435 QWidgetPrivate::editingWidget = 0;
436 QEvent event(QEvent::LeaveEditFocus);
437 QApplication::sendEvent(f, &event);
438 QApplication::sendEvent(f->style(), &event);
439 } else if (on) {
440 QWidgetPrivate::editingWidget = f;
441 QEvent event(QEvent::EnterEditFocus);
442 QApplication::sendEvent(f, &event);
443 QApplication::sendEvent(f->style(), &event);
444 }
445}
446#endif
447
448/*!
449 \property QWidget::autoFillBackground
450 \brief whether the widget background is filled automatically
451 \since 4.1
452
453 If enabled, this property will cause Qt to fill the background of the
454 widget before invoking the paint event. The color used is defined by the
455 QPalette::Window color role from the widget's \l{QPalette}{palette}.
456
457 In addition, Windows are always filled with QPalette::Window, unless the
458 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
459
460 This property cannot be turned off (i.e., set to false) if a widget's
461 parent has a static gradient for its background.
462
463 \warning Use this property with caution in conjunction with
464 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
465 background or a border-image, this property is automatically disabled.
466
467 By default, this property is \c false.
468
469 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
470 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
471*/
472bool QWidget::autoFillBackground() const
473{
474 Q_D(const QWidget);
475 return d->extra && d->extra->autoFillBackground;
476}
477
478void QWidget::setAutoFillBackground(bool enabled)
479{
480 Q_D(QWidget);
481 if (!d->extra)
482 d->createExtra();
483 if (d->extra->autoFillBackground == enabled)
484 return;
485
486 d->extra->autoFillBackground = enabled;
487 d->updateIsOpaque();
488 update();
489 d->updateIsOpaque();
490}
491
492/*!
493 \class QWidget
494 \brief The QWidget class is the base class of all user interface objects.
495
496 \ingroup basicwidgets
497 \inmodule QtWidgets
498
499 The widget is the atom of the user interface: it receives mouse, keyboard
500 and other events from the window system, and paints a representation of
501 itself on the screen. Every widget is rectangular, and they are sorted in a
502 Z-order. A widget is clipped by its parent and by the widgets in front of
503 it.
504
505 A widget that is not embedded in a parent widget is called a window.
506 Usually, windows have a frame and a title bar, although it is also possible
507 to create windows without such decoration using suitable
508 \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
509 subclasses of QDialog are the most common window types.
510
511 Every widget's constructor accepts one or two standard arguments:
512
513 \list 1
514 \li \c{QWidget *parent = \nullptr} is the parent of the new widget.
515 If it is \nullptr (the default), the new widget will be a window.
516 If not, it will be a child of \e parent, and be constrained by
517 \e parent's geometry (unless you specify Qt::Window as window flag).
518 \li \c{Qt::WindowFlags f = 0} (where available) sets the window flags;
519 the default is suitable for almost all widgets, but to get, for
520 example, a window without a window system frame, you must use
521 special flags.
522 \endlist
523
524 QWidget has many member functions, but some of them have little direct
525 functionality; for example, QWidget has a font property, but never uses
526 this itself. There are many subclasses which provide real functionality,
527 such as QLabel, QPushButton, QListWidget, and QTabWidget.
528
529
530 \section1 Top-Level and Child Widgets
531
532 A widget without a parent widget is always an independent window (top-level
533 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
534 title bar and icon respectively.
535
536 Non-window widgets are child widgets, displayed within their parent
537 widgets. Most widgets in Qt are mainly useful as child widgets. For
538 example, it is possible to display a button as a top-level window, but most
539 people prefer to put their buttons inside other widgets, such as QDialog.
540
541 \image parent-child-widgets.png A parent widget containing various child widgets.
542
543 The diagram above shows a QGroupBox widget being used to hold various child
544 widgets in a layout provided by QGridLayout. The QLabel child widgets have
545 been outlined to indicate their full sizes.
546
547 If you want to use a QWidget to hold child widgets you will usually want to
548 add a layout to the parent QWidget. See \l{Layout Management} for more
549 information.
550
551
552 \section1 Composite Widgets
553
554 When a widget is used as a container to group a number of child widgets, it
555 is known as a composite widget. These can be created by constructing a
556 widget with the required visual properties - a QFrame, for example - and
557 adding child widgets to it, usually managed by a layout. The above diagram
558 shows such a composite widget that was created using Qt Designer.
559
560 Composite widgets can also be created by subclassing a standard widget,
561 such as QWidget or QFrame, and adding the necessary layout and child
562 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
563 {examples provided with Qt} use this approach, and it is also covered in
564 the Qt \l{Tutorials}.
565
566
567 \section1 Custom Widgets and Painting
568
569 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
570 display custom content that is composed using a series of painting
571 operations with an instance of the QPainter class. This approach contrasts
572 with the canvas-style approach used by the \l{Graphics View}
573 {Graphics View Framework} where items are added to a scene by the
574 application and are rendered by the framework itself.
575
576 Each widget performs all painting operations from within its paintEvent()
577 function. This is called whenever the widget needs to be redrawn, either
578 as a result of some external change or when requested by the application.
579
580 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
581 can handle paint events.
582
583
584 \section1 Size Hints and Size Policies
585
586 When implementing a new widget, it is almost always useful to reimplement
587 sizeHint() to provide a reasonable default size for the widget and to set
588 the correct size policy with setSizePolicy().
589
590 By default, composite widgets which do not provide a size hint will be
591 sized according to the space requirements of their child widgets.
592
593 The size policy lets you supply good default behavior for the layout
594 management system, so that other widgets can contain and manage yours
595 easily. The default size policy indicates that the size hint represents
596 the preferred size of the widget, and this is often good enough for many
597 widgets.
598
599 \note The size of top-level widgets are constrained to 2/3 of the desktop's
600 height and width. You can resize() the widget manually if these bounds are
601 inadequate.
602
603
604 \section1 Events
605
606 Widgets respond to events that are typically caused by user actions. Qt
607 delivers events to widgets by calling specific event handler functions with
608 instances of QEvent subclasses containing information about each event.
609
610 If your widget only contains child widgets, you probably do not need to
611 implement any event handlers. If you want to detect a mouse click in a
612 child widget call the child's underMouse() function inside the widget's
613 mousePressEvent().
614
615 The \l{widgets/scribble}{Scribble example} implements a wider set of
616 events to handle mouse movement, button presses, and window resizing.
617
618 You will need to supply the behavior and content for your own widgets, but
619 here is a brief overview of the events that are relevant to QWidget,
620 starting with the most common ones:
621
622 \list
623 \li paintEvent() is called whenever the widget needs to be repainted.
624 Every widget displaying custom content must implement it. Painting
625 using a QPainter can only take place in a paintEvent() or a
626 function called by a paintEvent().
627 \li resizeEvent() is called when the widget has been resized.
628 \li mousePressEvent() is called when a mouse button is pressed while
629 the mouse cursor is inside the widget, or when the widget has
630 grabbed the mouse using grabMouse(). Pressing the mouse without
631 releasing it is effectively the same as calling grabMouse().
632 \li mouseReleaseEvent() is called when a mouse button is released. A
633 widget receives mouse release events when it has received the
634 corresponding mouse press event. This means that if the user
635 presses the mouse inside \e your widget, then drags the mouse
636 somewhere else before releasing the mouse button, \e your widget
637 receives the release event. There is one exception: if a popup menu
638 appears while the mouse button is held down, this popup immediately
639 steals the mouse events.
640 \li mouseDoubleClickEvent() is called when the user double-clicks in
641 the widget. If the user double-clicks, the widget receives a mouse
642 press event, a mouse release event, (a mouse click event,) a second
643 mouse press, this event and finally a second mouse release event.
644 (Some mouse move events may also be
645 received if the mouse is not held steady during this operation.) It
646 is \e{not possible} to distinguish a click from a double-click
647 until the second click arrives. (This is one reason why most GUI
648 books recommend that double-clicks be an extension of
649 single-clicks, rather than trigger a different action.)
650 \endlist
651
652 Widgets that accept keyboard input need to reimplement a few more event
653 handlers:
654
655 \list
656 \li keyPressEvent() is called whenever a key is pressed, and again when
657 a key has been held down long enough for it to auto-repeat. The
658 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
659 they are not used by the focus-change mechanisms. To force those
660 keys to be processed by your widget, you must reimplement
661 QWidget::event().
662 \li focusInEvent() is called when the widget gains keyboard focus
663 (assuming you have called setFocusPolicy()). Well-behaved widgets
664 indicate that they own the keyboard focus in a clear but discreet
665 way.
666 \li focusOutEvent() is called when the widget loses keyboard focus.
667 \endlist
668
669 You may be required to also reimplement some of the less common event
670 handlers:
671
672 \list
673 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
674 button is held down. This can be useful during drag and drop
675 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
676 you get mouse move events even when no buttons are held down.
677 (See also the \l{Drag and Drop} guide.)
678 \li keyReleaseEvent() is called whenever a key is released and while it
679 is held down (if the key is auto-repeating). In that case, the
680 widget will receive a pair of key release and key press event for
681 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
682 to the widget if they are not used by the focus-change mechanisms.
683 To force those keys to be processed by your widget, you must
684 reimplement QWidget::event().
685 \li wheelEvent() is called whenever the user turns the mouse wheel
686 while the widget has the focus.
687 \li enterEvent() is called when the mouse enters the widget's screen
688 space. (This excludes screen space owned by any of the widget's
689 children.)
690 \li leaveEvent() is called when the mouse leaves the widget's screen
691 space. If the mouse enters a child widget it will not cause a
692 leaveEvent().
693 \li moveEvent() is called when the widget has been moved relative to
694 its parent.
695 \li closeEvent() is called when the user closes the widget (or when
696 close() is called).
697 \endlist
698
699 There are also some rather obscure events described in the documentation
700 for QEvent::Type. To handle these events, you need to reimplement event()
701 directly.
702
703 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
704 (to move the keyboard focus), and passes on most of the other events to
705 one of the more specialized handlers above.
706
707 Events and the mechanism used to deliver them are covered in
708 \l{The Event System}.
709
710 \section1 Groups of Functions and Properties
711
712 \table
713 \header \li Context \li Functions and Properties
714
715 \row \li Window functions \li
716 show(),
717 hide(),
718 raise(),
719 lower(),
720 close().
721
722 \row \li Top-level windows \li
723 \l windowModified, \l windowTitle, \l windowIcon,
724 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
725 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
726 showNormal().
727
728 \row \li Window contents \li
729 update(),
730 repaint(),
731 scroll().
732
733 \row \li Geometry \li
734 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
735 \l sizePolicy, sizeHint(), minimumSizeHint(),
736 updateGeometry(), layout(),
737 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
738 adjustSize(),
739 mapFromGlobal(), mapToGlobal(),
740 mapFromParent(), mapToParent(),
741 \l maximumSize, \l minimumSize, \l sizeIncrement,
742 \l baseSize, setFixedSize()
743
744 \row \li Mode \li
745 \l visible, isVisibleTo(),
746 \l enabled, isEnabledTo(),
747 \l modal,
748 isWindow(),
749 \l mouseTracking,
750 \l updatesEnabled,
751 visibleRegion().
752
753 \row \li Look and feel \li
754 style(),
755 setStyle(),
756 \l styleSheet,
757 \l cursor,
758 \l font,
759 \l palette,
760 backgroundRole(), setBackgroundRole(),
761 fontInfo(), fontMetrics().
762
763 \row \li Keyboard focus functions \li
764 \l focus, \l focusPolicy,
765 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
766 focusNextChild(), focusPreviousChild().
767
768 \row \li Mouse and keyboard grabbing \li
769 grabMouse(), releaseMouse(),
770 grabKeyboard(), releaseKeyboard(),
771 mouseGrabber(), keyboardGrabber().
772
773 \row \li Event handlers \li
774 event(),
775 mousePressEvent(),
776 mouseReleaseEvent(),
777 mouseDoubleClickEvent(),
778 mouseMoveEvent(),
779 keyPressEvent(),
780 keyReleaseEvent(),
781 focusInEvent(),
782 focusOutEvent(),
783 wheelEvent(),
784 enterEvent(),
785 leaveEvent(),
786 paintEvent(),
787 moveEvent(),
788 resizeEvent(),
789 closeEvent(),
790 dragEnterEvent(),
791 dragMoveEvent(),
792 dragLeaveEvent(),
793 dropEvent(),
794 childEvent(),
795 showEvent(),
796 hideEvent(),
797 customEvent().
798 changeEvent(),
799
800 \row \li System functions \li
801 parentWidget(), window(), setParent(), winId(),
802 find(), metric().
803
804 \row \li Context menu \li
805 contextMenuPolicy, contextMenuEvent(),
806 customContextMenuRequested(), actions()
807
808 \row \li Interactive help \li
809 setToolTip(), setWhatsThis()
810
811 \endtable
812
813
814 \section1 Widget Style Sheets
815
816 In addition to the standard widget styles for each platform, widgets can
817 also be styled according to rules specified in a \l{styleSheet}
818 {style sheet}. This feature enables you to customize the appearance of
819 specific widgets to provide visual cues to users about their purpose. For
820 example, a button could be styled in a particular way to indicate that it
821 performs a destructive action.
822
823 The use of widget style sheets is described in more detail in the
824 \l{Qt Style Sheets} document.
825
826
827 \section1 Transparency and Double Buffering
828
829 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
830 is no need to write double-buffering code in paintEvent() to avoid
831 flicker.
832
833 Since Qt 4.1, the Qt::WA_ContentsPropagated widget attribute has been
834 deprecated. Instead, the contents of parent widgets are propagated by
835 default to each of their children as long as Qt::WA_PaintOnScreen is not
836 set. Custom widgets can be written to take advantage of this feature by
837 updating irregular regions (to create non-rectangular child widgets), or
838 painting with colors that have less than full alpha component. The
839 following diagram shows how attributes and properties of a custom widget
840 can be fine-tuned to achieve different effects.
841
842 \image propagation-custom.png
843
844 In the above diagram, a semi-transparent rectangular child widget with an
845 area removed is constructed and added to a parent widget (a QLabel showing
846 a pixmap). Then, different properties and widget attributes are set to
847 achieve different effects:
848
849 \list
850 \li The left widget has no additional properties or widget attributes
851 set. This default state suits most custom widgets using
852 transparency, are irregularly-shaped, or do not paint over their
853 entire area with an opaque brush.
854 \li The center widget has the \l autoFillBackground property set. This
855 property is used with custom widgets that rely on the widget to
856 supply a default background, and do not paint over their entire
857 area with an opaque brush.
858 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
859 set. This indicates that the widget will paint over its entire area
860 with opaque colors. The widget's area will initially be
861 \e{uninitialized}, represented in the diagram with a red diagonal
862 grid pattern that shines through the overpainted area. The
863 Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
864 paint their own specialized contents quickly and do not need a
865 default filled background.
866 \endlist
867
868 To rapidly update custom widgets with simple background colors, such as
869 real-time plotting or graphing widgets, it is better to define a suitable
870 background color (using setBackgroundRole() with the
871 QPalette::Window role), set the \l autoFillBackground property, and only
872 implement the necessary drawing functionality in the widget's paintEvent().
873
874 To rapidly update custom widgets that constantly paint over their entire
875 areas with opaque content, e.g., video streaming widgets, it is better to
876 set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
877 associated with repainting the widget's background.
878
879 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
880 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
881 attribute takes precedence. Depending on your requirements, you should
882 choose either one of them.
883
884 Since Qt 4.1, the contents of parent widgets are also propagated to
885 standard Qt widgets. This can lead to some unexpected results if the
886 parent widget is decorated in a non-standard way, as shown in the diagram
887 below.
888
889 \image propagation-standard.png
890
891 The scope for customizing the painting behavior of standard Qt widgets,
892 without resorting to subclassing, is slightly less than that possible for
893 custom widgets. Usually, the desired appearance of a standard widget can be
894 achieved by setting its \l autoFillBackground property.
895
896
897 \section1 Creating Translucent Windows
898
899 Since Qt 4.5, it has been possible to create windows with translucent regions
900 on window systems that support compositing.
901
902 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
903 attribute with setAttribute() and ensure that its background is painted with
904 non-opaque colors in the regions you want to be partially transparent.
905
906 Platform notes:
907
908 \list
909 \li X11: This feature relies on the use of an X server that supports ARGB visuals
910 and a compositing window manager.
911 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
912 for the translucency to work.
913 \endlist
914
915
916 \section1 Native Widgets vs Alien Widgets
917
918 Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
919 system. They do not have a native window handle associated with them. This
920 feature significantly speeds up widget painting, resizing, and removes flicker.
921
922 Should you require the old behavior with native windows, you can choose
923 one of the following options:
924
925 \list 1
926 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
927 \li Set the Qt::AA_NativeWindows attribute on your application. All
928 widgets will be native widgets.
929 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
930 and all of its ancestors will become native (unless
931 Qt::WA_DontCreateNativeAncestors is set).
932 \li Call QWidget::winId to enforce a native window (this implies 3).
933 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
934 (this implies 3).
935 \endlist
936
937 \sa QEvent, QPainter, QGridLayout, QBoxLayout
938
939*/
940
941QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
942QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid
943
944
945/*****************************************************************************
946 QWidget utility functions
947 *****************************************************************************/
948
949QRegion qt_dirtyRegion(QWidget *widget)
950{
951 if (!widget)
952 return QRegion();
953
954 QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore();
955 if (!bs)
956 return QRegion();
957
958 return bs->dirtyRegion(widget);
959}
960
961/*****************************************************************************
962 QWidget member functions
963 *****************************************************************************/
964
965/*
966 Widget state flags:
967 \list
968 \li Qt::WA_WState_Created The widget has a valid winId().
969 \li Qt::WA_WState_Visible The widget is currently visible.
970 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
971 become visible unless you call show() on it. Qt::WA_WState_Hidden
972 implies !Qt::WA_WState_Visible.
973 \li Qt::WA_WState_CompressKeys Compress keyboard events.
974 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
975 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
976 \li Qt::WA_WState_Reparented The widget has been reparented.
977 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
978 \li Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
979 \endlist
980*/
981
982struct QWidgetExceptionCleaner
983{
984 /* this cleans up when the constructor throws an exception */
985 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
986 {
987#ifdef QT_NO_EXCEPTIONS
988 Q_UNUSED(that);
989 Q_UNUSED(d);
990#else
991 QWidgetPrivate::allWidgets->remove(that);
992 if (d->focus_next != that) {
993 if (d->focus_next)
994 d->focus_next->d_func()->focus_prev = d->focus_prev;
995 if (d->focus_prev)
996 d->focus_prev->d_func()->focus_next = d->focus_next;
997 }
998#endif
999 }
1000};
1001
1002/*!
1003 Constructs a widget which is a child of \a parent, with widget
1004 flags set to \a f.
1005
1006 If \a parent is \nullptr, the new widget becomes a window. If
1007 \a parent is another widget, this widget becomes a child window
1008 inside \a parent. The new widget is deleted when its \a parent is
1009 deleted.
1010
1011 The widget flags argument, \a f, is normally 0, but it can be set
1012 to customize the frame of a window (i.e. \a parent must be
1013 \nullptr). To customize the frame, use a value composed
1014 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
1015
1016 If you add a child widget to an already visible widget you must
1017 explicitly show the child to make it visible.
1018
1019 Note that the X11 version of Qt may not be able to deliver all
1020 combinations of style flags on all systems. This is because on
1021 X11, Qt can only ask the window manager, and the window manager
1022 can override the application's settings. On Windows, Qt can set
1023 whatever flags you want.
1024
1025 \sa windowFlags
1026*/
1027QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
1028 : QObject(*new QWidgetPrivate, 0), QPaintDevice()
1029{
1030 QT_TRY {
1031 d_func()->init(parent, f);
1032 } QT_CATCH(...) {
1033 QWidgetExceptionCleaner::cleanup(this, d_func());
1034 QT_RETHROW;
1035 }
1036}
1037
1038
1039/*! \internal
1040*/
1041QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
1042 : QObject(dd, 0), QPaintDevice()
1043{
1044 Q_D(QWidget);
1045 QT_TRY {
1046 d->init(parent, f);
1047 } QT_CATCH(...) {
1048 QWidgetExceptionCleaner::cleanup(this, d_func());
1049 QT_RETHROW;
1050 }
1051}
1052
1053/*!
1054 \internal
1055*/
1056int QWidget::devType() const
1057{
1058 return QInternal::Widget;
1059}
1060
1061
1062//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
1063void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
1064{
1065 bool customize = (flags & (Qt::CustomizeWindowHint
1066 | Qt::FramelessWindowHint
1067 | Qt::WindowTitleHint
1068 | Qt::WindowSystemMenuHint
1069 | Qt::WindowMinimizeButtonHint
1070 | Qt::WindowMaximizeButtonHint
1071 | Qt::WindowCloseButtonHint
1072 | Qt::WindowContextHelpButtonHint));
1073
1074 uint type = (flags & Qt::WindowType_Mask);
1075
1076 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
1077 type = Qt::Window;
1078 flags |= Qt::Window;
1079 }
1080
1081 if (flags & Qt::CustomizeWindowHint) {
1082 // modify window flags to make them consistent.
1083 // Only enable this on non-Mac platforms. Since the old way of doing this would
1084 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
1085 // we can't just add this in.
1086#if 1 // Used to be excluded in Qt4 for Q_WS_MAC
1087 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
1088# ifdef Q_OS_WIN
1089 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
1090# endif
1091 ) {
1092 flags |= Qt::WindowSystemMenuHint;
1093#else
1094 if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
1095 | Qt::WindowSystemMenuHint)) {
1096#endif
1097 flags |= Qt::WindowTitleHint;
1098 flags &= ~Qt::FramelessWindowHint;
1099 }
1100 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
1101 // if any of the window hints that affect the titlebar are set
1102 // and the window is supposed to have frame, we add a titlebar
1103 // and system menu by default.
1104 flags |= Qt::WindowSystemMenuHint;
1105 flags |= Qt::WindowTitleHint;
1106 }
1107 if (customize)
1108 ; // don't modify window flags if the user explicitly set them.
1109 else if (type == Qt::Dialog || type == Qt::Sheet) {
1110 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1111 // ### fixme: Qt 6: Never set Qt::WindowContextHelpButtonHint flag automatically
1112 if (!QApplicationPrivate::testAttribute(Qt::AA_DisableWindowContextHelpButton))
1113 flags |= Qt::WindowContextHelpButtonHint;
1114 } else if (type == Qt::Tool)
1115 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1116 else
1117 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint |
1118 Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint;
1119 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
1120 flags |= Qt::WindowTransparentForInput;
1121}
1122
1123void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
1124{
1125 Q_Q(QWidget);
1126 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
1127 qFatal("QWidget: Cannot create a QWidget without QApplication");
1128
1129 Q_ASSERT(allWidgets);
1130 if (allWidgets)
1131 allWidgets->insert(q);
1132
1133 int targetScreen = -1;
1134 if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
1135 const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
1136 targetScreen = sw ? sw->screenNumber() : 0;
1137 parentWidget = 0;
1138 }
1139
1140 q->data = &data;
1141
1142#if QT_CONFIG(thread)
1143 if (!parent) {
1144 Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
1145 "Widgets must be created in the GUI thread.");
1146 }
1147#endif
1148
1149#if 0 // Used to be included in Qt4 for Q_WS_X11
1150 if (desktopWidget) {
1151 // make sure the widget is created on the same screen as the
1152 // programmer specified desktop widget
1153 xinfo = desktopWidget->d_func()->xinfo;
1154 }
1155#endif
1156 if (targetScreen >= 0) {
1157 topData()->initialScreenIndex = targetScreen;
1158 if (QWindow *window = q->windowHandle())
1159 window->setScreen(QGuiApplication::screens().value(targetScreen, nullptr));
1160 }
1161
1162 data.fstrut_dirty = true;
1163
1164 data.winid = 0;
1165 data.widget_attributes = 0;
1166 data.window_flags = f;
1167 data.window_state = 0;
1168 data.focus_policy = 0;
1169 data.context_menu_policy = Qt::DefaultContextMenu;
1170 data.window_modality = Qt::NonModal;
1171
1172 data.sizehint_forced = 0;
1173 data.is_closing = 0;
1174 data.in_show = 0;
1175 data.in_set_window_state = 0;
1176 data.in_destructor = false;
1177
1178 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
1179 if (f & Qt::MSWindowsOwnDC) {
1180 mustHaveWindowHandle = 1;
1181 q->setAttribute(Qt::WA_NativeWindow);
1182 }
1183//#if 0 // Used to be included in Qt4 for Q_WS_MAC
1184// q->setAttribute(Qt::WA_NativeWindow);
1185//#endif
1186
1187 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
1188 adjustQuitOnCloseAttribute();
1189
1190 q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
1191 q->setAttribute(Qt::WA_WState_Hidden);
1192
1193 //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
1194 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
1195 focus_next = focus_prev = q;
1196
1197 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
1198 q->create();
1199 else if (parentWidget)
1200 q->setParent(parentWidget, data.window_flags);
1201 else {
1202 adjustFlags(data.window_flags, q);
1203 resolveLayoutDirection();
1204 // opaque system background?
1205 const QBrush &background = q->palette().brush(QPalette::Window);
1206 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1207 }
1208 data.fnt = QFont(data.fnt, q);
1209#if 0 // Used to be included in Qt4 for Q_WS_X11
1210 data.fnt.x11SetScreen(xinfo.screen());
1211#endif
1212
1213 q->setAttribute(Qt::WA_PendingMoveEvent);
1214 q->setAttribute(Qt::WA_PendingResizeEvent);
1215
1216 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1217 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1218
1219 if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
1220 q->create();
1221
1222 QEvent e(QEvent::Create);
1223 QApplication::sendEvent(q, &e);
1224 QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1225
1226 extraPaintEngine = 0;
1227
1228#if 0 // Used to be included in Qt4 for Q_WS_MAC
1229 // If we add a child to the unified toolbar, we have to redirect the painting.
1230 if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) {
1231 if (parentWidget->d_func()->unifiedSurface) {
1232 QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor;
1233 parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset);
1234 }
1235 }
1236#endif
1237}
1238
1239
1240
1241void QWidgetPrivate::createRecursively()
1242{
1243 Q_Q(QWidget);
1244 q->create(0, true, true);
1245 for (int i = 0; i < children.size(); ++i) {
1246 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1247 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1248 child->d_func()->createRecursively();
1249 }
1250}
1251
1252
1253// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1254
1255/*!
1256 Creates a new widget window.
1257
1258 The parameter \a window is ignored in Qt 5. Please use
1259 QWindow::fromWinId() to create a QWindow wrapping a foreign
1260 window and pass it to QWidget::createWindowContainer() instead.
1261
1262 Initializes the window (sets the geometry etc.) if \a
1263 initializeWindow is true. If \a initializeWindow is false, no
1264 initialization is performed. This parameter only makes sense if \a
1265 window is a valid window.
1266
1267 Destroys the old window if \a destroyOldWindow is true. If \a
1268 destroyOldWindow is false, you are responsible for destroying the
1269 window yourself (using platform native code).
1270
1271 The QWidget constructor calls create(0,true,true) to create a
1272 window for this widget.
1273
1274 \sa createWindowContainer(), QWindow::fromWinId()
1275*/
1276
1277void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1278{
1279 Q_D(QWidget);
1280 if (Q_UNLIKELY(window))
1281 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1282 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1283 return;
1284
1285 if (d->data.in_destructor)
1286 return;
1287
1288 Qt::WindowType type = windowType();
1289 Qt::WindowFlags &flags = data->window_flags;
1290
1291 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1292 type = Qt::Window;
1293 flags |= Qt::Window;
1294 }
1295
1296 if (QWidget *parent = parentWidget()) {
1297 if (type & Qt::Window) {
1298 if (!parent->testAttribute(Qt::WA_WState_Created))
1299 parent->createWinId();
1300 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1301 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1302 // We're about to create a native child widget that doesn't have a native parent;
1303 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1304 // attribute is set.
1305 d->createWinId();
1306 // Nothing more to do.
1307 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1308 Q_ASSERT(internalWinId());
1309 return;
1310 }
1311 }
1312
1313
1314 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1315 if (paintOnScreenEnv)
1316 setAttribute(Qt::WA_PaintOnScreen);
1317
1318 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1319 setAttribute(Qt::WA_NativeWindow);
1320
1321#ifdef ALIEN_DEBUG
1322 qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
1323 << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
1324#endif
1325
1326#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && QT_CONFIG(draganddrop)
1327 // Unregister the dropsite (if already registered) before we
1328 // re-create the widget with a native window.
1329 if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
1330 && d->extra && d->extra->dropTarget) {
1331 d->registerDropSite(false);
1332 }
1333#endif
1334
1335 d->updateIsOpaque();
1336
1337 setAttribute(Qt::WA_WState_Created); // set created flag
1338 d->create_sys(window, initializeWindow, destroyOldWindow);
1339
1340 // a real toplevel window needs a backing store
1341 if (isWindow() && windowType() != Qt::Desktop) {
1342 d->topData()->backingStoreTracker.destroy();
1343 d->topData()->backingStoreTracker.create(this);
1344 }
1345
1346 d->setModal_sys();
1347
1348 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1349 setAttribute(Qt::WA_DropSiteRegistered, true);
1350
1351 // need to force the resting of the icon after changing parents
1352 if (testAttribute(Qt::WA_SetWindowIcon))
1353 d->setWindowIcon_sys();
1354
1355 if (isWindow() && !d->topData()->iconText.isEmpty())
1356 d->setWindowIconText_helper(d->topData()->iconText);
1357 if (isWindow() && !d->topData()->caption.isEmpty())
1358 d->setWindowTitle_helper(d->topData()->caption);
1359 if (isWindow() && !d->topData()->filePath.isEmpty())
1360 d->setWindowFilePath_helper(d->topData()->filePath);
1361 if (windowType() != Qt::Desktop) {
1362 d->updateSystemBackground();
1363
1364 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1365 d->setWindowIcon_sys();
1366 }
1367
1368 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1369 // as those force native window creation on their ancestors before they are shown.
1370 // If the strut is not updated, any subsequent move of the top level window before show
1371 // will cause window frame to be ignored when positioning the window.
1372 // Note that this only helps on platforms that handle window creation synchronously.
1373 d->updateFrameStrut();
1374}
1375
1376void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1377{
1378 QObjectList children = parentWidget->children();
1379 for (int i = 0; i < children.size(); i++) {
1380 if (children.at(i)->isWidgetType()) {
1381 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1382 if (childWidget) { // should not be necessary
1383 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1384 if (!childWidget->internalWinId())
1385 childWidget->winId();
1386 if (childWidget->windowHandle()) {
1387 if (childWidget->isWindow()) {
1388 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1389 } else {
1390 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1391 }
1392 }
1393 } else {
1394 q_createNativeChildrenAndSetParent(childWidget);
1395 }
1396 }
1397 }
1398 }
1399
1400}
1401
1402void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
1403{
1404 Q_Q(QWidget);
1405
1406 Q_UNUSED(window);
1407 Q_UNUSED(initializeWindow);
1408 Q_UNUSED(destroyOldWindow);
1409
1410 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1411 return; // we only care about real toplevels
1412
1413 QWidgetWindow *win = topData()->window;
1414 // topData() ensures the extra is created but does not ensure 'window' is non-null
1415 // in case the extra was already valid.
1416 if (!win) {
1417 createTLSysExtra();
1418 win = topData()->window;
1419 }
1420
1421 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1422 for (const QByteArray &propertyName : dynamicPropertyNames) {
1423 if (!qstrncmp(propertyName, "_q_platform_", 12))
1424 win->setProperty(propertyName, q->property(propertyName));
1425 }
1426
1427 Qt::WindowFlags &flags = data.window_flags;
1428
1429#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
1430 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1431 flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1432#endif
1433
1434 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1435 win->setProperty("_q_showWithoutActivating", QVariant(true));
1436 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1437 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1438 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1439 win->setFlags(flags);
1440 fixPosIncludesFrame();
1441 if (q->testAttribute(Qt::WA_Moved)
1442 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1443 win->setGeometry(q->geometry());
1444 else
1445 win->resize(q->size());
1446 if (win->isTopLevel()) {
1447 int screenNumber = topData()->initialScreenIndex;
1448 topData()->initialScreenIndex = -1;
1449 if (screenNumber < 0) {
1450 screenNumber = q->windowType() != Qt::Desktop
1451 ? QDesktopWidgetPrivate::screenNumber(q) : 0;
1452 }
1453 win->setScreen(QGuiApplication::screens().value(screenNumber, nullptr));
1454 }
1455
1456 QSurfaceFormat format = win->requestedFormat();
1457 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1458 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1459 format.setAlphaBufferSize(8);
1460 }
1461 win->setFormat(format);
1462
1463 if (QWidget *nativeParent = q->nativeParentWidget()) {
1464 if (nativeParent->windowHandle()) {
1465 if (flags & Qt::Window) {
1466 win->setTransientParent(nativeParent->window()->windowHandle());
1467 win->setParent(0);
1468 } else {
1469 win->setTransientParent(0);
1470 win->setParent(nativeParent->windowHandle());
1471 }
1472 }
1473 }
1474
1475 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1476 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1477
1478 if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
1479 win->create();
1480 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1481 if (QPlatformWindow *platformWindow = win->handle())
1482 platformWindow->setFrameStrutEventsEnabled(true);
1483 }
1484
1485 data.window_flags = win->flags();
1486 if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1487 data.window_flags &= ~Qt::ForeignWindow;
1488
1489 if (!topData()->role.isNull())
1490 QXcbWindowFunctions::setWmWindowRole(win, topData()->role.toLatin1());
1491
1492 QBackingStore *store = q->backingStore();
1493
1494 if (!store) {
1495 if (q->windowType() != Qt::Desktop) {
1496 if (q->isTopLevel())
1497 q->setBackingStore(new QBackingStore(win));
1498 } else {
1499 q->setAttribute(Qt::WA_PaintOnScreen, true);
1500 }
1501 }
1502
1503 setWindowModified_helper();
1504
1505 if (win->handle()) {
1506 WId id = win->winId();
1507 // See the QPlatformWindow::winId() documentation
1508 Q_ASSERT(id != WId(0));
1509 setWinId(id);
1510 }
1511
1512 // Check children and create windows for them if necessary
1513 q_createNativeChildrenAndSetParent(q);
1514
1515 if (extra && !extra->mask.isEmpty())
1516 setMask_sys(extra->mask);
1517
1518 if (data.crect.width() == 0 || data.crect.height() == 0) {
1519 q->setAttribute(Qt::WA_OutsideWSRange, true);
1520 } else if (q->isVisible()) {
1521 // If widget is already shown, set window visible, too
1522 win->setNativeWindowVisibility(true);
1523 }
1524}
1525
1526#ifdef Q_OS_WIN
1527static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1528#endif
1529
1530void QWidgetPrivate::createTLSysExtra()
1531{
1532 Q_Q(QWidget);
1533 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1534 extra->topextra->window = new QWidgetWindow(q);
1535 if (extra->minw || extra->minh)
1536 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1537 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1538 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1539 if (extra->topextra->opacity != 255 && q->isWindow())
1540 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1541#ifdef Q_OS_WIN
1542 // Pass on native parent handle for Widget embedded into Active X.
1543 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1544 if (activeXNativeParentHandle.isValid())
1545 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1546 if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
1547 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1548#endif
1549 }
1550
1551}
1552
1553/*!
1554 Destroys the widget.
1555
1556 All this widget's children are deleted first. The application
1557 exits if this widget is the main widget.
1558*/
1559
1560QWidget::~QWidget()
1561{
1562 Q_D(QWidget);
1563 d->data.in_destructor = true;
1564
1565#if defined (QT_CHECK_STATE)
1566 if (Q_UNLIKELY(paintingActive()))
1567 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1568#endif
1569
1570#ifndef QT_NO_GESTURES
1571 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1572 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1573 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1574 manager->cleanupCachedGestures(this, *it);
1575 }
1576 d->gestureContext.clear();
1577#endif
1578
1579#ifndef QT_NO_ACTION
1580 // remove all actions from this widget
1581 for (int i = 0; i < d->actions.size(); ++i) {
1582 QActionPrivate *apriv = d->actions.at(i)->d_func();
1583 apriv->widgets.removeAll(this);
1584 }
1585 d->actions.clear();
1586#endif
1587
1588#ifndef QT_NO_SHORTCUT
1589 // Remove all shortcuts grabbed by this
1590 // widget, unless application is closing
1591 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1592 qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence());
1593#endif
1594
1595 // delete layout while we still are a valid widget
1596 delete d->layout;
1597 d->layout = 0;
1598 // Remove myself from focus list
1599
1600 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1601 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1602
1603 if (d->focus_next != this) {
1604 d->focus_next->d_func()->focus_prev = d->focus_prev;
1605 d->focus_prev->d_func()->focus_next = d->focus_next;
1606 d->focus_next = d->focus_prev = 0;
1607 }
1608
1609
1610 QT_TRY {
1611#if QT_CONFIG(graphicsview)
1612 const QWidget* w = this;
1613 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1614 w = w->d_func()->extra->focus_proxy;
1615 QWidget *window = w->window();
1616 QWExtra *e = window ? window->d_func()->extra : 0;
1617 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1618#endif
1619 clearFocus();
1620 } QT_CATCH(...) {
1621 // swallow this problem because we are in a destructor
1622 }
1623
1624 d->setDirtyOpaqueRegion();
1625
1626 if (isWindow() && isVisible() && internalWinId()) {
1627 QT_TRY {
1628 d->close_helper(QWidgetPrivate::CloseNoEvent);
1629 } QT_CATCH(...) {
1630 // if we're out of memory, at least hide the window.
1631 QT_TRY {
1632 hide();
1633 } QT_CATCH(...) {
1634 // and if that also doesn't work, then give up
1635 }
1636 }
1637 }
1638
1639#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */|| 0 /* Used to be included in Qt4 for Q_WS_MAC */
1640 else if (!internalWinId() && isVisible()) {
1641 qApp->d_func()->sendSyntheticEnterLeave(this);
1642 }
1643#endif
1644 else if (isVisible()) {
1645 qApp->d_func()->sendSyntheticEnterLeave(this);
1646 }
1647
1648 if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
1649 bs->removeDirtyWidget(this);
1650 if (testAttribute(Qt::WA_StaticContents))
1651 bs->removeStaticWidget(this);
1652 }
1653
1654 delete d->needsFlush;
1655 d->needsFlush = 0;
1656
1657 // The next 20 lines are duplicated from QObject, but required here
1658 // since QWidget deletes is children itself
1659 bool blocked = d->blockSig;
1660 d->blockSig = 0; // unblock signals so we always emit destroyed()
1661
1662 if (d->isSignalConnected(0)) {
1663 QT_TRY {
1664 emit destroyed(this);
1665 } QT_CATCH(...) {
1666 // all the signal/slots connections are still in place - if we don't
1667 // quit now, we will crash pretty soon.
1668 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1669 QT_RETHROW;
1670 }
1671 }
1672
1673 if (d->declarativeData) {
1674 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1675 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1676 if (QAbstractDeclarativeData::destroyed_qml1)
1677 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1678 } else {
1679 if (QAbstractDeclarativeData::destroyed)
1680 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1681 }
1682 d->declarativeData = 0; // don't activate again in ~QObject
1683 d->wasDeleted = false;
1684 }
1685
1686 d->blockSig = blocked;
1687
1688#if 0 // Used to be included in Qt4 for Q_WS_MAC
1689 // QCocoaView holds a pointer back to this widget. Clear it now
1690 // to make sure it's not followed later on. The lifetime of the
1691 // QCocoaView might exceed the lifetime of this widget in cases
1692 // where Cocoa itself holds references to it.
1693 extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
1694 qt_mac_clearCocoaViewQWidgetPointers(this);
1695#endif
1696
1697 if (!d->children.isEmpty())
1698 d->deleteChildren();
1699
1700 QApplication::removePostedEvents(this);
1701
1702 QT_TRY {
1703 destroy(); // platform-dependent cleanup
1704 } QT_CATCH(...) {
1705 // if this fails we can't do anything about it but at least we are not allowed to throw.
1706 }
1707 --QWidgetPrivate::instanceCounter;
1708
1709 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1710 QWidgetPrivate::allWidgets->remove(this);
1711
1712 QT_TRY {
1713 QEvent e(QEvent::Destroy);
1714 QCoreApplication::sendEvent(this, &e);
1715 } QT_CATCH(const std::exception&) {
1716 // if this fails we can't do anything about it but at least we are not allowed to throw.
1717 }
1718
1719#if QT_CONFIG(graphicseffect)
1720 delete d->graphicsEffect;
1721#endif
1722}
1723
1724int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1725int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1726
1727void QWidgetPrivate::setWinId(WId id) // set widget identifier
1728{
1729 Q_Q(QWidget);
1730 // the user might create a widget with Qt::Desktop window
1731 // attribute (or create another QDesktopWidget instance), which
1732 // will have the same windowid (the root window id) as the
1733 // qt_desktopWidget. We should not add the second desktop widget
1734 // to the mapper.
1735 bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
1736 if (mapper && data.winid && !userDesktopWidget) {
1737 mapper->remove(data.winid);
1738 }
1739
1740 const WId oldWinId = data.winid;
1741
1742 data.winid = id;
1743#if 0 // Used to be included in Qt4 for Q_WS_X11
1744 hd = id; // X11: hd == ident
1745#endif
1746 if (mapper && id && !userDesktopWidget) {
1747 mapper->insert(data.winid, q);
1748 }
1749
1750 if(oldWinId != id) {
1751 QEvent e(QEvent::WinIdChange);
1752 QCoreApplication::sendEvent(q, &e);
1753 }
1754}
1755
1756void QWidgetPrivate::createTLExtra()
1757{
1758 if (!extra)
1759 createExtra();
1760 if (!extra->topextra) {
1761 QTLWExtra* x = extra->topextra = new QTLWExtra;
1762 x->icon = 0;
1763 x->backingStore = 0;
1764 x->sharedPainter = 0;
1765 x->incw = x->inch = 0;
1766 x->basew = x->baseh = 0;
1767 x->frameStrut.setCoords(0, 0, 0, 0);
1768 x->normalGeometry = QRect(0,0,-1,-1);
1769 x->savedFlags = 0;
1770 x->opacity = 255;
1771 x->posIncludesFrame = 0;
1772 x->sizeAdjusted = false;
1773 x->inTopLevelResize = false;
1774 x->embedded = 0;
1775 x->window = 0;
1776 x->shareContext = 0;
1777 x->initialScreenIndex = -1;
1778#if 0 // Used to be included in Qt4 for Q_WS_MAC
1779 x->wasMaximized = false;
1780#endif
1781#ifdef QWIDGET_EXTRA_DEBUG
1782 static int count = 0;
1783 qDebug() << "tlextra" << ++count;
1784#endif
1785 }
1786}
1787
1788/*!
1789 \internal
1790 Creates the widget extra data.
1791*/
1792
1793void QWidgetPrivate::createExtra()
1794{
1795 if (!extra) { // if not exists
1796 extra = new QWExtra;
1797 extra->glContext = 0;
1798 extra->topextra = 0;
1799#if QT_CONFIG(graphicsview)
1800 extra->proxyWidget = 0;
1801#endif
1802#ifndef QT_NO_CURSOR
1803 extra->curs = 0;
1804#endif
1805 extra->minw = 0;
1806 extra->minh = 0;
1807 extra->maxw = QWIDGETSIZE_MAX;
1808 extra->maxh = QWIDGETSIZE_MAX;
1809 extra->customDpiX = 0;
1810 extra->customDpiY = 0;
1811 extra->explicitMinSize = 0;
1812 extra->explicitMaxSize = 0;
1813 extra->autoFillBackground = 0;
1814 extra->nativeChildrenForced = 0;
1815 extra->inRenderWithPainter = 0;
1816 extra->hasWindowContainer = false;
1817 extra->hasMask = 0;
1818 createSysExtra();
1819#ifdef QWIDGET_EXTRA_DEBUG
1820 static int count = 0;
1821 qDebug() << "extra" << ++count;
1822#endif
1823 }
1824}
1825
1826void QWidgetPrivate::createSysExtra()
1827{
1828}
1829
1830/*!
1831 \internal
1832 Deletes the widget extra data.
1833*/
1834
1835void QWidgetPrivate::deleteExtra()
1836{
1837 if (extra) { // if exists
1838#ifndef QT_NO_CURSOR
1839 delete extra->curs;
1840#endif
1841 deleteSysExtra();
1842#ifndef QT_NO_STYLE_STYLESHEET
1843 // dereference the stylesheet style
1844 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1845 proxy->deref();
1846#endif
1847 if (extra->topextra) {
1848 deleteTLSysExtra();
1849 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1850 delete extra->topextra->icon;
1851 delete extra->topextra;
1852 }
1853 delete extra;
1854 // extra->xic destroyed in QWidget::destroy()
1855 extra = 0;
1856 }
1857}
1858
1859void QWidgetPrivate::deleteSysExtra()
1860{
1861}
1862
1863static void deleteBackingStore(QWidgetPrivate *d)
1864{
1865 QTLWExtra *topData = d->topData();
1866
1867 delete topData->backingStore;
1868 topData->backingStore = 0;
1869}
1870
1871void QWidgetPrivate::deleteTLSysExtra()
1872{
1873 if (extra && extra->topextra) {
1874 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1875 //needs to be deleted first.
1876
1877 extra->topextra->backingStoreTracker.destroy();
1878 deleteBackingStore(this);
1879#ifndef QT_NO_OPENGL
1880 qDeleteAll(extra->topextra->widgetTextures);
1881 extra->topextra->widgetTextures.clear();
1882 delete extra->topextra->shareContext;
1883 extra->topextra->shareContext = 0;
1884#endif
1885
1886 //the toplevel might have a context with a "qglcontext associated with it. We need to
1887 //delete the qglcontext before we delete the qplatformopenglcontext.
1888 //One unfortunate thing about this is that we potentially create a glContext just to
1889 //delete it straight afterwards.
1890 if (extra->topextra->window) {
1891 extra->topextra->window->destroy();
1892 }
1893 delete extra->topextra->window;
1894 extra->topextra->window = 0;
1895
1896 }
1897}
1898
1899/*
1900 Returns \c region of widgets above this which overlap with
1901 \a rect, which is in parent's coordinate system (same as crect).
1902*/
1903
1904QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1905{
1906 Q_Q(const QWidget);
1907
1908 const QWidget *w = q;
1909 QRect r = rect;
1910 QPoint p;
1911 QRegion region;
1912 while (w) {
1913 if (w->isWindow())
1914 break;
1915 QWidgetPrivate *pd = w->parentWidget()->d_func();
1916 bool above = false;
1917 for (int i = 0; i < pd->children.size(); ++i) {
1918 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1919 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1920 continue;
1921 if (!above) {
1922 above = (sibling == w);
1923 continue;
1924 }
1925
1926 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1927 if (qRectIntersects(siblingRect, r)) {
1928 const QWExtra *siblingExtra = sibling->d_func()->extra;
1929 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1930 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1931 continue;
1932 }
1933 region += siblingRect.translated(-p);
1934 if (breakAfterFirst)
1935 break;
1936 }
1937 }
1938 w = w->parentWidget();
1939 r.translate(pd->data.crect.topLeft());
1940 p += pd->data.crect.topLeft();
1941 }
1942 return region;
1943}
1944
1945void QWidgetPrivate::syncBackingStore()
1946{
1947 if (paintOnScreen()) {
1948 repaint_sys(dirty);
1949 dirty = QRegion();
1950 } else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1951 bs->sync();
1952 }
1953}
1954
1955void QWidgetPrivate::syncBackingStore(const QRegion &region)
1956{
1957 if (paintOnScreen())
1958 repaint_sys(region);
1959 else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1960 bs->sync(q_func(), region);
1961 }
1962}
1963
1964void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1965{
1966 Q_Q(QWidget);
1967
1968 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1969 return; // nothing we can do
1970
1971 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1972 return; // nothing to do
1973
1974 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1975 if (enable)
1976 q->update();
1977
1978 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1979 for (int i = 0; i < children.size(); ++i) {
1980 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1981 if (w && !w->isWindow() && !w->testAttribute(attribute))
1982 w->d_func()->setUpdatesEnabled_helper(enable);
1983 }
1984}
1985
1986/*!
1987 \internal
1988
1989 Propagate this widget's palette to all children, except style sheet
1990 widgets, and windows that don't enable window propagation (palettes don't
1991 normally propagate to windows).
1992*/
1993void QWidgetPrivate::propagatePaletteChange()
1994{
1995 Q_Q(QWidget);
1996 // Propagate a new inherited mask to all children.
1997#if QT_CONFIG(graphicsview)
1998 if (!q->parentWidget() && extra && extra->proxyWidget) {
1999 QGraphicsProxyWidget *p = extra->proxyWidget;
2000 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
2001 } else
2002#endif // QT_CONFIG(graphicsview)
2003 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
2004 inheritedPaletteResolveMask = 0;
2005 }
2006 int mask = data.pal.resolve() | inheritedPaletteResolveMask;
2007
2008 const bool useStyleSheetPropagationInWidgetStyles =
2009 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
2010
2011 QEvent pc(QEvent::PaletteChange);
2012 QApplication::sendEvent(q, &pc);
2013 for (int i = 0; i < children.size(); ++i) {
2014 QWidget *w = qobject_cast<QWidget*>(children.at(i));
2015 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
2016 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
2017 QWidgetPrivate *wd = w->d_func();
2018 wd->inheritedPaletteResolveMask = mask;
2019 wd->resolvePalette();
2020 }
2021 }
2022}
2023
2024/*
2025 Returns the widget's clipping rectangle.
2026*/
2027QRect QWidgetPrivate::clipRect() const
2028{
2029 Q_Q(const QWidget);
2030 const QWidget * w = q;
2031 if (!w->isVisible())
2032 return QRect();
2033 QRect r = effectiveRectFor(q->rect());
2034 int ox = 0;
2035 int oy = 0;
2036 while (w
2037 && w->isVisible()
2038 && !w->isWindow()
2039 && w->parentWidget()) {
2040 ox -= w->x();
2041 oy -= w->y();
2042 w = w->parentWidget();
2043 r &= QRect(ox, oy, w->width(), w->height());
2044 }
2045 return r;
2046}
2047
2048/*
2049 Returns the widget's clipping region (without siblings).
2050*/
2051QRegion QWidgetPrivate::clipRegion() const
2052{
2053 Q_Q(const QWidget);
2054 if (!q->isVisible())
2055 return QRegion();
2056 QRegion r(q->rect());
2057 const QWidget * w = q;
2058 const QWidget *ignoreUpTo;
2059 int ox = 0;
2060 int oy = 0;
2061 while (w
2062 && w->isVisible()
2063 && !w->isWindow()
2064 && w->parentWidget()) {
2065 ox -= w->x();
2066 oy -= w->y();
2067 ignoreUpTo = w;
2068 w = w->parentWidget();
2069 r &= QRegion(ox, oy, w->width(), w->height());
2070
2071 int i = 0;
2072 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
2073 ;
2074 for ( ; i < w->d_func()->children.size(); ++i) {
2075 if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
2076 if(sibling->isVisible() && !sibling->isWindow()) {
2077 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
2078 sibling->width(), sibling->height());
2079 if (qRectIntersects(siblingRect, q->rect()))
2080 r -= QRegion(siblingRect);
2081 }
2082 }
2083 }
2084 }
2085 return r;
2086}
2087
2088void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
2089{
2090// Transform the system clip region from device-independent pixels to device pixels
2091 QTransform scaleTransform;
2092 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
2093
2094 paintEngine->d_func()->baseSystemClip = region;
2095 paintEngine->d_func()->setSystemTransform(scaleTransform);
2096
2097}
2098
2099#if QT_CONFIG(graphicseffect)
2100void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
2101{
2102 Q_Q(QWidget);
2103 QWidget *w = q;
2104 do {
2105 if (w->graphicsEffect()) {
2106 QWidgetEffectSourcePrivate *sourced =
2107 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
2108 if (!sourced->updateDueToGraphicsEffect)
2109 w->graphicsEffect()->source()->d_func()->invalidateCache();
2110 }
2111 w = w->parentWidget();
2112 } while (w);
2113}
2114#endif // QT_CONFIG(graphicseffect)
2115
2116void QWidgetPrivate::setDirtyOpaqueRegion()
2117{
2118 Q_Q(QWidget);
2119
2120 dirtyOpaqueChildren = true;
2121
2122#if QT_CONFIG(graphicseffect)
2123 invalidateGraphicsEffectsRecursively();
2124#endif // QT_CONFIG(graphicseffect)
2125
2126 if (q->isWindow())
2127 return;
2128
2129 QWidget *parent = q->parentWidget();
2130 if (!parent)
2131 return;
2132
2133 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2134 QWidgetPrivate *pd = parent->d_func();
2135 if (!pd->dirtyOpaqueChildren)
2136 pd->setDirtyOpaqueRegion();
2137}
2138
2139const QRegion &QWidgetPrivate::getOpaqueChildren() const
2140{
2141 if (!dirtyOpaqueChildren)
2142 return opaqueChildren;
2143
2144 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2145 that->opaqueChildren = QRegion();
2146
2147 for (int i = 0; i < children.size(); ++i) {
2148 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2149 if (!child || !child->isVisible() || child->isWindow())
2150 continue;
2151
2152 const QPoint offset = child->geometry().topLeft();
2153 QWidgetPrivate *childd = child->d_func();
2154 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2155 if (childd->extra && childd->extra->hasMask)
2156 r &= childd->extra->mask;
2157 if (r.isEmpty())
2158 continue;
2159 r.translate(offset);
2160 that->opaqueChildren += r;
2161 }
2162
2163 that->opaqueChildren &= q_func()->rect();
2164 that->dirtyOpaqueChildren = false;
2165
2166 return that->opaqueChildren;
2167}
2168
2169void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2170{
2171 if (children.isEmpty() || clipRect.isEmpty())
2172 return;
2173
2174 const QRegion &r = getOpaqueChildren();
2175 if (!r.isEmpty())
2176 source -= (r & clipRect);
2177}
2178
2179//subtract any relatives that are higher up than me --- this is too expensive !!!
2180void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2181 bool alsoNonOpaque) const
2182{
2183 Q_Q(const QWidget);
2184 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2185 if (disableSubtractOpaqueSiblings || q->isWindow())
2186 return;
2187
2188#if 0 // Used to be included in Qt4 for Q_WS_MAC
2189 if (q->d_func()->isInUnifiedToolbar)
2190 return;
2191#endif
2192
2193 QRect clipBoundingRect;
2194 bool dirtyClipBoundingRect = true;
2195
2196 QRegion parentClip;
2197 bool dirtyParentClip = true;
2198
2199 QPoint parentOffset = data.crect.topLeft();
2200
2201 const QWidget *w = q;
2202
2203 while (w) {
2204 if (w->isWindow())
2205 break;
2206 QWidgetPrivate *pd = w->parentWidget()->d_func();
2207 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2208 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2209 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2210 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2211 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2212 continue;
2213
2214 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2215 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2216 continue;
2217
2218 if (dirtyClipBoundingRect) {
2219 clipBoundingRect = sourceRegion.boundingRect();
2220 dirtyClipBoundingRect = false;
2221 }
2222
2223 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2224 continue;
2225
2226 if (dirtyParentClip) {
2227 parentClip = sourceRegion.translated(parentOffset);
2228 dirtyParentClip = false;
2229 }
2230
2231 const QPoint siblingPos(sibling->data->crect.topLeft());
2232 const QRect siblingClipRect(sibling->d_func()->clipRect());
2233 QRegion siblingDirty(parentClip);
2234 siblingDirty &= (siblingClipRect.translated(siblingPos));
2235 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2236 && !sibling->d_func()->graphicsEffect;
2237 if (hasMask)
2238 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2239 if (siblingDirty.isEmpty())
2240 continue;
2241
2242 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2243 if (hasMask) {
2244 siblingDirty.translate(-parentOffset);
2245 sourceRegion -= siblingDirty;
2246 } else {
2247 sourceRegion -= siblingGeometry.translated(-parentOffset);
2248 }
2249 } else {
2250 if (hasDirtySiblingsAbove)
2251 *hasDirtySiblingsAbove = true;
2252 if (sibling->d_func()->children.isEmpty())
2253 continue;
2254 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2255 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2256 sourceRegion -= opaqueSiblingChildren;
2257 }
2258 if (sourceRegion.isEmpty())
2259 return;
2260
2261 dirtyClipBoundingRect = true;
2262 dirtyParentClip = true;
2263 }
2264
2265 w = w->parentWidget();
2266 parentOffset += pd->data.crect.topLeft();
2267 dirtyParentClip = true;
2268 }
2269}
2270
2271void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2272{
2273 Q_Q(const QWidget);
2274
2275 const QWidget *w = q;
2276 QPoint offset;
2277
2278#if QT_CONFIG(graphicseffect)
2279 if (graphicsEffect) {
2280 w = q->parentWidget();
2281 offset -= data.crect.topLeft();
2282 }
2283#endif // QT_CONFIG(graphicseffect)
2284
2285 while (w) {
2286 const QWidgetPrivate *wd = w->d_func();
2287 if (wd->extra && wd->extra->hasMask)
2288 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2289 if (w->isWindow())
2290 return;
2291 offset -= wd->data.crect.topLeft();
2292 w = w->parentWidget();
2293 }
2294}
2295
2296bool QWidgetPrivate::paintOnScreen() const
2297{
2298#if defined(QT_NO_BACKINGSTORE)
2299 return true;
2300#else
2301 Q_Q(const QWidget);
2302 if (q->testAttribute(Qt::WA_PaintOnScreen)
2303 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2304 return true;
2305 }
2306
2307 return false;
2308#endif
2309}
2310
2311void QWidgetPrivate::updateIsOpaque()
2312{
2313 // hw: todo: only needed if opacity actually changed
2314 setDirtyOpaqueRegion();
2315
2316#if QT_CONFIG(graphicseffect)
2317 if (graphicsEffect) {
2318 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2319 setOpaque(false);
2320 return;
2321 }
2322#endif // QT_CONFIG(graphicseffect)
2323
2324 Q_Q(QWidget);
2325#if 0 // Used to be included in Qt4 for Q_WS_X11
2326 if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
2327 setOpaque(false);
2328 return;
2329 }
2330#endif
2331
2332 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2333 setOpaque(true);
2334 return;
2335 }
2336
2337 const QPalette &pal = q->palette();
2338
2339 if (q->autoFillBackground()) {
2340 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2341 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2342 setOpaque(true);
2343 return;
2344 }
2345 }
2346
2347 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2348 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2349 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2350 setOpaque(true);
2351 return;
2352 }
2353 }
2354 setOpaque(false);
2355}
2356
2357void QWidgetPrivate::setOpaque(bool opaque)
2358{
2359 if (isOpaque != opaque) {
2360 isOpaque = opaque;
2361 updateIsTranslucent();
2362 }
2363}
2364
2365void QWidgetPrivate::updateIsTranslucent()
2366{
2367 Q_Q(QWidget);
2368 if (QWindow *window = q->windowHandle()) {
2369 QSurfaceFormat format = window->format();
2370 const int oldAlpha = format.alphaBufferSize();
2371 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2372 if (oldAlpha != newAlpha) {
2373 format.setAlphaBufferSize(newAlpha);
2374 window->setFormat(format);
2375 }
2376 }
2377}
2378
2379static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2380{
2381 Q_ASSERT(painter);
2382
2383 if (brush.style() == Qt::TexturePattern) {
2384#if 0 // Used to be included in Qt4 for Q_WS_MAC
2385 // Optimize pattern filling on mac by using HITheme directly
2386 // when filling with the standard widget background.
2387 // Defined in qmacstyle_mac.cpp
2388 extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
2389 qt_mac_fill_background(painter, rgn, brush);
2390#else
2391 {
2392 const QRect rect(rgn.boundingRect());
2393 painter->setClipRegion(rgn);
2394 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2395 }
2396#endif
2397
2398 } else if (brush.gradient()
2399 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2400 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2401 painter->save();
2402 painter->setClipRegion(rgn);
2403 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2404 painter->restore();
2405 } else {
2406 for (const QRect &rect : rgn)
2407 painter->fillRect(rect, brush);
2408 }
2409}
2410
2411bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2412{
2413#if QT_CONFIG(scrollarea)
2414 Q_Q(const QWidget);
2415 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2416 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2417 return false;
2418 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2419 if (scrollArea && scrollArea->viewport() == q) {
2420 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2421 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2422 painter->setBrushOrigin(-priv->contentsOffset());
2423 }
2424#endif // QT_CONFIG(scrollarea)
2425 return true;
2426}
2427
2428void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
2429{
2430 Q_Q(const QWidget);
2431
2432 bool brushOriginSet = false;
2433 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2434
2435 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2436 const QBrush bg = q->palette().brush(QPalette::Window);
2437 if (!brushOriginSet)
2438 brushOriginSet = updateBrushOrigin(painter, bg);
2439 if (!(flags & DontSetCompositionMode)) {
2440 //copy alpha straight in
2441 QPainter::CompositionMode oldMode = painter->compositionMode();
2442 painter->setCompositionMode(QPainter::CompositionMode_Source);
2443 fillRegion(painter, rgn, bg);
2444 painter->setCompositionMode(oldMode);
2445 } else {
2446 fillRegion(painter, rgn, bg);
2447 }
2448 }
2449
2450 if (q->autoFillBackground()) {
2451 if (!brushOriginSet)
2452 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2453 fillRegion(painter, rgn, autoFillBrush);
2454 }
2455
2456 if (q->testAttribute(Qt::WA_StyledBackground)) {
2457 painter->setClipRegion(rgn);
2458 QStyleOption opt;
2459 opt.initFrom(q);
2460 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2461 }
2462}
2463
2464/*
2465 \internal
2466 This function is called when a widget is hidden or destroyed.
2467 It resets some application global pointers that should only refer active,
2468 visible widgets.
2469*/
2470
2471#if 0 // Used to be included in Qt4 for Q_WS_MAC
2472 extern QPointer<QWidget> qt_button_down;
2473#else
2474 extern QWidget *qt_button_down;
2475#endif
2476
2477void QWidgetPrivate::deactivateWidgetCleanup()
2478{
2479 Q_Q(QWidget);
2480 // If this was the active application window, reset it
2481 if (QApplication::activeWindow() == q)
2482 QApplication::setActiveWindow(0);
2483 // If the is the active mouse press widget, reset it
2484 if (q == qt_button_down)
2485 qt_button_down = 0;
2486}
2487
2488
2489/*!
2490 Returns a pointer to the widget with window identifer/handle \a
2491 id.
2492
2493 The window identifier type depends on the underlying window
2494 system, see \c qwindowdefs.h for the actual definition. If there
2495 is no widget with this identifier, \nullptr is returned.
2496*/
2497
2498QWidget *QWidget::find(WId id)
2499{
2500 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2501}
2502
2503
2504
2505/*!
2506 \fn WId QWidget::internalWinId() const
2507 \internal
2508 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2509
2510*/
2511
2512/*!
2513 \fn WId QWidget::winId() const
2514
2515 Returns the window system identifier of the widget.
2516
2517 Portable in principle, but if you use it you are probably about to
2518 do something non-portable. Be careful.
2519
2520 If a widget is non-native (alien) and winId() is invoked on it, that widget
2521 will be provided a native handle.
2522
2523 This value may change at run-time. An event with type QEvent::WinIdChange
2524 will be sent to the widget following a change in window system identifier.
2525
2526 \sa find()
2527*/
2528WId QWidget::winId() const
2529{
2530 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
2531#ifdef ALIEN_DEBUG
2532 qDebug() << "QWidget::winId: creating native window for" << this;
2533#endif
2534 QWidget *that = const_cast<QWidget*>(this);
2535 that->setAttribute(Qt::WA_NativeWindow);
2536 that->d_func()->createWinId();
2537 return that->data->winid;
2538 }
2539 return data->winid;
2540}
2541
2542void QWidgetPrivate::createWinId()
2543{
2544 Q_Q(QWidget);
2545
2546#ifdef ALIEN_DEBUG
2547 qDebug() << "QWidgetPrivate::createWinId for" << q;
2548#endif
2549 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2550 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2551 if (!q->isWindow()) {
2552 QWidget *parent = q->parentWidget();
2553 QWidgetPrivate *pd = parent->d_func();
2554 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2555 parent->setAttribute(Qt::WA_NativeWindow);
2556 if (!parent->internalWinId()) {
2557 pd->createWinId();
2558 }
2559
2560 for (int i = 0; i < pd->children.size(); ++i) {
2561 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2562 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2563 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2564 w->create();
2565 }
2566 }
2567 } else {
2568 q->create();
2569 }
2570 }
2571}
2572
2573/*!
2574\internal
2575Ensures that the widget is set on the screen point is on. This is handy getting a correct
2576size hint before a resize in e.g QMenu and QToolTip
2577*/
2578
2579void QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2580{
2581 Q_Q(QWidget);
2582 if (!q->isWindow())
2583 return;
2584 // Find the screen for pos and make the widget undertand it is on that screen.
2585 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2586 QScreen *actualScreen = QGuiApplication::screenAt(pos);
2587 if (actualScreen && currentScreen != actualScreen) {
2588 if (!windowHandle()) // Try to create a window handle if not created.
2589 createWinId();
2590 if (windowHandle())
2591 windowHandle()->setScreen(actualScreen);
2592 }
2593}
2594
2595/*!
2596\internal
2597Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2598
2599*/
2600
2601void QWidget::createWinId()
2602{
2603 Q_D(QWidget);
2604#ifdef ALIEN_DEBUG
2605 qDebug() << "QWidget::createWinId" << this;
2606#endif
2607// qWarning("QWidget::createWinId is obsolete, please fix your code.");
2608 d->createWinId();
2609}
2610
2611/*!
2612 \since 4.4
2613
2614 Returns the effective window system identifier of the widget, i.e. the
2615 native parent's window system identifier.
2616
2617 If the widget is native, this function returns the native widget ID.
2618 Otherwise, the window ID of the first native parent widget, i.e., the
2619 top-level widget that contains this widget, is returned.
2620
2621 \note We recommend that you do not store this value as it is likely to
2622 change at run-time.
2623
2624 \sa nativeParentWidget()
2625*/
2626WId QWidget::effectiveWinId() const
2627{
2628 const WId id = internalWinId();
2629 if (id || !testAttribute(Qt::WA_WState_Created))
2630 return id;
2631 if (const QWidget *realParent = nativeParentWidget())
2632 return realParent->internalWinId();
2633 return 0;
2634}
2635
2636/*!
2637 If this is a native widget, return the associated QWindow.
2638 Otherwise return null.
2639
2640 Native widgets include toplevel widgets, QGLWidget, and child widgets
2641 on which winId() was called.
2642
2643 \since 5.0
2644
2645 \sa winId()
2646*/
2647QWindow *QWidget::windowHandle() const
2648{
2649 Q_D(const QWidget);
2650 return d->windowHandle();
2651}
2652
2653#ifndef QT_NO_STYLE_STYLESHEET
2654
2655/*!
2656 \property QWidget::styleSheet
2657 \brief the widget's style sheet
2658 \since 4.2
2659
2660 The style sheet contains a textual description of customizations to the
2661 widget's style, as described in the \l{Qt Style Sheets} document.
2662
2663 Since Qt 4.5, Qt style sheets fully supports \macos.
2664
2665 \warning Qt style sheets are currently not supported for custom QStyle
2666 subclasses. We plan to address this in some future release.
2667
2668 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2669*/
2670QString QWidget::styleSheet() const
2671{
2672 Q_D(const QWidget);
2673 if (!d->extra)
2674 return QString();
2675 return d->extra->styleSheet;
2676}
2677
2678void QWidget::setStyleSheet(const QString& styleSheet)
2679{
2680 Q_D(QWidget);
2681 if (data->in_destructor)
2682 return;
2683 d->createExtra();
2684
2685 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2686 d->extra->styleSheet = styleSheet;
2687 if (styleSheet.isEmpty()) { // stylesheet removed
2688 if (!proxy)
2689 return;
2690
2691 d->inheritStyle();
2692 return;
2693 }
2694
2695 if (proxy) { // style sheet update
2696 if (d->polished)
2697 proxy->repolish(this);
2698 return;
2699 }
2700
2701 if (testAttribute(Qt::WA_SetStyle)) {
2702 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2703 } else {
2704 d->setStyle_helper(new QStyleSheetStyle(0), true);
2705 }
2706}
2707
2708#endif // QT_NO_STYLE_STYLESHEET
2709
2710/*!
2711 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2712*/
2713
2714QStyle *QWidget::style() const
2715{
2716 Q_D(const QWidget);
2717
2718 if (d->extra && d->extra->style)
2719 return d->extra->style;
2720 return QApplication::style();
2721}
2722
2723/*!
2724 Sets the widget's GUI style to \a style. The ownership of the style
2725 object is not transferred.
2726
2727 If no style is set, the widget uses the application's style,
2728 QApplication::style() instead.
2729
2730 Setting a widget's style has no effect on existing or future child
2731 widgets.
2732
2733 \warning This function is particularly useful for demonstration
2734 purposes, where you want to show Qt's styling capabilities. Real
2735 applications should avoid it and use one consistent GUI style
2736 instead.
2737
2738 \warning Qt style sheets are currently not supported for custom QStyle
2739 subclasses. We plan to address this in some future release.
2740
2741 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2742*/
2743
2744void QWidget::setStyle(QStyle *style)
2745{
2746 Q_D(QWidget);
2747 setAttribute(Qt::WA_SetStyle, style != 0);
2748 d->createExtra();
2749#ifndef QT_NO_STYLE_STYLESHEET
2750 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2751 //if for some reason someone try to set a QStyleSheetStyle, ref it
2752 //(this may happen for exemple in QButtonDialogBox which propagates its style)
2753 styleSheetStyle->ref();
2754 d->setStyle_helper(style, false);
2755 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2756 // if we have an application stylesheet or have a proxy already, propagate
2757 d->setStyle_helper(new QStyleSheetStyle(style), true);
2758 } else
2759#endif
2760 d->setStyle_helper(style, false);
2761}
2762
2763void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2764{
2765 Q_Q(QWidget);
2766 QStyle *oldStyle = q->style();
2767
2768 createExtra();
2769
2770#ifndef QT_NO_STYLE_STYLESHEET
2771 QPointer<QStyle> origStyle = extra->style;
2772#endif
2773 extra->style = newStyle;
2774
2775 // repolish
2776 if (polished && q->windowType() != Qt::Desktop) {
2777 oldStyle->unpolish(q);
2778 q->style()->polish(q);
2779 }
2780
2781 if (propagate) {
2782 // We copy the list because the order may be modified
2783 const QObjectList childrenList = children;
2784 for (int i = 0; i < childrenList.size(); ++i) {
2785 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2786 if (c)
2787 c->d_func()->inheritStyle();
2788 }
2789 }
2790
2791#ifndef QT_NO_STYLE_STYLESHEET
2792 if (!qt_styleSheet(newStyle)) {
2793 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2794 cssStyle->clearWidgetFont(q);
2795 }
2796 }
2797#endif
2798
2799 QEvent e(QEvent::StyleChange);
2800 QApplication::sendEvent(q, &e);
2801
2802#ifndef QT_NO_STYLE_STYLESHEET
2803 // dereference the old stylesheet style
2804 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2805 proxy->deref();
2806#endif
2807}
2808
2809// Inherits style from the current parent and propagates it as necessary
2810void QWidgetPrivate::inheritStyle()
2811{
2812#ifndef QT_NO_STYLE_STYLESHEET
2813 Q_Q(QWidget);
2814
2815 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2816
2817 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2818
2819 if (!q->styleSheet().isEmpty()) {
2820 Q_ASSERT(proxy);
2821 proxy->repolish(q);
2822 return;
2823 }
2824
2825 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2826 QWidget *parent = q->parentWidget();
2827 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
2828 // If we have stylesheet on app or parent has stylesheet style, we need
2829 // to be running a proxy
2830 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2831 QStyle *newStyle = parentStyle;
2832 if (q->testAttribute(Qt::WA_SetStyle))
2833 newStyle = new QStyleSheetStyle(origStyle);
2834 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2835 newProxy->ref();
2836
2837 setStyle_helper(newStyle, true);
2838 return;
2839 }
2840
2841 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2842 // we just need our original style back
2843 if (origStyle == extraStyle) // is it any different?
2844 return;
2845
2846 // We could have inherited the proxy from our parent (which has a custom style)
2847 // In such a case we need to start following the application style (i.e revert
2848 // the propagation behavior of QStyleSheetStyle)
2849 if (!q->testAttribute(Qt::WA_SetStyle))
2850 origStyle = 0;
2851
2852 setStyle_helper(origStyle, true);
2853#endif // QT_NO_STYLE_STYLESHEET
2854}
2855
2856
2857/*!
2858 \fn bool QWidget::isWindow() const
2859
2860 Returns \c true if the widget is an independent window, otherwise
2861 returns \c false.
2862
2863 A window is a widget that isn't visually the child of any other
2864 widget and that usually has a frame and a
2865 \l{QWidget::setWindowTitle()}{window title}.
2866
2867 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2868 It will then be grouped with its parent and deleted when the
2869 parent is deleted, minimized when the parent is minimized etc. If
2870 supported by the window manager, it will also have a common
2871 taskbar entry with its parent.
2872
2873 QDialog and QMainWindow widgets are by default windows, even if a
2874 parent widget is specified in the constructor. This behavior is
2875 specified by the Qt::Window flag.
2876
2877 \sa window(), isModal(), parentWidget()
2878*/
2879
2880/*!
2881 \property QWidget::modal
2882 \brief whether the widget is a modal widget
2883
2884 This property only makes sense for windows. A modal widget
2885 prevents widgets in all other windows from getting any input.
2886
2887 By default, this property is \c false.
2888
2889 \sa isWindow(), windowModality, QDialog
2890*/
2891
2892/*!
2893 \property QWidget::windowModality
2894 \brief which windows are blocked by the modal widget
2895 \since 4.1
2896
2897 This property only makes sense for windows. A modal widget
2898 prevents widgets in other windows from getting input. The value of
2899 this property controls which windows are blocked when the widget
2900 is visible. Changing this property while the window is visible has
2901 no effect; you must hide() the widget first, then show() it again.
2902
2903 By default, this property is Qt::NonModal.
2904
2905 \sa isWindow(), QWidget::modal, QDialog
2906*/
2907
2908Qt::WindowModality QWidget::windowModality() const
2909{
2910 return static_cast<Qt::WindowModality>(data->window_modality);
2911}
2912
2913void QWidget::setWindowModality(Qt::WindowModality windowModality)
2914{
2915 data->window_modality = windowModality;
2916 // setModal_sys() will be called by setAttribute()
2917 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2918 setAttribute(Qt::WA_SetWindowModality, true);
2919}
2920
2921void QWidgetPrivate::setModal_sys()
2922{
2923 Q_Q(QWidget);
2924 if (q->windowHandle())
2925 q->windowHandle()->setModality(q->windowModality());
2926}
2927
2928/*!
2929 \fn bool QWidget::underMouse() const
2930
2931 Returns \c true if the widget is under the mouse cursor; otherwise
2932 returns \c false.
2933
2934 This value is not updated properly during drag and drop
2935 operations.
2936
2937 \sa enterEvent(), leaveEvent()
2938*/
2939
2940/*!
2941 \property QWidget::minimized
2942 \brief whether this widget is minimized (iconified)
2943
2944 This property is only relevant for windows.
2945
2946 By default, this property is \c false.
2947
2948 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2949*/
2950bool QWidget::isMinimized() const
2951{ return data->window_state & Qt::WindowMinimized; }
2952
2953/*!
2954 Shows the widget minimized, as an icon.
2955
2956 Calling this function only affects \l{isWindow()}{windows}.
2957
2958 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2959 isMinimized()
2960*/
2961void QWidget::showMinimized()
2962{
2963 bool isMin = isMinimized();
2964 if (isMin && isVisible())
2965 return;
2966
2967 ensurePolished();
2968
2969 if (!isMin)
2970 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2971 setVisible(true);
2972}
2973
2974/*!
2975 \property QWidget::maximized
2976 \brief whether this widget is maximized
2977
2978 This property is only relevant for windows.
2979
2980 \note Due to limitations on some window systems, this does not always
2981 report the expected results (e.g., if the user on X11 maximizes the
2982 window via the window manager, Qt has no way of distinguishing this
2983 from any other resize). This is expected to improve as window manager
2984 protocols evolve.
2985
2986 By default, this property is \c false.
2987
2988 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2989*/
2990bool QWidget::isMaximized() const
2991{ return data->window_state & Qt::WindowMaximized; }
2992
2993
2994
2995/*!
2996 Returns the current window state. The window state is a OR'ed
2997 combination of Qt::WindowState: Qt::WindowMinimized,
2998 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2999
3000 \sa Qt::WindowState, setWindowState()
3001 */
3002Qt::WindowStates QWidget::windowState() const
3003{
3004 return Qt::WindowStates(data->window_state);
3005}
3006
3007/*!\internal
3008
3009 The function sets the window state on child widgets similar to
3010 setWindowState(). The difference is that the window state changed
3011 event has the isOverride() flag set. It exists mainly to keep
3012 QWorkspace working.
3013 */
3014void QWidget::overrideWindowState(Qt::WindowStates newstate)
3015{
3016 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
3017 data->window_state = newstate;
3018 QApplication::sendEvent(this, &e);
3019}
3020
3021/*!
3022 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
3023
3024 Sets the window state to \a windowState. The window state is a OR'ed
3025 combination of Qt::WindowState: Qt::WindowMinimized,
3026 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
3027
3028 If the window is not visible (i.e. isVisible() returns \c false), the
3029 window state will take effect when show() is called. For visible
3030 windows, the change is immediate. For example, to toggle between
3031 full-screen and normal mode, use the following code:
3032
3033 \snippet code/src_gui_kernel_qwidget.cpp 0
3034
3035 In order to restore and activate a minimized window (while
3036 preserving its maximized and/or full-screen state), use the following:
3037
3038 \snippet code/src_gui_kernel_qwidget.cpp 1
3039
3040 Calling this function will hide the widget. You must call show() to make
3041 the widget visible again.
3042
3043 \note On some window systems Qt::WindowActive is not immediate, and may be
3044 ignored in certain cases.
3045
3046 When the window state changes, the widget receives a changeEvent()
3047 of type QEvent::WindowStateChange.
3048
3049 \sa Qt::WindowState, windowState()
3050*/
3051void QWidget::setWindowState(Qt::WindowStates newstate)
3052{
3053 Q_D(QWidget);
3054 Qt::WindowStates oldstate = windowState();
3055 if (oldstate == newstate)
3056 return;
3057 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
3058 create();
3059
3060 data->window_state = newstate;
3061 data->in_set_window_state = 1;
3062 if (isWindow()) {
3063 // Ensure the initial size is valid, since we store it as normalGeometry below.
3064 if (!testAttribute(Qt::WA_Resized) && !isVisible())
3065 adjustSize();
3066
3067 d->createTLExtra();
3068 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3069 d->topData()->normalGeometry = geometry();
3070
3071 Q_ASSERT(windowHandle());
3072 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3073 }
3074 data->in_set_window_state = 0;
3075
3076 if (newstate & Qt::WindowActive)
3077 activateWindow();
3078
3079 QWindowStateChangeEvent e(oldstate);
3080 QApplication::sendEvent(this, &e);
3081}
3082
3083/*!
3084 \property QWidget::fullScreen
3085 \brief whether the widget is shown in full screen mode
3086
3087 A widget in full screen mode occupies the whole screen area and does not
3088 display window decorations, such as a title bar.
3089
3090 By default, this property is \c false.
3091
3092 \sa windowState(), minimized, maximized
3093*/
3094bool QWidget::isFullScreen() const
3095{ return data->window_state & Qt::WindowFullScreen; }
3096
3097/*!
3098 Shows the widget in full-screen mode.
3099
3100 Calling this function only affects \l{isWindow()}{windows}.
3101
3102 To return from full-screen mode, call showNormal().
3103
3104 Full-screen mode works fine under Windows, but has certain
3105 problems under X. These problems are due to limitations of the
3106 ICCCM protocol that specifies the communication between X11
3107 clients and the window manager. ICCCM simply does not understand
3108 the concept of non-decorated full-screen windows. Therefore, the
3109 best we can do is to request a borderless window and place and
3110 resize it to fill the entire screen. Depending on the window
3111 manager, this may or may not work. The borderless window is
3112 requested using MOTIF hints, which are at least partially
3113 supported by virtually all modern window managers.
3114
3115 An alternative would be to bypass the window manager entirely and
3116 create a window with the Qt::X11BypassWindowManagerHint flag. This
3117 has other severe problems though, like totally broken keyboard focus
3118 and very strange effects on desktop changes or when the user raises
3119 other windows.
3120
3121 X11 window managers that follow modern post-ICCCM specifications
3122 support full-screen mode properly.
3123
3124 \sa showNormal(), showMaximized(), show(), hide(), isVisible()
3125*/
3126void QWidget::showFullScreen()
3127{
3128#if 0 // Used to be included in Qt4 for Q_WS_MAC
3129 // If the unified toolbar is enabled, we have to disable it before going fullscreen.
3130 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3131 if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) {
3132 mainWindow->setUnifiedTitleAndToolBarOnMac(false);
3133 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3134 mainLayout->activateUnifiedToolbarAfterFullScreen = true;
3135 }
3136#endif
3137 ensurePolished();
3138
3139 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3140 | Qt::WindowFullScreen);
3141 setVisible(true);
3142#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3143 // activating it here before libscreen activates it causes problems
3144 activateWindow();
3145#endif
3146}
3147
3148/*!
3149 Shows the widget maximized.
3150
3151 Calling this function only affects \l{isWindow()}{windows}.
3152
3153 On X11, this function may not work properly with certain window
3154 managers. See the \l{Window Geometry} documentation for an explanation.
3155
3156 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3157*/
3158void QWidget::showMaximized()
3159{
3160 ensurePolished();
3161
3162 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3163 | Qt::WindowMaximized);
3164#if 0 // Used to be included in Qt4 for Q_WS_MAC
3165 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3166 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3167 if (mainWindow)
3168 {
3169 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3170 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3171 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3172 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3173 }
3174 }
3175#endif
3176 setVisible(true);
3177}
3178
3179/*!
3180 Restores the widget after it has been maximized or minimized.
3181
3182 Calling this function only affects \l{isWindow()}{windows}.
3183
3184 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3185*/
3186void QWidget::showNormal()
3187{
3188 ensurePolished();
3189
3190 setWindowState(windowState() & ~(Qt::WindowMinimized
3191 | Qt::WindowMaximized
3192 | Qt::WindowFullScreen));
3193#if 0 // Used to be included in Qt4 for Q_WS_MAC
3194 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3195 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3196 if (mainWindow)
3197 {
3198 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3199 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3200 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3201 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3202 }
3203 }
3204#endif
3205 setVisible(true);
3206}
3207
3208/*!
3209 Returns \c true if this widget would become enabled if \a ancestor is
3210 enabled; otherwise returns \c false.
3211
3212
3213
3214 This is the case if neither the widget itself nor every parent up
3215 to but excluding \a ancestor has been explicitly disabled.
3216
3217 isEnabledTo(0) returns false if this widget or any if its ancestors
3218 was explicitly disabled.
3219
3220 The word ancestor here means a parent widget within the same window.
3221
3222 Therefore isEnabledTo(0) stops at this widget's window, unlike
3223 isEnabled() which also takes parent windows into considerations.
3224
3225 \sa setEnabled(), enabled
3226*/
3227
3228bool QWidget::isEnabledTo(const QWidget *ancestor) const
3229{
3230 const QWidget * w = this;
3231 while (!w->testAttribute(Qt::WA_ForceDisabled)
3232 && !w->isWindow()
3233 && w->parentWidget()
3234 && w->parentWidget() != ancestor)
3235 w = w->parentWidget();
3236 return !w->testAttribute(Qt::WA_ForceDisabled);
3237}
3238
3239#ifndef QT_NO_ACTION
3240/*!
3241 Appends the action \a action to this widget's list of actions.
3242
3243 All QWidgets have a list of \l{QAction}s, however they can be
3244 represented graphically in many different ways. The default use of
3245 the QAction list (as returned by actions()) is to create a context
3246 QMenu.
3247
3248 A QWidget should only have one of each action and adding an action
3249 it already has will not cause the same action to be in the widget twice.
3250
3251 The ownership of \a action is not transferred to this QWidget.
3252
3253 \sa removeAction(), insertAction(), actions(), QMenu
3254*/
3255void QWidget::addAction(QAction *action)
3256{
3257 insertAction(0, action);
3258}
3259
3260/*!
3261 Appends the actions \a actions to this widget's list of actions.
3262
3263 \sa removeAction(), QMenu, addAction()
3264*/
3265#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3266void QWidget::addActions(const QList<QAction *> &actions)
3267#else
3268void QWidget::addActions(QList<QAction*> actions)
3269#endif
3270{
3271 for(int i = 0; i < actions.count(); i++)
3272 insertAction(0, actions.at(i));
3273}
3274
3275/*!
3276 Inserts the action \a action to this widget's list of actions,
3277 before the action \a before. It appends the action if \a before is \nullptr or
3278 \a before is not a valid action for this widget.
3279
3280 A QWidget should only have one of each action.
3281
3282 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3283*/
3284void QWidget::insertAction(QAction *before, QAction *action)
3285{
3286 if (Q_UNLIKELY(!action)) {
3287 qWarning("QWidget::insertAction: Attempt to insert null action");
3288 return;
3289 }
3290
3291 Q_D(QWidget);
3292 if(d->actions.contains(action))
3293 removeAction(action);
3294
3295 int pos = d->actions.indexOf(before);
3296 if (pos < 0) {
3297 before = 0;
3298 pos = d->actions.size();
3299 }
3300 d->actions.insert(pos, action);
3301
3302 QActionPrivate *apriv = action->d_func();
3303 apriv->widgets.append(this);
3304
3305 QActionEvent e(QEvent::ActionAdded, action, before);
3306 QApplication::sendEvent(this, &e);
3307}
3308
3309/*!
3310 Inserts the actions \a actions to this widget's list of actions,
3311 before the action \a before. It appends the action if \a before is \nullptr or
3312 \a before is not a valid action for this widget.
3313
3314 A QWidget can have at most one of each action.
3315
3316 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3317*/
3318#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3319void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3320#else
3321void QWidget::insertActions(QAction *before, QList<QAction*> actions)
3322#endif
3323{
3324 for(int i = 0; i < actions.count(); ++i)
3325 insertAction(before, actions.at(i));
3326}
3327
3328/*!
3329 Removes the action \a action from this widget's list of actions.
3330 \sa insertAction(), actions(), insertAction()
3331*/
3332void QWidget::removeAction(QAction *action)
3333{
3334 if (!action)
3335 return;
3336
3337 Q_D(QWidget);
3338
3339 QActionPrivate *apriv = action->d_func();
3340 apriv->widgets.removeAll(this);
3341
3342 if (d->actions.removeAll(action)) {
3343 QActionEvent e(QEvent::ActionRemoved, action);
3344 QApplication::sendEvent(this, &e);
3345 }
3346}
3347
3348/*!
3349 Returns the (possibly empty) list of this widget's actions.
3350
3351 \sa contextMenuPolicy, insertAction(), removeAction()
3352*/
3353QList<QAction*> QWidget::actions() const
3354{
3355 Q_D(const QWidget);
3356 return d->actions;
3357}
3358#endif // QT_NO_ACTION
3359
3360/*!
3361 \fn bool QWidget::isEnabledToTLW() const
3362 \obsolete
3363
3364 This function is deprecated. It is equivalent to isEnabled()
3365*/
3366
3367/*!
3368 \property QWidget::enabled
3369 \brief whether the widget is enabled
3370
3371 In general an enabled widget handles keyboard and mouse events; a disabled
3372 widget does not. An exception is made with \l{QAbstractButton}.
3373
3374 Some widgets display themselves differently when they are
3375 disabled. For example a button might draw its label grayed out. If
3376 your widget needs to know when it becomes enabled or disabled, you
3377 can use the changeEvent() with type QEvent::EnabledChange.
3378
3379 Disabling a widget implicitly disables all its children. Enabling
3380 respectively enables all child widgets unless they have been
3381 explicitly disabled. It it not possible to explicitly enable a child
3382 widget which is not a window while its parent widget remains disabled.
3383
3384 By default, this property is \c true.
3385
3386 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3387*/
3388void QWidget::setEnabled(bool enable)
3389{
3390 Q_D(QWidget);
3391 setAttribute(Qt::WA_ForceDisabled, !enable);
3392 d->setEnabled_helper(enable);
3393}
3394
3395void QWidgetPrivate::setEnabled_helper(bool enable)
3396{
3397 Q_Q(QWidget);
3398
3399 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3400 return; // nothing we can do
3401
3402 if (enable != q->testAttribute(Qt::WA_Disabled))
3403 return; // nothing to do
3404
3405 q->setAttribute(Qt::WA_Disabled, !enable);
3406 updateSystemBackground();
3407
3408 if (!enable && q->window()->focusWidget() == q) {
3409 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3410 if (!parentIsEnabled || !q->focusNextChild())
3411 q->clearFocus();
3412 }
3413
3414 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3415 for (int i = 0; i < children.size(); ++i) {
3416 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3417 if (w && !w->testAttribute(attribute))
3418 w->d_func()->setEnabled_helper(enable);
3419 }
3420#if 0 // Used to be included in Qt4 for Q_WS_X11
3421 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3422 // enforce the windows behavior of clearing the cursor on
3423 // disabled widgets
3424 qt_x11_enforce_cursor(q);
3425 }
3426#endif
3427#ifndef QT_NO_CURSOR
3428 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3429 // enforce the windows behavior of clearing the cursor on
3430 // disabled widgets
3431 qt_qpa_set_cursor(q, false);
3432 }
3433#endif
3434#if 0 // Used to be included in Qt4 for Q_WS_MAC
3435 setEnabled_helper_sys(enable);
3436#endif
3437#ifndef QT_NO_IM
3438 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3439 QWidget *focusWidget = effectiveFocusWidget();
3440
3441 if (enable) {
3442 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3443 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3444 } else {
3445 QGuiApplication::inputMethod()->commit();
3446 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3447 }
3448 }
3449#endif //QT_NO_IM
3450 QEvent e(QEvent::EnabledChange);
3451 QApplication::sendEvent(q, &e);
3452}
3453
3454/*!
3455 \property QWidget::acceptDrops
3456 \brief whether drop events are enabled for this widget
3457
3458 Setting this property to true announces to the system that this
3459 widget \e may be able to accept drop events.
3460
3461 If the widget is the desktop (windowType() == Qt::Desktop), this may
3462 fail if another application is using the desktop; you can call
3463 acceptDrops() to test if this occurs.
3464
3465 \warning Do not modify this property in a drag and drop event handler.
3466
3467 By default, this property is \c false.
3468
3469 \sa {Drag and Drop}
3470*/
3471bool QWidget::acceptDrops() const
3472{
3473 return testAttribute(Qt::WA_AcceptDrops);
3474}
3475
3476void QWidget::setAcceptDrops(bool on)
3477{
3478 setAttribute(Qt::WA_AcceptDrops, on);
3479
3480}
3481
3482/*!
3483 Disables widget input events if \a disable is true; otherwise
3484 enables input events.
3485
3486 See the \l enabled documentation for more information.
3487
3488 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3489*/
3490void QWidget::setDisabled(bool disable)
3491{
3492 setEnabled(!disable);
3493}
3494
3495/*!
3496 \property QWidget::frameGeometry
3497 \brief geometry of the widget relative to its parent including any
3498 window frame
3499
3500 See the \l{Window Geometry} documentation for an overview of geometry
3501 issues with windows.
3502
3503 By default, this property contains a value that depends on the user's
3504 platform and screen geometry.
3505
3506 \sa geometry(), x(), y(), pos()
3507*/
3508QRect QWidget::frameGeometry() const
3509{
3510 Q_D(const QWidget);
3511 if (isWindow() && ! (windowType() == Qt::Popup)) {
3512 QRect fs = d->frameStrut();
3513 return QRect(data->crect.x() - fs.left(),
3514 data->crect.y() - fs.top(),
3515 data->crect.width() + fs.left() + fs.right(),
3516 data->crect.height() + fs.top() + fs.bottom());
3517 }
3518 return data->crect;
3519}
3520
3521/*!
3522 \property QWidget::x
3523
3524 \brief the x coordinate of the widget relative to its parent including
3525 any window frame
3526
3527 See the \l{Window Geometry} documentation for an overview of geometry
3528 issues with windows.
3529
3530 By default, this property has a value of 0.
3531
3532 \sa frameGeometry, y, pos
3533*/
3534int QWidget::x() const
3535{
3536 Q_D(const QWidget);
3537 if (isWindow() && ! (windowType() == Qt::Popup))
3538 return data->crect.x() - d->frameStrut().left();
3539 return data->crect.x();
3540}
3541
3542/*!
3543 \property QWidget::y
3544 \brief the y coordinate of the widget relative to its parent and
3545 including any window frame
3546
3547 See the \l{Window Geometry} documentation for an overview of geometry
3548 issues with windows.
3549
3550 By default, this property has a value of 0.
3551
3552 \sa frameGeometry, x, pos
3553*/
3554int QWidget::y() const
3555{
3556 Q_D(const QWidget);
3557 if (isWindow() && ! (windowType() == Qt::Popup))
3558 return data->crect.y() - d->frameStrut().top();
3559 return data->crect.y();
3560}
3561
3562/*!
3563 \property QWidget::pos
3564 \brief the position of the widget within its parent widget
3565
3566 If the widget is a window, the position is that of the widget on
3567 the desktop, including its frame.
3568
3569 When changing the position, the widget, if visible, receives a
3570 move event (moveEvent()) immediately. If the widget is not
3571 currently visible, it is guaranteed to receive an event before it
3572 is shown.
3573
3574 By default, this property contains a position that refers to the
3575 origin.
3576
3577 \warning Calling move() or setGeometry() inside moveEvent() can
3578 lead to infinite recursion.
3579
3580 See the \l{Window Geometry} documentation for an overview of geometry
3581 issues with windows.
3582
3583 \sa frameGeometry, size, x(), y()
3584*/
3585QPoint QWidget::pos() const
3586{
3587 Q_D(const QWidget);
3588 QPoint result = data->crect.topLeft();
3589 if (isWindow() && ! (windowType() == Qt::Popup))
3590 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3591 result -= d->frameStrut().topLeft();
3592 return result;
3593}
3594
3595/*!
3596 \property QWidget::geometry
3597 \brief the geometry of the widget relative to its parent and
3598 excluding the window frame
3599
3600 When changing the geometry, the widget, if visible, receives a
3601 move event (moveEvent()) and/or a resize event (resizeEvent())
3602 immediately. If the widget is not currently visible, it is
3603 guaranteed to receive appropriate events before it is shown.
3604
3605 The size component is adjusted if it lies outside the range
3606 defined by minimumSize() and maximumSize().
3607
3608 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3609 can lead to infinite recursion.
3610
3611 See the \l{Window Geometry} documentation for an overview of geometry
3612 issues with windows.
3613
3614 By default, this property contains a value that depends on the user's
3615 platform and screen geometry.
3616
3617 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3618 resizeEvent(), minimumSize(), maximumSize()
3619*/
3620
3621/*!
3622 \property QWidget::normalGeometry
3623
3624 \brief the geometry of the widget as it will appear when shown as
3625 a normal (not maximized or full screen) top-level widget
3626
3627 For child widgets this property always holds an empty rectangle.
3628
3629 By default, this property contains an empty rectangle.
3630
3631 \sa QWidget::windowState(), QWidget::geometry
3632*/
3633
3634/*!
3635 \property QWidget::size
3636 \brief the size of the widget excluding any window frame
3637
3638 If the widget is visible when it is being resized, it receives a resize event
3639 (resizeEvent()) immediately. If the widget is not currently
3640 visible, it is guaranteed to receive an event before it is shown.
3641
3642 The size is adjusted if it lies outside the range defined by
3643 minimumSize() and maximumSize().
3644
3645 By default, this property contains a value that depends on the user's
3646 platform and screen geometry.
3647
3648 \warning Calling resize() or setGeometry() inside resizeEvent() can
3649 lead to infinite recursion.
3650
3651 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3652 appear on screen. This also applies to windows.
3653
3654 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3655*/
3656
3657/*!
3658 \property QWidget::width
3659 \brief the width of the widget excluding any window frame
3660
3661 See the \l{Window Geometry} documentation for an overview of geometry
3662 issues with windows.
3663
3664 \note Do not use this function to find the width of a screen on
3665 a \l{QDesktopWidget}{multiple screen desktop}. Read
3666 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3667
3668 By default, this property contains a value that depends on the user's
3669 platform and screen geometry.
3670
3671 \sa geometry, height, size
3672*/
3673
3674/*!
3675 \property QWidget::height
3676 \brief the height of the widget excluding any window frame
3677
3678 See the \l{Window Geometry} documentation for an overview of geometry
3679 issues with windows.
3680
3681 \note Do not use this function to find the height of a screen
3682 on a \l{QDesktopWidget}{multiple screen desktop}. Read
3683 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3684
3685 By default, this property contains a value that depends on the user's
3686 platform and screen geometry.
3687
3688 \sa geometry, width, size
3689*/
3690
3691/*!
3692 \property QWidget::rect
3693 \brief the internal geometry of the widget excluding any window
3694 frame
3695
3696 The rect property equals QRect(0, 0, width(), height()).
3697
3698 See the \l{Window Geometry} documentation for an overview of geometry
3699 issues with windows.
3700
3701 By default, this property contains a value that depends on the user's
3702 platform and screen geometry.
3703
3704 \sa size
3705*/
3706
3707
3708QRect QWidget::normalGeometry() const
3709{
3710 Q_D(const QWidget);
3711 if (!d->extra || !d->extra->topextra)
3712 return QRect();
3713
3714 if (!isMaximized() && !isFullScreen())
3715 return geometry();
3716
3717 return d->topData()->normalGeometry;
3718}
3719
3720
3721/*!
3722 \property QWidget::childrenRect
3723 \brief the bounding rectangle of the widget's children
3724
3725 Hidden children are excluded.
3726
3727 By default, for a widget with no children, this property contains a
3728 rectangle with zero width and height located at the origin.
3729
3730 \sa childrenRegion(), geometry()
3731*/
3732
3733QRect QWidget::childrenRect() const
3734{
3735 Q_D(const QWidget);
3736 QRect r(0, 0, 0, 0);
3737 for (int i = 0; i < d->children.size(); ++i) {
3738 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3739 if (w && !w->isWindow() && !w->isHidden())
3740 r |= w->geometry();
3741 }
3742 return r;
3743}
3744
3745/*!
3746 \property QWidget::childrenRegion
3747 \brief the combined region occupied by the widget's children
3748
3749 Hidden children are excluded.
3750
3751 By default, for a widget with no children, this property contains an
3752 empty region.
3753
3754 \sa childrenRect(), geometry(), mask()
3755*/
3756
3757QRegion QWidget::childrenRegion() const
3758{
3759 Q_D(const QWidget);
3760 QRegion r;
3761 for (int i = 0; i < d->children.size(); ++i) {
3762 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3763 if (w && !w->isWindow() && !w->isHidden()) {
3764 QRegion mask = w->mask();
3765 if (mask.isEmpty())
3766 r |= w->geometry();
3767 else
3768 r |= mask.translated(w->pos());
3769 }
3770 }
3771 return r;
3772}
3773
3774
3775/*!
3776 \property QWidget::minimumSize
3777 \brief the widget's minimum size
3778
3779 The widget cannot be resized to a smaller size than the minimum
3780 widget size. The widget's size is forced to the minimum size if
3781 the current size is smaller.
3782
3783 The minimum size set by this function will override the minimum size
3784 defined by QLayout. In order to unset the minimum size, use a
3785 value of \c{QSize(0, 0)}.
3786
3787 By default, this property contains a size with zero width and height.
3788
3789 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3790*/
3791
3792QSize QWidget::minimumSize() const
3793{
3794 Q_D(const QWidget);
3795 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3796}
3797
3798/*!
3799 \property QWidget::maximumSize
3800 \brief the widget's maximum size in pixels
3801
3802 The widget cannot be resized to a larger size than the maximum
3803 widget size.
3804
3805 By default, this property contains a size in which both width and height
3806 have values of 16777215.
3807
3808 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3809 of widgets.
3810
3811 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3812*/
3813
3814QSize QWidget::maximumSize() const
3815{
3816 Q_D(const QWidget);
3817 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3818 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3819}
3820
3821
3822/*!
3823 \property QWidget::minimumWidth
3824 \brief the widget's minimum width in pixels
3825
3826 This property corresponds to the width held by the \l minimumSize property.
3827
3828 By default, this property has a value of 0.
3829
3830 \sa minimumSize, minimumHeight
3831*/
3832
3833/*!
3834 \property QWidget::minimumHeight
3835 \brief the widget's minimum height in pixels
3836
3837 This property corresponds to the height held by the \l minimumSize property.
3838
3839 By default, this property has a value of 0.
3840
3841 \sa minimumSize, minimumWidth
3842*/
3843
3844/*!
3845 \property QWidget::maximumWidth
3846 \brief the widget's maximum width in pixels
3847
3848 This property corresponds to the width held by the \l maximumSize property.
3849
3850 By default, this property contains a value of 16777215.
3851
3852 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3853 of widgets.
3854
3855 \sa maximumSize, maximumHeight
3856*/
3857
3858/*!
3859 \property QWidget::maximumHeight
3860 \brief the widget's maximum height in pixels
3861
3862 This property corresponds to the height held by the \l maximumSize property.
3863
3864 By default, this property contains a value of 16777215.
3865
3866 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3867 of widgets.
3868
3869 \sa maximumSize, maximumWidth
3870*/
3871
3872/*!
3873 \property QWidget::sizeIncrement
3874 \brief the size increment of the widget
3875
3876 When the user resizes the window, the size will move in steps of
3877 sizeIncrement().width() pixels horizontally and
3878 sizeIncrement.height() pixels vertically, with baseSize() as the
3879 basis. Preferred widget sizes are for non-negative integers \e i
3880 and \e j:
3881 \snippet code/src_gui_kernel_qwidget.cpp 2
3882
3883 Note that while you can set the size increment for all widgets, it
3884 only affects windows.
3885
3886 By default, this property contains a size with zero width and height.
3887
3888 \warning The size increment has no effect under Windows, and may
3889 be disregarded by the window manager on X11.
3890
3891 \sa size, minimumSize, maximumSize
3892*/
3893QSize QWidget::sizeIncrement() const
3894{
3895 Q_D(const QWidget);
3896 return (d->extra && d->extra->topextra)
3897 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3898 : QSize(0, 0);
3899}
3900
3901/*!
3902 \property QWidget::baseSize
3903 \brief the base size of the widget
3904
3905 The base size is used to calculate a proper widget size if the
3906 widget defines sizeIncrement().
3907
3908 By default, for a newly-created widget, this property contains a size with
3909 zero width and height.
3910
3911 \sa setSizeIncrement()
3912*/
3913
3914QSize QWidget::baseSize() const
3915{
3916 Q_D(const QWidget);
3917 return (d->extra != 0 && d->extra->topextra != 0)
3918 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3919 : QSize(0, 0);
3920}
3921
3922bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3923{
3924 Q_Q(QWidget);
3925
3926 int mw = minw, mh = minh;
3927 if (mw == QWIDGETSIZE_MAX)
3928 mw = 0;
3929 if (mh == QWIDGETSIZE_MAX)
3930 mh = 0;
3931 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3932 qWarning("QWidget::setMinimumSize: (%s/%s) "
3933 "The largest allowed size is (%d,%d)",
3934 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3935 QWIDGETSIZE_MAX);
3936 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3937 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3938 }
3939 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3940 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3941 "are not possible",
3942 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3943 minw = mw = qMax(minw, 0);
3944 minh = mh = qMax(minh, 0);
3945 }
3946 createExtra();
3947 if (extra->minw == mw && extra->minh == mh)
3948 return false;
3949 extra->minw = mw;
3950 extra->minh = mh;
3951 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3952 return true;
3953}
3954
3955void QWidgetPrivate::setConstraints_sys()
3956{
3957 Q_Q(QWidget);
3958 if (extra && q->windowHandle()) {
3959 QWindow *win = q->windowHandle();
3960 QWindowPrivate *winp = qt_window_private(win);
3961
3962 winp->minimumSize = QSize(extra->minw, extra->minh);
3963 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3964
3965 if (extra->topextra) {
3966 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3967 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3968 }
3969
3970 if (winp->platformWindow) {
3971 fixPosIncludesFrame();
3972 winp->platformWindow->propagateSizeHints();
3973 }
3974 }
3975}
3976
3977/*!
3978 \overload
3979
3980 This function corresponds to setMinimumSize(QSize(minw, minh)).
3981 Sets the minimum width to \a minw and the minimum height to \a
3982 minh.
3983*/
3984
3985void QWidget::setMinimumSize(int minw, int minh)
3986{
3987 Q_D(QWidget);
3988 if (!d->setMinimumSize_helper(minw, minh))
3989 return;
3990
3991 if (isWindow())
3992 d->setConstraints_sys();
3993 if (minw > width() || minh > height()) {
3994 bool resized = testAttribute(Qt::WA_Resized);
3995 bool maximized = isMaximized();
3996 resize(qMax(minw,width()), qMax(minh,height()));
3997 setAttribute(Qt::WA_Resized, resized); //not a user resize
3998 if (maximized)
3999 data->window_state = data->window_state | Qt::WindowMaximized;
4000 }
4001#if QT_CONFIG(graphicsview)
4002 if (d->extra) {
4003 if (d->extra->proxyWidget)
4004 d->extra->proxyWidget->setMinimumSize(minw, minh);
4005 }
4006#endif
4007 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->