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