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(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
127 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), 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("QWidget: Must construct a QApplication before a QWidget");
192 return;
193 }
194
195 checkForIncompatibleLibraryVersion(version);
196
197 isWidget = true;
198 memset(high_attributes, 0, 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*>(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(Qt::WA_WState_Created))
232 w->d_func()->setWSGeometry();
233 w->d_func()->setDirtyOpaqueRegion();
234 QMoveEvent e(r.topLeft(), oldp);
235 QCoreApplication::sendEvent(w, &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(p.x(), p.y());
255 QGuiApplication::inputMethod()->setInputItemTransform(t);
256 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
257 QGuiApplication::inputMethod()->update(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 \endlist
787
788
789 \section1 Native Widgets vs Alien Widgets
790
791 Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
792 system. They do not have a native window handle associated with them. This
793 feature significantly speeds up widget painting, resizing, and removes flicker.
794
795 Should you require the old behavior with native windows, you can choose
796 one of the following options:
797
798 \list 1
799 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
800 \li Set the Qt::AA_NativeWindows attribute on your application. All
801 widgets will be native widgets.
802 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
803 and all of its ancestors will become native (unless
804 Qt::WA_DontCreateNativeAncestors is set).
805 \li Call QWidget::winId to enforce a native window (this implies 3).
806 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
807 (this implies 3).
808 \endlist
809
810 \sa QEvent, QPainter, QGridLayout, QBoxLayout
811
812*/
813
814QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
815QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
816
817
818/*****************************************************************************
819 QWidget member functions
820 *****************************************************************************/
821
822/*
823 Widget state flags:
824 \list
825 \li Qt::WA_WState_Created The widget has a valid winId().
826 \li Qt::WA_WState_Visible The widget is currently visible.
827 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
828 become visible unless you call show() on it. Qt::WA_WState_Hidden
829 implies !Qt::WA_WState_Visible.
830 \li Qt::WA_WState_CompressKeys Compress keyboard events.
831 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
832 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
833 \li Qt::WA_WState_Reparented The widget has been reparented.
834 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
835 \li Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
836 \endlist
837*/
838
839struct QWidgetExceptionCleaner
840{
841 /* this cleans up when the constructor throws an exception */
842 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
843 {
844#ifdef QT_NO_EXCEPTIONS
845 Q_UNUSED(that);
846 Q_UNUSED(d);
847#else
848 QWidgetPrivate::allWidgets->remove(that);
849 if (d->focus_next != that) {
850 if (d->focus_next)
851 d->focus_next->d_func()->focus_prev = d->focus_prev;
852 if (d->focus_prev)
853 d->focus_prev->d_func()->focus_next = d->focus_next;
854 }
855#endif
856 }
857};
858
859/*!
860 Constructs a widget which is a child of \a parent, with widget
861 flags set to \a f.
862
863 If \a parent is \nullptr, the new widget becomes a window. If
864 \a parent is another widget, this widget becomes a child window
865 inside \a parent. The new widget is deleted when its \a parent is
866 deleted.
867
868 The widget flags argument, \a f, is normally 0, but it can be set
869 to customize the frame of a window (i.e. \a parent must be
870 \nullptr). To customize the frame, use a value composed
871 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
872
873 If you add a child widget to an already visible widget you must
874 explicitly show the child to make it visible.
875
876 Note that the X11 version of Qt may not be able to deliver all
877 combinations of style flags on all systems. This is because on
878 X11, Qt can only ask the window manager, and the window manager
879 can override the application's settings. On Windows, Qt can set
880 whatever flags you want.
881
882 \sa windowFlags
883*/
884QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
885 : QObject(*new QWidgetPrivate, nullptr), QPaintDevice()
886{
887 QT_TRY {
888 d_func()->init(parent, f);
889 } QT_CATCH(...) {
890 QWidgetExceptionCleaner::cleanup(this, d_func());
891 QT_RETHROW;
892 }
893}
894
895
896/*! \internal
897*/
898QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
899 : QObject(dd, nullptr), QPaintDevice()
900{
901 Q_D(QWidget);
902 QT_TRY {
903 d->init(parent, f);
904 } QT_CATCH(...) {
905 QWidgetExceptionCleaner::cleanup(this, d_func());
906 QT_RETHROW;
907 }
908}
909
910/*!
911 \internal
912*/
913int QWidget::devType() const
914{
915 return QInternal::Widget;
916}
917
918
919//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
920void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
921{
922 bool customize = (flags & (Qt::CustomizeWindowHint
923 | Qt::FramelessWindowHint
924 | Qt::WindowTitleHint
925 | Qt::WindowSystemMenuHint
926 | Qt::WindowMinimizeButtonHint
927 | Qt::WindowMaximizeButtonHint
928 | Qt::WindowCloseButtonHint
929 | Qt::WindowContextHelpButtonHint));
930
931 uint type = (flags & Qt::WindowType_Mask);
932
933 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
934 type = Qt::Window;
935 flags |= Qt::Window;
936 }
937
938 if (flags & Qt::CustomizeWindowHint) {
939 // modify window flags to make them consistent.
940 // Only enable this on non-Mac platforms. Since the old way of doing this would
941 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
942 // we can't just add this in.
943 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
944# ifdef Q_OS_WIN
945 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
946# endif
947 ) {
948 flags |= Qt::WindowSystemMenuHint;
949 flags |= Qt::WindowTitleHint;
950 flags &= ~Qt::FramelessWindowHint;
951 }
952 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
953 // if any of the window hints that affect the titlebar are set
954 // and the window is supposed to have frame, we add a titlebar
955 // and system menu by default.
956 flags |= Qt::WindowSystemMenuHint;
957 flags |= Qt::WindowTitleHint;
958 }
959 if (customize)
960 ; // don't modify window flags if the user explicitly set them.
961 else if (type == Qt::Dialog || type == Qt::Sheet) {
962 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
963 // ### fixme: Qt 6: Never set Qt::WindowContextHelpButtonHint flag automatically
964 if (!QApplicationPrivate::testAttribute(Qt::AA_DisableWindowContextHelpButton))
965 flags |= Qt::WindowContextHelpButtonHint;
966 } else if (type == Qt::Tool)
967 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
968 else
969 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint |
970 Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint;
971 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
972 flags |= Qt::WindowTransparentForInput;
973}
974
975void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
976{
977 Q_Q(QWidget);
978 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
979
980 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
981 qFatal("QWidget: Cannot create a QWidget without QApplication");
982
983 Q_ASSERT(allWidgets);
984 if (allWidgets)
985 allWidgets->insert(q);
986
987 int targetScreen = -1;
988 if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
989 const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
990 targetScreen = sw ? sw->screenNumber() : 0;
991 parentWidget = nullptr;
992 }
993
994 q->data = &data;
995
996#if QT_CONFIG(thread)
997 if (!parent) {
998 Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
999 "Widgets must be created in the GUI thread.");
1000 }
1001#endif
1002
1003 if (targetScreen >= 0) {
1004 topData()->initialScreenIndex = targetScreen;
1005 if (QWindow *window = q->windowHandle())
1006 window->setScreen(QGuiApplication::screens().value(targetScreen, nullptr));
1007 }
1008
1009 data.fstrut_dirty = true;
1010
1011 data.winid = 0;
1012 data.widget_attributes = 0;
1013 data.window_flags = f;
1014 data.window_state = 0;
1015 data.focus_policy = 0;
1016 data.context_menu_policy = Qt::DefaultContextMenu;
1017 data.window_modality = Qt::NonModal;
1018
1019 data.sizehint_forced = 0;
1020 data.is_closing = 0;
1021 data.in_show = 0;
1022 data.in_set_window_state = 0;
1023 data.in_destructor = false;
1024
1025 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
1026 if (f & Qt::MSWindowsOwnDC) {
1027 mustHaveWindowHandle = 1;
1028 q->setAttribute(Qt::WA_NativeWindow);
1029 }
1030
1031 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
1032 adjustQuitOnCloseAttribute();
1033
1034 q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
1035 q->setAttribute(Qt::WA_WState_Hidden);
1036
1037 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
1038 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
1039 focus_next = focus_prev = q;
1040
1041 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
1042 q->create();
1043 else if (parentWidget)
1044 q->setParent(parentWidget, data.window_flags);
1045 else {
1046 adjustFlags(data.window_flags, q);
1047 resolveLayoutDirection();
1048 // opaque system background?
1049 const QBrush &background = q->palette().brush(QPalette::Window);
1050 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1051 }
1052 data.fnt = QFont(data.fnt, q);
1053
1054 q->setAttribute(Qt::WA_PendingMoveEvent);
1055 q->setAttribute(Qt::WA_PendingResizeEvent);
1056
1057 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1058 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1059
1060 if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
1061 q->create();
1062
1063 QEvent e(QEvent::Create);
1064 QCoreApplication::sendEvent(q, &e);
1065 QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1066
1067 extraPaintEngine = nullptr;
1068}
1069
1070void QWidgetPrivate::createRecursively()
1071{
1072 Q_Q(QWidget);
1073 q->create(0, true, true);
1074 for (int i = 0; i < children.size(); ++i) {
1075 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1076 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1077 child->d_func()->createRecursively();
1078 }
1079}
1080
1081QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1082{
1083 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1084 if (QTLWExtra *x = maybeTopData()) {
1085 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1086 return x->window;
1087 }
1088 }
1089 if (mode == WindowHandleMode::Closest) {
1090 if (auto nativeParent = q_func()->nativeParentWidget()) {
1091 if (auto window = nativeParent->windowHandle())
1092 return window;
1093 }
1094 }
1095 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1096 if (auto topLevel = q_func()->topLevelWidget()) {
1097 if (auto window = topLevel ->windowHandle())
1098 return window;
1099 }
1100 }
1101 return nullptr;
1102}
1103
1104QScreen *QWidgetPrivate::associatedScreen() const
1105{
1106 if (auto window = windowHandle(WindowHandleMode::Closest))
1107 return window->screen();
1108 return nullptr;
1109}
1110
1111// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1112
1113/*!
1114 Creates a new widget window.
1115
1116 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1117 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1118 QWindow wrapping a foreign window and pass it to
1119 QWidget::createWindowContainer() instead.
1120
1121 \sa createWindowContainer(), QWindow::fromWinId()
1122*/
1123
1124void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1125{
1126 Q_UNUSED(initializeWindow);
1127 Q_UNUSED(destroyOldWindow);
1128
1129 Q_D(QWidget);
1130 if (Q_UNLIKELY(window))
1131 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1132 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1133 return;
1134
1135 if (d->data.in_destructor)
1136 return;
1137
1138 Qt::WindowType type = windowType();
1139 Qt::WindowFlags &flags = data->window_flags;
1140
1141 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1142 type = Qt::Window;
1143 flags |= Qt::Window;
1144 }
1145
1146 if (QWidget *parent = parentWidget()) {
1147 if (type & Qt::Window) {
1148 if (!parent->testAttribute(Qt::WA_WState_Created))
1149 parent->createWinId();
1150 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1151 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1152 // We're about to create a native child widget that doesn't have a native parent;
1153 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1154 // attribute is set.
1155 d->createWinId();
1156 // Nothing more to do.
1157 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1158 Q_ASSERT(internalWinId());
1159 return;
1160 }
1161 }
1162
1163
1164 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1165 if (paintOnScreenEnv)
1166 setAttribute(Qt::WA_PaintOnScreen);
1167
1168 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1169 setAttribute(Qt::WA_NativeWindow);
1170
1171#ifdef ALIEN_DEBUG
1172 qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
1173 << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
1174#endif
1175
1176 d->updateIsOpaque();
1177
1178 setAttribute(Qt::WA_WState_Created); // set created flag
1179 d->create();
1180
1181 // A real toplevel window needs a paint manager
1182 if (isWindow() && windowType() != Qt::Desktop)
1183 d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1184
1185 d->setModal_sys();
1186
1187 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1188 setAttribute(Qt::WA_DropSiteRegistered, true);
1189
1190 // need to force the resting of the icon after changing parents
1191 if (testAttribute(Qt::WA_SetWindowIcon))
1192 d->setWindowIcon_sys();
1193
1194 if (isWindow() && !d->topData()->iconText.isEmpty())
1195 d->setWindowIconText_helper(d->topData()->iconText);
1196 if (isWindow() && !d->topData()->caption.isEmpty())
1197 d->setWindowTitle_helper(d->topData()->caption);
1198 if (isWindow() && !d->topData()->filePath.isEmpty())
1199 d->setWindowFilePath_helper(d->topData()->filePath);
1200 if (windowType() != Qt::Desktop) {
1201 d->updateSystemBackground();
1202
1203 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1204 d->setWindowIcon_sys();
1205 }
1206
1207 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1208 // as those force native window creation on their ancestors before they are shown.
1209 // If the strut is not updated, any subsequent move of the top level window before show
1210 // will cause window frame to be ignored when positioning the window.
1211 // Note that this only helps on platforms that handle window creation synchronously.
1212 d->updateFrameStrut();
1213}
1214
1215void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1216{
1217 QObjectList children = parentWidget->children();
1218 for (int i = 0; i < children.size(); i++) {
1219 if (children.at(i)->isWidgetType()) {
1220 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1221 if (childWidget) { // should not be necessary
1222 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1223 if (!childWidget->internalWinId())
1224 childWidget->winId();
1225 if (childWidget->windowHandle()) {
1226 if (childWidget->isWindow()) {
1227 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1228 } else {
1229 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1230 }
1231 }
1232 } else {
1233 q_createNativeChildrenAndSetParent(childWidget);
1234 }
1235 }
1236 }
1237 }
1238
1239}
1240
1241void QWidgetPrivate::create()
1242{
1243 Q_Q(QWidget);
1244
1245 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1246 return; // we only care about real toplevels
1247
1248 QWidgetWindow *win = topData()->window;
1249 // topData() ensures the extra is created but does not ensure 'window' is non-null
1250 // in case the extra was already valid.
1251 if (!win) {
1252 createTLSysExtra();
1253 win = topData()->window;
1254 }
1255
1256 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1257 for (const QByteArray &propertyName : dynamicPropertyNames) {
1258 if (!qstrncmp(propertyName, "_q_platform_", 12))
1259 win->setProperty(propertyName, q->property(propertyName));
1260 }
1261
1262 Qt::WindowFlags &flags = data.window_flags;
1263
1264#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
1265 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1266 flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1267#endif
1268
1269 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1270 win->setProperty("_q_showWithoutActivating", QVariant(true));
1271 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1272 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1273 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1274 win->setFlags(flags);
1275 fixPosIncludesFrame();
1276 if (q->testAttribute(Qt::WA_Moved)
1277 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1278 win->setGeometry(q->geometry());
1279 else
1280 win->resize(q->size());
1281 if (win->isTopLevel()) {
1282 int screenNumber = topData()->initialScreenIndex;
1283 topData()->initialScreenIndex = -1;
1284 if (screenNumber < 0) {
1285 screenNumber = q->windowType() != Qt::Desktop
1286 ? QDesktopWidgetPrivate::screenNumber(q) : 0;
1287 }
1288 win->setScreen(QGuiApplication::screens().value(screenNumber, nullptr));
1289 }
1290
1291 QSurfaceFormat format = win->requestedFormat();
1292 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1293 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1294 format.setAlphaBufferSize(8);
1295 }
1296 win->setFormat(format);
1297
1298 if (QWidget *nativeParent = q->nativeParentWidget()) {
1299 if (nativeParent->windowHandle()) {
1300 if (flags & Qt::Window) {
1301 win->setTransientParent(nativeParent->window()->windowHandle());
1302 win->setParent(nullptr);
1303 } else {
1304 win->setTransientParent(nullptr);
1305 win->setParent(nativeParent->windowHandle());
1306 }
1307 }
1308 }
1309
1310 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1311 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1312
1313 if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
1314 win->create();
1315 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1316 if (QPlatformWindow *platformWindow = win->handle())
1317 platformWindow->setFrameStrutEventsEnabled(true);
1318 }
1319
1320 data.window_flags = win->flags();
1321 if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1322 data.window_flags &= ~Qt::ForeignWindow;
1323
1324 if (!topData()->role.isNull())
1325 QXcbWindowFunctions::setWmWindowRole(win, topData()->role.toLatin1());
1326
1327 QBackingStore *store = q->backingStore();
1328
1329 if (!store) {
1330 if (q->windowType() != Qt::Desktop) {
1331 if (q->isTopLevel())
1332 q->setBackingStore(new QBackingStore(win));
1333 } else {
1334 q->setAttribute(Qt::WA_PaintOnScreen, true);
1335 }
1336 }
1337
1338 setWindowModified_helper();
1339
1340 if (win->handle()) {
1341 WId id = win->winId();
1342 // See the QPlatformWindow::winId() documentation
1343 Q_ASSERT(id != WId(0));
1344 setWinId(id);
1345 }
1346
1347 // Check children and create windows for them if necessary
1348 q_createNativeChildrenAndSetParent(q);
1349
1350 if (extra && !extra->mask.isEmpty())
1351 setMask_sys(extra->mask);
1352
1353 if (data.crect.width() == 0 || data.crect.height() == 0) {
1354 q->setAttribute(Qt::WA_OutsideWSRange, true);
1355 } else if (q->isVisible()) {
1356 // If widget is already shown, set window visible, too
1357 win->setNativeWindowVisibility(true);
1358 }
1359}
1360
1361#ifdef Q_OS_WIN
1362static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1363#endif
1364
1365void QWidgetPrivate::createTLSysExtra()
1366{
1367 Q_Q(QWidget);
1368 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1369 extra->topextra->window = new QWidgetWindow(q);
1370 if (extra->minw || extra->minh)
1371 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1372 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1373 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1374 if (extra->topextra->opacity != 255 && q->isWindow())
1375 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1376
1377 const bool isTipLabel = q->inherits("QTipLabel");
1378 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1379#ifdef Q_OS_WIN
1380 // Pass on native parent handle for Widget embedded into Active X.
1381 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1382 if (activeXNativeParentHandle.isValid())
1383 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1384 if (isTipLabel || isAlphaWidget)
1385 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1386#endif
1387 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1388 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1389 }
1390
1391}
1392
1393/*!
1394 Destroys the widget.
1395
1396 All this widget's children are deleted first. The application
1397 exits if this widget is the main widget.
1398*/
1399
1400QWidget::~QWidget()
1401{
1402 Q_D(QWidget);
1403 d->data.in_destructor = true;
1404
1405#if defined (QT_CHECK_STATE)
1406 if (Q_UNLIKELY(paintingActive()))
1407 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1408#endif
1409
1410#ifndef QT_NO_GESTURES
1411 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1412 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1413 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1414 manager->cleanupCachedGestures(this, *it);
1415 }
1416 d->gestureContext.clear();
1417#endif
1418
1419#ifndef QT_NO_ACTION
1420 // remove all actions from this widget
1421 for (int i = 0; i < d->actions.size(); ++i) {
1422 QActionPrivate *apriv = d->actions.at(i)->d_func();
1423 apriv->widgets.removeAll(this);
1424 }
1425 d->actions.clear();
1426#endif
1427
1428#ifndef QT_NO_SHORTCUT
1429 // Remove all shortcuts grabbed by this
1430 // widget, unless application is closing
1431 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1432 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1433#endif
1434
1435 // delete layout while we still are a valid widget
1436 delete d->layout;
1437 d->layout = nullptr;
1438 // Remove myself from focus list
1439
1440 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1441 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1442
1443 if (d->focus_next != this) {
1444 d->focus_next->d_func()->focus_prev = d->focus_prev;
1445 d->focus_prev->d_func()->focus_next = d->focus_next;
1446 d->focus_next = d->focus_prev = nullptr;
1447 }
1448
1449
1450 QT_TRY {
1451#if QT_CONFIG(graphicsview)
1452 const QWidget* w = this;
1453 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1454 w = w->d_func()->extra->focus_proxy;
1455 QWidget *window = w->window();
1456 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1457 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1458#endif
1459 clearFocus();
1460 } QT_CATCH(...) {
1461 // swallow this problem because we are in a destructor
1462 }
1463
1464 d->setDirtyOpaqueRegion();
1465
1466 if (isWindow() && isVisible() && internalWinId()) {
1467 QT_TRY {
1468 d->close_helper(QWidgetPrivate::CloseNoEvent);
1469 } QT_CATCH(...) {
1470 // if we're out of memory, at least hide the window.
1471 QT_TRY {
1472 hide();
1473 } QT_CATCH(...) {
1474 // and if that also doesn't work, then give up
1475 }
1476 }
1477 } else if (isVisible()) {
1478 qApp->d_func()->sendSyntheticEnterLeave(this);
1479 }
1480
1481 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1482 repaintManager->removeDirtyWidget(this);
1483 if (testAttribute(Qt::WA_StaticContents))
1484 repaintManager->removeStaticWidget(this);
1485 }
1486
1487 delete d->needsFlush;
1488 d->needsFlush = nullptr;
1489
1490 // The next 20 lines are duplicated from QObject, but required here
1491 // since QWidget deletes is children itself
1492 bool blocked = d->blockSig;
1493 d->blockSig = 0; // unblock signals so we always emit destroyed()
1494
1495 if (d->isSignalConnected(0)) {
1496 QT_TRY {
1497 emit destroyed(this);
1498 } QT_CATCH(...) {
1499 // all the signal/slots connections are still in place - if we don't
1500 // quit now, we will crash pretty soon.
1501 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1502 QT_RETHROW;
1503 }
1504 }
1505
1506 if (d->declarativeData) {
1507 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1508 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1509 if (QAbstractDeclarativeData::destroyed_qml1)
1510 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1511 } else {
1512 if (QAbstractDeclarativeData::destroyed)
1513 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1514 }
1515 d->declarativeData = nullptr; // don't activate again in ~QObject
1516 d->wasDeleted = false;
1517 }
1518
1519 d->blockSig = blocked;
1520
1521 if (!d->children.isEmpty())
1522 d->deleteChildren();
1523
1524 QCoreApplication::removePostedEvents(this);
1525
1526 QT_TRY {
1527 destroy(); // platform-dependent cleanup
1528 } QT_CATCH(...) {
1529 // if this fails we can't do anything about it but at least we are not allowed to throw.
1530 }
1531 --QWidgetPrivate::instanceCounter;
1532
1533 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1534 QWidgetPrivate::allWidgets->remove(this);
1535
1536 QT_TRY {
1537 QEvent e(QEvent::Destroy);
1538 QCoreApplication::sendEvent(this, &e);
1539 } QT_CATCH(const std::exception&) {
1540 // if this fails we can't do anything about it but at least we are not allowed to throw.
1541 }
1542
1543#if QT_CONFIG(graphicseffect)
1544 delete d->graphicsEffect;
1545#endif
1546}
1547
1548int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1549int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1550
1551void QWidgetPrivate::setWinId(WId id) // set widget identifier
1552{
1553 Q_Q(QWidget);
1554 // the user might create a widget with Qt::Desktop window
1555 // attribute (or create another QDesktopWidget instance), which
1556 // will have the same windowid (the root window id) as the
1557 // qt_desktopWidget. We should not add the second desktop widget
1558 // to the mapper.
1559 bool userDesktopWidget = qt_desktopWidget != nullptr && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
1560 if (mapper && data.winid && !userDesktopWidget) {
1561 mapper->remove(data.winid);
1562 }
1563
1564 const WId oldWinId = data.winid;
1565
1566 data.winid = id;
1567 if (mapper && id && !userDesktopWidget) {
1568 mapper->insert(data.winid, q);
1569 }
1570
1571 if(oldWinId != id) {
1572 QEvent e(QEvent::WinIdChange);
1573 QCoreApplication::sendEvent(q, &e);
1574 }
1575}
1576
1577void QWidgetPrivate::createTLExtra()
1578{
1579 if (!extra)
1580 createExtra();
1581 if (!extra->topextra) {
1582 extra->topextra = qt_make_unique<QTLWExtra>();
1583 QTLWExtra* x = extra->topextra.get();
1584 x->backingStore = nullptr;
1585 x->sharedPainter = nullptr;
1586 x->incw = x->inch = 0;
1587 x->basew = x->baseh = 0;
1588 x->frameStrut.setCoords(0, 0, 0, 0);
1589 x->normalGeometry = QRect(0,0,-1,-1);
1590 x->savedFlags = { };
1591 x->opacity = 255;
1592 x->posIncludesFrame = 0;
1593 x->sizeAdjusted = false;
1594 x->embedded = 0;
1595 x->window = nullptr;
1596 x->initialScreenIndex = -1;
1597
1598#ifdef QWIDGET_EXTRA_DEBUG
1599 static int count = 0;
1600 qDebug() << "tlextra" << ++count;
1601#endif
1602 }
1603}
1604
1605/*!
1606 \internal
1607 Creates the widget extra data.
1608*/
1609
1610void QWidgetPrivate::createExtra()
1611{
1612 if (!extra) { // if not exists
1613 extra = qt_make_unique<QWExtra>();
1614 extra->glContext = nullptr;
1615#if QT_CONFIG(graphicsview)
1616 extra->proxyWidget = nullptr;
1617#endif
1618 extra->minw = 0;
1619 extra->minh = 0;
1620 extra->maxw = QWIDGETSIZE_MAX;
1621 extra->maxh = QWIDGETSIZE_MAX;
1622 extra->customDpiX = 0;
1623 extra->customDpiY = 0;
1624 extra->explicitMinSize = 0;
1625 extra->explicitMaxSize = 0;
1626 extra->autoFillBackground = 0;
1627 extra->nativeChildrenForced = 0;
1628 extra->inRenderWithPainter = 0;
1629 extra->hasWindowContainer = false;
1630 extra->hasMask = 0;
1631 createSysExtra();
1632#ifdef QWIDGET_EXTRA_DEBUG
1633 static int count = 0;
1634 qDebug() << "extra" << ++count;
1635#endif
1636 }
1637}
1638
1639void QWidgetPrivate::createSysExtra()
1640{
1641}
1642
1643/*!
1644 \internal
1645 Deletes the widget extra data.
1646*/
1647
1648void QWidgetPrivate::deleteExtra()
1649{
1650 if (extra) { // if exists
1651 deleteSysExtra();
1652#ifndef QT_NO_STYLE_STYLESHEET
1653 // dereference the stylesheet style
1654 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1655 proxy->deref();
1656#endif
1657 if (extra->topextra) {
1658 deleteTLSysExtra();
1659 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1660 }
1661 // extra->xic destroyed in QWidget::destroy()
1662 extra.reset();
1663 }
1664}
1665
1666void QWidgetPrivate::deleteSysExtra()
1667{
1668}
1669
1670static void deleteBackingStore(QWidgetPrivate *d)
1671{
1672 QTLWExtra *topData = d->topData();
1673
1674 delete topData->backingStore;
1675 topData->backingStore = nullptr;
1676}
1677
1678void QWidgetPrivate::deleteTLSysExtra()
1679{
1680 if (extra && extra->topextra) {
1681 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1682 //needs to be deleted first.
1683
1684 extra->topextra->repaintManager.reset(nullptr);
1685 deleteBackingStore(this);
1686#ifndef QT_NO_OPENGL
1687 extra->topextra->widgetTextures.clear();
1688 extra->topextra->shareContext.reset();
1689#endif
1690
1691 //the toplevel might have a context with a "qglcontext associated with it. We need to
1692 //delete the qglcontext before we delete the qplatformopenglcontext.
1693 //One unfortunate thing about this is that we potentially create a glContext just to
1694 //delete it straight afterwards.
1695 if (extra->topextra->window) {
1696 extra->topextra->window->destroy();
1697 }
1698 delete extra->topextra->window;
1699 extra->topextra->window = nullptr;
1700
1701 }
1702}
1703
1704/*
1705 Returns \c region of widgets above this which overlap with
1706 \a rect, which is in parent's coordinate system (same as crect).
1707*/
1708
1709QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1710{
1711 Q_Q(const QWidget);
1712
1713 const QWidget *w = q;
1714 QRect r = rect;
1715 QPoint p;
1716 QRegion region;
1717 while (w) {
1718 if (w->isWindow())
1719 break;
1720 QWidgetPrivate *pd = w->parentWidget()->d_func();
1721 bool above = false;
1722 for (int i = 0; i < pd->children.size(); ++i) {
1723 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1724 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1725 continue;
1726 if (!above) {
1727 above = (sibling == w);
1728 continue;
1729 }
1730
1731 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1732 if (qRectIntersects(siblingRect, r)) {
1733 const auto &siblingExtra = sibling->d_func()->extra;
1734 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1735 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1736 continue;
1737 }
1738 region += siblingRect.translated(-p);
1739 if (breakAfterFirst)
1740 break;
1741 }
1742 }
1743 w = w->parentWidget();
1744 r.translate(pd->data.crect.topLeft());
1745 p += pd->data.crect.topLeft();
1746 }
1747 return region;
1748}
1749
1750void QWidgetPrivate::syncBackingStore()
1751{
1752 if (shouldPaintOnScreen()) {
1753 paintOnScreen(dirty);
1754 dirty = QRegion();
1755 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1756 repaintManager->sync();
1757 }
1758}
1759
1760void QWidgetPrivate::syncBackingStore(const QRegion &region)
1761{
1762 if (shouldPaintOnScreen())
1763 paintOnScreen(region);
1764 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1765 repaintManager->sync(q_func(), region);
1766 }
1767}
1768
1769void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1770{
1771 if (data.in_destructor)
1772 return;
1773
1774 if (shouldDiscardSyncRequest())
1775 return;
1776
1777 Q_Q(QWidget);
1778 if (q->testAttribute(Qt::WA_StaticContents)) {
1779 if (!extra)
1780 createExtra();
1781 extra->staticContentsSize = data.crect.size();
1782 }
1783
1784 QPaintEngine *engine = q->paintEngine();
1785
1786 // QGLWidget does not support partial updates if:
1787 // 1) The context is double buffered
1788 // 2) The context is single buffered and auto-fill background is enabled.
1789 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1790 || engine->type() == QPaintEngine::OpenGL2))
1791 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1792 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1793
1794 toBePainted &= clipRect();
1795 clipToEffectiveMask(toBePainted);
1796 if (toBePainted.isEmpty())
1797 return; // Nothing to repaint.
1798
1799 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1800
1801 if (Q_UNLIKELY(q->paintingActive()))
1802 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1803}
1804
1805void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1806{
1807 Q_Q(QWidget);
1808
1809 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1810 return; // nothing we can do
1811
1812 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1813 return; // nothing to do
1814
1815 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1816 if (enable)
1817 q->update();
1818
1819 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1820 for (int i = 0; i < children.size(); ++i) {
1821 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1822 if (w && !w->isWindow() && !w->testAttribute(attribute))
1823 w->d_func()->setUpdatesEnabled_helper(enable);
1824 }
1825}
1826
1827/*!
1828 \internal
1829
1830 Propagate this widget's palette to all children, except style sheet
1831 widgets, and windows that don't enable window propagation (palettes don't
1832 normally propagate to windows).
1833*/
1834void QWidgetPrivate::propagatePaletteChange()
1835{
1836 Q_Q(QWidget);
1837 // Propagate a new inherited mask to all children.
1838#if QT_CONFIG(graphicsview)
1839 if (!q->parentWidget() && extra && extra->proxyWidget) {
1840 QGraphicsProxyWidget *p = extra->proxyWidget;
1841 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
1842 } else
1843#endif // QT_CONFIG(graphicsview)
1844 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1845 inheritedPaletteResolveMask = 0;
1846 }
1847
1848 directPaletteResolveMask = data.pal.resolve();
1849 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1850
1851 const bool useStyleSheetPropagationInWidgetStyles =
1852 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1853
1854 QEvent pc(QEvent::PaletteChange);
1855 QCoreApplication::sendEvent(q, &pc);
1856 for (int i = 0; i < children.size(); ++i) {
1857 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1858 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1859 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1860 QWidgetPrivate *wd = w->d_func();
1861 wd->inheritedPaletteResolveMask = mask;
1862 wd->resolvePalette();
1863 }
1864 }
1865}
1866
1867/*
1868 Returns the widget's clipping rectangle.
1869*/
1870QRect QWidgetPrivate::clipRect() const
1871{
1872 Q_Q(const QWidget);
1873 const QWidget * w = q;
1874 if (!w->isVisible())
1875 return QRect();
1876 QRect r = effectiveRectFor(q->rect());
1877 int ox = 0;
1878 int oy = 0;
1879 while (w
1880 && w->isVisible()
1881 && !w->isWindow()
1882 && w->parentWidget()) {
1883 ox -= w->x();
1884 oy -= w->y();
1885 w = w->parentWidget();
1886 r &= QRect(ox, oy, w->width(), w->height());
1887 }
1888 return r;
1889}
1890
1891/*
1892 Returns the widget's clipping region (without siblings).
1893*/
1894QRegion QWidgetPrivate::clipRegion() const
1895{
1896 Q_Q(const QWidget);
1897 if (!q->isVisible())
1898 return QRegion();
1899 QRegion r(q->rect());
1900 const QWidget * w = q;
1901 const QWidget *ignoreUpTo;
1902 int ox = 0;
1903 int oy = 0;
1904 while (w
1905 && w->isVisible()
1906 && !w->isWindow()
1907 && w->parentWidget()) {
1908 ox -= w->x();
1909 oy -= w->y();
1910 ignoreUpTo = w;
1911 w = w->parentWidget();
1912 r &= QRegion(ox, oy, w->width(), w->height());
1913
1914 int i = 0;
1915 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1916 ;
1917 for ( ; i < w->d_func()->children.size(); ++i) {
1918 if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1919 if(sibling->isVisible() && !sibling->isWindow()) {
1920 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1921 sibling->width(), sibling->height());
1922 if (qRectIntersects(siblingRect, q->rect()))
1923 r -= QRegion(siblingRect);
1924 }
1925 }
1926 }
1927 }
1928 return r;
1929}
1930
1931void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1932{
1933// Transform the system clip region from device-independent pixels to device pixels
1934 QTransform scaleTransform;
1935 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1936
1937 paintEngine->d_func()->baseSystemClip = region;
1938 paintEngine->d_func()->setSystemTransform(scaleTransform);
1939
1940}
1941
1942#if QT_CONFIG(graphicseffect)
1943void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1944{
1945 Q_Q(QWidget);
1946 QWidget *w = q;
1947 do {
1948 if (w->graphicsEffect()) {
1949 QWidgetEffectSourcePrivate *sourced =
1950 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1951 if (!sourced->updateDueToGraphicsEffect)
1952 w->graphicsEffect()->source()->d_func()->invalidateCache();
1953 }
1954 w = w->parentWidget();
1955 } while (w);
1956}
1957#endif // QT_CONFIG(graphicseffect)
1958
1959void QWidgetPrivate::setDirtyOpaqueRegion()
1960{
1961 Q_Q(QWidget);
1962
1963 dirtyOpaqueChildren = true;
1964
1965#if QT_CONFIG(graphicseffect)
1966 invalidateGraphicsEffectsRecursively();
1967#endif // QT_CONFIG(graphicseffect)
1968
1969 if (q->isWindow())
1970 return;
1971
1972 QWidget *parent = q->parentWidget();
1973 if (!parent)
1974 return;
1975
1976 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1977 QWidgetPrivate *pd = parent->d_func();
1978 if (!pd->dirtyOpaqueChildren)
1979 pd->setDirtyOpaqueRegion();
1980}
1981
1982const QRegion &QWidgetPrivate::getOpaqueChildren() const
1983{
1984 if (!dirtyOpaqueChildren)
1985 return opaqueChildren;
1986
1987 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
1988 that->opaqueChildren = QRegion();
1989
1990 for (int i = 0; i < children.size(); ++i) {
1991 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1992 if (!child || !child->isVisible() || child->isWindow())
1993 continue;
1994
1995 const QPoint offset = child->geometry().topLeft();
1996 QWidgetPrivate *childd = child->d_func();
1997 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
1998 if (childd->extra && childd->extra->hasMask)
1999 r &= childd->extra->mask;
2000 if (r.isEmpty())
2001 continue;
2002 r.translate(offset);
2003 that->opaqueChildren += r;
2004 }
2005
2006 that->opaqueChildren &= q_func()->rect();
2007 that->dirtyOpaqueChildren = false;
2008
2009 return that->opaqueChildren;
2010}
2011
2012void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2013{
2014 if (children.isEmpty() || clipRect.isEmpty())
2015 return;
2016
2017 const QRegion &r = getOpaqueChildren();
2018 if (!r.isEmpty())
2019 source -= (r & clipRect);
2020}
2021
2022//subtract any relatives that are higher up than me --- this is too expensive !!!
2023void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2024 bool alsoNonOpaque) const
2025{
2026 Q_Q(const QWidget);
2027 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2028 if (disableSubtractOpaqueSiblings || q->isWindow())
2029 return;
2030
2031 QRect clipBoundingRect;
2032 bool dirtyClipBoundingRect = true;
2033
2034 QRegion parentClip;
2035 bool dirtyParentClip = true;
2036
2037 QPoint parentOffset = data.crect.topLeft();
2038
2039 const QWidget *w = q;
2040
2041 while (w) {
2042 if (w->isWindow())
2043 break;
2044 QWidgetPrivate *pd = w->parentWidget()->d_func();
2045 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2046 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2047 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2048 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2049 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2050 continue;
2051
2052 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2053 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2054 continue;
2055
2056 if (dirtyClipBoundingRect) {
2057 clipBoundingRect = sourceRegion.boundingRect();
2058 dirtyClipBoundingRect = false;
2059 }
2060
2061 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2062 continue;
2063
2064 if (dirtyParentClip) {
2065 parentClip = sourceRegion.translated(parentOffset);
2066 dirtyParentClip = false;
2067 }
2068
2069 const QPoint siblingPos(sibling->data->crect.topLeft());
2070 const QRect siblingClipRect(sibling->d_func()->clipRect());
2071 QRegion siblingDirty(parentClip);
2072 siblingDirty &= (siblingClipRect.translated(siblingPos));
2073 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2074 && !sibling->d_func()->graphicsEffect;
2075 if (hasMask)
2076 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2077 if (siblingDirty.isEmpty())
2078 continue;
2079
2080 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2081 if (hasMask) {
2082 siblingDirty.translate(-parentOffset);
2083 sourceRegion -= siblingDirty;
2084 } else {
2085 sourceRegion -= siblingGeometry.translated(-parentOffset);
2086 }
2087 } else {
2088 if (hasDirtySiblingsAbove)
2089 *hasDirtySiblingsAbove = true;
2090 if (sibling->d_func()->children.isEmpty())
2091 continue;
2092 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2093 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2094 sourceRegion -= opaqueSiblingChildren;
2095 }
2096 if (sourceRegion.isEmpty())
2097 return;
2098
2099 dirtyClipBoundingRect = true;
2100 dirtyParentClip = true;
2101 }
2102
2103 w = w->parentWidget();
2104 parentOffset += pd->data.crect.topLeft();
2105 dirtyParentClip = true;
2106 }
2107}
2108
2109void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2110{
2111 Q_Q(const QWidget);
2112
2113 const QWidget *w = q;
2114 QPoint offset;
2115
2116#if QT_CONFIG(graphicseffect)
2117 if (graphicsEffect) {
2118 w = q->parentWidget();
2119 offset -= data.crect.topLeft();
2120 }
2121#endif // QT_CONFIG(graphicseffect)
2122
2123 while (w) {
2124 const QWidgetPrivate *wd = w->d_func();
2125 if (wd->extra && wd->extra->hasMask)
2126 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2127 if (w->isWindow())
2128 return;
2129 offset -= wd->data.crect.topLeft();
2130 w = w->parentWidget();
2131 }
2132}
2133
2134bool QWidgetPrivate::shouldPaintOnScreen() const
2135{
2136#if defined(QT_NO_BACKINGSTORE)
2137 return true;
2138#else
2139 Q_Q(const QWidget);
2140 if (q->testAttribute(Qt::WA_PaintOnScreen)
2141 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2142 return true;
2143 }
2144
2145 return false;
2146#endif
2147}
2148
2149void QWidgetPrivate::updateIsOpaque()
2150{
2151 // hw: todo: only needed if opacity actually changed
2152 setDirtyOpaqueRegion();
2153
2154#if QT_CONFIG(graphicseffect)
2155 if (graphicsEffect) {
2156 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2157 setOpaque(false);
2158 return;
2159 }
2160#endif // QT_CONFIG(graphicseffect)
2161
2162 Q_Q(QWidget);
2163 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2164 setOpaque(true);
2165 return;
2166 }
2167
2168 const QPalette &pal = q->palette();
2169
2170 if (q->autoFillBackground()) {
2171 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2172 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2173 setOpaque(true);
2174 return;
2175 }
2176 }
2177
2178 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2179 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2180 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2181 setOpaque(true);
2182 return;
2183 }
2184 }
2185 setOpaque(false);
2186}
2187
2188void QWidgetPrivate::setOpaque(bool opaque)
2189{
2190 if (isOpaque != opaque) {
2191 isOpaque = opaque;
2192 updateIsTranslucent();
2193 }
2194}
2195
2196void QWidgetPrivate::updateIsTranslucent()
2197{
2198 Q_Q(QWidget);
2199 if (QWindow *window = q->windowHandle()) {
2200 QSurfaceFormat format = window->format();
2201 const int oldAlpha = format.alphaBufferSize();
2202 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2203 if (oldAlpha != newAlpha) {
2204 format.setAlphaBufferSize(newAlpha);
2205 window->setFormat(format);
2206 }
2207 }
2208}
2209
2210static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2211{
2212 Q_ASSERT(painter);
2213
2214 if (brush.style() == Qt::TexturePattern) {
2215 const QRect rect(rgn.boundingRect());
2216 painter->setClipRegion(rgn);
2217 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2218 } else if (brush.gradient()
2219 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2220 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2221 painter->save();
2222 painter->setClipRegion(rgn);
2223 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2224 painter->restore();
2225 } else {
2226 for (const QRect &rect : rgn)
2227 painter->fillRect(rect, brush);
2228 }
2229}
2230
2231bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2232{
2233#if QT_CONFIG(scrollarea)
2234 Q_Q(const QWidget);
2235 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2236 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2237 return false;
2238 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2239 if (scrollArea && scrollArea->viewport() == q) {
2240 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2241 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2242 painter->setBrushOrigin(-priv->contentsOffset());
2243 }
2244#endif // QT_CONFIG(scrollarea)
2245 return true;
2246}
2247
2248void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2249{
2250 Q_Q(const QWidget);
2251
2252 bool brushOriginSet = false;
2253 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2254
2255 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2256 const QBrush bg = q->palette().brush(QPalette::Window);
2257 if (!brushOriginSet)
2258 brushOriginSet = updateBrushOrigin(painter, bg);
2259 if (!(flags & DontSetCompositionMode)) {
2260 //copy alpha straight in
2261 QPainter::CompositionMode oldMode = painter->compositionMode();
2262 painter->setCompositionMode(QPainter::CompositionMode_Source);
2263 fillRegion(painter, rgn, bg);
2264 painter->setCompositionMode(oldMode);
2265 } else {
2266 fillRegion(painter, rgn, bg);
2267 }
2268 }
2269
2270 if (q->autoFillBackground()) {
2271 if (!brushOriginSet)
2272 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2273 fillRegion(painter, rgn, autoFillBrush);
2274 }
2275
2276 if (q->testAttribute(Qt::WA_StyledBackground)) {
2277 painter->setClipRegion(rgn);
2278 QStyleOption opt;
2279 opt.initFrom(q);
2280 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2281 }
2282}
2283
2284/*
2285 \internal
2286 This function is called when a widget is hidden or destroyed.
2287 It resets some application global pointers that should only refer active,
2288 visible widgets.
2289*/
2290
2291extern QWidget *qt_button_down;
2292
2293void QWidgetPrivate::deactivateWidgetCleanup()
2294{
2295 Q_Q(QWidget);
2296 // If this was the active application window, reset it
2297 if (QApplication::activeWindow() == q)
2298 QApplication::setActiveWindow(nullptr);
2299 // If the is the active mouse press widget, reset it
2300 if (q == qt_button_down)
2301 qt_button_down = nullptr;
2302}
2303
2304
2305/*!
2306 Returns a pointer to the widget with window identifer/handle \a
2307 id.
2308
2309 The window identifier type depends on the underlying window
2310 system, see \c qwindowdefs.h for the actual definition. If there
2311 is no widget with this identifier, \nullptr is returned.
2312*/
2313
2314QWidget *QWidget::find(WId id)
2315{
2316 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2317}
2318
2319
2320
2321/*!
2322 \fn WId QWidget::internalWinId() const
2323 \internal
2324 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2325
2326*/
2327
2328/*!
2329 \fn WId QWidget::winId() const
2330
2331 Returns the window system identifier of the widget.
2332
2333 Portable in principle, but if you use it you are probably about to
2334 do something non-portable. Be careful.
2335
2336 If a widget is non-native (alien) and winId() is invoked on it, that widget
2337 will be provided a native handle.
2338
2339 This value may change at run-time. An event with type QEvent::WinIdChange
2340 will be sent to the widget following a change in window system identifier.
2341
2342 \sa find()
2343*/
2344WId QWidget::winId() const
2345{
2346 if (!data->in_destructor
2347 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2348 {
2349#ifdef ALIEN_DEBUG
2350 qDebug() << "QWidget::winId: creating native window for" << this;
2351#endif
2352 QWidget *that = const_cast<QWidget*>(this);
2353 that->setAttribute(Qt::WA_NativeWindow);
2354 that->d_func()->createWinId();
2355 return that->data->winid;
2356 }
2357 return data->winid;
2358}
2359
2360void QWidgetPrivate::createWinId()
2361{
2362 Q_Q(QWidget);
2363
2364#ifdef ALIEN_DEBUG
2365 qDebug() << "QWidgetPrivate::createWinId for" << q;
2366#endif
2367 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2368 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2369 if (!q->isWindow()) {
2370 QWidget *parent = q->parentWidget();
2371 QWidgetPrivate *pd = parent->d_func();
2372 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2373 parent->setAttribute(Qt::WA_NativeWindow);
2374 if (!parent->internalWinId()) {
2375 pd->createWinId();
2376 }
2377
2378 for (int i = 0; i < pd->children.size(); ++i) {
2379 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2380 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2381 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2382 w->create();
2383 }
2384 }
2385 } else {
2386 q->create();
2387 }
2388 }
2389}
2390
2391/*!
2392\internal
2393Ensures that the widget is set on the screen point is on. This is handy getting a correct
2394size hint before a resize in e.g QMenu and QToolTip.
2395Returns if the screen was changed.
2396*/
2397
2398bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2399{
2400 Q_Q(QWidget);
2401 if (!q->isWindow())
2402 return false;
2403 // Find the screen for pos and make the widget understand it is on that screen.
2404 return setScreen(QGuiApplication::screenAt(pos));
2405}
2406
2407/*!
2408\internal
2409Ensures that the widget's QWindow is set to be on the given \a screen.
2410Returns true if the screen was changed.
2411*/
2412
2413bool QWidgetPrivate::setScreen(QScreen *screen)
2414{
2415 Q_Q(QWidget);
2416 if (!screen || !q->isWindow())
2417 return false;
2418 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2419 if (currentScreen != screen) {
2420 if (!windowHandle()) // Try to create a window handle if not created.
2421 createWinId();
2422 if (windowHandle())
2423 windowHandle()->setScreen(screen);
2424 return true;
2425 }
2426 return false;
2427}
2428
2429/*!
2430\internal
2431Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2432
2433*/
2434
2435void QWidget::createWinId()
2436{
2437 Q_D(QWidget);
2438#ifdef ALIEN_DEBUG
2439 qDebug() << "QWidget::createWinId" << this;
2440#endif
2441// qWarning("QWidget::createWinId is obsolete, please fix your code.");
2442 d->createWinId();
2443}
2444
2445/*!
2446 \since 4.4
2447
2448 Returns the effective window system identifier of the widget, i.e. the
2449 native parent's window system identifier.
2450
2451 If the widget is native, this function returns the native widget ID.
2452 Otherwise, the window ID of the first native parent widget, i.e., the
2453 top-level widget that contains this widget, is returned.
2454
2455 \note We recommend that you do not store this value as it is likely to
2456 change at run-time.
2457
2458 \sa nativeParentWidget()
2459*/
2460WId QWidget::effectiveWinId() const
2461{
2462 const WId id = internalWinId();
2463 if (id || !testAttribute(Qt::WA_WState_Created))
2464 return id;
2465 if (const QWidget *realParent = nativeParentWidget())
2466 return realParent->internalWinId();
2467 return 0;
2468}
2469
2470/*!
2471 If this is a native widget, return the associated QWindow.
2472 Otherwise return null.
2473
2474 Native widgets include toplevel widgets, QGLWidget, and child widgets
2475 on which winId() was called.
2476
2477 \since 5.0
2478
2479 \sa winId(), screen()
2480*/
2481QWindow *QWidget::windowHandle() const
2482{
2483 Q_D(const QWidget);
2484 return d->windowHandle();
2485}
2486
2487/*!
2488 Returns the screen the widget is on.
2489
2490 \since 5.14
2491
2492 \sa windowHandle()
2493*/
2494QScreen *QWidget::screen() const
2495{
2496 Q_D(const QWidget);
2497 if (auto associatedScreen = d->associatedScreen())
2498 return associatedScreen;
2499 if (auto topLevel = window()) {
2500 if (auto topData = qt_widget_private(topLevel)->topData()) {
2501 if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex))
2502 return initialScreen;
2503 }
2504 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2505 return screenByPos;
2506 }
2507 return QGuiApplication::primaryScreen();
2508}
2509
2510#ifndef QT_NO_STYLE_STYLESHEET
2511
2512/*!
2513 \property QWidget::styleSheet
2514 \brief the widget's style sheet
2515 \since 4.2
2516
2517 The style sheet contains a textual description of customizations to the
2518 widget's style, as described in the \l{Qt Style Sheets} document.
2519
2520 Since Qt 4.5, Qt style sheets fully supports \macos.
2521
2522 \warning Qt style sheets are currently not supported for custom QStyle
2523 subclasses. We plan to address this in some future release.
2524
2525 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2526*/
2527QString QWidget::styleSheet() const
2528{
2529 Q_D(const QWidget);
2530 if (!d->extra)
2531 return QString();
2532 return d->extra->styleSheet;
2533}
2534
2535void QWidget::setStyleSheet(const QString& styleSheet)
2536{
2537 Q_D(QWidget);
2538 if (data->in_destructor)
2539 return;
2540 d->createExtra();
2541
2542 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2543 d->extra->styleSheet = styleSheet;
2544 if (styleSheet.isEmpty()) { // stylesheet removed
2545 if (!proxy)
2546 return;
2547
2548 d->inheritStyle();
2549 return;
2550 }
2551
2552 if (proxy) { // style sheet update
2553 if (d->polished)
2554 proxy->repolish(this);
2555 return;
2556 }
2557
2558 if (testAttribute(Qt::WA_SetStyle)) {
2559 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2560 } else {
2561 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2562 }
2563}
2564
2565#endif // QT_NO_STYLE_STYLESHEET
2566
2567/*!
2568 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2569*/
2570
2571QStyle *QWidget::style() const
2572{
2573 Q_D(const QWidget);
2574
2575 if (d->extra && d->extra->style)
2576 return d->extra->style;
2577 return QApplication::style();
2578}
2579
2580/*!
2581 Sets the widget's GUI style to \a style. The ownership of the style
2582 object is not transferred.
2583
2584 If no style is set, the widget uses the application's style,
2585 QApplication::style() instead.
2586
2587 Setting a widget's style has no effect on existing or future child
2588 widgets.
2589
2590 \warning This function is particularly useful for demonstration
2591 purposes, where you want to show Qt's styling capabilities. Real
2592 applications should avoid it and use one consistent GUI style
2593 instead.
2594
2595 \warning Qt style sheets are currently not supported for custom QStyle
2596 subclasses. We plan to address this in some future release.
2597
2598 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2599*/
2600
2601void QWidget::setStyle(QStyle *style)
2602{
2603 Q_D(QWidget);
2604 setAttribute(Qt::WA_SetStyle, style != nullptr);
2605 d->createExtra();
2606#ifndef QT_NO_STYLE_STYLESHEET
2607 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2608 //if for some reason someone try to set a QStyleSheetStyle, ref it
2609 //(this may happen for exemple in QButtonDialogBox which propagates its style)
2610 styleSheetStyle->ref();
2611 d->setStyle_helper(style, false);
2612 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2613 // if we have an application stylesheet or have a proxy already, propagate
2614 d->setStyle_helper(new QStyleSheetStyle(style), true);
2615 } else
2616#endif
2617 d->setStyle_helper(style, false);
2618}
2619
2620void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2621{
2622 Q_Q(QWidget);
2623 QStyle *oldStyle = q->style();
2624
2625 createExtra();
2626
2627#ifndef QT_NO_STYLE_STYLESHEET
2628 QPointer<QStyle> origStyle = extra->style;
2629#endif
2630 extra->style = newStyle;
2631
2632 // repolish
2633 if (polished && q->windowType() != Qt::Desktop) {
2634 oldStyle->unpolish(q);
2635 q->style()->polish(q);
2636 }
2637
2638 if (propagate) {
2639 // We copy the list because the order may be modified
2640 const QObjectList childrenList = children;
2641 for (int i = 0; i < childrenList.size(); ++i) {
2642 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2643 if (c)
2644 c->d_func()->inheritStyle();
2645 }
2646 }
2647
2648#ifndef QT_NO_STYLE_STYLESHEET
2649 if (!qt_styleSheet(newStyle)) {
2650 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2651 cssStyle->clearWidgetFont(q);
2652 }
2653 }
2654#endif
2655
2656 QEvent e(QEvent::StyleChange);
2657 QCoreApplication::sendEvent(q, &e);
2658
2659#ifndef QT_NO_STYLE_STYLESHEET
2660 // dereference the old stylesheet style
2661 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2662 proxy->deref();
2663#endif
2664}
2665
2666// Inherits style from the current parent and propagates it as necessary
2667void QWidgetPrivate::inheritStyle()
2668{
2669#ifndef QT_NO_STYLE_STYLESHEET
2670 Q_Q(QWidget);
2671
2672 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2673
2674 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2675
2676 if (!q->styleSheet().isEmpty()) {
2677 Q_ASSERT(proxy);
2678 proxy->repolish(q);
2679 return;
2680 }
2681
2682 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2683 QWidget *parent = q->parentWidget();
2684 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2685 // If we have stylesheet on app or parent has stylesheet style, we need
2686 // to be running a proxy
2687 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2688 QStyle *newStyle = parentStyle;
2689 if (q->testAttribute(Qt::WA_SetStyle))
2690 newStyle = new QStyleSheetStyle(origStyle);
2691 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2692 newProxy->ref();
2693
2694 setStyle_helper(newStyle, true);
2695 return;
2696 }
2697
2698 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2699 // we just need our original style back
2700 if (origStyle == extraStyle) // is it any different?
2701 return;
2702
2703 // We could have inherited the proxy from our parent (which has a custom style)
2704 // In such a case we need to start following the application style (i.e revert
2705 // the propagation behavior of QStyleSheetStyle)
2706 if (!q->testAttribute(Qt::WA_SetStyle))
2707 origStyle = nullptr;
2708
2709 setStyle_helper(origStyle, true);
2710#endif // QT_NO_STYLE_STYLESHEET
2711}
2712
2713
2714/*!
2715 \fn bool QWidget::isWindow() const
2716
2717 Returns \c true if the widget is an independent window, otherwise
2718 returns \c false.
2719
2720 A window is a widget that isn't visually the child of any other
2721 widget and that usually has a frame and a
2722 \l{QWidget::setWindowTitle()}{window title}.
2723
2724 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2725 It will then be grouped with its parent and deleted when the
2726 parent is deleted, minimized when the parent is minimized etc. If
2727 supported by the window manager, it will also have a common
2728 taskbar entry with its parent.
2729
2730 QDialog and QMainWindow widgets are by default windows, even if a
2731 parent widget is specified in the constructor. This behavior is
2732 specified by the Qt::Window flag.
2733
2734 \sa window(), isModal(), parentWidget()
2735*/
2736
2737/*!
2738 \property QWidget::modal
2739 \brief whether the widget is a modal widget
2740
2741 This property only makes sense for windows. A modal widget
2742 prevents widgets in all other windows from getting any input.
2743
2744 By default, this property is \c false.
2745
2746 \sa isWindow(), windowModality, QDialog
2747*/
2748
2749/*!
2750 \property QWidget::windowModality
2751 \brief which windows are blocked by the modal widget
2752 \since 4.1
2753
2754 This property only makes sense for windows. A modal widget
2755 prevents widgets in other windows from getting input. The value of
2756 this property controls which windows are blocked when the widget
2757 is visible. Changing this property while the window is visible has
2758 no effect; you must hide() the widget first, then show() it again.
2759
2760 By default, this property is Qt::NonModal.
2761
2762 \sa isWindow(), QWidget::modal, QDialog
2763*/
2764
2765Qt::WindowModality QWidget::windowModality() const
2766{
2767 return static_cast<Qt::WindowModality>(data->window_modality);
2768}
2769
2770void QWidget::setWindowModality(Qt::WindowModality windowModality)
2771{
2772 data->window_modality = windowModality;
2773 // setModal_sys() will be called by setAttribute()
2774 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2775 setAttribute(Qt::WA_SetWindowModality, true);
2776}
2777
2778void QWidgetPrivate::setModal_sys()
2779{
2780 Q_Q(QWidget);
2781 if (q->windowHandle())
2782 q->windowHandle()->setModality(q->windowModality());
2783}
2784
2785/*!
2786 \fn bool QWidget::underMouse() const
2787
2788 Returns \c true if the widget is under the mouse cursor; otherwise
2789 returns \c false.
2790
2791 This value is not updated properly during drag and drop
2792 operations.
2793
2794 \sa enterEvent(), leaveEvent()
2795*/
2796
2797/*!
2798 \property QWidget::minimized
2799 \brief whether this widget is minimized (iconified)
2800
2801 This property is only relevant for windows.
2802
2803 By default, this property is \c false.
2804
2805 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2806*/
2807bool QWidget::isMinimized() const
2808{ return data->window_state & Qt::WindowMinimized; }
2809
2810/*!
2811 Shows the widget minimized, as an icon.
2812
2813 Calling this function only affects \l{isWindow()}{windows}.
2814
2815 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2816 isMinimized()
2817*/
2818void QWidget::showMinimized()
2819{
2820 bool isMin = isMinimized();
2821 if (isMin && isVisible())
2822 return;
2823
2824 ensurePolished();
2825
2826 if (!isMin)
2827 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2828 setVisible(true);
2829}
2830
2831/*!
2832 \property QWidget::maximized
2833 \brief whether this widget is maximized
2834
2835 This property is only relevant for windows.
2836
2837 \note Due to limitations on some window systems, this does not always
2838 report the expected results (e.g., if the user on X11 maximizes the
2839 window via the window manager, Qt has no way of distinguishing this
2840 from any other resize). This is expected to improve as window manager
2841 protocols evolve.
2842
2843 By default, this property is \c false.
2844
2845 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2846*/
2847bool QWidget::isMaximized() const
2848{ return data->window_state & Qt::WindowMaximized; }
2849
2850
2851
2852/*!
2853 Returns the current window state. The window state is a OR'ed
2854 combination of Qt::WindowState: Qt::WindowMinimized,
2855 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2856
2857 \sa Qt::WindowState, setWindowState()
2858 */
2859Qt::WindowStates QWidget::windowState() const
2860{
2861 return Qt::WindowStates(data->window_state);
2862}
2863
2864/*!\internal
2865
2866 The function sets the window state on child widgets similar to
2867 setWindowState(). The difference is that the window state changed
2868 event has the isOverride() flag set. It exists mainly to keep
2869 QWorkspace working.
2870 */
2871void QWidget::overrideWindowState(Qt::WindowStates newstate)
2872{
2873 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2874 data->window_state = newstate;
2875 QCoreApplication::sendEvent(this, &e);
2876}
2877
2878/*!
2879 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2880
2881 Sets the window state to \a windowState. The window state is a OR'ed
2882 combination of Qt::WindowState: Qt::WindowMinimized,
2883 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2884
2885 If the window is not visible (i.e. isVisible() returns \c false), the
2886 window state will take effect when show() is called. For visible
2887 windows, the change is immediate. For example, to toggle between
2888 full-screen and normal mode, use the following code:
2889
2890 \snippet code/src_gui_kernel_qwidget.cpp 0
2891
2892 In order to restore and activate a minimized window (while
2893 preserving its maximized and/or full-screen state), use the following:
2894
2895 \snippet code/src_gui_kernel_qwidget.cpp 1
2896
2897 Calling this function will hide the widget. You must call show() to make
2898 the widget visible again.
2899
2900 \note On some window systems Qt::WindowActive is not immediate, and may be
2901 ignored in certain cases.
2902
2903 When the window state changes, the widget receives a changeEvent()
2904 of type QEvent::WindowStateChange.
2905
2906 \sa Qt::WindowState, windowState()
2907*/
2908void QWidget::setWindowState(Qt::WindowStates newstate)
2909{
2910 Q_D(QWidget);
2911 Qt::WindowStates oldstate = windowState();
2912 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2913 newstate.setFlag(Qt::WindowActive, false);
2914 if (oldstate == newstate)
2915 return;
2916 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2917 create();
2918
2919 data->window_state = newstate;
2920 data->in_set_window_state = 1;
2921 if (isWindow()) {
2922 // Ensure the initial size is valid, since we store it as normalGeometry below.
2923 if (!testAttribute(Qt::WA_Resized) && !isVisible())
2924 adjustSize();
2925
2926 d->createTLExtra();
2927 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2928 d->topData()->normalGeometry = geometry();
2929
2930 Q_ASSERT(windowHandle());
2931 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2932 }
2933 data->in_set_window_state = 0;
2934
2935 if (newstate & Qt::WindowActive)
2936 activateWindow();
2937
2938 QWindowStateChangeEvent e(oldstate);
2939 QCoreApplication::sendEvent(this, &e);
2940}
2941
2942/*!
2943 \property QWidget::fullScreen
2944 \brief whether the widget is shown in full screen mode
2945
2946 A widget in full screen mode occupies the whole screen area and does not
2947 display window decorations, such as a title bar.
2948
2949 By default, this property is \c false.
2950
2951 \sa windowState(), minimized, maximized
2952*/
2953bool QWidget::isFullScreen() const
2954{ return data->window_state & Qt::WindowFullScreen; }
2955
2956/*!
2957 Shows the widget in full-screen mode.
2958
2959 Calling this function only affects \l{isWindow()}{windows}.
2960
2961 To return from full-screen mode, call showNormal().
2962
2963 Full-screen mode works fine under Windows, but has certain
2964 problems under X. These problems are due to limitations of the
2965 ICCCM protocol that specifies the communication between X11
2966 clients and the window manager. ICCCM simply does not understand
2967 the concept of non-decorated full-screen windows. Therefore, the
2968 best we can do is to request a borderless window and place and
2969 resize it to fill the entire screen. Depending on the window
2970 manager, this may or may not work. The borderless window is
2971 requested using MOTIF hints, which are at least partially
2972 supported by virtually all modern window managers.
2973
2974 An alternative would be to bypass the window manager entirely and
2975 create a window with the Qt::X11BypassWindowManagerHint flag. This
2976 has other severe problems though, like totally broken keyboard focus
2977 and very strange effects on desktop changes or when the user raises
2978 other windows.
2979
2980 X11 window managers that follow modern post-ICCCM specifications
2981 support full-screen mode properly.
2982
2983 \sa showNormal(), showMaximized(), show(), hide(), isVisible()
2984*/
2985void QWidget::showFullScreen()
2986{
2987 ensurePolished();
2988
2989 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
2990 | Qt::WindowFullScreen);
2991 setVisible(true);
2992#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
2993 // activating it here before libscreen activates it causes problems
2994 activateWindow();
2995#endif
2996}
2997
2998/*!
2999 Shows the widget maximized.
3000
3001 Calling this function only affects \l{isWindow()}{windows}.
3002
3003 On X11, this function may not work properly with certain window
3004 managers. See the \l{Window Geometry} documentation for an explanation.
3005
3006 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3007*/
3008void QWidget::showMaximized()
3009{
3010 ensurePolished();
3011
3012 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3013 | Qt::WindowMaximized);
3014 setVisible(true);
3015}
3016
3017/*!
3018 Restores the widget after it has been maximized or minimized.
3019
3020 Calling this function only affects \l{isWindow()}{windows}.
3021
3022 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3023*/
3024void QWidget::showNormal()
3025{
3026 ensurePolished();
3027
3028 setWindowState(windowState() & ~(Qt::WindowMinimized
3029 | Qt::WindowMaximized
3030 | Qt::WindowFullScreen));
3031 setVisible(true);
3032}
3033
3034/*!
3035 Returns \c true if this widget would become enabled if \a ancestor is
3036 enabled; otherwise returns \c false.
3037
3038
3039
3040 This is the case if neither the widget itself nor every parent up
3041 to but excluding \a ancestor has been explicitly disabled.
3042
3043 isEnabledTo(0) returns false if this widget or any if its ancestors
3044 was explicitly disabled.
3045
3046 The word ancestor here means a parent widget within the same window.
3047
3048 Therefore isEnabledTo(0) stops at this widget's window, unlike
3049 isEnabled() which also takes parent windows into considerations.
3050
3051 \sa setEnabled(), enabled
3052*/
3053
3054bool QWidget::isEnabledTo(const QWidget *ancestor) const
3055{
3056 const QWidget * w = this;
3057 while (!w->testAttribute(Qt::WA_ForceDisabled)
3058 && !w->isWindow()
3059 && w->parentWidget()
3060 && w->parentWidget() != ancestor)
3061 w = w->parentWidget();
3062 return !w->testAttribute(Qt::WA_ForceDisabled);
3063}
3064
3065#ifndef QT_NO_ACTION
3066/*!
3067 Appends the action \a action to this widget's list of actions.
3068
3069 All QWidgets have a list of \l{QAction}s, however they can be
3070 represented graphically in many different ways. The default use of
3071 the QAction list (as returned by actions()) is to create a context
3072 QMenu.
3073
3074 A QWidget should only have one of each action and adding an action
3075 it already has will not cause the same action to be in the widget twice.
3076
3077 The ownership of \a action is not transferred to this QWidget.
3078
3079 \sa removeAction(), insertAction(), actions(), QMenu
3080*/
3081void QWidget::addAction(QAction *action)
3082{
3083 insertAction(nullptr, action);
3084}
3085
3086/*!
3087 Appends the actions \a actions to this widget's list of actions.
3088
3089 \sa removeAction(), QMenu, addAction()
3090*/
3091#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3092void QWidget::addActions(const QList<QAction *> &actions)
3093#else
3094void QWidget::addActions(QList<QAction*> actions)
3095#endif
3096{
3097 for(int i = 0; i < actions.count(); i++)
3098 insertAction(nullptr, actions.at(i));
3099}
3100
3101/*!
3102 Inserts the action \a action to this widget's list of actions,
3103 before the action \a before. It appends the action if \a before is \nullptr or
3104 \a before is not a valid action for this widget.
3105
3106 A QWidget should only have one of each action.
3107
3108 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3109*/
3110void QWidget::insertAction(QAction *before, QAction *action)
3111{
3112 if (Q_UNLIKELY(!action)) {
3113 qWarning("QWidget::insertAction: Attempt to insert null action");
3114 return;
3115 }
3116
3117 Q_D(QWidget);
3118 if(d->actions.contains(action))
3119 removeAction(action);
3120
3121 int pos = d->actions.indexOf(before);
3122 if (pos < 0) {
3123 before = nullptr;
3124 pos = d->actions.size();
3125 }
3126 d->actions.insert(pos, action);
3127
3128 QActionPrivate *apriv = action->d_func();
3129 apriv->widgets.append(this);
3130
3131 QActionEvent e(QEvent::ActionAdded, action, before);
3132 QCoreApplication::sendEvent(this, &e);
3133}
3134
3135/*!
3136 Inserts the actions \a actions to this widget's list of actions,
3137 before the action \a before. It appends the action if \a before is \nullptr or
3138 \a before is not a valid action for this widget.
3139
3140 A QWidget can have at most one of each action.
3141
3142 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3143*/
3144#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3145void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3146#else
3147void QWidget::insertActions(QAction *before, QList<QAction*> actions)
3148#endif
3149{
3150 for(int i = 0; i < actions.count(); ++i)
3151 insertAction(before, actions.at(i));
3152}
3153
3154/*!
3155 Removes the action \a action from this widget's list of actions.
3156 \sa insertAction(), actions(), insertAction()
3157*/
3158void QWidget::removeAction(QAction *action)
3159{
3160 if (!action)
3161 return;
3162
3163 Q_D(QWidget);
3164
3165 QActionPrivate *apriv = action->d_func();
3166 apriv->widgets.removeAll(this);
3167
3168 if (d->actions.removeAll(action)) {
3169 QActionEvent e(QEvent::ActionRemoved, action);
3170 QCoreApplication::sendEvent(this, &e);
3171 }
3172}
3173
3174/*!
3175 Returns the (possibly empty) list of this widget's actions.
3176
3177 \sa contextMenuPolicy, insertAction(), removeAction()
3178*/
3179QList<QAction*> QWidget::actions() const
3180{
3181 Q_D(const QWidget);
3182 return d->actions;
3183}
3184#endif // QT_NO_ACTION
3185
3186/*!
3187 \fn bool QWidget::isEnabledToTLW() const
3188 \obsolete
3189
3190 This function is deprecated. It is equivalent to isEnabled()
3191*/
3192
3193/*!
3194 \property QWidget::enabled
3195 \brief whether the widget is enabled
3196
3197 In general an enabled widget handles keyboard and mouse events; a disabled
3198 widget does not. An exception is made with \l{QAbstractButton}.
3199
3200 Some widgets display themselves differently when they are
3201 disabled. For example a button might draw its label grayed out. If
3202 your widget needs to know when it becomes enabled or disabled, you
3203 can use the changeEvent() with type QEvent::EnabledChange.
3204
3205 Disabling a widget implicitly disables all its children. Enabling
3206 respectively enables all child widgets unless they have been
3207 explicitly disabled. It it not possible to explicitly enable a child
3208 widget which is not a window while its parent widget remains disabled.
3209
3210 By default, this property is \c true.
3211
3212 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3213*/
3214void QWidget::setEnabled(bool enable)
3215{
3216 Q_D(QWidget);
3217 setAttribute(Qt::WA_ForceDisabled, !enable);
3218 d->setEnabled_helper(enable);
3219}
3220
3221void QWidgetPrivate::setEnabled_helper(bool enable)
3222{
3223 Q_Q(QWidget);
3224
3225 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3226 return; // nothing we can do
3227
3228 if (enable != q->testAttribute(Qt::WA_Disabled))
3229 return; // nothing to do
3230
3231 q->setAttribute(Qt::WA_Disabled, !enable);
3232 updateSystemBackground();
3233
3234 if (!enable && q->window()->focusWidget() == q) {
3235 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3236 if (!parentIsEnabled || !q->focusNextChild())
3237 q->clearFocus();
3238 }
3239
3240 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3241 for (int i = 0; i < children.size(); ++i) {
3242 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3243 if (w && !w->testAttribute(attribute))
3244 w->d_func()->setEnabled_helper(enable);
3245 }
3246#ifndef QT_NO_CURSOR
3247 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3248 // enforce the windows behavior of clearing the cursor on
3249 // disabled widgets
3250 qt_qpa_set_cursor(q, false);
3251 }
3252#endif
3253#ifndef QT_NO_IM
3254 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3255 QWidget *focusWidget = effectiveFocusWidget();
3256
3257 if (enable) {
3258 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3259 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3260 } else {
3261 QGuiApplication::inputMethod()->commit();
3262 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3263 }
3264 }
3265#endif //QT_NO_IM
3266 QEvent e(QEvent::EnabledChange);
3267 QCoreApplication::sendEvent(q, &e);
3268}
3269
3270/*!
3271 \property QWidget::acceptDrops
3272 \brief whether drop events are enabled for this widget
3273
3274 Setting this property to true announces to the system that this
3275 widget \e may be able to accept drop events.
3276
3277 If the widget is the desktop (windowType() == Qt::Desktop), this may
3278 fail if another application is using the desktop; you can call
3279 acceptDrops() to test if this occurs.
3280
3281 \warning Do not modify this property in a drag and drop event handler.
3282
3283 By default, this property is \c false.
3284
3285 \sa {Drag and Drop}
3286*/
3287bool QWidget::acceptDrops() const
3288{
3289 return testAttribute(Qt::WA_AcceptDrops);
3290}
3291
3292void QWidget::setAcceptDrops(bool on)
3293{
3294 setAttribute(Qt::WA_AcceptDrops, on);
3295
3296}
3297
3298/*!
3299 Disables widget input events if \a disable is true; otherwise
3300 enables input events.
3301
3302 See the \l enabled documentation for more information.
3303
3304 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3305*/
3306void QWidget::setDisabled(bool disable)
3307{
3308 setEnabled(!disable);
3309}
3310
3311/*!
3312 \property QWidget::frameGeometry
3313 \brief geometry of the widget relative to its parent including any
3314 window frame
3315
3316 See the \l{Window Geometry} documentation for an overview of geometry
3317 issues with windows.
3318
3319 By default, this property contains a value that depends on the user's
3320 platform and screen geometry.
3321
3322 \sa geometry(), x(), y(), pos()
3323*/
3324QRect QWidget::frameGeometry() const
3325{
3326 Q_D(const QWidget);
3327 if (isWindow() && ! (windowType() == Qt::Popup)) {
3328 QRect fs = d->frameStrut();
3329 return QRect(data->crect.x() - fs.left(),
3330 data->crect.y() - fs.top(),
3331 data->crect.width() + fs.left() + fs.right(),
3332 data->crect.height() + fs.top() + fs.bottom());
3333 }
3334 return data->crect;
3335}
3336
3337/*!
3338 \property QWidget::x
3339
3340 \brief the x coordinate of the widget relative to its parent including
3341 any window frame
3342
3343 See the \l{Window Geometry} documentation for an overview of geometry
3344 issues with windows.
3345
3346 By default, this property has a value of 0.
3347
3348 \sa frameGeometry, y, pos
3349*/
3350int QWidget::x() const
3351{
3352 Q_D(const QWidget);
3353 if (isWindow() && ! (windowType() == Qt::Popup))
3354 return data->crect.x() - d->frameStrut().left();
3355 return data->crect.x();
3356}
3357
3358/*!
3359 \property QWidget::y
3360 \brief the y coordinate of the widget relative to its parent and
3361 including any window frame
3362
3363 See the \l{Window Geometry} documentation for an overview of geometry
3364 issues with windows.
3365
3366 By default, this property has a value of 0.
3367
3368 \sa frameGeometry, x, pos
3369*/
3370int QWidget::y() const
3371{
3372 Q_D(const QWidget);
3373 if (isWindow() && ! (windowType() == Qt::Popup))
3374 return data->crect.y() - d->frameStrut().top();
3375 return data->crect.y();
3376}
3377
3378/*!
3379 \property QWidget::pos
3380 \brief the position of the widget within its parent widget
3381
3382 If the widget is a window, the position is that of the widget on
3383 the desktop, including its frame.
3384
3385 When changing the position, the widget, if visible, receives a
3386 move event (moveEvent()) immediately. If the widget is not
3387 currently visible, it is guaranteed to receive an event before it
3388 is shown.
3389
3390 By default, this property contains a position that refers to the
3391 origin.
3392
3393 \warning Calling move() or setGeometry() inside moveEvent() can
3394 lead to infinite recursion.
3395
3396 See the \l{Window Geometry} documentation for an overview of geometry
3397 issues with windows.
3398
3399 \sa frameGeometry, size, x(), y()
3400*/
3401QPoint QWidget::pos() const
3402{
3403 Q_D(const QWidget);
3404 QPoint result = data->crect.topLeft();
3405 if (isWindow() && ! (windowType() == Qt::Popup))
3406 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3407 result -= d->frameStrut().topLeft();
3408 return result;
3409}
3410
3411/*!
3412 \property QWidget::geometry
3413 \brief the geometry of the widget relative to its parent and
3414 excluding the window frame
3415
3416 When changing the geometry, the widget, if visible, receives a
3417 move event (moveEvent()) and/or a resize event (resizeEvent())
3418 immediately. If the widget is not currently visible, it is
3419 guaranteed to receive appropriate events before it is shown.
3420
3421 The size component is adjusted if it lies outside the range
3422 defined by minimumSize() and maximumSize().
3423
3424 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3425 can lead to infinite recursion.
3426
3427 See the \l{Window Geometry} documentation for an overview of geometry
3428 issues with windows.
3429
3430 By default, this property contains a value that depends on the user's
3431 platform and screen geometry.
3432
3433 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3434 resizeEvent(), minimumSize(), maximumSize()
3435*/
3436
3437/*!
3438 \property QWidget::normalGeometry
3439
3440 \brief the geometry of the widget as it will appear when shown as
3441 a normal (not maximized or full screen) top-level widget
3442
3443 For child widgets this property always holds an empty rectangle.
3444
3445 By default, this property contains an empty rectangle.
3446
3447 \sa QWidget::windowState(), QWidget::geometry
3448*/
3449
3450/*!
3451 \property QWidget::size
3452 \brief the size of the widget excluding any window frame
3453
3454 If the widget is visible when it is being resized, it receives a resize event
3455 (resizeEvent()) immediately. If the widget is not currently
3456 visible, it is guaranteed to receive an event before it is shown.
3457
3458 The size is adjusted if it lies outside the range defined by
3459 minimumSize() and maximumSize().
3460
3461 By default, this property contains a value that depends on the user's
3462 platform and screen geometry.
3463
3464 \warning Calling resize() or setGeometry() inside resizeEvent() can
3465 lead to infinite recursion.
3466
3467 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3468 appear on screen. This also applies to windows.
3469
3470 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3471*/
3472
3473/*!
3474 \property QWidget::width
3475 \brief the width of the widget excluding any window frame
3476
3477 See the \l{Window Geometry} documentation for an overview of geometry
3478 issues with windows.
3479
3480 \note Do not use this function to find the width of a screen on
3481 a \l{QDesktopWidget}{multiple screen desktop}. Read
3482 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3483
3484 By default, this property contains a value that depends on the user's
3485 platform and screen geometry.
3486
3487 \sa geometry, height, size
3488*/
3489
3490/*!
3491 \property QWidget::height
3492 \brief the height of the widget excluding any window frame
3493
3494 See the \l{Window Geometry} documentation for an overview of geometry
3495 issues with windows.
3496
3497 \note Do not use this function to find the height of a screen
3498 on a \l{QDesktopWidget}{multiple screen desktop}. Read
3499 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3500
3501 By default, this property contains a value that depends on the user's
3502 platform and screen geometry.
3503
3504 \sa geometry, width, size
3505*/
3506
3507/*!
3508 \property QWidget::rect
3509 \brief the internal geometry of the widget excluding any window
3510 frame
3511
3512 The rect property equals QRect(0, 0, width(), height()).
3513
3514 See the \l{Window Geometry} documentation for an overview of geometry
3515 issues with windows.
3516
3517 By default, this property contains a value that depends on the user's
3518 platform and screen geometry.
3519
3520 \sa size
3521*/
3522
3523
3524QRect QWidget::normalGeometry() const
3525{
3526 Q_D(const QWidget);
3527 if (!d->extra || !d->extra->topextra)
3528 return QRect();
3529
3530 if (!isMaximized() && !isFullScreen())
3531 return geometry();
3532
3533 return d->topData()->normalGeometry;
3534}
3535
3536
3537/*!
3538 \property QWidget::childrenRect
3539 \brief the bounding rectangle of the widget's children
3540
3541 Hidden children are excluded.
3542
3543 By default, for a widget with no children, this property contains a
3544 rectangle with zero width and height located at the origin.
3545
3546 \sa childrenRegion(), geometry()
3547*/
3548
3549QRect QWidget::childrenRect() const
3550{
3551 Q_D(const QWidget);
3552 QRect r(0, 0, 0, 0);
3553 for (int i = 0; i < d->children.size(); ++i) {
3554 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3555 if (w && !w->isWindow() && !w->isHidden())
3556 r |= w->geometry();
3557 }
3558 return r;
3559}
3560
3561/*!
3562 \property QWidget::childrenRegion
3563 \brief the combined region occupied by the widget's children
3564
3565 Hidden children are excluded.
3566
3567 By default, for a widget with no children, this property contains an
3568 empty region.
3569
3570 \sa childrenRect(), geometry(), mask()
3571*/
3572
3573QRegion QWidget::childrenRegion() const
3574{
3575 Q_D(const QWidget);
3576 QRegion r;
3577 for (int i = 0; i < d->children.size(); ++i) {
3578 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3579 if (w && !w->isWindow() && !w->isHidden()) {
3580 QRegion mask = w->mask();
3581 if (mask.isEmpty())
3582 r |= w->geometry();
3583 else
3584 r |= mask.translated(w->pos());
3585 }
3586 }
3587 return r;
3588}
3589
3590
3591/*!
3592 \property QWidget::minimumSize
3593 \brief the widget's minimum size
3594
3595 The widget cannot be resized to a smaller size than the minimum
3596 widget size. The widget's size is forced to the minimum size if
3597 the current size is smaller.
3598
3599 The minimum size set by this function will override the minimum size
3600 defined by QLayout. In order to unset the minimum size, use a
3601 value of \c{QSize(0, 0)}.
3602
3603 By default, this property contains a size with zero width and height.
3604
3605 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3606*/
3607
3608QSize QWidget::minimumSize() const
3609{
3610 Q_D(const QWidget);
3611 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3612}
3613
3614/*!
3615 \property QWidget::maximumSize
3616 \brief the widget's maximum size in pixels
3617
3618 The widget cannot be resized to a larger size than the maximum
3619 widget size.
3620
3621 By default, this property contains a size in which both width and height
3622 have values of 16777215.
3623
3624 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3625 of widgets.
3626
3627 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3628*/
3629
3630QSize QWidget::maximumSize() const
3631{
3632 Q_D(const QWidget);
3633 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3634 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3635}
3636
3637
3638/*!
3639 \property QWidget::minimumWidth
3640 \brief the widget's minimum width in pixels
3641
3642 This property corresponds to the width held by the \l minimumSize property.
3643
3644 By default, this property has a value of 0.
3645
3646 \sa minimumSize, minimumHeight
3647*/
3648
3649/*!
3650 \property QWidget::minimumHeight
3651 \brief the widget's minimum height in pixels
3652
3653 This property corresponds to the height held by the \l minimumSize property.
3654
3655 By default, this property has a value of 0.
3656
3657 \sa minimumSize, minimumWidth
3658*/
3659
3660/*!
3661 \property QWidget::maximumWidth
3662 \brief the widget's maximum width in pixels
3663
3664 This property corresponds to the width held by the \l maximumSize property.
3665
3666 By default, this property contains a value of 16777215.
3667
3668 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3669 of widgets.
3670
3671 \sa maximumSize, maximumHeight
3672*/
3673
3674/*!
3675 \property QWidget::maximumHeight
3676 \brief the widget's maximum height in pixels
3677
3678 This property corresponds to the height held by the \l maximumSize property.
3679
3680 By default, this property contains a value of 16777215.
3681
3682 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3683 of widgets.
3684
3685 \sa maximumSize, maximumWidth
3686*/
3687
3688/*!
3689 \property QWidget::sizeIncrement
3690 \brief the size increment of the widget
3691
3692 When the user resizes the window, the size will move in steps of
3693 sizeIncrement().width() pixels horizontally and
3694 sizeIncrement.height() pixels vertically, with baseSize() as the
3695 basis. Preferred widget sizes are for non-negative integers \e i
3696 and \e j:
3697 \snippet code/src_gui_kernel_qwidget.cpp 2
3698
3699 Note that while you can set the size increment for all widgets, it
3700 only affects windows.
3701
3702 By default, this property contains a size with zero width and height.
3703
3704 \warning The size increment has no effect under Windows, and may
3705 be disregarded by the window manager on X11.
3706
3707 \sa size, minimumSize, maximumSize
3708*/
3709QSize QWidget::sizeIncrement() const
3710{
3711 Q_D(const QWidget);
3712 return (d->extra && d->extra->topextra)
3713 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3714 : QSize(0, 0);
3715}
3716
3717/*!
3718 \property QWidget::baseSize
3719 \brief the base size of the widget
3720
3721 The base size is used to calculate a proper widget size if the
3722 widget defines sizeIncrement().
3723
3724 By default, for a newly-created widget, this property contains a size with
3725 zero width and height.
3726
3727 \sa setSizeIncrement()
3728*/
3729
3730QSize QWidget::baseSize() const
3731{
3732 Q_D(const QWidget);
3733 return (d->extra && d->extra->topextra)
3734 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3735 : QSize(0, 0);
3736}
3737
3738bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3739{
3740 Q_Q(QWidget);
3741
3742 int mw = minw, mh = minh;
3743 if (mw == QWIDGETSIZE_MAX)
3744 mw = 0;
3745 if (mh == QWIDGETSIZE_MAX)
3746 mh = 0;
3747 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3748 qWarning("QWidget::setMinimumSize: (%s/%s) "
3749 "The largest allowed size is (%d,%d)",
3750 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3751 QWIDGETSIZE_MAX);
3752 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3753 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3754 }
3755 if (Q_UNLIKELY(