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