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