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#ifndef QT_NO_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 */ && !defined(QT_NO_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()) {
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 // force acceptDrops false before winId is destroyed.
1584 d->registerDropSite(false);
1585
1586#ifndef QT_NO_ACTION
1587 // remove all actions from this widget
1588 for (int i = 0; i < d->actions.size(); ++i) {
1589 QActionPrivate *apriv = d->actions.at(i)->d_func();
1590 apriv->widgets.removeAll(this);
1591 }
1592 d->actions.clear();
1593#endif
1594
1595#ifndef QT_NO_SHORTCUT
1596 // Remove all shortcuts grabbed by this
1597 // widget, unless application is closing
1598 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1599 qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence());
1600#endif
1601
1602 // delete layout while we still are a valid widget
1603 delete d->layout;
1604 d->layout = 0;
1605 // Remove myself from focus list
1606
1607 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1608 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1609
1610 if (d->focus_next != this) {
1611 d->focus_next->d_func()->focus_prev = d->focus_prev;
1612 d->focus_prev->d_func()->focus_next = d->focus_next;
1613 d->focus_next = d->focus_prev = 0;
1614 }
1615
1616
1617 QT_TRY {
1618#if QT_CONFIG(graphicsview)
1619 const QWidget* w = this;
1620 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1621 w = w->d_func()->extra->focus_proxy;
1622 QWidget *window = w->window();
1623 QWExtra *e = window ? window->d_func()->extra : 0;
1624 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1625#endif
1626 clearFocus();
1627 } QT_CATCH(...) {
1628 // swallow this problem because we are in a destructor
1629 }
1630
1631 d->setDirtyOpaqueRegion();
1632
1633 if (isWindow() && isVisible() && internalWinId()) {
1634 QT_TRY {
1635 d->close_helper(QWidgetPrivate::CloseNoEvent);
1636 } QT_CATCH(...) {
1637 // if we're out of memory, at least hide the window.
1638 QT_TRY {
1639 hide();
1640 } QT_CATCH(...) {
1641 // and if that also doesn't work, then give up
1642 }
1643 }
1644 }
1645
1646#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 */
1647 else if (!internalWinId() && isVisible()) {
1648 qApp->d_func()->sendSyntheticEnterLeave(this);
1649 }
1650#endif
1651 else if (isVisible()) {
1652 qApp->d_func()->sendSyntheticEnterLeave(this);
1653 }
1654
1655 if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
1656 bs->removeDirtyWidget(this);
1657 if (testAttribute(Qt::WA_StaticContents))
1658 bs->removeStaticWidget(this);
1659 }
1660
1661 delete d->needsFlush;
1662 d->needsFlush = 0;
1663
1664 // The next 20 lines are duplicated from QObject, but required here
1665 // since QWidget deletes is children itself
1666 bool blocked = d->blockSig;
1667 d->blockSig = 0; // unblock signals so we always emit destroyed()
1668
1669 if (d->isSignalConnected(0)) {
1670 QT_TRY {
1671 emit destroyed(this);
1672 } QT_CATCH(...) {
1673 // all the signal/slots connections are still in place - if we don't
1674 // quit now, we will crash pretty soon.
1675 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1676 QT_RETHROW;
1677 }
1678 }
1679
1680 d->wasDeleted = true;
1681 if (d->declarativeData) {
1682 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1683 if (QAbstractDeclarativeData::destroyed_qml1)
1684 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1685 } else {
1686 if (QAbstractDeclarativeData::destroyed)
1687 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1688 }
1689 d->declarativeData = 0; // don't activate again in ~QObject
1690 }
1691
1692 d->blockSig = blocked;
1693
1694#if 0 // Used to be included in Qt4 for Q_WS_MAC
1695 // QCocoaView holds a pointer back to this widget. Clear it now
1696 // to make sure it's not followed later on. The lifetime of the
1697 // QCocoaView might exceed the lifetime of this widget in cases
1698 // where Cocoa itself holds references to it.
1699 extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
1700 qt_mac_clearCocoaViewQWidgetPointers(this);
1701#endif
1702
1703 if (!d->children.isEmpty())
1704 d->deleteChildren();
1705
1706 QApplication::removePostedEvents(this);
1707
1708 QT_TRY {
1709 destroy(); // platform-dependent cleanup
1710 } QT_CATCH(...) {
1711 // if this fails we can't do anything about it but at least we are not allowed to throw.
1712 }
1713 --QWidgetPrivate::instanceCounter;
1714
1715 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1716 QWidgetPrivate::allWidgets->remove(this);
1717
1718 QT_TRY {
1719 QEvent e(QEvent::Destroy);
1720 QCoreApplication::sendEvent(this, &e);
1721 } QT_CATCH(const std::exception&) {
1722 // if this fails we can't do anything about it but at least we are not allowed to throw.
1723 }
1724
1725#if QT_CONFIG(graphicseffect)
1726 delete d->graphicsEffect;
1727#endif
1728}
1729
1730int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1731int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1732
1733void QWidgetPrivate::setWinId(WId id) // set widget identifier
1734{
1735 Q_Q(QWidget);
1736 // the user might create a widget with Qt::Desktop window
1737 // attribute (or create another QDesktopWidget instance), which
1738 // will have the same windowid (the root window id) as the
1739 // qt_desktopWidget. We should not add the second desktop widget
1740 // to the mapper.
1741 bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
1742 if (mapper && data.winid && !userDesktopWidget) {
1743 mapper->remove(data.winid);
1744 }
1745
1746 const WId oldWinId = data.winid;
1747
1748 data.winid = id;
1749#if 0 // Used to be included in Qt4 for Q_WS_X11
1750 hd = id; // X11: hd == ident
1751#endif
1752 if (mapper && id && !userDesktopWidget) {
1753 mapper->insert(data.winid, q);
1754 }
1755
1756 if(oldWinId != id) {
1757 QEvent e(QEvent::WinIdChange);
1758 QCoreApplication::sendEvent(q, &e);
1759 }
1760}
1761
1762void QWidgetPrivate::createTLExtra()
1763{
1764 if (!extra)
1765 createExtra();
1766 if (!extra->topextra) {
1767 QTLWExtra* x = extra->topextra = new QTLWExtra;
1768 x->icon = 0;
1769 x->backingStore = 0;
1770 x->sharedPainter = 0;
1771 x->incw = x->inch = 0;
1772 x->basew = x->baseh = 0;
1773 x->frameStrut.setCoords(0, 0, 0, 0);
1774 x->normalGeometry = QRect(0,0,-1,-1);
1775 x->savedFlags = 0;
1776 x->opacity = 255;
1777 x->posIncludesFrame = 0;
1778 x->sizeAdjusted = false;
1779 x->inTopLevelResize = false;
1780 x->inRepaint = false;
1781 x->embedded = 0;
1782 x->window = 0;
1783 x->shareContext = 0;
1784 x->initialScreenIndex = -1;
1785#if 0 // Used to be included in Qt4 for Q_WS_MAC
1786 x->wasMaximized = false;
1787#endif
1788#ifdef QWIDGET_EXTRA_DEBUG
1789 static int count = 0;
1790 qDebug() << "tlextra" << ++count;
1791#endif
1792 }
1793}
1794
1795/*!
1796 \internal
1797 Creates the widget extra data.
1798*/
1799
1800void QWidgetPrivate::createExtra()
1801{
1802 if (!extra) { // if not exists
1803 extra = new QWExtra;
1804 extra->glContext = 0;
1805 extra->topextra = 0;
1806#if QT_CONFIG(graphicsview)
1807 extra->proxyWidget = 0;
1808#endif
1809#ifndef QT_NO_CURSOR
1810 extra->curs = 0;
1811#endif
1812 extra->minw = 0;
1813 extra->minh = 0;
1814 extra->maxw = QWIDGETSIZE_MAX;
1815 extra->maxh = QWIDGETSIZE_MAX;
1816 extra->customDpiX = 0;
1817 extra->customDpiY = 0;
1818 extra->explicitMinSize = 0;
1819 extra->explicitMaxSize = 0;
1820 extra->autoFillBackground = 0;
1821 extra->nativeChildrenForced = 0;
1822 extra->inRenderWithPainter = 0;
1823 extra->hasWindowContainer = false;
1824 extra->hasMask = 0;
1825 createSysExtra();
1826#ifdef QWIDGET_EXTRA_DEBUG
1827 static int count = 0;
1828 qDebug() << "extra" << ++count;
1829#endif
1830 }
1831}
1832
1833void QWidgetPrivate::createSysExtra()
1834{
1835}
1836
1837/*!
1838 \internal
1839 Deletes the widget extra data.
1840*/
1841
1842void QWidgetPrivate::deleteExtra()
1843{
1844 if (extra) { // if exists
1845#ifndef QT_NO_CURSOR
1846 delete extra->curs;
1847#endif
1848 deleteSysExtra();
1849#ifndef QT_NO_STYLE_STYLESHEET
1850 // dereference the stylesheet style
1851 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1852 proxy->deref();
1853#endif
1854 if (extra->topextra) {
1855 deleteTLSysExtra();
1856 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1857 delete extra->topextra->icon;
1858 delete extra->topextra;
1859 }
1860 delete extra;
1861 // extra->xic destroyed in QWidget::destroy()
1862 extra = 0;
1863 }
1864}
1865
1866void QWidgetPrivate::deleteSysExtra()
1867{
1868}
1869
1870static void deleteBackingStore(QWidgetPrivate *d)
1871{
1872 QTLWExtra *topData = d->topData();
1873
1874 delete topData->backingStore;
1875 topData->backingStore = 0;
1876}
1877
1878void QWidgetPrivate::deleteTLSysExtra()
1879{
1880 if (extra && extra->topextra) {
1881 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1882 //needs to be deleted first.
1883
1884 extra->topextra->backingStoreTracker.destroy();
1885 deleteBackingStore(this);
1886#ifndef QT_NO_OPENGL
1887 qDeleteAll(extra->topextra->widgetTextures);
1888 extra->topextra->widgetTextures.clear();
1889 delete extra->topextra->shareContext;
1890 extra->topextra->shareContext = 0;
1891#endif
1892
1893 //the toplevel might have a context with a "qglcontext associated with it. We need to
1894 //delete the qglcontext before we delete the qplatformopenglcontext.
1895 //One unfortunate thing about this is that we potentially create a glContext just to
1896 //delete it straight afterwards.
1897 if (extra->topextra->window) {
1898 extra->topextra->window->destroy();
1899 }
1900 delete extra->topextra->window;
1901 extra->topextra->window = 0;
1902
1903 }
1904}
1905
1906/*
1907 Returns \c region of widgets above this which overlap with
1908 \a rect, which is in parent's coordinate system (same as crect).
1909*/
1910
1911QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1912{
1913 Q_Q(const QWidget);
1914
1915 const QWidget *w = q;
1916 QRect r = rect;
1917 QPoint p;
1918 QRegion region;
1919 while (w) {
1920 if (w->isWindow())
1921 break;
1922 QWidgetPrivate *pd = w->parentWidget()->d_func();
1923 bool above = false;
1924 for (int i = 0; i < pd->children.size(); ++i) {
1925 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1926 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1927 continue;
1928 if (!above) {
1929 above = (sibling == w);
1930 continue;
1931 }
1932
1933 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1934 if (qRectIntersects(siblingRect, r)) {
1935 const QWExtra *siblingExtra = sibling->d_func()->extra;
1936 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1937 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1938 continue;
1939 }
1940 region += siblingRect.translated(-p);
1941 if (breakAfterFirst)
1942 break;
1943 }
1944 }
1945 w = w->parentWidget();
1946 r.translate(pd->data.crect.topLeft());
1947 p += pd->data.crect.topLeft();
1948 }
1949 return region;
1950}
1951
1952void QWidgetPrivate::syncBackingStore()
1953{
1954 if (paintOnScreen()) {
1955 repaint_sys(dirty);
1956 dirty = QRegion();
1957 } else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1958 bs->sync();
1959 }
1960}
1961
1962void QWidgetPrivate::syncBackingStore(const QRegion &region)
1963{
1964 if (paintOnScreen())
1965 repaint_sys(region);
1966 else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1967 bs->sync(q_func(), region);
1968 }
1969}
1970
1971void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1972{
1973 Q_Q(QWidget);
1974
1975 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1976 return; // nothing we can do
1977
1978 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1979 return; // nothing to do
1980
1981 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1982 if (enable)
1983 q->update();
1984
1985 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1986 for (int i = 0; i < children.size(); ++i) {
1987 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1988 if (w && !w->isWindow() && !w->testAttribute(attribute))
1989 w->d_func()->setUpdatesEnabled_helper(enable);
1990 }
1991}
1992
1993/*!
1994 \internal
1995
1996 Propagate this widget's palette to all children, except style sheet
1997 widgets, and windows that don't enable window propagation (palettes don't
1998 normally propagate to windows).
1999*/
2000void QWidgetPrivate::propagatePaletteChange()
2001{
2002 Q_Q(QWidget);
2003 // Propagate a new inherited mask to all children.
2004#if QT_CONFIG(graphicsview)
2005 if (!q->parentWidget() && extra && extra->proxyWidget) {
2006 QGraphicsProxyWidget *p = extra->proxyWidget;
2007 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
2008 } else
2009#endif // QT_CONFIG(graphicsview)
2010 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
2011 inheritedPaletteResolveMask = 0;
2012 }
2013 int mask = data.pal.resolve() | inheritedPaletteResolveMask;
2014
2015 const bool useStyleSheetPropagationInWidgetStyles =
2016 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
2017
2018 QEvent pc(QEvent::PaletteChange);
2019 QApplication::sendEvent(q, &pc);
2020 for (int i = 0; i < children.size(); ++i) {
2021 QWidget *w = qobject_cast<QWidget*>(children.at(i));
2022 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
2023 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
2024 QWidgetPrivate *wd = w->d_func();
2025 wd->inheritedPaletteResolveMask = mask;
2026 wd->resolvePalette();
2027 }
2028 }
2029}
2030
2031/*
2032 Returns the widget's clipping rectangle.
2033*/
2034QRect QWidgetPrivate::clipRect() const
2035{
2036 Q_Q(const QWidget);
2037 const QWidget * w = q;
2038 if (!w->isVisible())
2039 return QRect();
2040 QRect r = effectiveRectFor(q->rect());
2041 int ox = 0;
2042 int oy = 0;
2043 while (w
2044 && w->isVisible()
2045 && !w->isWindow()
2046 && w->parentWidget()) {
2047 ox -= w->x();
2048 oy -= w->y();
2049 w = w->parentWidget();
2050 r &= QRect(ox, oy, w->width(), w->height());
2051 }
2052 return r;
2053}
2054
2055/*
2056 Returns the widget's clipping region (without siblings).
2057*/
2058QRegion QWidgetPrivate::clipRegion() const
2059{
2060 Q_Q(const QWidget);
2061 if (!q->isVisible())
2062 return QRegion();
2063 QRegion r(q->rect());
2064 const QWidget * w = q;
2065 const QWidget *ignoreUpTo;
2066 int ox = 0;
2067 int oy = 0;
2068 while (w
2069 && w->isVisible()
2070 && !w->isWindow()
2071 && w->parentWidget()) {
2072 ox -= w->x();
2073 oy -= w->y();
2074 ignoreUpTo = w;
2075 w = w->parentWidget();
2076 r &= QRegion(ox, oy, w->width(), w->height());
2077
2078 int i = 0;
2079 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
2080 ;
2081 for ( ; i < w->d_func()->children.size(); ++i) {
2082 if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
2083 if(sibling->isVisible() && !sibling->isWindow()) {
2084 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
2085 sibling->width(), sibling->height());
2086 if (qRectIntersects(siblingRect, q->rect()))
2087 r -= QRegion(siblingRect);
2088 }
2089 }
2090 }
2091 }
2092 return r;
2093}
2094
2095void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
2096{
2097// Transform the system clip region from device-independent pixels to device pixels
2098 QTransform scaleTransform;
2099 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
2100
2101 paintEngine->d_func()->baseSystemClip = region;
2102 paintEngine->d_func()->setSystemTransform(scaleTransform);
2103
2104}
2105
2106#if QT_CONFIG(graphicseffect)
2107void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
2108{
2109 Q_Q(QWidget);
2110 QWidget *w = q;
2111 do {
2112 if (w->graphicsEffect()) {
2113 QWidgetEffectSourcePrivate *sourced =
2114 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
2115 if (!sourced->updateDueToGraphicsEffect)
2116 w->graphicsEffect()->source()->d_func()->invalidateCache();
2117 }
2118 w = w->parentWidget();
2119 } while (w);
2120}
2121#endif // QT_CONFIG(graphicseffect)
2122
2123void QWidgetPrivate::setDirtyOpaqueRegion()
2124{
2125 Q_Q(QWidget);
2126
2127 dirtyOpaqueChildren = true;
2128
2129#if QT_CONFIG(graphicseffect)
2130 invalidateGraphicsEffectsRecursively();
2131#endif // QT_CONFIG(graphicseffect)
2132
2133 if (q->isWindow())
2134 return;
2135
2136 QWidget *parent = q->parentWidget();
2137 if (!parent)
2138 return;
2139
2140 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2141 QWidgetPrivate *pd = parent->d_func();
2142 if (!pd->dirtyOpaqueChildren)
2143 pd->setDirtyOpaqueRegion();
2144}
2145
2146const QRegion &QWidgetPrivate::getOpaqueChildren() const
2147{
2148 if (!dirtyOpaqueChildren)
2149 return opaqueChildren;
2150
2151 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2152 that->opaqueChildren = QRegion();
2153
2154 for (int i = 0; i < children.size(); ++i) {
2155 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2156 if (!child || !child->isVisible() || child->isWindow())
2157 continue;
2158
2159 const QPoint offset = child->geometry().topLeft();
2160 QWidgetPrivate *childd = child->d_func();
2161 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2162 if (childd->extra && childd->extra->hasMask)
2163 r &= childd->extra->mask;
2164 if (r.isEmpty())
2165 continue;
2166 r.translate(offset);
2167 that->opaqueChildren += r;
2168 }
2169
2170 that->opaqueChildren &= q_func()->rect();
2171 that->dirtyOpaqueChildren = false;
2172
2173 return that->opaqueChildren;
2174}
2175
2176void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2177{
2178 if (children.isEmpty() || clipRect.isEmpty())
2179 return;
2180
2181 const QRegion &r = getOpaqueChildren();
2182 if (!r.isEmpty())
2183 source -= (r & clipRect);
2184}
2185
2186//subtract any relatives that are higher up than me --- this is too expensive !!!
2187void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2188 bool alsoNonOpaque) const
2189{
2190 Q_Q(const QWidget);
2191 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2192 if (disableSubtractOpaqueSiblings || q->isWindow())
2193 return;
2194
2195#if 0 // Used to be included in Qt4 for Q_WS_MAC
2196 if (q->d_func()->isInUnifiedToolbar)
2197 return;
2198#endif
2199
2200 QRect clipBoundingRect;
2201 bool dirtyClipBoundingRect = true;
2202
2203 QRegion parentClip;
2204 bool dirtyParentClip = true;
2205
2206 QPoint parentOffset = data.crect.topLeft();
2207
2208 const QWidget *w = q;
2209
2210 while (w) {
2211 if (w->isWindow())
2212 break;
2213 QWidgetPrivate *pd = w->parentWidget()->d_func();
2214 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2215 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2216 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2217 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2218 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2219 continue;
2220
2221 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2222 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2223 continue;
2224
2225 if (dirtyClipBoundingRect) {
2226 clipBoundingRect = sourceRegion.boundingRect();
2227 dirtyClipBoundingRect = false;
2228 }
2229
2230 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2231 continue;
2232
2233 if (dirtyParentClip) {
2234 parentClip = sourceRegion.translated(parentOffset);
2235 dirtyParentClip = false;
2236 }
2237
2238 const QPoint siblingPos(sibling->data->crect.topLeft());
2239 const QRect siblingClipRect(sibling->d_func()->clipRect());
2240 QRegion siblingDirty(parentClip);
2241 siblingDirty &= (siblingClipRect.translated(siblingPos));
2242 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2243 && !sibling->d_func()->graphicsEffect;
2244 if (hasMask)
2245 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2246 if (siblingDirty.isEmpty())
2247 continue;
2248
2249 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2250 if (hasMask) {
2251 siblingDirty.translate(-parentOffset);
2252 sourceRegion -= siblingDirty;
2253 } else {
2254 sourceRegion -= siblingGeometry.translated(-parentOffset);
2255 }
2256 } else {
2257 if (hasDirtySiblingsAbove)
2258 *hasDirtySiblingsAbove = true;
2259 if (sibling->d_func()->children.isEmpty())
2260 continue;
2261 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2262 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2263 sourceRegion -= opaqueSiblingChildren;
2264 }
2265 if (sourceRegion.isEmpty())
2266 return;
2267
2268 dirtyClipBoundingRect = true;
2269 dirtyParentClip = true;
2270 }
2271
2272 w = w->parentWidget();
2273 parentOffset += pd->data.crect.topLeft();
2274 dirtyParentClip = true;
2275 }
2276}
2277
2278void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2279{
2280 Q_Q(const QWidget);
2281
2282 const QWidget *w = q;
2283 QPoint offset;
2284
2285#if QT_CONFIG(graphicseffect)
2286 if (graphicsEffect) {
2287 w = q->parentWidget();
2288 offset -= data.crect.topLeft();
2289 }
2290#endif // QT_CONFIG(graphicseffect)
2291
2292 while (w) {
2293 const QWidgetPrivate *wd = w->d_func();
2294 if (wd->extra && wd->extra->hasMask)
2295 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2296 if (w->isWindow())
2297 return;
2298 offset -= wd->data.crect.topLeft();
2299 w = w->parentWidget();
2300 }
2301}
2302
2303bool QWidgetPrivate::paintOnScreen() const
2304{
2305#if defined(QT_NO_BACKINGSTORE)
2306 return true;
2307#else
2308 Q_Q(const QWidget);
2309 if (q->testAttribute(Qt::WA_PaintOnScreen)
2310 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2311 return true;
2312 }
2313
2314 return false;
2315#endif
2316}
2317
2318void QWidgetPrivate::updateIsOpaque()
2319{
2320 // hw: todo: only needed if opacity actually changed
2321 setDirtyOpaqueRegion();
2322
2323#if QT_CONFIG(graphicseffect)
2324 if (graphicsEffect) {
2325 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2326 setOpaque(false);
2327 return;
2328 }
2329#endif // QT_CONFIG(graphicseffect)
2330
2331 Q_Q(QWidget);
2332#if 0 // Used to be included in Qt4 for Q_WS_X11
2333 if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
2334 setOpaque(false);
2335 return;
2336 }
2337#endif
2338
2339 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2340 setOpaque(true);
2341 return;
2342 }
2343
2344 const QPalette &pal = q->palette();
2345
2346 if (q->autoFillBackground()) {
2347 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2348 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2349 setOpaque(true);
2350 return;
2351 }
2352 }
2353
2354 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2355 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2356 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2357 setOpaque(true);
2358 return;
2359 }
2360 }
2361 setOpaque(false);
2362}
2363
2364void QWidgetPrivate::setOpaque(bool opaque)
2365{
2366 if (isOpaque != opaque) {
2367 isOpaque = opaque;
2368 updateIsTranslucent();
2369 }
2370}
2371
2372void QWidgetPrivate::updateIsTranslucent()
2373{
2374 Q_Q(QWidget);
2375 if (QWindow *window = q->windowHandle()) {
2376 QSurfaceFormat format = window->format();
2377 const int oldAlpha = format.alphaBufferSize();
2378 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2379 if (oldAlpha != newAlpha) {
2380 format.setAlphaBufferSize(newAlpha);
2381 window->setFormat(format);
2382 }
2383 }
2384}
2385
2386static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2387{
2388 Q_ASSERT(painter);
2389
2390 if (brush.style() == Qt::TexturePattern) {
2391#if 0 // Used to be included in Qt4 for Q_WS_MAC
2392 // Optimize pattern filling on mac by using HITheme directly
2393 // when filling with the standard widget background.
2394 // Defined in qmacstyle_mac.cpp
2395 extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
2396 qt_mac_fill_background(painter, rgn, brush);
2397#else
2398 {
2399 const QRect rect(rgn.boundingRect());
2400 painter->setClipRegion(rgn);
2401 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2402 }
2403#endif
2404
2405 } else if (brush.gradient()
2406 && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
2407 painter->save();
2408 painter->setClipRegion(rgn);
2409 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2410 painter->restore();
2411 } else {
2412 for (const QRect &rect : rgn)
2413 painter->fillRect(rect, brush);
2414 }
2415}
2416
2417void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
2418{
2419 Q_Q(const QWidget);
2420
2421#if QT_CONFIG(scrollarea)
2422 bool resetBrushOrigin = false;
2423 QPointF oldBrushOrigin;
2424 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2425 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2426 if (scrollArea && scrollArea->viewport() == q) {
2427 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2428 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2429 oldBrushOrigin = painter->brushOrigin();
2430 resetBrushOrigin = true;
2431 painter->setBrushOrigin(-priv->contentsOffset());
2432
2433 }
2434#endif // QT_CONFIG(scrollarea)
2435
2436 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2437
2438 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2439 const QBrush bg = q->palette().brush(QPalette::Window);
2440 if (!(flags & DontSetCompositionMode)) {
2441 //copy alpha straight in
2442 QPainter::CompositionMode oldMode = painter->compositionMode();
2443 painter->setCompositionMode(QPainter::CompositionMode_Source);
2444 fillRegion(painter, rgn, bg);
2445 painter->setCompositionMode(oldMode);
2446 } else {
2447 fillRegion(painter, rgn, bg);
2448 }
2449 }
2450
2451 if (q->autoFillBackground())
2452 fillRegion(painter, rgn, autoFillBrush);
2453
2454 if (q->testAttribute(Qt::WA_StyledBackground)) {
2455 painter->setClipRegion(rgn);
2456 QStyleOption opt;
2457 opt.initFrom(q);
2458 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2459 }
2460
2461#if QT_CONFIG(scrollarea)
2462 if (resetBrushOrigin)
2463 painter->setBrushOrigin(oldBrushOrigin);
2464#endif // QT_CONFIG(scrollarea)
2465}
2466
2467/*
2468 \internal
2469 This function is called when a widget is hidden or destroyed.
2470 It resets some application global pointers that should only refer active,
2471 visible widgets.
2472*/
2473
2474#if 0 // Used to be included in Qt4 for Q_WS_MAC
2475 extern QPointer<QWidget> qt_button_down;
2476#else
2477 extern QWidget *qt_button_down;
2478#endif
2479
2480void QWidgetPrivate::deactivateWidgetCleanup()
2481{
2482 Q_Q(QWidget);
2483 // If this was the active application window, reset it
2484 if (QApplication::activeWindow() == q)
2485 QApplication::setActiveWindow(0);
2486 // If the is the active mouse press widget, reset it
2487 if (q == qt_button_down)
2488 qt_button_down = 0;
2489}
2490
2491
2492/*!
2493 Returns a pointer to the widget with window identifer/handle \a
2494 id.
2495
2496 The window identifier type depends on the underlying window
2497 system, see \c qwindowdefs.h for the actual definition. If there
2498 is no widget with this identifier, 0 is returned.
2499*/
2500
2501QWidget *QWidget::find(WId id)
2502{
2503 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
2504}
2505
2506
2507
2508/*!
2509 \fn WId QWidget::internalWinId() const
2510 \internal
2511 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2512
2513*/
2514
2515/*!
2516 \fn WId QWidget::winId() const
2517
2518 Returns the window system identifier of the widget.
2519
2520 Portable in principle, but if you use it you are probably about to
2521 do something non-portable. Be careful.
2522
2523 If a widget is non-native (alien) and winId() is invoked on it, that widget
2524 will be provided a native handle.
2525
2526 This value may change at run-time. An event with type QEvent::WinIdChange
2527 will be sent to the widget following a change in window system identifier.
2528
2529 \sa find()
2530*/
2531WId QWidget::winId() const
2532{
2533 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
2534#ifdef ALIEN_DEBUG
2535 qDebug() << "QWidget::winId: creating native window for" << this;
2536#endif
2537 QWidget *that = const_cast<QWidget*>(this);
2538 that->setAttribute(Qt::WA_NativeWindow);
2539 that->d_func()->createWinId();
2540 return that->data->winid;
2541 }
2542 return data->winid;
2543}
2544
2545void QWidgetPrivate::createWinId()
2546{
2547 Q_Q(QWidget);
2548
2549#ifdef ALIEN_DEBUG
2550 qDebug() << "QWidgetPrivate::createWinId for" << q;
2551#endif
2552 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2553 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2554 if (!q->isWindow()) {
2555 QWidget *parent = q->parentWidget();
2556 QWidgetPrivate *pd = parent->d_func();
2557 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2558 parent->setAttribute(Qt::WA_NativeWindow);
2559 if (!parent->internalWinId()) {
2560 pd->createWinId();
2561 }
2562
2563 for (int i = 0; i < pd->children.size(); ++i) {
2564 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2565 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2566 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2567 w->create();
2568 }
2569 }
2570 } else {
2571 q->create();
2572 }
2573 }
2574}
2575
2576
2577/*!
2578\internal
2579Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2580
2581*/
2582
2583void QWidget::createWinId()
2584{
2585 Q_D(QWidget);
2586#ifdef ALIEN_DEBUG
2587 qDebug() << "QWidget::createWinId" << this;
2588#endif
2589// qWarning("QWidget::createWinId is obsolete, please fix your code.");
2590 d->createWinId();
2591}
2592
2593/*!
2594 \since 4.4
2595
2596 Returns the effective window system identifier of the widget, i.e. the
2597 native parent's window system identifier.
2598
2599 If the widget is native, this function returns the native widget ID.
2600 Otherwise, the window ID of the first native parent widget, i.e., the
2601 top-level widget that contains this widget, is returned.
2602
2603 \note We recommend that you do not store this value as it is likely to
2604 change at run-time.
2605
2606 \sa nativeParentWidget()
2607*/
2608WId QWidget::effectiveWinId() const
2609{
2610 const WId id = internalWinId();
2611 if (id || !testAttribute(Qt::WA_WState_Created))
2612 return id;
2613 if (const QWidget *realParent = nativeParentWidget())
2614 return realParent->internalWinId();
2615 return 0;
2616}
2617
2618/*!
2619 If this is a native widget, return the associated QWindow.
2620 Otherwise return null.
2621
2622 Native widgets include toplevel widgets, QGLWidget, and child widgets
2623 on which winId() was called.
2624
2625 \since 5.0
2626
2627 \sa winId()
2628*/
2629QWindow *QWidget::windowHandle() const
2630{
2631 Q_D(const QWidget);
2632 return d->windowHandle();
2633}
2634
2635#ifndef QT_NO_STYLE_STYLESHEET
2636
2637/*!
2638 \property QWidget::styleSheet
2639 \brief the widget's style sheet
2640 \since 4.2
2641
2642 The style sheet contains a textual description of customizations to the
2643 widget's style, as described in the \l{Qt Style Sheets} document.
2644
2645 Since Qt 4.5, Qt style sheets fully supports \macos.
2646
2647 \warning Qt style sheets are currently not supported for custom QStyle
2648 subclasses. We plan to address this in some future release.
2649
2650 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2651*/
2652QString QWidget::styleSheet() const
2653{
2654 Q_D(const QWidget);
2655 if (!d->extra)
2656 return QString();
2657 return d->extra->styleSheet;
2658}
2659
2660void QWidget::setStyleSheet(const QString& styleSheet)
2661{
2662 Q_D(QWidget);
2663 if (data->in_destructor)
2664 return;
2665 d->createExtra();
2666
2667 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2668 d->extra->styleSheet = styleSheet;
2669 if (styleSheet.isEmpty()) { // stylesheet removed
2670 if (!proxy)
2671 return;
2672
2673 d->inheritStyle();
2674 return;
2675 }
2676
2677 if (proxy) { // style sheet update
2678 if (d->polished)
2679 proxy->repolish(this);
2680 return;
2681 }
2682
2683 if (testAttribute(Qt::WA_SetStyle)) {
2684 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2685 } else {
2686 d->setStyle_helper(new QStyleSheetStyle(0), true);
2687 }
2688}
2689
2690#endif // QT_NO_STYLE_STYLESHEET
2691
2692/*!
2693 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2694*/
2695
2696QStyle *QWidget::style() const
2697{
2698 Q_D(const QWidget);
2699
2700 if (d->extra && d->extra->style)
2701 return d->extra->style;
2702 return QApplication::style();
2703}
2704
2705/*!
2706 Sets the widget's GUI style to \a style. The ownership of the style
2707 object is not transferred.
2708
2709 If no style is set, the widget uses the application's style,
2710 QApplication::style() instead.
2711
2712 Setting a widget's style has no effect on existing or future child
2713 widgets.
2714
2715 \warning This function is particularly useful for demonstration
2716 purposes, where you want to show Qt's styling capabilities. Real
2717 applications should avoid it and use one consistent GUI style
2718 instead.
2719
2720 \warning Qt style sheets are currently not supported for custom QStyle
2721 subclasses. We plan to address this in some future release.
2722
2723 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2724*/
2725
2726void QWidget::setStyle(QStyle *style)
2727{
2728 Q_D(QWidget);
2729 setAttribute(Qt::WA_SetStyle, style != 0);
2730 d->createExtra();
2731#ifndef QT_NO_STYLE_STYLESHEET
2732 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2733 //if for some reason someone try to set a QStyleSheetStyle, ref it
2734 //(this may happen for exemple in QButtonDialogBox which propagates its style)
2735 styleSheetStyle->ref();
2736 d->setStyle_helper(style, false);
2737 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2738 // if we have an application stylesheet or have a proxy already, propagate
2739 d->setStyle_helper(new QStyleSheetStyle(style), true);
2740 } else
2741#endif
2742 d->setStyle_helper(style, false);
2743}
2744
2745void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2746{
2747 Q_Q(QWidget);
2748 QStyle *oldStyle = q->style();
2749
2750 createExtra();
2751
2752#ifndef QT_NO_STYLE_STYLESHEET
2753 QPointer<QStyle> origStyle = extra->style;
2754#endif
2755 extra->style = newStyle;
2756
2757 // repolish
2758 if (polished && q->windowType() != Qt::Desktop) {
2759 oldStyle->unpolish(q);
2760 q->style()->polish(q);
2761 }
2762
2763 if (propagate) {
2764 // We copy the list because the order may be modified
2765 const QObjectList childrenList = children;
2766 for (int i = 0; i < childrenList.size(); ++i) {
2767 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2768 if (c)
2769 c->d_func()->inheritStyle();
2770 }
2771 }
2772
2773#ifndef QT_NO_STYLE_STYLESHEET
2774 if (!qt_styleSheet(newStyle)) {
2775 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2776 cssStyle->clearWidgetFont(q);
2777 }
2778 }
2779#endif
2780
2781 QEvent e(QEvent::StyleChange);
2782 QApplication::sendEvent(q, &e);
2783
2784#ifndef QT_NO_STYLE_STYLESHEET
2785 // dereference the old stylesheet style
2786 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2787 proxy->deref();
2788#endif
2789}
2790
2791// Inherits style from the current parent and propagates it as necessary
2792void QWidgetPrivate::inheritStyle()
2793{
2794#ifndef QT_NO_STYLE_STYLESHEET
2795 Q_Q(QWidget);
2796
2797 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2798
2799 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2800
2801 if (!q->styleSheet().isEmpty()) {
2802 Q_ASSERT(proxy);
2803 proxy->repolish(q);
2804 return;
2805 }
2806
2807 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2808 QWidget *parent = q->parentWidget();
2809 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
2810 // If we have stylesheet on app or parent has stylesheet style, we need
2811 // to be running a proxy
2812 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2813 QStyle *newStyle = parentStyle;
2814 if (q->testAttribute(Qt::WA_SetStyle))
2815 newStyle = new QStyleSheetStyle(origStyle);
2816 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2817 newProxy->ref();
2818
2819 setStyle_helper(newStyle, true);
2820 return;
2821 }
2822
2823 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2824 // we just need our original style back
2825 if (origStyle == extraStyle) // is it any different?
2826 return;
2827
2828 // We could have inherited the proxy from our parent (which has a custom style)
2829 // In such a case we need to start following the application style (i.e revert
2830 // the propagation behavior of QStyleSheetStyle)
2831 if (!q->testAttribute(Qt::WA_SetStyle))
2832 origStyle = 0;
2833
2834 setStyle_helper(origStyle, true);
2835#endif // QT_NO_STYLE_STYLESHEET
2836}
2837
2838
2839/*!
2840 \fn bool QWidget::isWindow() const
2841
2842 Returns \c true if the widget is an independent window, otherwise
2843 returns \c false.
2844
2845 A window is a widget that isn't visually the child of any other
2846 widget and that usually has a frame and a
2847 \l{QWidget::setWindowTitle()}{window title}.
2848
2849 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2850 It will then be grouped with its parent and deleted when the
2851 parent is deleted, minimized when the parent is minimized etc. If
2852 supported by the window manager, it will also have a common
2853 taskbar entry with its parent.
2854
2855 QDialog and QMainWindow widgets are by default windows, even if a
2856 parent widget is specified in the constructor. This behavior is
2857 specified by the Qt::Window flag.
2858
2859 \sa window(), isModal(), parentWidget()
2860*/
2861
2862/*!
2863 \property QWidget::modal
2864 \brief whether the widget is a modal widget
2865
2866 This property only makes sense for windows. A modal widget
2867 prevents widgets in all other windows from getting any input.
2868
2869 By default, this property is \c false.
2870
2871 \sa isWindow(), windowModality, QDialog
2872*/
2873
2874/*!
2875 \property QWidget::windowModality
2876 \brief which windows are blocked by the modal widget
2877 \since 4.1
2878
2879 This property only makes sense for windows. A modal widget
2880 prevents widgets in other windows from getting input. The value of
2881 this property controls which windows are blocked when the widget
2882 is visible. Changing this property while the window is visible has
2883 no effect; you must hide() the widget first, then show() it again.
2884
2885 By default, this property is Qt::NonModal.
2886
2887 \sa isWindow(), QWidget::modal, QDialog
2888*/
2889
2890Qt::WindowModality QWidget::windowModality() const
2891{
2892 return static_cast<Qt::WindowModality>(data->window_modality);
2893}
2894
2895void QWidget::setWindowModality(Qt::WindowModality windowModality)
2896{
2897 data->window_modality = windowModality;
2898 // setModal_sys() will be called by setAttribute()
2899 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2900 setAttribute(Qt::WA_SetWindowModality, true);
2901}
2902
2903void QWidgetPrivate::setModal_sys()
2904{
2905 Q_Q(QWidget);
2906 if (q->windowHandle())
2907 q->windowHandle()->setModality(q->windowModality());
2908}
2909
2910/*!
2911 \fn bool QWidget::underMouse() const
2912
2913 Returns \c true if the widget is under the mouse cursor; otherwise
2914 returns \c false.
2915
2916 This value is not updated properly during drag and drop
2917 operations.
2918
2919 \sa enterEvent(), leaveEvent()
2920*/
2921
2922/*!
2923 \property QWidget::minimized
2924 \brief whether this widget is minimized (iconified)
2925
2926 This property is only relevant for windows.
2927
2928 By default, this property is \c false.
2929
2930 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2931*/
2932bool QWidget::isMinimized() const
2933{ return data->window_state & Qt::WindowMinimized; }
2934
2935/*!
2936 Shows the widget minimized, as an icon.
2937
2938 Calling this function only affects \l{isWindow()}{windows}.
2939
2940 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2941 isMinimized()
2942*/
2943void QWidget::showMinimized()
2944{
2945 bool isMin = isMinimized();
2946 if (isMin && isVisible())
2947 return;
2948
2949 ensurePolished();
2950
2951 if (!isMin)
2952 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2953 setVisible(true);
2954}
2955
2956/*!
2957 \property QWidget::maximized
2958 \brief whether this widget is maximized
2959
2960 This property is only relevant for windows.
2961
2962 \note Due to limitations on some window systems, this does not always
2963 report the expected results (e.g., if the user on X11 maximizes the
2964 window via the window manager, Qt has no way of distinguishing this
2965 from any other resize). This is expected to improve as window manager
2966 protocols evolve.
2967
2968 By default, this property is \c false.
2969
2970 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2971*/
2972bool QWidget::isMaximized() const
2973{ return data->window_state & Qt::WindowMaximized; }
2974
2975
2976
2977/*!
2978 Returns the current window state. The window state is a OR'ed
2979 combination of Qt::WindowState: Qt::WindowMinimized,
2980 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2981
2982 \sa Qt::WindowState, setWindowState()
2983 */
2984Qt::WindowStates QWidget::windowState() const
2985{
2986 return Qt::WindowStates(data->window_state);
2987}
2988
2989/*!\internal
2990
2991 The function sets the window state on child widgets similar to
2992 setWindowState(). The difference is that the window state changed
2993 event has the isOverride() flag set. It exists mainly to keep
2994 QWorkspace working.
2995 */
2996void QWidget::overrideWindowState(Qt::WindowStates newstate)
2997{
2998 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2999 data->window_state = newstate;
3000 QApplication::sendEvent(this, &e);
3001}
3002
3003/*!
3004 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
3005
3006 Sets the window state to \a windowState. The window state is a OR'ed
3007 combination of Qt::WindowState: Qt::WindowMinimized,
3008 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
3009
3010 If the window is not visible (i.e. isVisible() returns \c false), the
3011 window state will take effect when show() is called. For visible
3012 windows, the change is immediate. For example, to toggle between
3013 full-screen and normal mode, use the following code:
3014
3015 \snippet code/src_gui_kernel_qwidget.cpp 0
3016
3017 In order to restore and activate a minimized window (while
3018 preserving its maximized and/or full-screen state), use the following:
3019
3020 \snippet code/src_gui_kernel_qwidget.cpp 1
3021
3022 Calling this function will hide the widget. You must call show() to make
3023 the widget visible again.
3024
3025 \note On some window systems Qt::WindowActive is not immediate, and may be
3026 ignored in certain cases.
3027
3028 When the window state changes, the widget receives a changeEvent()
3029 of type QEvent::WindowStateChange.
3030
3031 \sa Qt::WindowState, windowState()
3032*/
3033void QWidget::setWindowState(Qt::WindowStates newstate)
3034{
3035 Q_D(QWidget);
3036 Qt::WindowStates oldstate = windowState();
3037 if (oldstate == newstate)
3038 return;
3039 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
3040 create();
3041
3042 data->window_state = newstate;
3043 data->in_set_window_state = 1;
3044 if (isWindow()) {
3045 // Ensure the initial size is valid, since we store it as normalGeometry below.
3046 if (!testAttribute(Qt::WA_Resized) && !isVisible())
3047 adjustSize();
3048
3049 d->createTLExtra();
3050 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3051 d->topData()->normalGeometry = geometry();
3052
3053 Q_ASSERT(windowHandle());
3054 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3055 }
3056 data->in_set_window_state = 0;
3057
3058 if (newstate & Qt::WindowActive)
3059 activateWindow();
3060
3061 QWindowStateChangeEvent e(oldstate);
3062 QApplication::sendEvent(this, &e);
3063}
3064
3065/*!
3066 \property QWidget::fullScreen
3067 \brief whether the widget is shown in full screen mode
3068
3069 A widget in full screen mode occupies the whole screen area and does not
3070 display window decorations, such as a title bar.
3071
3072 By default, this property is \c false.
3073
3074 \sa windowState(), minimized, maximized
3075*/
3076bool QWidget::isFullScreen() const
3077{ return data->window_state & Qt::WindowFullScreen; }
3078
3079/*!
3080 Shows the widget in full-screen mode.
3081
3082 Calling this function only affects \l{isWindow()}{windows}.
3083
3084 To return from full-screen mode, call showNormal().
3085
3086 Full-screen mode works fine under Windows, but has certain
3087 problems under X. These problems are due to limitations of the
3088 ICCCM protocol that specifies the communication between X11
3089 clients and the window manager. ICCCM simply does not understand
3090 the concept of non-decorated full-screen windows. Therefore, the
3091 best we can do is to request a borderless window and place and
3092 resize it to fill the entire screen. Depending on the window
3093 manager, this may or may not work. The borderless window is
3094 requested using MOTIF hints, which are at least partially
3095 supported by virtually all modern window managers.
3096
3097 An alternative would be to bypass the window manager entirely and
3098 create a window with the Qt::X11BypassWindowManagerHint flag. This
3099 has other severe problems though, like totally broken keyboard focus
3100 and very strange effects on desktop changes or when the user raises
3101 other windows.
3102
3103 X11 window managers that follow modern post-ICCCM specifications
3104 support full-screen mode properly.
3105
3106 \sa showNormal(), showMaximized(), show(), hide(), isVisible()
3107*/
3108void QWidget::showFullScreen()
3109{
3110#if 0 // Used to be included in Qt4 for Q_WS_MAC
3111 // If the unified toolbar is enabled, we have to disable it before going fullscreen.
3112 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3113 if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) {
3114 mainWindow->setUnifiedTitleAndToolBarOnMac(false);
3115 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3116 mainLayout->activateUnifiedToolbarAfterFullScreen = true;
3117 }
3118#endif
3119 ensurePolished();
3120
3121 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3122 | Qt::WindowFullScreen);
3123 setVisible(true);
3124#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3125 // activating it here before libscreen activates it causes problems
3126 activateWindow();
3127#endif
3128}
3129
3130/*!
3131 Shows the widget maximized.
3132
3133 Calling this function only affects \l{isWindow()}{windows}.
3134
3135 On X11, this function may not work properly with certain window
3136 managers. See the \l{Window Geometry} documentation for an explanation.
3137
3138 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3139*/
3140void QWidget::showMaximized()
3141{
3142 ensurePolished();
3143
3144 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3145 | Qt::WindowMaximized);
3146#if 0 // Used to be included in Qt4 for Q_WS_MAC
3147 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3148 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3149 if (mainWindow)
3150 {
3151 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3152 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3153 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3154 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3155 }
3156 }
3157#endif
3158 setVisible(true);
3159}
3160
3161/*!
3162 Restores the widget after it has been maximized or minimized.
3163
3164 Calling this function only affects \l{isWindow()}{windows}.
3165
3166 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3167*/
3168void QWidget::showNormal()
3169{
3170 ensurePolished();
3171
3172 setWindowState(windowState() & ~(Qt::WindowMinimized
3173 | Qt::WindowMaximized
3174 | Qt::WindowFullScreen));
3175#if 0 // Used to be included in Qt4 for Q_WS_MAC
3176 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3177 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3178 if (mainWindow)
3179 {
3180 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3181 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3182 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3183 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3184 }
3185 }
3186#endif
3187 setVisible(true);
3188}
3189
3190/*!
3191 Returns \c true if this widget would become enabled if \a ancestor is
3192 enabled; otherwise returns \c false.
3193
3194
3195
3196 This is the case if neither the widget itself nor every parent up
3197 to but excluding \a ancestor has been explicitly disabled.
3198
3199 isEnabledTo(0) returns false if this widget or any if its ancestors
3200 was explicitly disabled.
3201
3202 The word ancestor here means a parent widget within the same window.
3203
3204 Therefore isEnabledTo(0) stops at this widget's window, unlike
3205 isEnabled() which also takes parent windows into considerations.
3206
3207 \sa setEnabled(), enabled
3208*/
3209
3210bool QWidget::isEnabledTo(const QWidget *ancestor) const
3211{
3212 const QWidget * w = this;
3213 while (!w->testAttribute(Qt::WA_ForceDisabled)
3214 && !w->isWindow()
3215 && w->parentWidget()
3216 && w->parentWidget() != ancestor)
3217 w = w->parentWidget();
3218 return !w->testAttribute(Qt::WA_ForceDisabled);
3219}
3220
3221#ifndef QT_NO_ACTION
3222/*!
3223 Appends the action \a action to this widget's list of actions.
3224
3225 All QWidgets have a list of \l{QAction}s, however they can be
3226 represented graphically in many different ways. The default use of
3227 the QAction list (as returned by actions()) is to create a context
3228 QMenu.
3229
3230 A QWidget should only have one of each action and adding an action
3231 it already has will not cause the same action to be in the widget twice.
3232
3233 The ownership of \a action is not transferred to this QWidget.
3234
3235 \sa removeAction(), insertAction(), actions(), QMenu
3236*/
3237void QWidget::addAction(QAction *action)
3238{
3239 insertAction(0, action);
3240}
3241
3242/*!
3243 Appends the actions \a actions to this widget's list of actions.
3244
3245 \sa removeAction(), QMenu, addAction()
3246*/
3247#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3248void QWidget::addActions(const QList<QAction *> &actions)
3249#else
3250void QWidget::addActions(QList<QAction*> actions)
3251#endif
3252{
3253 for(int i = 0; i < actions.count(); i++)
3254 insertAction(0, actions.at(i));
3255}
3256
3257/*!
3258 Inserts the action \a action to this widget's list of actions,
3259 before the action \a before. It appends the action if \a before is 0 or
3260 \a before is not a valid action for this widget.
3261
3262 A QWidget should only have one of each action.
3263
3264 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3265*/
3266void QWidget::insertAction(QAction *before, QAction *action)
3267{
3268 if (Q_UNLIKELY(!action)) {
3269 qWarning("QWidget::insertAction: Attempt to insert null action");
3270 return;
3271 }
3272
3273 Q_D(QWidget);
3274 if(d->actions.contains(action))
3275 removeAction(action);
3276
3277 int pos = d->actions.indexOf(before);
3278 if (pos < 0) {
3279 before = 0;
3280 pos = d->actions.size();
3281 }
3282 d->actions.insert(pos, action);
3283
3284 QActionPrivate *apriv = action->d_func();
3285 apriv->widgets.append(this);
3286
3287 QActionEvent e(QEvent::ActionAdded, action, before);
3288 QApplication::sendEvent(this, &e);
3289}
3290
3291/*!
3292 Inserts the actions \a actions to this widget's list of actions,
3293 before the action \a before. It appends the action if \a before is 0 or
3294 \a before is not a valid action for this widget.
3295
3296 A QWidget can have at most one of each action.
3297
3298 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3299*/
3300#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3301void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3302#else
3303void QWidget::insertActions(QAction *before, QList<QAction*> actions)
3304#endif
3305{
3306 for(int i = 0; i < actions.count(); ++i)
3307 insertAction(before, actions.at(i));
3308}
3309
3310/*!
3311 Removes the action \a action from this widget's list of actions.
3312 \sa insertAction(), actions(), insertAction()
3313*/
3314void QWidget::removeAction(QAction *action)
3315{
3316 if (!action)
3317 return;
3318
3319 Q_D(QWidget);
3320
3321 QActionPrivate *apriv = action->d_func();
3322 apriv->widgets.removeAll(this);
3323
3324 if (d->actions.removeAll(action)) {
3325 QActionEvent e(QEvent::ActionRemoved, action);
3326 QApplication::sendEvent(this, &e);
3327 }
3328}
3329
3330/*!
3331 Returns the (possibly empty) list of this widget's actions.
3332
3333 \sa contextMenuPolicy, insertAction(), removeAction()
3334*/
3335QList<QAction*> QWidget::actions() const
3336{
3337 Q_D(const QWidget);
3338 return d->actions;
3339}
3340#endif // QT_NO_ACTION
3341
3342/*!
3343 \fn bool QWidget::isEnabledToTLW() const
3344 \obsolete
3345
3346 This function is deprecated. It is equivalent to isEnabled()
3347*/
3348
3349/*!
3350 \property QWidget::enabled
3351 \brief whether the widget is enabled
3352
3353 In general an enabled widget handles keyboard and mouse events; a disabled
3354 widget does not. An exception is made with \l{QAbstractButton}.
3355
3356 Some widgets display themselves differently when they are
3357 disabled. For example a button might draw its label grayed out. If
3358 your widget needs to know when it becomes enabled or disabled, you
3359 can use the changeEvent() with type QEvent::EnabledChange.
3360
3361 Disabling a widget implicitly disables all its children. Enabling
3362 respectively enables all child widgets unless they have been
3363 explicitly disabled. It it not possible to explicitly enable a child
3364 widget which is not a window while its parent widget remains disabled.
3365
3366 By default, this property is \c true.
3367
3368 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3369*/
3370void QWidget::setEnabled(bool enable)
3371{
3372 Q_D(QWidget);
3373 setAttribute(Qt::WA_ForceDisabled, !enable);
3374 d->setEnabled_helper(enable);
3375}
3376
3377void QWidgetPrivate::setEnabled_helper(bool enable)
3378{
3379 Q_Q(QWidget);
3380
3381 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3382 return; // nothing we can do
3383
3384 if (enable != q->testAttribute(Qt::WA_Disabled))
3385 return; // nothing to do
3386
3387 q->setAttribute(Qt::WA_Disabled, !enable);
3388 updateSystemBackground();
3389
3390 if (!enable && q->window()->focusWidget() == q) {
3391 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3392 if (!parentIsEnabled || !q->focusNextChild())
3393 q->clearFocus();
3394 }
3395
3396 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3397 for (int i = 0; i < children.size(); ++i) {
3398 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3399 if (w && !w->testAttribute(attribute))
3400 w->d_func()->setEnabled_helper(enable);
3401 }
3402#if 0 // Used to be included in Qt4 for Q_WS_X11
3403 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3404 // enforce the windows behavior of clearing the cursor on
3405 // disabled widgets
3406 qt_x11_enforce_cursor(q);
3407 }
3408#endif
3409#ifndef QT_NO_CURSOR
3410 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3411 // enforce the windows behavior of clearing the cursor on
3412 // disabled widgets
3413 qt_qpa_set_cursor(q, false);
3414 }
3415#endif
3416#if 0 // Used to be included in Qt4 for Q_WS_MAC
3417 setEnabled_helper_sys(enable);
3418#endif
3419#ifndef QT_NO_IM
3420 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3421 QWidget *focusWidget = effectiveFocusWidget();
3422
3423 if (enable) {
3424 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3425 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3426 } else {
3427 QGuiApplication::inputMethod()->commit();
3428 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3429 }
3430 }
3431#endif //QT_NO_IM
3432 QEvent e(QEvent::EnabledChange);
3433 QApplication::sendEvent(q, &e);
3434}
3435
3436/*!
3437 \property QWidget::acceptDrops
3438 \brief whether drop events are enabled for this widget
3439
3440 Setting this property to true announces to the system that this
3441 widget \e may be able to accept drop events.
3442
3443 If the widget is the desktop (windowType() == Qt::Desktop), this may
3444 fail if another application is using the desktop; you can call
3445 acceptDrops() to test if this occurs.
3446
3447 \warning Do not modify this property in a drag and drop event handler.
3448
3449 By default, this property is \c false.
3450
3451 \sa {Drag and Drop}
3452*/
3453bool QWidget::acceptDrops() const
3454{
3455 return testAttribute(Qt::WA_AcceptDrops);
3456}
3457
3458void QWidget::setAcceptDrops(bool on)
3459{
3460 setAttribute(Qt::WA_AcceptDrops, on);
3461
3462}
3463
3464void QWidgetPrivate::registerDropSite(bool on)
3465{
3466 Q_UNUSED(on);
3467}
3468
3469/*!
3470 Disables widget input events if \a disable is true; otherwise
3471 enables input events.
3472
3473 See the \l enabled documentation for more information.
3474
3475 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3476*/
3477void QWidget::setDisabled(bool disable)
3478{
3479 setEnabled(!disable);
3480}
3481
3482/*!
3483 \property QWidget::frameGeometry
3484 \brief geometry of the widget relative to its parent including any
3485 window frame
3486
3487 See the \l{Window Geometry} documentation for an overview of geometry
3488 issues with windows.
3489
3490 By default, this property contains a value that depends on the user's
3491 platform and screen geometry.
3492
3493 \sa geometry(), x(), y(), pos()
3494*/
3495QRect QWidget::frameGeometry() const
3496{
3497 Q_D(const QWidget);
3498 if (isWindow() && ! (windowType() == Qt::Popup)) {
3499 QRect fs = d->frameStrut();
3500 return QRect(data->crect.x() - fs.left(),
3501 data->crect.y() - fs.top(),
3502 data->crect.width() + fs.left() + fs.right(),
3503 data->crect.height() + fs.top() + fs.bottom());
3504 }
3505 return data->crect;
3506}
3507
3508/*!
3509 \property QWidget::x
3510
3511 \brief the x coordinate of the widget relative to its parent including
3512 any window frame
3513
3514 See the \l{Window Geometry} documentation for an overview of geometry
3515 issues with windows.
3516
3517 By default, this property has a value of 0.
3518
3519 \sa frameGeometry, y, pos
3520*/
3521int QWidget::x() const
3522{
3523 Q_D(const QWidget);
3524 if (isWindow() && ! (windowType() == Qt::Popup))
3525 return data->crect.x() - d->frameStrut().left();
3526 return data->crect.x();
3527}
3528
3529/*!
3530 \property QWidget::y
3531 \brief the y coordinate of the widget relative to its parent and
3532 including any window frame
3533
3534 See the \l{Window Geometry} documentation for an overview of geometry
3535 issues with windows.
3536
3537 By default, this property has a value of 0.
3538
3539 \sa frameGeometry, x, pos
3540*/
3541int QWidget::y() const
3542{
3543 Q_D(const QWidget);
3544 if (isWindow() && ! (windowType() == Qt::Popup))
3545 return data->crect.y() - d->frameStrut().top();
3546 return data->crect.y();
3547}
3548
3549/*!
3550 \property QWidget::pos
3551 \brief the position of the widget within its parent widget
3552
3553 If the widget is a window, the position is that of the widget on
3554 the desktop, including its frame.
3555
3556 When changing the position, the widget, if visible, receives a
3557 move event (moveEvent()) immediately. If the widget is not
3558 currently visible, it is guaranteed to receive an event before it
3559 is shown.
3560
3561 By default, this property contains a position that refers to the
3562 origin.
3563
3564 \warning Calling move() or setGeometry() inside moveEvent() can
3565 lead to infinite recursion.
3566
3567 See the \l{Window Geometry} documentation for an overview of geometry
3568 issues with windows.
3569
3570 \sa frameGeometry, size, x(), y()
3571*/
3572QPoint QWidget::pos() const
3573{
3574 Q_D(const QWidget);
3575 QPoint result = data->crect.topLeft();
3576 if (isWindow() && ! (windowType() == Qt::Popup))
3577 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3578 result -= d->frameStrut().topLeft();
3579 return result;
3580}
3581
3582/*!
3583 \property QWidget::geometry
3584 \brief the geometry of the widget relative to its parent and
3585 excluding the window frame
3586
3587 When changing the geometry, the widget, if visible, receives a
3588 move event (moveEvent()) and/or a resize event (resizeEvent())
3589 immediately. If the widget is not currently visible, it is
3590 guaranteed to receive appropriate events before it is shown.
3591
3592 The size component is adjusted if it lies outside the range
3593 defined by minimumSize() and maximumSize().
3594
3595 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3596 can lead to infinite recursion.
3597
3598 See the \l{Window Geometry} documentation for an overview of geometry
3599 issues with windows.
3600
3601 By default, this property contains a value that depends on the user's
3602 platform and screen geometry.
3603
3604 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3605 resizeEvent(), minimumSize(), maximumSize()
3606*/
3607
3608/*!
3609 \property QWidget::normalGeometry
3610
3611 \brief the geometry of the widget as it will appear when shown as
3612 a normal (not maximized or full screen) top-level widget
3613
3614 For child widgets this property always holds an empty rectangle.
3615
3616 By default, this property contains an empty rectangle.
3617
3618 \sa QWidget::windowState(), QWidget::geometry
3619*/
3620
3621/*!
3622 \property QWidget::size
3623 \brief the size of the widget excluding any window frame
3624
3625 If the widget is visible when it is being resized, it receives a resize event
3626 (resizeEvent()) immediately. If the widget is not currently
3627 visible, it is guaranteed to receive an event before it is shown.
3628
3629 The size is adjusted if it lies outside the range defined by
3630 minimumSize() and maximumSize().
3631
3632 By default, this property contains a value that depends on the user's
3633 platform and screen geometry.
3634
3635 \warning Calling resize() or setGeometry() inside resizeEvent() can
3636 lead to infinite recursion.
3637
3638 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3639 appear on screen. This also applies to windows.
3640
3641 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3642*/
3643
3644/*!
3645 \property QWidget::width
3646 \brief the width of the widget excluding any window frame
3647
3648 See the \l{Window Geometry} documentation for an overview of geometry
3649 issues with windows.
3650
3651 \note Do not use this function to find the width of a screen on
3652 a \l{QDesktopWidget}{multiple screen desktop}. Read
3653 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3654
3655 By default, this property contains a value that depends on the user's
3656 platform and screen geometry.
3657
3658 \sa geometry, height, size
3659*/
3660
3661/*!
3662 \property QWidget::height
3663 \brief the height of the widget excluding any window frame
3664
3665 See the \l{Window Geometry} documentation for an overview of geometry
3666 issues with windows.
3667
3668 \note Do not use this function to find the height of a screen
3669 on a \l{QDesktopWidget}{multiple screen desktop}. Read
3670 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3671
3672 By default, this property contains a value that depends on the user's
3673 platform and screen geometry.
3674
3675 \sa geometry, width, size
3676*/
3677
3678/*!
3679 \property QWidget::rect
3680 \brief the internal geometry of the widget excluding any window
3681 frame
3682
3683 The rect property equals QRect(0, 0, width(), height()).
3684
3685 See the \l{Window Geometry} documentation for an overview of geometry
3686 issues with windows.
3687
3688 By default, this property contains a value that depends on the user's
3689 platform and screen geometry.
3690
3691 \sa size
3692*/
3693
3694
3695QRect QWidget::normalGeometry() const
3696{
3697 Q_D(const QWidget);
3698 if (!d->extra || !d->extra->topextra)
3699 return QRect();
3700
3701 if (!isMaximized() && !isFullScreen())
3702 return geometry();
3703
3704 return d->topData()->normalGeometry;
3705}
3706
3707
3708/*!
3709 \property QWidget::childrenRect
3710 \brief the bounding rectangle of the widget's children
3711
3712 Hidden children are excluded.
3713
3714 By default, for a widget with no children, this property contains a
3715 rectangle with zero width and height located at the origin.
3716
3717 \sa childrenRegion(), geometry()
3718*/
3719
3720QRect QWidget::childrenRect() const
3721{
3722 Q_D(const QWidget);
3723 QRect r(0, 0, 0, 0);
3724 for (int i = 0; i < d->children.size(); ++i) {
3725 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3726 if (w && !w->isWindow() && !w->isHidden())
3727 r |= w->geometry();
3728 }
3729 return r;
3730}
3731
3732/*!
3733 \property QWidget::childrenRegion
3734 \brief the combined region occupied by the widget's children
3735
3736 Hidden children are excluded.
3737
3738 By default, for a widget with no children, this property contains an
3739 empty region.
3740
3741 \sa childrenRect(), geometry(), mask()
3742*/
3743
3744QRegion QWidget::childrenRegion() const
3745{
3746 Q_D(const QWidget);
3747 QRegion r;
3748 for (int i = 0; i < d->children.size(); ++i) {
3749 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3750 if (w && !w->isWindow() && !w->isHidden()) {
3751 QRegion mask = w->mask();
3752 if (mask.isEmpty())
3753 r |= w->geometry();
3754 else
3755 r |= mask.translated(w->pos());
3756 }
3757 }
3758 return r;
3759}
3760
3761
3762/*!
3763 \property QWidget::minimumSize
3764 \brief the widget's minimum size
3765
3766 The widget cannot be resized to a smaller size than the minimum
3767 widget size. The widget's size is forced to the minimum size if
3768 the current size is smaller.
3769
3770 The minimum size set by this function will override the minimum size
3771 defined by QLayout. In order to unset the minimum size, use a
3772 value of \c{QSize(0, 0)}.
3773
3774 By default, this property contains a size with zero width and height.
3775
3776 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3777*/
3778
3779QSize QWidget::minimumSize() const
3780{
3781 Q_D(const QWidget);
3782 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3783}
3784
3785/*!
3786 \property QWidget::maximumSize
3787 \brief the widget's maximum size in pixels
3788
3789 The widget cannot be resized to a larger size than the maximum
3790 widget size.
3791
3792 By default, this property contains a size in which both width and height
3793 have values of 16777215.
3794
3795 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3796 of widgets.
3797
3798 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3799*/
3800
3801QSize QWidget::maximumSize() const
3802{
3803 Q_D(const QWidget);
3804 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3805 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3806}
3807
3808
3809/*!
3810 \property QWidget::minimumWidth
3811 \brief the widget's minimum width in pixels
3812
3813 This property corresponds to the width held by the \l minimumSize property.
3814
3815 By default, this property has a value of 0.
3816
3817 \sa minimumSize, minimumHeight
3818*/
3819
3820/*!
3821 \property QWidget::minimumHeight
3822 \brief the widget's minimum height in pixels
3823
3824 This property corresponds to the height held by the \l minimumSize property.
3825
3826 By default, this property has a value of 0.
3827
3828 \sa minimumSize, minimumWidth
3829*/
3830
3831/*!
3832 \property QWidget::maximumWidth
3833 \brief the widget's maximum width in pixels
3834
3835 This property corresponds to the width held by the \l maximumSize property.
3836
3837 By default, this property contains a value of 16777215.
3838
3839 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3840 of widgets.
3841
3842 \sa maximumSize, maximumHeight
3843*/
3844
3845/*!
3846 \property QWidget::maximumHeight
3847 \brief the widget's maximum height in pixels
3848
3849 This property corresponds to the height held by the \l maximumSize property.
3850
3851 By default, this property contains a value of 16777215.
3852
3853 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3854 of widgets.
3855
3856 \sa maximumSize, maximumWidth
3857*/
3858
3859/*!
3860 \property QWidget::sizeIncrement
3861 \brief the size increment of the widget
3862
3863 When the user resizes the window, the size will move in steps of
3864 sizeIncrement().width() pixels horizontally and
3865 sizeIncrement.height() pixels vertically, with baseSize() as the
3866 basis. Preferred widget sizes are for non-negative integers \e i
3867 and \e j:
3868 \snippet code/src_gui_kernel_qwidget.cpp 2
3869
3870 Note that while you can set the size increment for all widgets, it
3871 only affects windows.
3872
3873 By default, this property contains a size with zero width and height.
3874
3875 \warning The size increment has no effect under Windows, and may
3876 be disregarded by the window manager on X11.
3877
3878 \sa size, minimumSize, maximumSize
3879*/
3880QSize QWidget::sizeIncrement() const
3881{
3882 Q_D(const QWidget);
3883 return (d->extra && d->extra->topextra)
3884 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3885 : QSize(0, 0);
3886}
3887
3888/*!
3889 \property QWidget::baseSize
3890 \brief the base size of the widget
3891
3892 The base size is used to calculate a proper widget size if the
3893 widget defines sizeIncrement().
3894
3895 By default, for a newly-created widget, this property contains a size with
3896 zero width and height.
3897
3898 \sa setSizeIncrement()
3899*/
3900
3901QSize QWidget::baseSize() const
3902{
3903 Q_D(const QWidget);
3904 return (d->extra != 0 && d->extra->topextra != 0)
3905 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3906 : QSize(0, 0);
3907}
3908
3909bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3910{
3911 Q_Q(QWidget);
3912
3913 int mw = minw, mh = minh;
3914 if (mw == QWIDGETSIZE_MAX)
3915 mw = 0;
3916 if (mh == QWIDGETSIZE_MAX)
3917 mh = 0;
3918 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3919 qWarning("QWidget::setMinimumSize: (%s/%s) "
3920 "The largest allowed size is (%d,%d)",
3921 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3922 QWIDGETSIZE_MAX);
3923 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3924 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3925 }
3926 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3927 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3928 "are not possible",
3929 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3930 minw = mw = qMax(minw, 0);
3931 minh = mh = qMax(minh, 0);
3932 }
3933 createExtra();
3934 if (extra->minw == mw && extra->minh == mh)
3935 return false;
3936 extra->minw = mw;
3937 extra->minh = mh;
3938 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3939 return true;
3940}
3941
3942void QWidgetPrivate::setConstraints_sys()
3943{
3944 Q_Q(QWidget);
3945 if (extra && q->windowHandle()) {
3946 QWindow *win = q->windowHandle();
3947 QWindowPrivate *winp = qt_window_private(win);
3948
3949 winp->minimumSize = QSize(extra->minw, extra->minh);
3950 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3951
3952 if (extra->topextra) {
3953 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3954 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3955 }
3956
3957 if (winp->platformWindow) {
3958 fixPosIncludesFrame();
3959 winp->platformWindow->propagateSizeHints();
3960 }
3961 }
3962}
3963
3964/*!
3965 \overload
3966
3967 This function corresponds to setMinimumSize(QSize(minw, minh)).
3968 Sets the minimum width to \a minw and the minimum height to \a
3969 minh.
3970*/
3971
3972void QWidget::setMinimumSize(int minw, int minh)
3973{
3974 Q_D(QWidget);
3975 if (!d->setMinimumSize_helper(minw, minh))
3976 return;
3977
3978 if (isWindow())
3979 d->setConstraints_sys();
3980 if (minw > width() || minh > height()) {
3981 bool resized = testAttribute(Qt::WA_Resized);
3982 bool maximized = isMaximized();
3983 resize(qMax(minw,width()), qMax(minh,height()));
3984 setAttribute(Qt::WA_Resized, resized); //not a user resize
3985 if (maximized)
3986 data->window_state = data->window_state | Qt::WindowMaximized;
3987 }
3988#if QT_CONFIG(graphicsview)
3989 if (d->extra) {
3990 if (d->extra->proxyWidget)
3991 d->extra->proxyWidget->setMinimumSize(minw, minh);
3992 }
3993#endif
3994 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3995}
3996
3997bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3998{
3999 Q_Q(QWidget);
4000 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
4001 qWarning("QWidget::setMaximumSize: (%s/%s) "
4002 "The largest allowed size is (%d,%d)",
4003 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4004 QWIDGETSIZE_MAX);
4005 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4006 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4007 }
4008 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4009 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4010 "are not possible",
4011 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4012 maxw = qMax(maxw, 0);
4013 maxh = qMax(maxh, 0);
4014 }
4015 createExtra();
4016 if (extra->maxw == maxw && extra->maxh == maxh)
4017 return false;
4018 extra->maxw = maxw;
4019 extra->maxh = maxh;
4020 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4021 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4022 return true;
4023}
4024
4025/*!
4026 \overload
4027
4028 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4029 maxh)). Sets the maximum width to \a maxw and the maximum height
4030 to \a maxh.
4031*/
4032void QWidget::setMaximumSize(int maxw, int maxh)
4033{
4034 Q_D(QWidget);
4035 if (!d->setMaximumSize_helper(maxw, maxh))
4036 return;
4037
4038 if (isWindow())
4039 d->setConstraints_sys();
4040 if (maxw < width() || maxh < height()) {
4041 bool resized = testAttribute(Qt::WA_Resized);
4042 resize(qMin(maxw,width()), qMin(maxh,height()));
4043 setAttribute(Qt::WA_Resized, resized); //not a user resize
4044 }
4045
4046#if QT_CONFIG(graphicsview)
4047 if (d->extra) {
4048 if (d->extra->proxyWidget)
4049 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4050 }
4051#endif
4052
4053 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4054}
4055
4056/*!
4057 \overload
4058
4059 Sets the x (width) size increment to \a w and the y (height) size
4060 increment to \a h.
4061*/
4062void QWidget::setSizeIncrement(int w, int h)
4063{
4064 Q_D(QWidget);
4065 d->createTLExtra();
4066 QTLWExtra* x = d->topData();
4067 if (x->incw == w && x->inch == h)
4068 return;
4069 x->incw = w;
4070 x->inch = h;
4071 if (isWindow())
4072 d->setConstraints_sys();
4073}
4074
4075/*!
4076 \overload
4077
4078 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4079 the widgets base size to width \a basew and height \a baseh.
4080*/
4081void QWidget::setBaseSize(int basew, int baseh)
4082{
4083 Q_D(QWidget);
4084 d->createTLExtra();
4085 QTLWExtra* x = d->topData();
4086 if (x->basew == basew && x->baseh == baseh)
4087 return;
4088 x->basew = basew;
4089 x->baseh = baseh;
4090 if (isWindow())
4091 d->setConstraints_sys();
4092}
4093
4094/*!
4095 Sets both the minimum and maximum sizes of the widget to \a s,
4096 thereby preventing it from ever growing or shrinking.
4097
4098 This will override the default size constraints set by QLayout.
4099
4100 To remove constraints, set the size to QWIDGETSIZE_MAX.
4101
4102 Alternatively, if you want the widget to have a
4103 fixed size based on its contents, you can call
4104 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4105
4106 \sa maximumSize, minimumSize
4107*/
4108
4109void QWidget::setFixedSize(const QSize & s)
4110{
4111 setFixedSize(s.width(), s.height());
4112}
4113
4114
4115/*!
4116 \fn void QWidget::setFixedSize(int w, int h)
4117 \overload
4118
4119 Sets the width of the widget to \a w and the height to \a h.
4120*/
4121
4122void QWidget::setFixedSize(int w, int h)
4123{
4124 Q_D(QWidget);
4125 bool minSizeSet = d->setMinimumSize_helper(w, h);
4126 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4127 if (!minSizeSet && !maxSizeSet)
4128 return;
4129
4130 if (isWindow())
4131 d->setConstraints_sys();
4132 else
4133 d->updateGeometry_helper(true);
4134
4135 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4136 resize(w, h);
4137}
4138
4139void QWidget::setMinimumWidth(int w)
4140{
4141 Q_D(QWidget);
4142 d->createExtra();
4143 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4144 setMinimumSize(w, minimumSize().height());
4145 d->extra->explicitMinSize = expl;
4146}
4147
4148void QWidget::setMinimumHeight(int h)
4149{
4150 Q_D(QWidget);
4151 d->createExtra();
4152 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4153 setMinimumSize(minimumSize().width(), h);
4154 d->extra->explicitMinSize = expl;
4155}
4156
4157void QWidget::setMaximumWidth(int w)
4158{
4159 Q_D(QWidget);
4160 d->createExtra();
4161 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4162 setMaximumSize(w, maximumSize().height());
4163 d->extra->explicitMaxSize = expl;
4164}
4165
4166void QWidget::setMaximumHeight(int h)
4167{
4168 Q_D(QWidget);
4169 d->createExtra();
4170 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4171 setMaximumSize(maximumSize().width(), h);
4172 d->extra->explicitMaxSize = expl;
4173}
4174
4175/*!
4176 Sets both the minimum and maximum width of the widget to \a w
4177 without changing the heights. Provided for convenience.
4178
4179 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4180*/
4181
4182void QWidget::setFixedWidth(int w)
4183{
4184 Q_D(QWidget);
4185 d->createExtra();
4186 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4187 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4188 setMinimumSize(w, minimumSize().height());
4189 setMaximumSize(w, maximumSize().height());
4190 d->extra->explicitMinSize = explMin;
4191 d->extra->explicitMaxSize = explMax;
4192}
4193
4194
4195/*!
4196 Sets both the minimum and maximum heights of the widget to \a h
4197 without changing the widths. Provided for convenience.
4198
4199 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4200*/
4201
4202void QWidget::setFixedHeight(int h)
4203{
4204 Q_D(QWidget);
4205 d->createExtra();
4206 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4207 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4208 setMinimumSize(minimumSize().width(), h);
4209 setMaximumSize(maximumSize().width(), h);
4210 d->extra->explicitMinSize = explMin;
4211 d->extra->explicitMaxSize = explMax;
4212}
4213
4214
4215/*!
4216 Translates the widget coordinate \a pos to the coordinate system
4217 of \a parent. The \a parent must not be 0 and must be a parent
4218 of the calling widget.
4219
4220 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4221*/
4222
4223QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
4224{
4225 QPoint p = pos;
4226 if (parent) {
4227 const QWidget * w = this;
4228 while (w != parent) {
4229 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
4230 "parent must be in parent hierarchy");
4231 p = w->mapToParent(p);
4232 w = w->parentWidget();
4233 }
4234 }
4235 return p;
4236}
4237
4238
4239/*!
4240 Translates the widget coordinate \a pos from the coordinate system
4241 of \a parent to this widget's coordinate system. The \a parent
4242 must not be 0 and must be a parent of the calling widget.
4243
4244 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4245*/
4246
4247QPoint QWidget::mapFrom(const QWidget * parent, const QPoint & pos) const
4248{
4249 QPoint p(pos);
4250 if (parent) {
4251 const QWidget * w = this;
4252 while (w != parent) {
4253 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4254 "parent must be in parent hierarchy");
4255
4256 p = w->mapFromParent(p);
4257 w = w->parentWidget();
4258 }
4259 }
4260 return p;
4261}
4262
4263
4264/*!
4265 Translates the widget coordinate \a pos to a coordinate in the
4266 parent widget.
4267
4268 Same as mapToGlobal() if the widget has no parent.
4269
4270 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4271*/
4272
4273QPoint QWidget::mapToParent(const QPoint &pos) const
4274{
4275 return pos + data->crect.topLeft();
4276}
4277
4278/*!
4279 Translates the parent widget coordinate \a pos to widget
4280 coordinates.
4281
4282 Same as mapFromGlobal() if the widget has no parent.
4283
4284 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4285*/
4286
4287QPoint QWidget::mapFromParent(const QPoint &pos) const
4288{
4289 return pos - data->crect.topLeft();
4290}
4291
4292
4293/*!
4294 Returns the window for this widget, i.e. the next ancestor widget
4295 that has (or could have) a window-system frame.
4296
4297 If the widget is a window, the widget itself is returned.
4298
4299 Typical usage is changing the window title:
4300
4301 \snippet code/src_gui_kernel_qwidget.cpp 3
4302
4303 \sa isWindow()
4304*/
4305
4306QWidget *QWidget::window() const
4307{
4308 QWidget *w = const_cast<QWidget *>(this);
4309 QWidget *p = w->parentWidget();
4310 while (!w->isWindow() && p) {
4311 w = p;
4312 p = p->parentWidget();
4313 }
4314 return w;
4315}
4316
4317/*!
4318 \since 4.4
4319
4320 Returns the native parent for this widget, i.e. the next ancestor widget
4321 that has a system identifier, or 0 if it does not have any native parent.
4322
4323 \sa effectiveWinId()
4324*/
4325QWidget *QWidget::nativeParentWidget() const
4326{
4327 QWidget *parent = parentWidget();
4328 while (parent && !parent->internalWinId())
4329 parent = parent->parentWidget();
4330 return parent;
4331}
4332
4333/*! \fn QWidget *QWidget::topLevelWidget() const
4334 \obsolete
4335
4336 Use window() instead.
4337*/
4338
4339
4340
4341/*!
4342 Returns the background role of the widget.
4343
4344 The background role defines the brush from the widget's \l palette that
4345 is used to render the background.
4346
4347 If no explicit background role is set, the widget inherts its parent
4348 widget's background role.
4349
4350 \sa setBackgroundRole(), foregroundRole()
4351 */
4352QPalette::ColorRole QWidget::backgroundRole() const
4353{
4354
4355 const QWidget *w = this;
4356 do {
4357 QPalette::ColorRole role = w->d_func()->bg_role;
4358 if (role != QPalette::NoRole)
4359 return role;
4360 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4361 break;
4362 w = w->parentWidget();
4363 } while (w);
4364 return QPalette::Window;
4365}
4366
4367/*!
4368 Sets the background role of the widget to \a role.
4369
4370 The background role defines the brush from the widget's \l palette that
4371 is used to render the background.
4372
4373 If \a role is QPalette::NoRole, then the widget inherits its
4374 parent's background role.
4375
4376 Note that styles are free to choose any color from the palette.
4377 You can modify the palette or set a style sheet if you don't
4378 achieve the result you want with setBackgroundRole().
4379
4380 \sa backgroundRole(), foregroundRole()
4381 */
4382
4383void QWidget::setBackgroundRole(QPalette::ColorRole role)
4384{
4385 Q_D(QWidget);
4386 d->bg_role = role;
4387 d->updateSystemBackground();
4388 d->propagatePaletteChange();
4389 d->updateIsOpaque();
4390}
4391
4392/*!
4393 Returns the foreground role.
4394
4395 The foreground role defines the color from the widget's \l palette that
4396 is used to draw the foreground.
4397
4398 If no explicit foreground role is set, the function returns a role
4399 that contrasts with the background role.
4400
4401 \sa setForegroundRole(), backgroundRole()
4402 */
4403QPalette::ColorRole QWidget::foregroundRole() const
4404{
4405 Q_D(const QWidget);
4406 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4407 if (rl != QPalette::NoRole)
4408 return rl;
4409 QPalette::ColorRole role = QPalette::WindowText;
4410 switch (backgroundRole()) {
4411 case QPalette::Button:
4412 role = QPalette::ButtonText;
4413 break;
4414 case QPalette::Base:
4415 role = QPalette::Text;
4416 break;
4417 case QPalette::Dark:
4418 case QPalette::Shadow:
4419 role = QPalette::Light;
4420 break;
4421 case QPalette::Highlight:
4422 role = QPalette::HighlightedText;
4423 break;
4424 case QPalette::ToolTipBase:
4425 role = QPalette::ToolTipText;
4426 break;
4427 default:
4428 ;
4429 }
4430 return role;
4431}
4432
4433/*!
4434 Sets the foreground role of the widget to \a role.
4435
4436 The foreground role defines the color from the widget's \l palette that
4437 is used to draw the foreground.
4438
4439 If \a role is QPalette::NoRole, the widget uses a foreground role
4440 that contrasts with the background role.
4441
4442 Note that styles are free to choose any color from the palette.
4443 You can modify the palette or set a style sheet if you don't
4444 achieve the result you want with setForegroundRole().
4445
4446 \sa foregroundRole(), backgroundRole()
4447 */
4448void QWidget::setForegroundRole(QPalette::ColorRole role)
4449{
4450 Q_D(QWidget);
4451 d->fg_role = role;
4452 d->updateSystemBackground();
4453 d->propagatePaletteChange();
4454}
4455
4456/*!
4457 \property QWidget::palette
4458 \brief the widget's palette
4459
4460 This property describes the widget's palette. The palette is used by the
4461 widget's style when rendering standard components, and is available as a
4462 means to ensure that custom widgets can maintain consistency with the
4463 native platform's look and feel. It's common that different platforms, or
4464 different styles, have different palettes.
4465
4466 When you assign a new palette to a widget, the color roles from this
4467 palette are combined with the widget's default palette to form the
4468 widget's final palette. The palette entry for the widget's background role
4469 is used to fill the widget's background (see QWidget::autoFillBackground),
4470 and the foreground role initializes QPainter's pen.
4471
4472 The default depends on the system environment. QApplication maintains a
4473 system/theme palette which serves as a default for all widgets. There may
4474 also be special palette defaults for certain types of widgets (e.g., on
4475 Windows Vista, all classes that derive from QMenuBar have a special
4476 default palette). You can also define default palettes for widgets
4477 yourself by passing a custom palette and the name of a widget to
4478 QApplication::setPalette(). Finally, the style always has the option of
4479 polishing the palette as it's assigned (see QStyle::polish()).
4480
4481 QWidget propagates explicit palette roles from parent to child. If you
4482 assign a brush or color to a specific role on a palette and assign that
4483 palette to a widget, that role will propagate to all the widget's
4484 children, overriding any system defaults for that role. Note that palettes
4485 by default don't propagate to windows (see isWindow()) unless the
4486 Qt::WA_WindowPropagation attribute is enabled.
4487
4488 QWidget's palette propagation is similar to its font propagation.
4489
4490 The current style, which is used to render the content of all standard Qt
4491 widgets, is free to choose colors and brushes from the widget palette, or
4492 in some cases, to ignore the palette (partially, or completely). In
4493 particular, certain styles like GTK style, Mac style, and Windows Vista
4494 style, depend on third party APIs to render the content of widgets,
4495 and these styles typically do not follow the palette. Because of this,
4496 assigning roles to a widget's palette is not guaranteed to change the
4497 appearance of the widget. Instead, you may choose to apply a \l
4498 styleSheet. You can refer to our Knowledge Base article
4499 \l{http://qt.nokia.com/developer/knowledgebase/22}{here} for more
4500 information.
4501
4502 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4503 When using style sheets, the palette of a widget can be customized using
4504 the "color", "background-color", "selection-color",
4505 "selection-background-color" and "alternate-background-color".
4506
4507 \sa QApplication::palette(), QWidget::font()
4508*/
4509const QPalette &QWidget::palette() const
4510{
4511 if (!isEnabled()) {
4512 data->pal.setCurrentColorGroup(QPalette::Disabled);
4513 } else if ((!isVisible() || isActiveWindow())
4514#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
4515 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4516#endif
4517 ) {
4518 data->pal.setCurrentColorGroup(QPalette::Active);
4519 } else {
4520#if 0 // Used to be included in Qt4 for Q_WS_MAC
4521 extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
4522 if (qt_mac_can_clickThrough(this))
4523 data->pal.setCurrentColorGroup(QPalette::Active);
4524 else
4525#endif
4526 data->pal.setCurrentColorGroup(QPalette::Inactive);
4527 }
4528 return data->pal;
4529}
4530
4531void QWidget::setPalette(const QPalette &palette)
4532{
4533 Q_D(QWidget);
4534 setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
4535
4536 // Determine which palette is inherited from this widget's ancestors and
4537 // QApplication::palette, resolve this against \a palette (attributes from
4538 // the inherited palette are copied over this widget's palette). Then
4539 // propagate this palette to this widget's children.
4540 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4541 QPalette resolvedPalette = palette.resolve(naturalPalette);
4542 d->setPalette_helper(resolvedPalette);
4543}
4544
4545/*!
4546 \internal
4547
4548 Returns the palette that the widget \a w inherits from its ancestors and
4549 QApplication::palette. \a inheritedMask is the combination of the widget's
4550 ancestors palette request masks (i.e., which attributes from the parent
4551 widget's palette are implicitly imposed on this widget by the user). Note
4552 that this font does not take into account the palette set on \a w itself.
4553*/
4554QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
4555{
4556 Q_Q(const QWidget);
4557
4558 const bool useStyleSheetPropagationInWidgetStyles =
4559 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4560
4561 QPalette naturalPalette = QApplication::palette(q);
4562 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4563 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4564#if QT_CONFIG(graphicsview)
4565 || (extra && extra->proxyWidget)
4566#endif // QT_CONFIG(graphicsview)
4567 )) {
4568 if (QWidget *p = q->parentWidget()) {
4569 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4570 if (!naturalPalette.isCopyOf(QApplication::palette())) {
4571 QPalette inheritedPalette = p->palette();
4572 inheritedPalette.resolve(inheritedMask);
4573 naturalPalette = inheritedPalette.resolve(naturalPalette);
4574 } else {
4575 naturalPalette = p->palette();
4576 }
4577 }
4578 }
4579#if QT_CONFIG(graphicsview)
4580 else if (extra && extra->proxyWidget) {
4581 QPalette inheritedPalette = extra->proxyWidget->palette();
4582 inheritedPalette.resolve(inheritedMask);
4583 naturalPalette = inheritedPalette.resolve(naturalPalette);
4584 }
4585#endif // QT_CONFIG(graphicsview)
4586 }
4587 naturalPalette.resolve(0);
4588 return naturalPalette;
4589}
4590/*!
4591 \internal
4592
4593 Determine which palette is inherited from this widget's ancestors and
4594 QApplication::palette, resolve this against this widget's palette
4595 (attributes from the inherited palette are copied over this widget's
4596 palette). Then propagate this palette to this widget's children.
4597*/
4598void QWidgetPrivate::resolvePalette()
4599{
4600 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4601 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4602 setPalette_helper(resolvedPalette);
4603}
4604
4605void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4606{
4607 Q_Q(QWidget);
4608 if (data.pal == palette && data.pal.resolve() == palette.resolve())
4609 return;
4610 data.pal = palette;
4611 updateSystemBackground();
4612 propagatePaletteChange();
4613 updateIsOpaque();
4614 q->update();
4615 updateIsOpaque();
4616}
4617
4618void QWidgetPrivate::updateSystemBackground()
4619{
4620}
4621
4622/*!
4623 \property QWidget::font
4624 \brief the font currently set for the widget
4625
4626 This property describes the widget's requested font. The font is used by
4627 the widget's style when rendering standard components, and is available as
4628 a means to ensure that custom widgets can maintain consistency with the
4629 native platform's look and feel. It's common that different platforms, or
4630 different styles, define different fonts for an application.
4631
4632 When you assign a new font to a widget, the properties from this font are
4633 combined with the widget's default font to form the widget's final
4634 font. You can call fontInfo() to get a copy of the widget's final
4635 font. The final font is also used to initialize QPainter's font.
4636
4637 The default depends on the system environment. QApplication maintains a
4638 system/theme font which serves as a default for all widgets. There may
4639 also be special font defaults for certain types of widgets. You can also
4640 define default fonts for widgets yourself by passing a custom font and the
4641 name of a widget to QApplication::setFont(). Finally, the font is matched
4642 against Qt's font database to find the best match.
4643
4644 QWidget propagates explicit font properties from parent to child. If you
4645 change a specific property on a font and assign that font to a widget,
4646 that property will propagate to all the widget's children, overriding any
4647 system defaults for that property. Note that fonts by default don't
4648 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4649 attribute is enabled.
4650
4651 QWidget's font propagation is similar to its palette propagation.
4652
4653 The current style, which is used to render the content of all standard Qt
4654 widgets, is free to choose to use the widget font, or in some cases, to
4655 ignore it (partially, or completely). In particular, certain styles like
4656 GTK style, Mac style, and Windows Vista style, apply special
4657 modifications to the widget font to match the platform's native look and
4658 feel. Because of this, assigning properties to a widget's font is not
4659 guaranteed to change the appearance of the widget. Instead, you may choose
4660 to apply a \l styleSheet.
4661
4662 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4663 style sheets will take precedence if the settings conflict.
4664
4665 \sa fontInfo(), fontMetrics()
4666*/
4667
4668void QWidget::setFont(const QFont &font)
4669{
4670 Q_D(QWidget);
4671
4672#ifndef QT_NO_STYLE_STYLESHEET
4673 const QStyleSheetStyle* style;
4674 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4675 style->saveWidgetFont(this, font);
4676#endif
4677
4678 setAttribute(Qt::WA_SetFont, font.resolve() != 0);
4679
4680 // Determine which font is inherited from this widget's ancestors and
4681 // QApplication::font, resolve this against \a font (attributes from the
4682 // inherited font are copied over). Then propagate this font to this
4683 // widget's children.
4684 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4685 QFont resolvedFont = font.resolve(naturalFont);
4686 d->setFont_helper(resolvedFont);
4687}
4688
4689/*
4690 \internal
4691
4692 Returns the font that the widget \a w inherits from its ancestors and
4693 QApplication::font. \a inheritedMask is the combination of the widget's
4694 ancestors font request masks (i.e., which attributes from the parent
4695 widget's font are implicitly imposed on this widget by the user). Note
4696 that this font does not take into account the font set on \a w itself.
4697
4698 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4699 is applied, fonts are not propagated anymore
4700*/
4701QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4702{
4703 Q_Q(const QWidget);
4704
4705 const bool useStyleSheetPropagationInWidgetStyles =
4706 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4707
4708 QFont naturalFont = QApplication::