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