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