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
120 QT_BEGIN_NAMESPACE
121
122 Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
123
qRectIntersects(const QRect & r1,const QRect & r2)124 static 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
130 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
131 extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
132
QWidgetPrivate(int version)133 QWidgetPrivate::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
~QWidgetPrivate()207 QWidgetPrivate::~QWidgetPrivate()
208 {
209 if (widgetItem)
210 widgetItem->wid = nullptr;
211
212 if (extra)
213 deleteExtra();
214 }
215
216 /*!
217 \internal
218 */
scrollChildren(int dx,int dy)219 void 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
setWSGeometry()241 void QWidgetPrivate::setWSGeometry()
242 {
243 Q_Q(QWidget);
244 if (QWindow *window = q->windowHandle())
245 window->setGeometry(data.crect);
246 }
247
updateWidgetTransform(QEvent * event)248 void 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
262 QPointer<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 */
hasEditFocus() const271 bool 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 */
setEditFocus(bool on)291 void 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 */
autoFillBackground() const346 bool QWidget::autoFillBackground() const
347 {
348 Q_D(const QWidget);
349 return d->extra && d->extra->autoFillBackground;
350 }
351
setAutoFillBackground(bool enabled)352 void 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
814 QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
815 QWidgetSet *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
839 struct QWidgetExceptionCleaner
840 {
841 /* this cleans up when the constructor throws an exception */
cleanupQWidgetExceptionCleaner842 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 */
QWidget(QWidget * parent,Qt::WindowFlags f)884 QWidget::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 */
QWidget(QWidgetPrivate & dd,QWidget * parent,Qt::WindowFlags f)898 QWidget::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 */
devType() const913 int 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
adjustFlags(Qt::WindowFlags & flags,QWidget * w)920 void 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
init(QWidget * parentWidget,Qt::WindowFlags f)975 void 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
createRecursively()1070 void 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
windowHandle(WindowHandleMode mode) const1081 QWindow *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
associatedScreen() const1104 QScreen *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
create(WId window,bool initializeWindow,bool destroyOldWindow)1124 void 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
q_createNativeChildrenAndSetParent(const QWidget * parentWidget)1215 void 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
create()1241 void 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
1362 static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1363 #endif
1364
createTLSysExtra()1365 void 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
~QWidget()1400 QWidget::~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
1548 int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1549 int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1550
setWinId(WId id)1551 void 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
createTLExtra()1577 void 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
createExtra()1610 void 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
createSysExtra()1639 void QWidgetPrivate::createSysExtra()
1640 {
1641 }
1642
1643 /*!
1644 \internal
1645 Deletes the widget extra data.
1646 */
1647
deleteExtra()1648 void 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
deleteSysExtra()1666 void QWidgetPrivate::deleteSysExtra()
1667 {
1668 }
1669
deleteBackingStore(QWidgetPrivate * d)1670 static void deleteBackingStore(QWidgetPrivate *d)
1671 {
1672 QTLWExtra *topData = d->topData();
1673
1674 delete topData->backingStore;
1675 topData->backingStore = nullptr;
1676 }
1677
deleteTLSysExtra()1678 void 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
overlappedRegion(const QRect & rect,bool breakAfterFirst) const1709 QRegion 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
syncBackingStore()1750 void QWidgetPrivate::syncBackingStore()
1751 {
1752 if (shouldPaintOnScreen()) {
1753 paintOnScreen(dirty);
1754 dirty = QRegion();
1755 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1756 repaintManager->sync();
1757 }
1758 }
1759
syncBackingStore(const QRegion & region)1760 void QWidgetPrivate::syncBackingStore(const QRegion ®ion)
1761 {
1762 if (shouldPaintOnScreen())
1763 paintOnScreen(region);
1764 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1765 repaintManager->sync(q_func(), region);
1766 }
1767 }
1768
paintOnScreen(const QRegion & rgn)1769 void 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
setUpdatesEnabled_helper(bool enable)1805 void 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 */
propagatePaletteChange()1834 void 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 */
clipRect() const1870 QRect 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 */
clipRegion() const1894 QRegion 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
setSystemClip(QPaintEngine * paintEngine,qreal devicePixelRatio,const QRegion & region)1931 void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion ®ion)
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)
invalidateGraphicsEffectsRecursively()1943 void 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
setDirtyOpaqueRegion()1959 void 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
getOpaqueChildren() const1982 const 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
subtractOpaqueChildren(QRegion & source,const QRect & clipRect) const2012 void 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 !!!
subtractOpaqueSiblings(QRegion & sourceRegion,bool * hasDirtySiblingsAbove,bool alsoNonOpaque) const2023 void 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
clipToEffectiveMask(QRegion & region) const2109 void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) 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
shouldPaintOnScreen() const2134 bool 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
updateIsOpaque()2149 void 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
setOpaque(bool opaque)2188 void QWidgetPrivate::setOpaque(bool opaque)
2189 {
2190 if (isOpaque != opaque) {
2191 isOpaque = opaque;
2192 updateIsTranslucent();
2193 }
2194 }
2195
updateIsTranslucent()2196 void 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
fillRegion(QPainter * painter,const QRegion & rgn,const QBrush & brush)2210 static 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
updateBrushOrigin(QPainter * painter,const QBrush & brush) const2231 bool 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
paintBackground(QPainter * painter,const QRegion & rgn,DrawWidgetFlags flags) const2248 void 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
2291 extern QWidget *qt_button_down;
2292
deactivateWidgetCleanup()2293 void 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
find(WId id)2314 QWidget *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 */
winId() const2344 WId 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
createWinId()2360 void 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
2393 Ensures that the widget is set on the screen point is on. This is handy getting a correct
2394 size hint before a resize in e.g QMenu and QToolTip.
2395 Returns if the screen was changed.
2396 */
2397
setScreenForPoint(const QPoint & pos)2398 bool 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
2409 Ensures that the widget's QWindow is set to be on the given \a screen.
2410 Returns true if the screen was changed.
2411 */
2412
setScreen(QScreen * screen)2413 bool 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
2431 Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2432
2433 */
2434
createWinId()2435 void 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 */
effectiveWinId() const2460 WId 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 */
windowHandle() const2481 QWindow *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 */
screen() const2494 QScreen *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 */
styleSheet() const2527 QString QWidget::styleSheet() const
2528 {
2529 Q_D(const QWidget);
2530 if (!d->extra)
2531 return QString();
2532 return d->extra->styleSheet;
2533 }
2534
setStyleSheet(const QString & styleSheet)2535 void 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
style() const2571 QStyle *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
setStyle(QStyle * style)2601 void 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
setStyle_helper(QStyle * newStyle,bool propagate)2620 void 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
inheritStyle()2667 void 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
windowModality() const2765 Qt::WindowModality QWidget::windowModality() const
2766 {
2767 return static_cast<Qt::WindowModality>(data->window_modality);
2768 }
2769
setWindowModality(Qt::WindowModality windowModality)2770 void 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
setModal_sys()2778 void 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 */
isMinimized() const2807 bool 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 */
showMinimized()2818 void 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 */
isMaximized() const2847 bool 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 */
windowState() const2859 Qt::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 */
overrideWindowState(Qt::WindowStates newstate)2871 void 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 */
setWindowState(Qt::WindowStates newstate)2908 void 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 */
isFullScreen() const2953 bool 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 */
showFullScreen()2985 void 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 */
showMaximized()3008 void 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 */
showNormal()3024 void 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
isEnabledTo(const QWidget * ancestor) const3054 bool 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 */
addAction(QAction * action)3081 void 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)
addActions(const QList<QAction * > & actions)3092 void QWidget::addActions(const QList<QAction *> &actions)
3093 #else
3094 void 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 */
insertAction(QAction * before,QAction * action)3110 void 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)
insertActions(QAction * before,const QList<QAction * > & actions)3145 void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3146 #else
3147 void 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 */
removeAction(QAction * action)3158 void 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 */
actions() const3179 QList<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 */
setEnabled(bool enable)3214 void QWidget::setEnabled(bool enable)
3215 {
3216 Q_D(QWidget);
3217 setAttribute(Qt::WA_ForceDisabled, !enable);
3218 d->setEnabled_helper(enable);
3219 }
3220
setEnabled_helper(bool enable)3221 void 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 */
acceptDrops() const3287 bool QWidget::acceptDrops() const
3288 {
3289 return testAttribute(Qt::WA_AcceptDrops);
3290 }
3291
setAcceptDrops(bool on)3292 void 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 */
setDisabled(bool disable)3306 void 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 */
frameGeometry() const3324 QRect 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 */
x() const3350 int 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 */
y() const3370 int 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 */
pos() const3401 QPoint 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
normalGeometry() const3524 QRect 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
childrenRect() const3549 QRect 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
childrenRegion() const3573 QRegion 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
minimumSize() const3608 QSize 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
maximumSize() const3630 QSize 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 */
sizeIncrement() const3709 QSize 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
baseSize() const3730 QSize 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
setMinimumSize_helper(int & minw,int & minh)3738 bool 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(minw < 0 || minh < 0)) {
3756 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3757 "are not possible",
3758 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3759 minw = mw = qMax(minw, 0);
3760 minh = mh = qMax(minh, 0);
3761 }
3762 createExtra();
3763 if (extra->minw == mw && extra->minh == mh)
3764 return false;
3765 extra->minw = mw;
3766 extra->minh = mh;
3767 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3768 return true;
3769 }
3770
setConstraints_sys()3771 void QWidgetPrivate::setConstraints_sys()
3772 {
3773 Q_Q(QWidget);
3774 if (extra && q->windowHandle()) {
3775 QWindow *win = q->windowHandle();
3776 QWindowPrivate *winp = qt_window_private(win);
3777
3778 winp->minimumSize = QSize(extra->minw, extra->minh);
3779 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3780
3781 if (extra->topextra) {
3782 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3783 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3784 }
3785
3786 if (winp->platformWindow) {
3787 fixPosIncludesFrame();
3788 winp->platformWindow->propagateSizeHints();
3789 }
3790 }
3791 }
3792
3793 /*!
3794 \overload
3795
3796 This function corresponds to setMinimumSize(QSize(minw, minh)).
3797 Sets the minimum width to \a minw and the minimum height to \a
3798 minh.
3799 */
3800
setMinimumSize(int minw,int minh)3801 void QWidget::setMinimumSize(int minw, int minh)
3802 {
3803 Q_D(QWidget);
3804 if (!d->setMinimumSize_helper(minw, minh))
3805 return;
3806
3807 if (isWindow())
3808 d->setConstraints_sys();
3809 if (minw > width() || minh > height()) {
3810 bool resized = testAttribute(Qt::WA_Resized);
3811 bool maximized = isMaximized();
3812 resize(qMax(minw,width()), qMax(minh,height()));
3813 setAttribute(Qt::WA_Resized, resized); //not a user resize
3814 if (maximized)
3815 data->window_state = data->window_state | Qt::WindowMaximized;
3816 }
3817 #if QT_CONFIG(graphicsview)
3818 if (d->extra) {
3819 if (d->extra->proxyWidget)
3820 d->extra->proxyWidget->setMinimumSize(minw, minh);
3821 }
3822 #endif
3823 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3824 }
3825
setMaximumSize_helper(int & maxw,int & maxh)3826 bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3827 {
3828 Q_Q(QWidget);
3829 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3830 qWarning("QWidget::setMaximumSize: (%s/%s) "
3831 "The largest allowed size is (%d,%d)",
3832 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3833 QWIDGETSIZE_MAX);
3834 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
3835 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
3836 }
3837 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
3838 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
3839 "are not possible",
3840 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
3841 maxw = qMax(maxw, 0);
3842 maxh = qMax(maxh, 0);
3843 }
3844 createExtra();
3845 if (extra->maxw == maxw && extra->maxh == maxh)
3846 return false;
3847 extra->maxw = maxw;
3848 extra->maxh = maxh;
3849 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
3850 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
3851 return true;
3852 }
3853
3854 /*!
3855 \overload
3856
3857 This function corresponds to setMaximumSize(QSize(\a maxw, \a
3858 maxh)). Sets the maximum width to \a maxw and the maximum height
3859 to \a maxh.
3860 */
setMaximumSize(int maxw,int maxh)3861 void QWidget::setMaximumSize(int maxw, int maxh)
3862 {
3863 Q_D(QWidget);
3864 if (!d->setMaximumSize_helper(maxw, maxh))
3865 return;
3866
3867 if (isWindow())
3868 d->setConstraints_sys();
3869 if (maxw < width() || maxh < height()) {
3870 bool resized = testAttribute(Qt::WA_Resized);
3871 resize(qMin(maxw,width()), qMin(maxh,height()));
3872 setAttribute(Qt::WA_Resized, resized); //not a user resize
3873 }
3874
3875 #if QT_CONFIG(graphicsview)
3876 if (d->extra) {
3877 if (d->extra->proxyWidget)
3878 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
3879 }
3880 #endif
3881
3882 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3883 }
3884
3885 /*!
3886 \overload
3887
3888 Sets the x (width) size increment to \a w and the y (height) size
3889 increment to \a h.
3890 */
setSizeIncrement(int w,int h)3891 void QWidget::setSizeIncrement(int w, int h)
3892 {
3893 Q_D(QWidget);
3894 d->createTLExtra();
3895 QTLWExtra* x = d->topData();
3896 if (x->incw == w && x->inch == h)
3897 return;
3898 x->incw = w;
3899 x->inch = h;
3900 if (isWindow())
3901 d->setConstraints_sys();
3902 }
3903
3904 /*!
3905 \overload
3906
3907 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
3908 the widgets base size to width \a basew and height \a baseh.
3909 */
setBaseSize(int basew,int baseh)3910 void QWidget::setBaseSize(int basew, int baseh)
3911 {
3912 Q_D(QWidget);
3913 d->createTLExtra();
3914 QTLWExtra* x = d->topData();
3915 if (x->basew == basew && x->baseh == baseh)
3916 return;
3917 x->basew = basew;
3918 x->baseh = baseh;
3919 if (isWindow())
3920 d->setConstraints_sys();
3921 }
3922
3923 /*!
3924 Sets both the minimum and maximum sizes of the widget to \a s,
3925 thereby preventing it from ever growing or shrinking.
3926
3927 This will override the default size constraints set by QLayout.
3928
3929 To remove constraints, set the size to QWIDGETSIZE_MAX.
3930
3931 Alternatively, if you want the widget to have a
3932 fixed size based on its contents, you can call
3933 QLayout::setSizeConstraint(QLayout::SetFixedSize);
3934
3935 \sa maximumSize, minimumSize
3936 */
3937
setFixedSize(const QSize & s)3938 void QWidget::setFixedSize(const QSize & s)
3939 {
3940 setFixedSize(s.width(), s.height());
3941 }
3942
3943
3944 /*!
3945 \fn void QWidget::setFixedSize(int w, int h)
3946 \overload
3947
3948 Sets the width of the widget to \a w and the height to \a h.
3949 */
3950
setFixedSize(int w,int h)3951 void QWidget::setFixedSize(int w, int h)
3952 {
3953 Q_D(QWidget);
3954 bool minSizeSet = d->setMinimumSize_helper(w, h);
3955 bool maxSizeSet = d->setMaximumSize_helper(w, h);
3956 if (!minSizeSet && !maxSizeSet)
3957 return;
3958
3959 if (isWindow())
3960 d->setConstraints_sys();
3961 else
3962 d->updateGeometry_helper(true);
3963
3964 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
3965 resize(w, h);
3966 }
3967
setMinimumWidth(int w)3968 void QWidget::setMinimumWidth(int w)
3969 {
3970 Q_D(QWidget);
3971 d->createExtra();
3972 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
3973 setMinimumSize(w, minimumSize().height());
3974 d->extra->explicitMinSize = expl;
3975 }
3976
setMinimumHeight(int h)3977 void QWidget::setMinimumHeight(int h)
3978 {
3979 Q_D(QWidget);
3980 d->createExtra();
3981 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
3982 setMinimumSize(minimumSize().width(), h);
3983 d->extra->explicitMinSize = expl;
3984 }
3985
setMaximumWidth(int w)3986 void QWidget::setMaximumWidth(int w)
3987 {
3988 Q_D(QWidget);
3989 d->createExtra();
3990 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
3991 setMaximumSize(w, maximumSize().height());
3992 d->extra->explicitMaxSize = expl;
3993 }
3994
setMaximumHeight(int h)3995 void QWidget::setMaximumHeight(int h)
3996 {
3997 Q_D(QWidget);
3998 d->createExtra();
3999 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4000 setMaximumSize(maximumSize().width(), h);
4001 d->extra->explicitMaxSize = expl;
4002 }
4003
4004 /*!
4005 Sets both the minimum and maximum width of the widget to \a w
4006 without changing the heights. Provided for convenience.
4007
4008 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4009 */
4010
setFixedWidth(int w)4011 void QWidget::setFixedWidth(int w)
4012 {
4013 Q_D(QWidget);
4014 d->createExtra();
4015 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4016 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4017 setMinimumSize(w, minimumSize().height());
4018 setMaximumSize(w, maximumSize().height());
4019 d->extra->explicitMinSize = explMin;
4020 d->extra->explicitMaxSize = explMax;
4021 }
4022
4023
4024 /*!
4025 Sets both the minimum and maximum heights of the widget to \a h
4026 without changing the widths. Provided for convenience.
4027
4028 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4029 */
4030
setFixedHeight(int h)4031 void QWidget::setFixedHeight(int h)
4032 {
4033 Q_D(QWidget);
4034 d->createExtra();
4035 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4036 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4037 setMinimumSize(minimumSize().width(), h);
4038 setMaximumSize(maximumSize().width(), h);
4039 d->extra->explicitMinSize = explMin;
4040 d->extra->explicitMaxSize = explMax;
4041 }
4042
4043
4044 /*!
4045 Translates the widget coordinate \a pos to the coordinate system
4046 of \a parent. The \a parent must not be \nullptr and must be a parent
4047 of the calling widget.
4048
4049 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4050 */
4051
mapTo(const QWidget * parent,const QPoint & pos) const4052 QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
4053 {
4054 QPoint p = pos;
4055 if (parent) {
4056 const QWidget * w = this;
4057 while (w != parent) {
4058 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
4059 "parent must be in parent hierarchy");
4060 p = w->mapToParent(p);
4061 w = w->parentWidget();
4062 }
4063 }
4064 return p;
4065 }
4066
4067
4068 /*!
4069 Translates the widget coordinate \a pos from the coordinate system
4070 of \a parent to this widget's coordinate system. The \a parent
4071 must not be \nullptr and must be a parent of the calling widget.
4072
4073 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4074 */
4075
mapFrom(const QWidget * parent,const QPoint & pos) const4076 QPoint QWidget::mapFrom(const QWidget * parent, const QPoint & pos) const
4077 {
4078 QPoint p(pos);
4079 if (parent) {
4080 const QWidget * w = this;
4081 while (w != parent) {
4082 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4083 "parent must be in parent hierarchy");
4084
4085 p = w->mapFromParent(p);
4086 w = w->parentWidget();
4087 }
4088 }
4089 return p;
4090 }
4091
4092
4093 /*!
4094 Translates the widget coordinate \a pos to a coordinate in the
4095 parent widget.
4096
4097 Same as mapToGlobal() if the widget has no parent.
4098
4099 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4100 */
4101
mapToParent(const QPoint & pos) const4102 QPoint QWidget::mapToParent(const QPoint &pos) const
4103 {
4104 return pos + data->crect.topLeft();
4105 }
4106
4107 /*!
4108 Translates the parent widget coordinate \a pos to widget
4109 coordinates.
4110
4111 Same as mapFromGlobal() if the widget has no parent.
4112
4113 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4114 */
4115
mapFromParent(const QPoint & pos) const4116 QPoint QWidget::mapFromParent(const QPoint &pos) const
4117 {
4118 return pos - data->crect.topLeft();
4119 }
4120
4121
4122 /*!
4123 Returns the window for this widget, i.e. the next ancestor widget
4124 that has (or could have) a window-system frame.
4125
4126 If the widget is a window, the widget itself is returned.
4127
4128 Typical usage is changing the window title:
4129
4130 \snippet code/src_gui_kernel_qwidget.cpp 3
4131
4132 \sa isWindow()
4133 */
4134
window() const4135 QWidget *QWidget::window() const
4136 {
4137 QWidget *w = const_cast<QWidget *>(this);
4138 QWidget *p = w->parentWidget();
4139 while (!w->isWindow() && p) {
4140 w = p;
4141 p = p->parentWidget();
4142 }
4143 return w;
4144 }
4145
4146 /*!
4147 \since 4.4
4148
4149 Returns the native parent for this widget, i.e. the next ancestor widget
4150 that has a system identifier, or \nullptr if it does not have any native
4151 parent.
4152
4153 \sa effectiveWinId()
4154 */
nativeParentWidget() const4155 QWidget *QWidget::nativeParentWidget() const
4156 {
4157 QWidget *parent = parentWidget();
4158 while (parent && !parent->internalWinId())
4159 parent = parent->parentWidget();
4160 return parent;
4161 }
4162
4163 /*! \fn QWidget *QWidget::topLevelWidget() const
4164 \obsolete
4165
4166 Use window() instead.
4167 */
4168
4169
4170
4171 /*!
4172 Returns the background role of the widget.
4173
4174 The background role defines the brush from the widget's \l palette that
4175 is used to render the background.
4176
4177 If no explicit background role is set, the widget inherts its parent
4178 widget's background role.
4179
4180 \sa setBackgroundRole(), foregroundRole()
4181 */
backgroundRole() const4182 QPalette::ColorRole QWidget::backgroundRole() const
4183 {
4184
4185 const QWidget *w = this;
4186 do {
4187 QPalette::ColorRole role = w->d_func()->bg_role;
4188 if (role != QPalette::NoRole)
4189 return role;
4190 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4191 break;
4192 w = w->parentWidget();
4193 } while (w);
4194 return QPalette::Window;
4195 }
4196
4197 /*!
4198 Sets the background role of the widget to \a role.
4199
4200 The background role defines the brush from the widget's \l palette that
4201 is used to render the background.
4202
4203 If \a role is QPalette::NoRole, then the widget inherits its
4204 parent's background role.
4205
4206 Note that styles are free to choose any color from the palette.
4207 You can modify the palette or set a style sheet if you don't
4208 achieve the result you want with setBackgroundRole().
4209
4210 \sa backgroundRole(), foregroundRole()
4211 */
4212
setBackgroundRole(QPalette::ColorRole role)4213 void QWidget::setBackgroundRole(QPalette::ColorRole role)
4214 {
4215 Q_D(QWidget);
4216 d->bg_role = role;
4217 d->updateSystemBackground();
4218 d->propagatePaletteChange();
4219 d->updateIsOpaque();
4220 }
4221
4222 /*!
4223 Returns the foreground role.
4224
4225 The foreground role defines the color from the widget's \l palette that
4226 is used to draw the foreground.
4227
4228 If no explicit foreground role is set, the function returns a role
4229 that contrasts with the background role.
4230
4231 \sa setForegroundRole(), backgroundRole()
4232 */
foregroundRole() const4233 QPalette::ColorRole QWidget::foregroundRole() const
4234 {
4235 Q_D(const QWidget);
4236 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4237 if (rl != QPalette::NoRole)
4238 return rl;
4239 QPalette::ColorRole role = QPalette::WindowText;
4240 switch (backgroundRole()) {
4241 case QPalette::Button:
4242 role = QPalette::ButtonText;
4243 break;
4244 case QPalette::Base:
4245 role = QPalette::Text;
4246 break;
4247 case QPalette::Dark:
4248 case QPalette::Shadow:
4249 role = QPalette::Light;
4250 break;
4251 case QPalette::Highlight:
4252 role = QPalette::HighlightedText;
4253 break;
4254 case QPalette::ToolTipBase:
4255 role = QPalette::ToolTipText;
4256 break;
4257 default:
4258 ;
4259 }
4260 return role;
4261 }
4262
4263 /*!
4264 Sets the foreground role of the widget to \a role.
4265
4266 The foreground role defines the color from the widget's \l palette that
4267 is used to draw the foreground.
4268
4269 If \a role is QPalette::NoRole, the widget uses a foreground role
4270 that contrasts with the background role.
4271
4272 Note that styles are free to choose any color from the palette.
4273 You can modify the palette or set a style sheet if you don't
4274 achieve the result you want with setForegroundRole().
4275
4276 \sa foregroundRole(), backgroundRole()
4277 */
setForegroundRole(QPalette::ColorRole role)4278 void QWidget::setForegroundRole(QPalette::ColorRole role)
4279 {
4280 Q_D(QWidget);
4281 d->fg_role = role;
4282 d->updateSystemBackground();
4283 d->propagatePaletteChange();
4284 }
4285
4286 /*!
4287 \property QWidget::palette
4288 \brief the widget's palette
4289
4290 This property describes the widget's palette. The palette is used by the
4291 widget's style when rendering standard components, and is available as a
4292 means to ensure that custom widgets can maintain consistency with the
4293 native platform's look and feel. It's common that different platforms, or
4294 different styles, have different palettes.
4295
4296 When you assign a new palette to a widget, the color roles from this
4297 palette are combined with the widget's default palette to form the
4298 widget's final palette. The palette entry for the widget's background role
4299 is used to fill the widget's background (see QWidget::autoFillBackground),
4300 and the foreground role initializes QPainter's pen.
4301
4302 The default depends on the system environment. QApplication maintains a
4303 system/theme palette which serves as a default for all widgets. There may
4304 also be special palette defaults for certain types of widgets (e.g., on
4305 Windows Vista, all classes that derive from QMenuBar have a special
4306 default palette). You can also define default palettes for widgets
4307 yourself by passing a custom palette and the name of a widget to
4308 QApplication::setPalette(). Finally, the style always has the option of
4309 polishing the palette as it's assigned (see QStyle::polish()).
4310
4311 QWidget propagates explicit palette roles from parent to child. If you
4312 assign a brush or color to a specific role on a palette and assign that
4313 palette to a widget, that role will propagate to all the widget's
4314 children, overriding any system defaults for that role. Note that palettes
4315 by default don't propagate to windows (see isWindow()) unless the
4316 Qt::WA_WindowPropagation attribute is enabled.
4317
4318 QWidget's palette propagation is similar to its font propagation.
4319
4320 The current style, which is used to render the content of all standard Qt
4321 widgets, is free to choose colors and brushes from the widget palette, or
4322 in some cases, to ignore the palette (partially, or completely). In
4323 particular, certain styles like GTK style, Mac style, and Windows Vista
4324 style, depend on third party APIs to render the content of widgets,
4325 and these styles typically do not follow the palette. Because of this,
4326 assigning roles to a widget's palette is not guaranteed to change the
4327 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4328
4329 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4330 When using style sheets, the palette of a widget can be customized using
4331 the "color", "background-color", "selection-color",
4332 "selection-background-color" and "alternate-background-color".
4333
4334 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4335 */
palette() const4336 const QPalette &QWidget::palette() const
4337 {
4338 if (!isEnabled()) {
4339 data->pal.setCurrentColorGroup(QPalette::Disabled);
4340 } else if ((!isVisible() || isActiveWindow())
4341 #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
4342 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4343 #endif
4344 ) {
4345 data->pal.setCurrentColorGroup(QPalette::Active);
4346 } else {
4347 data->pal.setCurrentColorGroup(QPalette::Inactive);
4348 }
4349 return data->pal;
4350 }
4351
setPalette(const QPalette & palette)4352 void QWidget::setPalette(const QPalette &palette)
4353 {
4354 Q_D(QWidget);
4355 setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
4356
4357 // Determine which palette is inherited from this widget's ancestors and
4358 // QApplication::palette, resolve this against \a palette (attributes from
4359 // the inherited palette are copied over this widget's palette). Then
4360 // propagate this palette to this widget's children.
4361 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4362 QPalette resolvedPalette = palette.resolve(naturalPalette);
4363 d->setPalette_helper(resolvedPalette);
4364 }
4365
4366 /*!
4367 \internal
4368
4369 Returns the palette that the widget \a w inherits from its ancestors and
4370 QApplication::palette. \a inheritedMask is the combination of the widget's
4371 ancestors palette request masks (i.e., which attributes from the parent
4372 widget's palette are implicitly imposed on this widget by the user). Note
4373 that this font does not take into account the palette set on \a w itself.
4374 */
naturalWidgetPalette(uint inheritedMask) const4375 QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
4376 {
4377 Q_Q(const QWidget);
4378
4379 const bool useStyleSheetPropagationInWidgetStyles =
4380 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4381
4382 QPalette naturalPalette = QApplication::palette(q);
4383 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4384 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4385 #if QT_CONFIG(graphicsview)
4386 || (extra && extra->proxyWidget)
4387 #endif // QT_CONFIG(graphicsview)
4388 )) {
4389 if (QWidget *p = q->parentWidget()) {
4390 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4391 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4392 QPalette inheritedPalette = p->palette();
4393 inheritedPalette.resolve(inheritedMask);
4394 naturalPalette = inheritedPalette.resolve(naturalPalette);
4395 } else {
4396 naturalPalette = p->palette();
4397 }
4398 }
4399 }
4400 #if QT_CONFIG(graphicsview)
4401 else if (extra && extra->proxyWidget) {
4402 QPalette inheritedPalette = extra->proxyWidget->palette();
4403 inheritedPalette.resolve(inheritedMask);
4404 naturalPalette = inheritedPalette.resolve(naturalPalette);
4405 }
4406 #endif // QT_CONFIG(graphicsview)
4407 }
4408 naturalPalette.resolve(0);
4409 return naturalPalette;
4410 }
4411 /*!
4412 \internal
4413
4414 Determine which palette is inherited from this widget's ancestors and
4415 QApplication::palette, resolve this against this widget's palette
4416 (attributes from the inherited palette are copied over this widget's
4417 palette). Then propagate this palette to this widget's children.
4418 */
resolvePalette()4419 void QWidgetPrivate::resolvePalette()
4420 {
4421 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4422 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4423 setPalette_helper(resolvedPalette);
4424 }
4425
setPalette_helper(const QPalette & palette)4426 void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4427 {
4428 Q_Q(QWidget);
4429 if (data.pal == palette && data.pal.resolve() == palette.resolve())
4430 return;
4431 data.pal = palette;
4432 updateSystemBackground();
4433 propagatePaletteChange();
4434 updateIsOpaque();
4435 q->update();
4436 updateIsOpaque();
4437 }
4438
updateSystemBackground()4439 void QWidgetPrivate::updateSystemBackground()
4440 {
4441 }
4442
4443 /*!
4444 \property QWidget::font
4445 \brief the font currently set for the widget
4446
4447 This property describes the widget's requested font. The font is used by
4448 the widget's style when rendering standard components, and is available as
4449 a means to ensure that custom widgets can maintain consistency with the
4450 native platform's look and feel. It's common that different platforms, or
4451 different styles, define different fonts for an application.
4452
4453 When you assign a new font to a widget, the properties from this font are
4454 combined with the widget's default font to form the widget's final
4455 font. You can call fontInfo() to get a copy of the widget's final
4456 font. The final font is also used to initialize QPainter's font.
4457
4458 The default depends on the system environment. QApplication maintains a
4459 system/theme font which serves as a default for all widgets. There may
4460 also be special font defaults for certain types of widgets. You can also
4461 define default fonts for widgets yourself by passing a custom font and the
4462 name of a widget to QApplication::setFont(). Finally, the font is matched
4463 against Qt's font database to find the best match.
4464
4465 QWidget propagates explicit font properties from parent to child. If you
4466 change a specific property on a font and assign that font to a widget,
4467 that property will propagate to all the widget's children, overriding any
4468 system defaults for that property. Note that fonts by default don't
4469 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4470 attribute is enabled.
4471
4472 QWidget's font propagation is similar to its palette propagation.
4473
4474 The current style, which is used to render the content of all standard Qt
4475 widgets, is free to choose to use the widget font, or in some cases, to
4476 ignore it (partially, or completely). In particular, certain styles like
4477 GTK style, Mac style, and Windows Vista style, apply special
4478 modifications to the widget font to match the platform's native look and
4479 feel. Because of this, assigning properties to a widget's font is not
4480 guaranteed to change the appearance of the widget. Instead, you may choose
4481 to apply a \l styleSheet.
4482
4483 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4484 style sheets will take precedence if the settings conflict.
4485
4486 \sa fontInfo(), fontMetrics()
4487 */
4488
setFont(const QFont & font)4489 void QWidget::setFont(const QFont &font)
4490 {
4491 Q_D(QWidget);
4492
4493 #ifndef QT_NO_STYLE_STYLESHEET
4494 const QStyleSheetStyle* style;
4495 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4496 style->saveWidgetFont(this, font);
4497 #endif
4498
4499 setAttribute(Qt::WA_SetFont, font.resolve() != 0);
4500
4501 // Determine which font is inherited from this widget's ancestors and
4502 // QApplication::font, resolve this against \a font (attributes from the
4503 // inherited font are copied over). Then propagate this font to this
4504 // widget's children.
4505 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4506 QFont resolvedFont = font.resolve(naturalFont);
4507 d->setFont_helper(resolvedFont);
4508 }
4509
4510 /*
4511 \internal
4512
4513 Returns the font that the widget \a w inherits from its ancestors and
4514 QApplication::font. \a inheritedMask is the combination of the widget's
4515 ancestors font request masks (i.e., which attributes from the parent
4516 widget's font are implicitly imposed on this widget by the user). Note
4517 that this font does not take into account the font set on \a w itself.
4518
4519 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4520 is applied, fonts are not propagated anymore
4521 */
naturalWidgetFont(uint inheritedMask) const4522 QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4523 {
4524 Q_Q(const QWidget);
4525
4526 const bool useStyleSheetPropagationInWidgetStyles =
4527 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4528
4529 QFont naturalFont = QApplication::font(q);
4530 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4531 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4532 #if QT_CONFIG(graphicsview)
4533 || (extra && extra->proxyWidget)
4534 #endif // QT_CONFIG(graphicsview)
4535 )) {
4536 if (QWidget *p = q->parentWidget()) {
4537 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4538 if (!naturalFont.isCopyOf(QApplication::font())) {
4539 if (inheritedMask != 0) {
4540 QFont inheritedFont = p->font();
4541 inheritedFont.resolve(inheritedMask);
4542 naturalFont = inheritedFont.resolve(naturalFont);
4543 } // else nothing to do (naturalFont = naturalFont)
4544 } else {
4545 naturalFont = p->font();
4546 }
4547 }
4548 }
4549 #if QT_CONFIG(graphicsview)
4550 else if (extra && extra->proxyWidget) {
4551 if (inheritedMask != 0) {
4552 QFont inheritedFont = extra->proxyWidget->font();
4553 inheritedFont.resolve(inheritedMask);
4554 naturalFont = inheritedFont.resolve(naturalFont);
4555 } // else nothing to do (naturalFont = naturalFont)
4556 }
4557 #endif // QT_CONFIG(graphicsview)
4558 }
4559 naturalFont.resolve(0);
4560 return naturalFont;
4561 }
4562
4563 /*!
4564 \internal
4565
4566 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4567 */
localFont() const4568 QFont QWidgetPrivate::localFont() const
4569 {
4570 QFont localfont = data.fnt;
4571 localfont.resolve(directFontResolveMask);
4572 return localfont;
4573 }
4574
4575 /*!
4576 \internal
4577
4578 Determine which font is implicitly imposed on this widget by its ancestors
4579 and QApplication::font, resolve this against its own font (attributes from
4580 the implicit font are copied over). Then propagate this font to this
4581 widget's children.
4582 */
resolveFont()4583 void QWidgetPrivate::resolveFont()
4584 {
4585 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4586 QFont resolvedFont = localFont().resolve(naturalFont);
4587 setFont_helper(resolvedFont);
4588 }
4589
4590 /*!
4591 \internal
4592
4593 Assign \a font to this widget, and propagate it to all children, except
4594 style sheet widgets (handled differently) and windows that don't enable
4595 window propagation. \a implicitMask is the union of all ancestor widgets'
4596 font request masks, and determines which attributes from this widget's
4597 font should propagate.
4598 */
updateFont(const QFont & font)4599 void QWidgetPrivate::updateFont(const QFont &font)
4600 {
4601 Q_Q(QWidget);
4602 #ifndef QT_NO_STYLE_STYLESHEET
4603 const QStyleSheetStyle* cssStyle;
4604 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4605 const bool useStyleSheetPropagationInWidgetStyles =
4606 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4607 #endif
4608
4609 data.fnt = QFont(font, q);
4610
4611 // Combine new mask with natural mask and propagate to children.
4612 #if QT_CONFIG(graphicsview)
4613 if (!q->parentWidget() && extra && extra->proxyWidget) {
4614 QGraphicsProxyWidget *p = extra->proxyWidget;
4615 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve();
4616 } else
4617 #endif // QT_CONFIG(graphicsview)
4618 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4619 inheritedFontResolveMask = 0;
4620 }
4621 uint newMask = data.fnt.resolve() | inheritedFontResolveMask;
4622 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4623 // isn't all weak information, but save the original mask to be able to let new changes on the
4624 // parent widget font propagate correctly.
4625 directFontResolveMask = data.fnt.resolve();
4626 data.fnt.resolve(newMask);
4627
4628 for (int i = 0; i < children.size(); ++i) {
4629 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4630 if (w) {
4631 if (0) {
4632 #ifndef QT_NO_STYLE_STYLESHEET
4633 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4634 // Style sheets follow a different font propagation scheme.
4635 if (cssStyle)
4636 cssStyle->updateStyleSheetFont(w);
4637 #endif
4638 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4639 // Propagate font changes.
4640 QWidgetPrivate *wd = w->d_func();
4641 wd->inheritedFontResolveMask = newMask;
4642 wd->resolveFont();
4643 }
4644 }
4645 }
4646
4647 #ifndef QT_NO_STYLE_STYLESHEET
4648 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4649 cssStyle->updateStyleSheetFont(q);
4650 }
4651 #endif
4652
4653 QEvent e(QEvent::FontChange);
4654 QCoreApplication::sendEvent(q, &e);
4655 }
4656
setLayoutDirection_helper(Qt::LayoutDirection direction)4657 void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4658 {
4659 Q_Q(QWidget);
4660
4661 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4662 return;
4663 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4664 if (!children.isEmpty()) {
4665 for (int i = 0; i < children.size(); ++i) {
4666 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4667 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4668 w->d_func()->setLayoutDirection_helper(direction);
4669 }
4670 }
4671 QEvent e(QEvent::LayoutDirectionChange);
4672 QCoreApplication::sendEvent(q, &e);
4673 }
4674
resolveLayoutDirection()4675 void QWidgetPrivate::resolveLayoutDirection()
4676 {
4677 Q_Q(const QWidget);
4678 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4679 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4680 }
4681
4682 /*!
4683 \property QWidget::layoutDirection
4684
4685 \brief the layout direction for this widget
4686
4687 By default, this property is set to Qt::LeftToRight.
4688
4689 When the layout direction is set on a widget, it will propagate to
4690 the widget's children, but not to a child that is a window and not
4691 to a child for which setLayoutDirection() has been explicitly
4692 called. Also, child widgets added \e after setLayoutDirection()
4693 has been called for the parent do not inherit the parent's layout
4694 direction.
4695
4696 This method no longer affects text layout direction since Qt 4.7.
4697
4698 \sa QApplication::layoutDirection
4699 */
setLayoutDirection(Qt::LayoutDirection direction)4700 void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4701 {
4702 Q_D(QWidget);
4703
4704 if (direction == Qt::LayoutDirectionAuto) {
4705 unsetLayoutDirection();
4706 return;
4707 }
4708
4709 setAttribute(Qt::WA_SetLayoutDirection);
4710 d->setLayoutDirection_helper(direction);
4711 }
4712
layoutDirection() const4713 Qt::LayoutDirection QWidget::layoutDirection() const
4714 {
4715 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4716 }
4717
unsetLayoutDirection()4718 void QWidget::unsetLayoutDirection()
4719 {
4720 Q_D(QWidget);
4721 setAttribute(Qt::WA_SetLayoutDirection, false);
4722 d->resolveLayoutDirection();
4723 }
4724
4725 /*!
4726 \fn QFontMetrics QWidget::fontMetrics() const
4727
4728 Returns the font metrics for the widget's current font.
4729 Equivalent to \c QFontMetrics(widget->font()).
4730
4731 \sa font(), fontInfo(), setFont()
4732 */
4733
4734 /*!
4735 \fn QFontInfo QWidget::fontInfo() const
4736
4737 Returns the font info for the widget's current font.
4738 Equivalent to \c QFontInfo(widget->font()).
4739
4740 \sa font(), fontMetrics(), setFont()
4741 */
4742
4743
4744 /*!
4745 \property QWidget::cursor
4746 \brief the cursor shape for this widget
4747
4748 The mouse cursor will assume this shape when it's over this
4749 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4750
4751 An editor widget might use an I-beam cursor:
4752 \snippet code/src_gui_kernel_qwidget.cpp 6
4753
4754 If no cursor has been set, or after a call to unsetCursor(), the
4755 parent's cursor is used.
4756
4757 By default, this property contains a cursor with the Qt::ArrowCursor
4758 shape.
4759
4760 Some underlying window implementations will reset the cursor if it
4761 leaves a widget even if the mouse is grabbed. If you want to have
4762 a cursor set for all widgets, even when outside the window, consider
4763 QGuiApplication::setOverrideCursor().
4764
4765 \sa QGuiApplication::setOverrideCursor()
4766 */
4767
4768 #ifndef QT_NO_CURSOR
cursor() const4769 QCursor QWidget::cursor() const
4770 {
4771 Q_D(const QWidget);
4772 if (testAttribute(Qt::WA_SetCursor))
4773 return (d->extra && d->extra->curs)
4774 ? *d->extra->curs
4775 : QCursor(Qt::ArrowCursor);
4776 if (isWindow() || !parentWidget())
4777 return QCursor(Qt::ArrowCursor);
4778 return parentWidget()->cursor();
4779 }
4780
setCursor(const QCursor & cursor)4781 void QWidget::setCursor(const QCursor &cursor)
4782 {
4783 Q_D(QWidget);
4784 if (cursor.shape() != Qt::ArrowCursor
4785 || (d->extra && d->extra->curs))
4786 {
4787 d->createExtra();
4788 d->extra->curs = qt_make_unique<QCursor>(cursor);
4789 }
4790 setAttribute(Qt::WA_SetCursor);
4791 d->setCursor_sys(cursor);
4792
4793 QEvent event(QEvent::CursorChange);
4794 QCoreApplication::sendEvent(this, &event);
4795 }
4796
setCursor_sys(const QCursor & cursor)4797 void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4798 {
4799 Q_UNUSED(cursor);
4800 Q_Q(QWidget);
4801 qt_qpa_set_cursor(q, false);
4802 }
4803
unsetCursor()4804 void QWidget::unsetCursor()
4805 {
4806 Q_D(QWidget);
4807 if (d->extra)
4808 d->extra->curs.reset();
4809 if (!isWindow())
4810 setAttribute(Qt::WA_SetCursor, false);
4811 d->unsetCursor_sys();
4812
4813 QEvent event(QEvent::CursorChange);
4814 QCoreApplication::sendEvent(this, &event);
4815 }
4816
unsetCursor_sys()4817 void QWidgetPrivate::unsetCursor_sys()
4818 {
4819 Q_Q(QWidget);
4820 qt_qpa_set_cursor(q, false);
4821 }
4822
applyCursor(QWidget * w,const QCursor & c)4823 static inline void applyCursor(QWidget *w, const QCursor &c)
4824 {
4825 if (QWindow *window = w->windowHandle())
4826 window->setCursor(c);
4827 }
4828
unsetCursor(QWidget * w)4829 static inline void unsetCursor(QWidget *w)
4830 {
4831 if (QWindow *window = w->windowHandle())
4832 window->unsetCursor();
4833 }
4834
qt_qpa_set_cursor(QWidget * w,bool force)4835 void qt_qpa_set_cursor(QWidget *w, bool force)
4836 {
4837 if (!w->testAttribute(Qt::WA_WState_Created))
4838 return;
4839
4840 static QPointer<QWidget> lastUnderMouse = nullptr;
4841 if (force) {
4842 lastUnderMouse = w;
4843 } else if (lastUnderMouse) {
4844 const WId lastWinId = lastUnderMouse->effectiveWinId();
4845 const WId winId = w->effectiveWinId();
4846 if (lastWinId && lastWinId == winId)
4847 w = lastUnderMouse;
4848 } else if (!w->internalWinId()) {
4849 return; // The mouse is not under this widget, and it's not native, so don't change it.
4850 }
4851
4852 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
4853 && !w->testAttribute(Qt::WA_SetCursor))
4854 w = w->parentWidget();
4855
4856 QWidget *nativeParent = w;
4857 if (!w->internalWinId())
4858 nativeParent = w->nativeParentWidget();
4859 if (!nativeParent || !nativeParent->internalWinId())
4860 return;
4861
4862 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
4863 if (w->isEnabled())
4864 applyCursor(nativeParent, w->cursor());
4865 else
4866 // Enforce the windows behavior of clearing the cursor on
4867 // disabled widgets.
4868 unsetCursor(nativeParent);
4869 } else {
4870 unsetCursor(nativeParent);
4871 }
4872 }
4873 #endif
4874
4875 /*!
4876 \enum QWidget::RenderFlag
4877
4878 This enum describes how to render the widget when calling QWidget::render().
4879
4880 \value DrawWindowBackground If you enable this option, the widget's background
4881 is rendered into the target even if autoFillBackground is not set. By default,
4882 this option is enabled.
4883
4884 \value DrawChildren If you enable this option, the widget's children
4885 are rendered recursively into the target. By default, this option is enabled.
4886
4887 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
4888 is ignored when rendering into the target. By default, this option is disabled.
4889
4890 \since 4.3
4891 */
4892
4893 /*!
4894 \since 4.3
4895
4896 Renders the \a sourceRegion of this widget into the \a target
4897 using \a renderFlags to determine how to render. Rendering
4898 starts at \a targetOffset in the \a target. For example:
4899
4900 \snippet code/src_gui_kernel_qwidget.cpp 7
4901
4902 If \a sourceRegion is a null region, this function will use QWidget::rect() as
4903 the region, i.e. the entire widget.
4904
4905 Ensure that you call QPainter::end() for the \a target device's
4906 active painter (if any) before rendering. For example:
4907
4908 \snippet code/src_gui_kernel_qwidget.cpp 8
4909
4910 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
4911 instead.
4912
4913 \note To obtain the contents of a QGLWidget (deprecated), use
4914 QGLWidget::grabFrameBuffer() or QGLWidget::renderPixmap() instead.
4915 */
render(QPaintDevice * target,const QPoint & targetOffset,const QRegion & sourceRegion,RenderFlags renderFlags)4916 void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
4917 const QRegion &sourceRegion, RenderFlags renderFlags)
4918 {
4919 QPainter p(target);
4920 render(&p, targetOffset, sourceRegion, renderFlags);
4921 }
4922
4923 /*!
4924 \overload
4925
4926 Renders the widget into the \a painter's QPainter::device().
4927
4928 Transformations and settings applied to the \a painter will be used
4929 when rendering.
4930
4931 \note The \a painter must be active. On \macos the widget will be
4932 rendered into a QPixmap and then drawn by the \a painter.
4933
4934 \sa QPainter::device()
4935 */
render(QPainter * painter,const QPoint & targetOffset,const QRegion & sourceRegion,RenderFlags renderFlags)4936 void QWidget::render(QPainter *painter, const QPoint &targetOffset,
4937 const QRegion &sourceRegion, RenderFlags renderFlags)
4938 {
4939 if (Q_UNLIKELY(!painter)) {
4940 qWarning("QWidget::render: Null pointer to painter");
4941 return;
4942 }
4943
4944 if (Q_UNLIKELY(!painter->isActive())) {
4945 qWarning("QWidget::render: Cannot render with an inactive painter");
4946 return;
4947 }
4948
4949 const qreal opacity = painter->opacity();
4950 if (qFuzzyIsNull(opacity))
4951 return; // Fully transparent.
4952
4953 Q_D(QWidget);
4954 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
4955 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
4956 : sourceRegion;
4957 if (toBePainted.isEmpty())
4958 return;
4959
4960 if (!d->extra)
4961 d->createExtra();
4962 d->extra->inRenderWithPainter = true;
4963
4964 QPaintEngine *engine = painter->paintEngine();
4965 Q_ASSERT(engine);
4966 QPaintEnginePrivate *enginePriv = engine->d_func();
4967 Q_ASSERT(enginePriv);
4968 QPaintDevice *target = engine->paintDevice();
4969 Q_ASSERT(target);
4970
4971 // Render via a pixmap when dealing with non-opaque painters or printers.
4972 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
4973 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
4974 d->extra->inRenderWithPainter = inRenderWithPainter;
4975 return;
4976 }
4977
4978 // Set new shared painter.
4979 QPainter *oldPainter = d->sharedPainter();
4980 d->setSharedPainter(painter);
4981
4982 // Save current system clip, viewport and transform,
4983 const QTransform oldTransform = enginePriv->systemTransform;
4984 const QRegion oldSystemClip = enginePriv->systemClip;
4985 const QRegion oldBaseClip = enginePriv->baseSystemClip;
4986 const QRegion oldSystemViewport = enginePriv->systemViewport;
4987
4988 // This ensures that all painting triggered by render() is clipped to the current engine clip.
4989 if (painter->hasClipping()) {
4990 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
4991 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
4992 } else {
4993 enginePriv->setSystemViewport(oldSystemClip);
4994 }
4995
4996 d->render(target, targetOffset, toBePainted, renderFlags);
4997
4998 // Restore system clip, viewport and transform.
4999 enginePriv->baseSystemClip = oldBaseClip;
5000 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5001 enginePriv->systemStateChanged();
5002
5003 // Restore shared painter.
5004 d->setSharedPainter(oldPainter);
5005
5006 d->extra->inRenderWithPainter = inRenderWithPainter;
5007 }
5008
sendResizeEvents(QWidget * target)5009 static void sendResizeEvents(QWidget *target)
5010 {
5011 QResizeEvent e(target->size(), QSize());
5012 QCoreApplication::sendEvent(target, &e);
5013
5014 const QObjectList children = target->children();
5015 for (int i = 0; i < children.size(); ++i) {
5016 if (!children.at(i)->isWidgetType())
5017 continue;
5018 QWidget *child = static_cast<QWidget*>(children.at(i));
5019 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5020 sendResizeEvents(child);
5021 }
5022 }
5023
5024 /*!
5025 \since 5.0
5026
5027 Renders the widget into a pixmap restricted by the
5028 given \a rectangle. If the widget has any children, then
5029 they are also painted in the appropriate positions.
5030
5031 If a rectangle with an invalid size is specified (the default),
5032 the entire widget is painted.
5033
5034 \sa render(), QPixmap
5035 */
grab(const QRect & rectangle)5036 QPixmap QWidget::grab(const QRect &rectangle)
5037 {
5038 Q_D(QWidget);
5039 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5040 sendResizeEvents(this);
5041
5042 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5043
5044 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5045 QRect r(rectangle);
5046 if (r.width() < 0 || r.height() < 0) {
5047 // For grabbing widgets that haven't been shown yet,
5048 // we trigger the layouting mechanism to determine the widget's size.
5049 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5050 r.setTopLeft(rectangle.topLeft());
5051 }
5052
5053 if (!r.intersects(rect()))
5054 return QPixmap();
5055
5056 const qreal dpr = devicePixelRatioF();
5057 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5058 res.setDevicePixelRatio(dpr);
5059 if (!d->isOpaque)
5060 res.fill(Qt::transparent);
5061 d->render(&res, QPoint(), QRegion(r), renderFlags);
5062
5063 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5064 return res;
5065 }
5066
5067 /*!
5068 \brief The graphicsEffect function returns a pointer to the
5069 widget's graphics effect.
5070
5071 If the widget has no graphics effect, \nullptr is returned.
5072
5073 \since 4.6
5074
5075 \sa setGraphicsEffect()
5076 */
5077 #if QT_CONFIG(graphicseffect)
graphicsEffect() const5078 QGraphicsEffect *QWidget::graphicsEffect() const
5079 {
5080 Q_D(const QWidget);
5081 return d->graphicsEffect;
5082 }
5083 #endif // QT_CONFIG(graphicseffect)
5084
5085 /*!
5086
5087 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5088
5089 Sets \a effect as the widget's effect. If there already is an effect installed
5090 on this widget, QWidget will delete the existing effect before installing
5091 the new \a effect.
5092
5093 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5094 the effect from the widget and install it on this widget.
5095
5096 QWidget takes ownership of \a effect.
5097
5098 \note This function will apply the effect on itself and all its children.
5099
5100 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5101 QOpenGLWidget and QQuickWidget.
5102
5103 \since 4.6
5104
5105 \sa graphicsEffect()
5106 */
5107 #if QT_CONFIG(graphicseffect)
setGraphicsEffect(QGraphicsEffect * effect)5108 void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5109 {
5110 Q_D(QWidget);
5111 if (d->graphicsEffect == effect)
5112 return;
5113
5114 if (d->graphicsEffect) {
5115 d->invalidateBackingStore(rect());
5116 delete d->graphicsEffect;
5117 d->graphicsEffect = nullptr;
5118 }
5119
5120 if (effect) {
5121 // Set new effect.
5122 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5123 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5124 d->graphicsEffect = effect;
5125 effect->d_func()->setGraphicsEffectSource(source);
5126 update();
5127 }
5128
5129 d->updateIsOpaque();
5130 }
5131 #endif // QT_CONFIG(graphicseffect)
5132
isAboutToShow() const5133 bool QWidgetPrivate::isAboutToShow() const
5134 {
5135 if (data.in_show)
5136 return true;
5137
5138 Q_Q(const QWidget);
5139 if (q->isHidden())
5140 return false;
5141
5142 // The widget will be shown if any of its ancestors are about to show.
5143 QWidget *parent = q->parentWidget();
5144 return parent ? parent->d_func()->isAboutToShow() : false;
5145 }
5146
prepareToRender(const QRegion & region,QWidget::RenderFlags renderFlags)5147 QRegion QWidgetPrivate::prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags)
5148 {
5149 Q_Q(QWidget);
5150 const bool isVisible = q->isVisible();
5151
5152 // Make sure the widget is laid out correctly.
5153 if (!isVisible && !isAboutToShow()) {
5154 QWidget *topLevel = q->window();
5155 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5156 topLevel->ensurePolished();
5157
5158 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5159 // they're not explicitly hidden.
5160 QWidget *widget = q;
5161 QWidgetList hiddenWidgets;
5162 while (widget) {
5163 if (widget->isHidden()) {
5164 widget->setAttribute(Qt::WA_WState_Hidden, false);
5165 hiddenWidgets.append(widget);
5166 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5167 widget->d_func()->updateGeometry_helper(true);
5168 }
5169 widget = widget->parentWidget();
5170 }
5171
5172 // Activate top-level layout.
5173 if (topLevel->d_func()->layout)
5174 topLevel->d_func()->layout->activate();
5175
5176 // Adjust size if necessary.
5177 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5178 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5179 && !topLevel->testAttribute(Qt::WA_Resized)) {
5180 topLevel->adjustSize();
5181 topLevel->setAttribute(Qt::WA_Resized, false);
5182 }
5183
5184 // Activate child layouts.
5185 topLevel->d_func()->activateChildLayoutsRecursively();
5186
5187 // We're not cheating with WA_WState_Hidden anymore.
5188 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5189 QWidget *widget = hiddenWidgets.at(i);
5190 widget->setAttribute(Qt::WA_WState_Hidden);
5191 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5192 widget->parentWidget()->d_func()->layout->invalidate();
5193 }
5194 } else if (isVisible) {
5195 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5196 }
5197
5198 // Calculate the region to be painted.
5199 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5200 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5201 toBePainted &= extra->mask;
5202 return toBePainted;
5203 }
5204
render_helper(QPainter * painter,const QPoint & targetOffset,const QRegion & toBePainted,QWidget::RenderFlags renderFlags)5205 void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5206 QWidget::RenderFlags renderFlags)
5207 {
5208 Q_ASSERT(painter);
5209 Q_ASSERT(!toBePainted.isEmpty());
5210
5211 Q_Q(QWidget);
5212 const QTransform originalTransform = painter->worldTransform();
5213 const bool useDeviceCoordinates = originalTransform.isScaling();
5214 if (!useDeviceCoordinates) {
5215 // Render via a pixmap.
5216 const QRect rect = toBePainted.boundingRect();
5217 const QSize size = rect.size();
5218 if (size.isNull())
5219 return;
5220
5221 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatioF();
5222 QPixmap pixmap(size * pixmapDevicePixelRatio);
5223 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5224
5225 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5226 pixmap.fill(Qt::transparent);
5227 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5228
5229 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5230 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5231
5232 painter->drawPixmap(targetOffset, pixmap);
5233
5234 if (restore)
5235 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5236
5237 } else {
5238 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5239 QTransform transform = originalTransform;
5240 transform.translate(targetOffset.x(), targetOffset.y());
5241
5242 QPaintDevice *device = painter->device();
5243 Q_ASSERT(device);
5244
5245 // Calculate device rect.
5246 const QRectF rect(toBePainted.boundingRect());
5247 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5248 deviceRect &= QRect(0, 0, device->width(), device->height());
5249
5250 QPixmap pixmap(deviceRect.size());
5251 pixmap.fill(Qt::transparent);
5252
5253 // Create a pixmap device coordinate painter.
5254 QPainter pixmapPainter(&pixmap);
5255 pixmapPainter.setRenderHints(painter->renderHints());
5256 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5257 pixmapPainter.setTransform(transform);
5258
5259 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5260 pixmapPainter.end();
5261
5262 // And then draw the pixmap.
5263 painter->setTransform(QTransform());
5264 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5265 painter->setTransform(originalTransform);
5266 }
5267 }
5268
drawWidget(QPaintDevice * pdev,const QRegion & rgn,const QPoint & offset,DrawWidgetFlags flags,QPainter * sharedPainter,QWidgetRepaintManager * repaintManager)5269 void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5270 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5271 {
5272 if (rgn.isEmpty())
5273 return;
5274
5275 Q_Q(QWidget);
5276
5277 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5278 << "into paint device" << pdev << "with" << flags;
5279
5280 const bool asRoot = flags & DrawAsRoot;
5281 bool onScreen = shouldPaintOnScreen();
5282
5283 #if QT_CONFIG(graphicseffect)
5284 if (graphicsEffect && graphicsEffect->isEnabled()) {
5285 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5286 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5287 (source->d_func());
5288 if (!sourced->context) {
5289 QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, repaintManager);
5290 sourced->context = &context;
5291 if (!sharedPainter) {
5292 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
5293 QPainter p(pdev);
5294 p.translate(offset);
5295 context.painter = &p;
5296 graphicsEffect->draw(&p);
5297 setSystemClip(pdev->paintEngine(), 1, QRegion());
5298 } else {
5299 context.painter = sharedPainter;
5300 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5301 sourced->invalidateCache();
5302 sourced->lastEffectTransform = sharedPainter->worldTransform();
5303 }
5304 sharedPainter->save();
5305 sharedPainter->translate(offset);
5306 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset));
5307 graphicsEffect->draw(sharedPainter);
5308 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5309 sharedPainter->restore();
5310 }
5311 sourced->context = nullptr;
5312
5313 if (repaintManager)
5314 repaintManager->markNeedsFlush(q, rgn, offset);
5315
5316 return;
5317 }
5318 }
5319 #endif // QT_CONFIG(graphicseffect)
5320
5321 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5322 const bool recursive = flags & DrawRecursive;
5323 const bool alsoInvisible = flags & DrawInvisible;
5324
5325 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5326
5327 QRegion toBePainted(rgn);
5328 if (asRoot && !alsoInvisible)
5329 toBePainted &= clipRect(); //(rgn & visibleRegion());
5330 if (!(flags & DontSubtractOpaqueChildren))
5331 subtractOpaqueChildren(toBePainted, q->rect());
5332
5333 if (!toBePainted.isEmpty()) {
5334 if (!onScreen || alsoOnScreen) {
5335 //update the "in paint event" flag
5336 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5337 qWarning("QWidget::repaint: Recursive repaint detected");
5338 q->setAttribute(Qt::WA_WState_InPaintEvent);
5339
5340 //clip away the new area
5341 QPaintEngine *paintEngine = pdev->paintEngine();
5342 if (paintEngine) {
5343 setRedirected(pdev, -offset);
5344
5345 if (sharedPainter)
5346 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted);
5347 else
5348 paintEngine->d_func()->systemRect = q->data->crect;
5349
5350 //paint the background
5351 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5352 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5353 #ifndef QT_NO_OPENGL
5354 beginBackingStorePainting();
5355 #endif
5356 QPainter p(q);
5357 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5358 #ifndef QT_NO_OPENGL
5359 endBackingStorePainting();
5360 #endif
5361 }
5362
5363 if (!sharedPainter)
5364 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset));
5365
5366 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5367 #ifndef QT_NO_OPENGL
5368 beginBackingStorePainting();
5369 #endif
5370 QPainter p(q);
5371 QColor tint = q->palette().window().color();
5372 tint.setAlphaF(qreal(.6));
5373 p.fillRect(toBePainted.boundingRect(), tint);
5374 #ifndef QT_NO_OPENGL
5375 endBackingStorePainting();
5376 #endif
5377 }
5378 }
5379
5380 #if 0
5381 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5382 qDebug() << "clipping to" << toBePainted << "location == " << offset
5383 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5384 #endif
5385
5386 bool skipPaintEvent = false;
5387 #ifndef QT_NO_OPENGL
5388 if (renderToTexture) {
5389 // This widget renders into a texture which is composed later. We just need to
5390 // punch a hole in the backingstore, so the texture will be visible.
5391 beginBackingStorePainting();
5392 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5393 QPainter p(q);
5394 p.setCompositionMode(QPainter::CompositionMode_Source);
5395 p.fillRect(q->rect(), Qt::transparent);
5396 } else if (!repaintManager) {
5397 // We are not drawing to a backingstore: fall back to QImage
5398 QImage img = grabFramebuffer();
5399 // grabFramebuffer() always sets the format to RGB32
5400 // regardless of whether it is transparent or not.
5401 if (img.format() == QImage::Format_RGB32)
5402 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5403 QPainter p(q);
5404 p.drawImage(q->rect(), img);
5405 skipPaintEvent = true;
5406 }
5407 endBackingStorePainting();
5408 if (renderToTextureReallyDirty)
5409 renderToTextureReallyDirty = 0;
5410 else
5411 skipPaintEvent = true;
5412 }
5413 #endif // QT_NO_OPENGL
5414
5415 if (!skipPaintEvent) {
5416 //actually send the paint event
5417 sendPaintEvent(toBePainted);
5418 }
5419
5420 if (repaintManager)
5421 repaintManager->markNeedsFlush(q, toBePainted, offset);
5422
5423 //restore
5424 if (paintEngine) {
5425 restoreRedirected();
5426 if (!sharedPainter)
5427 paintEngine->d_func()->systemRect = QRect();
5428 else
5429 paintEngine->d_func()->currentClipDevice = nullptr;
5430
5431 setSystemClip(pdev->paintEngine(), 1, QRegion());
5432 }
5433 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5434 if (Q_UNLIKELY(q->paintingActive()))
5435 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5436
5437 if (paintEngine && paintEngine->autoDestruct()) {
5438 delete paintEngine;
5439 }
5440 } else if (q->isWindow()) {
5441 QPaintEngine *engine = pdev->paintEngine();
5442 if (engine) {
5443 QPainter p(pdev);
5444 p.setClipRegion(toBePainted);
5445 const QBrush bg = q->palette().brush(QPalette::Window);
5446 if (bg.style() == Qt::TexturePattern)
5447 p.drawTiledPixmap(q->rect(), bg.texture());
5448 else
5449 p.fillRect(q->rect(), bg);
5450
5451 if (engine->autoDestruct())
5452 delete engine;
5453 }
5454 }
5455 }
5456
5457 if (recursive && !children.isEmpty()) {
5458 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5459 sharedPainter, repaintManager);
5460 }
5461 }
5462
sendPaintEvent(const QRegion & toBePainted)5463 void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5464 {
5465 Q_Q(QWidget);
5466 QPaintEvent e(toBePainted);
5467 QCoreApplication::sendSpontaneousEvent(q, &e);
5468
5469 #ifndef QT_NO_OPENGL
5470 if (renderToTexture)
5471 resolveSamples();
5472 #endif // QT_NO_OPENGL
5473 }
5474
render(QPaintDevice * target,const QPoint & targetOffset,const QRegion & sourceRegion,QWidget::RenderFlags renderFlags)5475 void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5476 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5477 {
5478 if (Q_UNLIKELY(!target)) {
5479 qWarning("QWidget::render: null pointer to paint device");
5480 return;
5481 }
5482
5483 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5484 QRegion paintRegion = !inRenderWithPainter
5485 ? prepareToRender(sourceRegion, renderFlags)
5486 : sourceRegion;
5487 if (paintRegion.isEmpty())
5488 return;
5489
5490 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5491
5492 // Use the target's shared painter if set (typically set when doing
5493 // "other->render(widget);" in the widget's paintEvent.
5494 if (target->devType() == QInternal::Widget) {
5495 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5496 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5497 QPainter *targetPainter = targetPrivate->sharedPainter();
5498 if (targetPainter && targetPainter->isActive())
5499 setSharedPainter(targetPainter);
5500 }
5501 }
5502
5503 // Use the target's redirected device if set and adjust offset and paint
5504 // region accordingly. This is typically the case when people call render
5505 // from the paintEvent.
5506 QPoint offset = targetOffset;
5507 offset -= paintRegion.boundingRect().topLeft();
5508 QPoint redirectionOffset;
5509 QPaintDevice *redirected = nullptr;
5510
5511 if (target->devType() == QInternal::Widget)
5512 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5513
5514 if (redirected) {
5515 target = redirected;
5516 offset -= redirectionOffset;
5517 }
5518
5519 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5520 if (QPaintEngine *targetEngine = target->paintEngine()) {
5521 const QRegion targetSystemClip = targetEngine->systemClip();
5522 if (!targetSystemClip.isEmpty())
5523 paintRegion &= targetSystemClip.translated(-offset);
5524 }
5525 }
5526
5527 // Set backingstore flags.
5528 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5529 if (renderFlags & QWidget::DrawWindowBackground)
5530 flags |= DrawAsRoot;
5531
5532 if (renderFlags & QWidget::DrawChildren)
5533 flags |= DrawRecursive;
5534 else
5535 flags |= DontSubtractOpaqueChildren;
5536
5537 flags |= DontSetCompositionMode;
5538
5539 // Render via backingstore.
5540 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5541
5542 // Restore shared painter.
5543 if (oldSharedPainter)
5544 setSharedPainter(oldSharedPainter);
5545 }
5546
paintSiblingsRecursive(QPaintDevice * pdev,const QObjectList & siblings,int index,const QRegion & rgn,const QPoint & offset,DrawWidgetFlags flags,QPainter * sharedPainter,QWidgetRepaintManager * repaintManager)5547 void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5548 const QPoint &offset, DrawWidgetFlags flags
5549 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5550 {
5551 QWidget *w = nullptr;
5552 QRect boundingRect;
5553 bool dirtyBoundingRect = true;
5554 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5555 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5556
5557 do {
5558 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5559 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5560 && !(excludeNativeChildren && x->internalWinId())) {
5561 if (dirtyBoundingRect) {
5562 boundingRect = rgn.boundingRect();
5563 dirtyBoundingRect = false;
5564 }
5565
5566 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5567 w = x;
5568 break;
5569 }
5570 }
5571 --index;
5572 } while (index >= 0);
5573
5574 if (!w)
5575 return;
5576
5577 QWidgetPrivate *wd = w->d_func();
5578 const QPoint widgetPos(w->data->crect.topLeft());
5579 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5580 if (index > 0) {
5581 QRegion wr(rgn);
5582 if (wd->isOpaque)
5583 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5584 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5585 sharedPainter, repaintManager);
5586 }
5587
5588 if (w->updatesEnabled()
5589 #if QT_CONFIG(graphicsview)
5590 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5591 #endif // QT_CONFIG(graphicsview)
5592 ) {
5593 QRegion wRegion(rgn);
5594 wRegion &= wd->effectiveRectFor(w->data->crect);
5595 wRegion.translate(-widgetPos);
5596 if (hasMask)
5597 wRegion &= wd->extra->mask;
5598 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5599 }
5600 }
5601
5602 #if QT_CONFIG(graphicseffect)
boundingRect(Qt::CoordinateSystem system) const5603 QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5604 {
5605 if (system != Qt::DeviceCoordinates)
5606 return m_widget->rect();
5607
5608 if (Q_UNLIKELY(!context)) {
5609 // Device coordinates without context not yet supported.
5610 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5611 return QRectF();
5612 }
5613
5614 return context->painter->worldTransform().mapRect(m_widget->rect());
5615 }
5616
draw(QPainter * painter)5617 void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5618 {
5619 if (!context || context->painter != painter) {
5620 m_widget->render(painter);
5621 return;
5622 }
5623
5624 // The region saved in the context is neither clipped to the rect
5625 // nor the mask, so we have to clip it here before calling drawWidget.
5626 QRegion toBePainted = context->rgn;
5627 toBePainted &= m_widget->rect();
5628 QWidgetPrivate *wd = qt_widget_private(m_widget);
5629 if (wd->extra && wd->extra->hasMask)
5630 toBePainted &= wd->extra->mask;
5631
5632 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5633 context->sharedPainter, context->repaintManager);
5634 }
5635
pixmap(Qt::CoordinateSystem system,QPoint * offset,QGraphicsEffect::PixmapPadMode mode) const5636 QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5637 QGraphicsEffect::PixmapPadMode mode) const
5638 {
5639 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5640 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5641 // Device coordinates without context not yet supported.
5642 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5643 return QPixmap();
5644 }
5645
5646 QPoint pixmapOffset;
5647 QRectF sourceRect = m_widget->rect();
5648
5649 if (deviceCoordinates) {
5650 const QTransform &painterTransform = context->painter->worldTransform();
5651 sourceRect = painterTransform.mapRect(sourceRect);
5652 pixmapOffset = painterTransform.map(pixmapOffset);
5653 }
5654
5655 QRect effectRect;
5656
5657 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5658 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5659 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5660 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5661 else
5662 effectRect = sourceRect.toAlignedRect();
5663
5664 if (offset)
5665 *offset = effectRect.topLeft();
5666
5667 pixmapOffset -= effectRect.topLeft();
5668
5669 qreal dpr(1.0);
5670 if (const auto *paintDevice = context->painter->device())
5671 dpr = paintDevice->devicePixelRatioF();
5672 else
5673 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5674 QPixmap pixmap(effectRect.size() * dpr);
5675 pixmap.setDevicePixelRatio(dpr);
5676
5677 pixmap.fill(Qt::transparent);
5678 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5679 return pixmap;
5680 }
5681 #endif // QT_CONFIG(graphicseffect)
5682
5683 #if QT_CONFIG(graphicsview)
5684 /*!
5685 \internal
5686
5687 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5688 widget and its ancestors. The search starts at \a origin (inclusive).
5689 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5690 embedded widget was found.
5691 */
nearestGraphicsProxyWidget(const QWidget * origin)5692 QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5693 {
5694 if (origin) {
5695 const auto &extra = origin->d_func()->extra;
5696 if (extra && extra->proxyWidget)
5697 return extra->proxyWidget;
5698 return nearestGraphicsProxyWidget(origin->parentWidget());
5699 }
5700 return nullptr;
5701 }
5702 #endif
5703
5704 /*!
5705 \property QWidget::locale
5706 \brief the widget's locale
5707 \since 4.3
5708
5709 As long as no special locale has been set, this is either
5710 the parent's locale or (if this widget is a top level widget),
5711 the default locale.
5712
5713 If the widget displays dates or numbers, these should be formatted
5714 using the widget's locale.
5715
5716 \sa QLocale, QLocale::setDefault()
5717 */
5718
setLocale_helper(const QLocale & loc,bool forceUpdate)5719 void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5720 {
5721 Q_Q(QWidget);
5722 if (locale == loc && !forceUpdate)
5723 return;
5724
5725 locale = loc;
5726
5727 if (!children.isEmpty()) {
5728 for (int i = 0; i < children.size(); ++i) {
5729 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5730 if (!w)
5731 continue;
5732 if (w->testAttribute(Qt::WA_SetLocale))
5733 continue;
5734 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5735 continue;
5736 w->d_func()->setLocale_helper(loc, forceUpdate);
5737 }
5738 }
5739 QEvent e(QEvent::LocaleChange);
5740 QCoreApplication::sendEvent(q, &e);
5741 }
5742
setLocale(const QLocale & locale)5743 void QWidget::setLocale(const QLocale &locale)
5744 {
5745 Q_D(QWidget);
5746
5747 setAttribute(Qt::WA_SetLocale);
5748 d->setLocale_helper(locale);
5749 }
5750
locale() const5751 QLocale QWidget::locale() const
5752 {
5753 Q_D(const QWidget);
5754
5755 return d->locale;
5756 }
5757
resolveLocale()5758 void QWidgetPrivate::resolveLocale()
5759 {
5760 Q_Q(const QWidget);
5761
5762 if (!q->testAttribute(Qt::WA_SetLocale)) {
5763 QWidget *parent = q->parentWidget();
5764 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5765 ? QLocale() : parent->locale());
5766 }
5767 }
5768
unsetLocale()5769 void QWidget::unsetLocale()
5770 {
5771 Q_D(QWidget);
5772 setAttribute(Qt::WA_SetLocale, false);
5773 d->resolveLocale();
5774 }
5775
5776 /*!
5777 \property QWidget::windowTitle
5778 \brief the window title (caption)
5779
5780 This property only makes sense for top-level widgets, such as
5781 windows and dialogs. If no caption has been set, the title is based of the
5782 \l windowFilePath. If neither of these is set, then the title is
5783 an empty string.
5784
5785 If you use the \l windowModified mechanism, the window title must
5786 contain a "[*]" placeholder, which indicates where the '*' should
5787 appear. Normally, it should appear right after the file name
5788 (e.g., "document1.txt[*] - Text Editor"). If the \l
5789 windowModified property is \c false (the default), the placeholder
5790 is simply removed.
5791
5792 On some desktop platforms (including Windows and Unix), the application name
5793 (from QGuiApplication::applicationDisplayName) is added at the end of the
5794 window title, if set. This is done by the QPA plugin, so it is shown to the
5795 user, but isn't part of the windowTitle string.
5796
5797 \sa windowIcon, windowModified, windowFilePath
5798 */
windowTitle() const5799 QString QWidget::windowTitle() const
5800 {
5801 Q_D(const QWidget);
5802 if (d->extra && d->extra->topextra) {
5803 if (!d->extra->topextra->caption.isEmpty())
5804 return d->extra->topextra->caption;
5805 if (!d->extra->topextra->filePath.isEmpty())
5806 return QFileInfo(d->extra->topextra->filePath).fileName() + QLatin1String("[*]");
5807 }
5808 return QString();
5809 }
5810
5811 /*!
5812 Returns a modified window title with the [*] place holder
5813 replaced according to the rules described in QWidget::setWindowTitle
5814
5815 This function assumes that "[*]" can be quoted by another
5816 "[*]", so it will replace two place holders by one and
5817 a single last one by either "*" or nothing depending on
5818 the modified flag.
5819
5820 \internal
5821 */
qt_setWindowTitle_helperHelper(const QString & title,const QWidget * widget)5822 QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
5823 {
5824 Q_ASSERT(widget);
5825
5826 QString cap = title;
5827 if (cap.isEmpty())
5828 return cap;
5829
5830 QLatin1String placeHolder("[*]");
5831 int index = cap.indexOf(placeHolder);
5832
5833 // here the magic begins
5834 while (index != -1) {
5835 index += placeHolder.size();
5836 int count = 1;
5837 while (cap.indexOf(placeHolder, index) == index) {
5838 ++count;
5839 index += placeHolder.size();
5840 }
5841
5842 if (count%2) { // odd number of [*] -> replace last one
5843 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
5844 if (widget->isWindowModified()
5845 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
5846 cap.replace(lastIndex, 3, QWidget::tr("*"));
5847 else
5848 cap.remove(lastIndex, 3);
5849 }
5850
5851 index = cap.indexOf(placeHolder, index);
5852 }
5853
5854 cap.replace(QLatin1String("[*][*]"), placeHolder);
5855
5856 return cap;
5857 }
5858
setWindowTitle_helper(const QString & title)5859 void QWidgetPrivate::setWindowTitle_helper(const QString &title)
5860 {
5861 Q_Q(QWidget);
5862 if (q->testAttribute(Qt::WA_WState_Created))
5863 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
5864 }
5865
setWindowTitle_sys(const QString & caption)5866 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
5867 {
5868 Q_Q(QWidget);
5869 if (!q->isWindow())
5870 return;
5871
5872 if (QWindow *window = q->windowHandle())
5873 window->setTitle(caption);
5874
5875 }
5876
setWindowIconText_helper(const QString & title)5877 void QWidgetPrivate::setWindowIconText_helper(const QString &title)
5878 {
5879 Q_Q(QWidget);
5880 if (q->testAttribute(Qt::WA_WState_Created))
5881 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
5882 }
5883
setWindowIconText_sys(const QString & iconText)5884 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
5885 {
5886 Q_Q(QWidget);
5887 // ### The QWidget property is deprecated, but the XCB window function is not.
5888 // It should remain available for the rare application that needs it.
5889 if (QWindow *window = q->windowHandle())
5890 QXcbWindowFunctions::setWmWindowIconText(window, iconText);
5891 }
5892
5893 /*!
5894 \fn void QWidget::windowIconTextChanged(const QString &iconText)
5895
5896 This signal is emitted when the window's icon text has changed, with the
5897 new \a iconText as an argument.
5898
5899 \since 5.2
5900 \obsolete
5901
5902 This signal is deprecated.
5903 */
5904
setWindowIconText(const QString & iconText)5905 void QWidget::setWindowIconText(const QString &iconText)
5906 {
5907 if (QWidget::windowIconText() == iconText)
5908 return;
5909
5910 Q_D(QWidget);
5911 d->topData()->iconText = iconText;
5912 d->setWindowIconText_helper(iconText);
5913
5914 QEvent e(QEvent::IconTextChange);
5915 QCoreApplication::sendEvent(this, &e);
5916
5917 emit windowIconTextChanged(iconText);
5918 }
5919
5920 /*!
5921 \fn void QWidget::windowTitleChanged(const QString &title)
5922
5923 This signal is emitted when the window's title has changed, with the
5924 new \a title as an argument.
5925
5926 \since 5.2
5927 */
5928
setWindowTitle(const QString & title)5929 void QWidget::setWindowTitle(const QString &title)
5930 {
5931 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
5932 return;
5933
5934 Q_D(QWidget);
5935 d->topData()->caption = title;
5936 d->setWindowTitle_helper(title);
5937
5938 QEvent e(QEvent::WindowTitleChange);
5939 QCoreApplication::sendEvent(this, &e);
5940
5941 emit windowTitleChanged(title);
5942 }
5943
5944
5945 /*!
5946 \property QWidget::windowIcon
5947 \brief the widget's icon
5948
5949 This property only makes sense for windows. If no icon
5950 has been set, windowIcon() returns the application icon
5951 (QApplication::windowIcon()).
5952
5953 \note On \macos, window icons represent the active document,
5954 and will not be displayed unless a file path has also been
5955 set using setWindowFilePath.
5956
5957 \sa windowTitle, setWindowFilePath
5958 */
windowIcon() const5959 QIcon QWidget::windowIcon() const
5960 {
5961 const QWidget *w = this;
5962 while (w) {
5963 const QWidgetPrivate *d = w->d_func();
5964 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
5965 return *d->extra->topextra->icon;
5966 w = w->parentWidget();
5967 }
5968 return QApplication::windowIcon();
5969 }
5970
setWindowIcon_helper()5971 void QWidgetPrivate::setWindowIcon_helper()
5972 {
5973 Q_Q(QWidget);
5974 QEvent e(QEvent::WindowIconChange);
5975
5976 // Do not send the event if the widget is a top level.
5977 // In that case, setWindowIcon_sys does it, and event propagation from
5978 // QWidgetWindow to the top level QWidget ensures that the event reaches
5979 // the top level anyhow
5980 if (!q->windowHandle())
5981 QCoreApplication::sendEvent(q, &e);
5982 for (int i = 0; i < children.size(); ++i) {
5983 QWidget *w = qobject_cast<QWidget *>(children.at(i));
5984 if (w && !w->isWindow())
5985 QCoreApplication::sendEvent(w, &e);
5986 }
5987 }
5988
5989 /*!
5990 \fn void QWidget::windowIconChanged(const QIcon &icon)
5991
5992 This signal is emitted when the window's icon has changed, with the
5993 new \a icon as an argument.
5994
5995 \since 5.2
5996 */
5997
setWindowIcon(const QIcon & icon)5998 void QWidget::setWindowIcon(const QIcon &icon)
5999 {
6000 Q_D(QWidget);
6001
6002 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6003 d->createTLExtra();
6004
6005 if (!d->extra->topextra->icon)
6006 d->extra->topextra->icon = qt_make_unique<QIcon>(icon);
6007 else
6008 *d->extra->topextra->icon = icon;
6009
6010 d->setWindowIcon_sys();
6011 d->setWindowIcon_helper();
6012
6013 emit windowIconChanged(icon);
6014 }
6015
setWindowIcon_sys()6016 void QWidgetPrivate::setWindowIcon_sys()
6017 {
6018 Q_Q(QWidget);
6019 if (QWindow *window = q->windowHandle())
6020 window->setIcon(q->windowIcon());
6021 }
6022
6023 /*!
6024 \property QWidget::windowIconText
6025 \brief the text to be displayed on the icon of a minimized window
6026
6027 This property only makes sense for windows. If no icon
6028 text has been set, this accessor returns an empty string.
6029 It is only implemented on the X11 platform, and only certain
6030 window managers use this window property.
6031
6032 \obsolete
6033 This property is deprecated.
6034
6035 \sa windowIcon, windowTitle
6036 */
6037
windowIconText() const6038 QString QWidget::windowIconText() const
6039 {
6040 Q_D(const QWidget);
6041 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6042 }
6043
6044 /*!
6045 \property QWidget::windowFilePath
6046 \since 4.4
6047 \brief the file path associated with a widget
6048
6049 This property only makes sense for windows. It associates a file path with
6050 a window. If you set the file path, but have not set the window title, Qt
6051 sets the window title to the file name of the specified path, obtained using
6052 QFileInfo::fileName().
6053
6054 If the window title is set at any point, then the window title takes precedence and
6055 will be shown instead of the file path string.
6056
6057 Additionally, on \macos, this has an added benefit that it sets the
6058 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6059 for the window, assuming that the file path exists.
6060
6061 If no file path is set, this property contains an empty string.
6062
6063 By default, this property contains an empty string.
6064
6065 \sa windowTitle, windowIcon
6066 */
6067
windowFilePath() const6068 QString QWidget::windowFilePath() const
6069 {
6070 Q_D(const QWidget);
6071 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6072 }
6073
setWindowFilePath(const QString & filePath)6074 void QWidget::setWindowFilePath(const QString &filePath)
6075 {
6076 if (filePath == windowFilePath())
6077 return;
6078
6079 Q_D(QWidget);
6080
6081 d->createTLExtra();
6082 d->extra->topextra->filePath = filePath;
6083 d->setWindowFilePath_helper(filePath);
6084 }
6085
setWindowFilePath_helper(const QString & filePath)6086 void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6087 {
6088 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6089 #ifdef Q_OS_MAC
6090 setWindowTitle_helper(QFileInfo(filePath).fileName());
6091 #else
6092 Q_Q(QWidget);
6093 Q_UNUSED(filePath);
6094 setWindowTitle_helper(q->windowTitle());
6095 #endif
6096 }
6097 #ifdef Q_OS_MAC
6098 setWindowFilePath_sys(filePath);
6099 #endif
6100 }
6101
setWindowFilePath_sys(const QString & filePath)6102 void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6103 {
6104 Q_Q(QWidget);
6105 if (!q->isWindow())
6106 return;
6107
6108 if (QWindow *window = q->windowHandle())
6109 window->setFilePath(filePath);
6110 }
6111
6112 /*!
6113 Returns the window's role, or an empty string.
6114
6115 \sa windowIcon, windowTitle
6116 */
6117
windowRole() const6118 QString QWidget::windowRole() const
6119 {
6120 Q_D(const QWidget);
6121 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6122 }
6123
6124 /*!
6125 Sets the window's role to \a role. This only makes sense for
6126 windows on X11.
6127 */
setWindowRole(const QString & role)6128 void QWidget::setWindowRole(const QString &role)
6129 {
6130 Q_D(QWidget);
6131 d->createTLExtra();
6132 d->topData()->role = role;
6133 if (windowHandle())
6134 QXcbWindowFunctions::setWmWindowRole(windowHandle(), role.toLatin1());
6135 }
6136
6137 /*!
6138 \property QWidget::mouseTracking
6139 \brief whether mouse tracking is enabled for the widget
6140
6141 If mouse tracking is disabled (the default), the widget only
6142 receives mouse move events when at least one mouse button is
6143 pressed while the mouse is being moved.
6144
6145 If mouse tracking is enabled, the widget receives mouse move
6146 events even if no buttons are pressed.
6147
6148 \sa mouseMoveEvent()
6149 */
6150
6151 /*!
6152 \property QWidget::tabletTracking
6153 \brief whether tablet tracking is enabled for the widget
6154 \since 5.9
6155
6156 If tablet tracking is disabled (the default), the widget only
6157 receives tablet move events when the stylus is in contact with
6158 the tablet, or at least one stylus button is pressed,
6159 while the stylus is being moved.
6160
6161 If tablet tracking is enabled, the widget receives tablet move
6162 events even while hovering in proximity. This is useful for
6163 monitoring position as well as the auxiliary properties such
6164 as rotation and tilt, and providing feedback in the UI.
6165
6166 \sa tabletEvent()
6167 */
6168
6169
6170 /*!
6171 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6172 function resets this widget to have no focus proxy.
6173
6174 Some widgets can "have focus", but create a child widget, such as
6175 QLineEdit, to actually handle the focus. In this case, the widget
6176 can set the line edit to be its focus proxy.
6177
6178 setFocusProxy() sets the widget which will actually get focus when
6179 "this widget" gets it. If there is a focus proxy, setFocus() and
6180 hasFocus() operate on the focus proxy. If "this widget" is the focus
6181 widget, then setFocusProxy() moves focus to the new focus proxy.
6182
6183 \sa focusProxy()
6184 */
6185
setFocusProxy(QWidget * w)6186 void QWidget::setFocusProxy(QWidget * w)
6187 {
6188 Q_D(QWidget);
6189 if (!w && !d->extra)
6190 return;
6191
6192 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6193 if (Q_UNLIKELY(fp == this)) {
6194 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6195 return;
6196 }
6197 }
6198
6199 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6200
6201 d->createExtra();
6202 d->extra->focus_proxy = w;
6203
6204 if (moveFocusToProxy)
6205 setFocus(Qt::OtherFocusReason);
6206 }
6207
6208
6209 /*!
6210 Returns the focus proxy, or \nullptr if there is no focus proxy.
6211
6212 \sa setFocusProxy()
6213 */
6214
focusProxy() const6215 QWidget *QWidget::focusProxy() const
6216 {
6217 Q_D(const QWidget);
6218 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6219 }
6220
6221
6222 /*!
6223 \property QWidget::focus
6224 \brief whether this widget (or its focus proxy) has the keyboard
6225 input focus
6226
6227 By default, this property is \c false.
6228
6229 \note Obtaining the value of this property for a widget is effectively equivalent
6230 to checking whether QApplication::focusWidget() refers to the widget.
6231
6232 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6233 */
hasFocus() const6234 bool QWidget::hasFocus() const
6235 {
6236 const QWidget* w = this;
6237 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6238 w = w->d_func()->extra->focus_proxy;
6239 #if QT_CONFIG(graphicsview)
6240 if (QWidget *window = w->window()) {
6241 const auto &e = window->d_func()->extra;
6242 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6243 return true;
6244 }
6245 #endif // QT_CONFIG(graphicsview)
6246 return (QApplication::focusWidget() == w);
6247 }
6248
6249 /*!
6250 Gives the keyboard input focus to this widget (or its focus
6251 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6252 be passed into any focus event sent from this function, it is used
6253 to give an explanation of what caused the widget to get focus.
6254 If the window is not active, the widget will be given the focus when
6255 the window becomes active.
6256
6257 First, a focus about to change event is sent to the focus widget (if any) to
6258 tell it that it is about to lose the focus. Then focus is changed, a
6259 focus out event is sent to the previous focus item and a focus in event is sent
6260 to the new item to tell it that it just received the focus.
6261 (Nothing happens if the focus in and focus out widgets are the
6262 same.)
6263
6264 \note On embedded platforms, setFocus() will not cause an input panel
6265 to be opened by the input method. If you want this to happen, you
6266 have to send a QEvent::RequestSoftwareInputPanel event to the
6267 widget yourself.
6268
6269 setFocus() gives focus to a widget regardless of its focus policy,
6270 but does not clear any keyboard grab (see grabKeyboard()).
6271
6272 Be aware that if the widget is hidden, it will not accept focus
6273 until it is shown.
6274
6275 \warning If you call setFocus() in a function which may itself be
6276 called from focusOutEvent() or focusInEvent(), you may get an
6277 infinite recursion.
6278
6279 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6280 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6281 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6282 */
6283
setFocus(Qt::FocusReason reason)6284 void QWidget::setFocus(Qt::FocusReason reason)
6285 {
6286 if (!isEnabled())
6287 return;
6288
6289 QWidget *f = d_func()->deepestFocusProxy();
6290 if (!f)
6291 f = this;
6292
6293 if (QApplication::focusWidget() == f)
6294 return;
6295
6296 #if QT_CONFIG(graphicsview)
6297 QWidget *previousProxyFocus = nullptr;
6298 if (const auto &topData = window()->d_func()->extra) {
6299 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6300 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6301 if (previousProxyFocus && previousProxyFocus->focusProxy())
6302 previousProxyFocus = previousProxyFocus->focusProxy();
6303 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6304 return;
6305 }
6306 }
6307 #endif
6308
6309 #if QT_CONFIG(graphicsview)
6310 // Update proxy state
6311 if (const auto &topData = window()->d_func()->extra) {
6312 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6313 f->d_func()->updateFocusChild();
6314 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6315 topData->proxyWidget->setFocus(reason);
6316 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6317 }
6318 }
6319 #endif
6320
6321 if (f->isActiveWindow()) {
6322 QWidget *prev = QApplicationPrivate::focus_widget;
6323 if (prev) {
6324 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6325 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6326 QGuiApplication::inputMethod()->commit();
6327 }
6328
6329 if (reason != Qt::NoFocusReason) {
6330 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6331 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6332 }
6333 }
6334
6335 f->d_func()->updateFocusChild();
6336
6337 QApplicationPrivate::setFocusWidget(f, reason);
6338 #ifndef QT_NO_ACCESSIBILITY
6339 // menus update the focus manually and this would create bogus events
6340 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6341 {
6342 QAccessibleEvent event(f, QAccessible::Focus);
6343 QAccessible::updateAccessibility(&event);
6344 }
6345 #endif
6346 #if QT_CONFIG(graphicsview)
6347 if (const auto &topData = window()->d_func()->extra) {
6348 if (topData->proxyWidget) {
6349 if (previousProxyFocus && previousProxyFocus != f) {
6350 // Send event to self
6351 QFocusEvent event(QEvent::FocusOut, reason);
6352 QPointer<QWidget> that = previousProxyFocus;
6353 QCoreApplication::sendEvent(previousProxyFocus, &event);
6354 if (that)
6355 QCoreApplication::sendEvent(that->style(), &event);
6356 }
6357 if (!isHidden()) {
6358 #if QT_CONFIG(graphicsview)
6359 // Update proxy state
6360 if (const auto &topData = window()->d_func()->extra)
6361 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6362 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6363 #endif
6364 // Send event to self
6365 QFocusEvent event(QEvent::FocusIn, reason);
6366 QPointer<QWidget> that = f;
6367 QCoreApplication::sendEvent(f, &event);
6368 if (that)
6369 QCoreApplication::sendEvent(that->style(), &event);
6370 }
6371 }
6372 }
6373 #endif
6374 } else {
6375 f->d_func()->updateFocusChild();
6376 }
6377 }
6378
6379
6380 /*!\internal
6381 * A focus proxy can have its own focus proxy, which can have its own
6382 * proxy, and so on. This helper function returns the widget that sits
6383 * at the bottom of the proxy chain, and therefore the one that should
6384 * normally get focus if this widget receives a focus request.
6385 */
deepestFocusProxy() const6386 QWidget *QWidgetPrivate::deepestFocusProxy() const
6387 {
6388 Q_Q(const QWidget);
6389
6390 QWidget *focusProxy = q->focusProxy();
6391 if (!focusProxy)
6392 return nullptr;
6393
6394 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6395 focusProxy = nextFocusProxy;
6396
6397 return focusProxy;
6398 }
6399
isEmbedded(const QWindow * w)6400 static inline bool isEmbedded(const QWindow *w)
6401 {
6402 const auto platformWindow = w->handle();
6403 return platformWindow && platformWindow->isEmbedded();
6404 }
6405
setFocus_sys()6406 void QWidgetPrivate::setFocus_sys()
6407 {
6408 Q_Q(QWidget);
6409 // Embedded native widget may have taken the focus; get it back to toplevel
6410 // if that is the case (QTBUG-25852)
6411 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6412 // unless the application is embedded (QTBUG-71991).
6413 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6414 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6415 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6416 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6417 || isEmbedded(nativeWindow))) {
6418 nativeWindow->requestActivate();
6419 }
6420 }
6421 }
6422
6423 // updates focus_child on parent widgets to point into this widget
updateFocusChild()6424 void QWidgetPrivate::updateFocusChild()
6425 {
6426 Q_Q(QWidget);
6427
6428 QWidget *w = q;
6429 if (q->isHidden()) {
6430 while (w && w->isHidden()) {
6431 w->d_func()->focus_child = q;
6432 w = w->isWindow() ? nullptr : w->parentWidget();
6433 }
6434 } else {
6435 while (w) {
6436 w->d_func()->focus_child = q;
6437 w = w->isWindow() ? nullptr : w->parentWidget();
6438 }
6439 }
6440
6441 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6442 if (extra->window)
6443 emit extra->window->focusObjectChanged(q);
6444 }
6445 }
6446
6447 /*!
6448 \fn void QWidget::setFocus()
6449 \overload
6450
6451 Gives the keyboard input focus to this widget (or its focus
6452 proxy) if this widget or one of its parents is the
6453 \l{isActiveWindow()}{active window}.
6454 */
6455
6456 /*!
6457 Takes keyboard input focus from the widget.
6458
6459 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6460 lost the focus.
6461
6462 This widget must enable focus setting in order to get the keyboard
6463 input focus, i.e. it must call setFocusPolicy().
6464
6465 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6466 setFocusPolicy(), QApplication::focusWidget()
6467 */
6468
clearFocus()6469 void QWidget::clearFocus()
6470 {
6471 if (hasFocus()) {
6472 if (testAttribute(Qt::WA_InputMethodEnabled))
6473 QGuiApplication::inputMethod()->commit();
6474
6475 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6476 QCoreApplication::sendEvent(this, &focusAboutToChange);
6477 }
6478
6479 QTLWExtra *extra = window()->d_func()->maybeTopData();
6480 QObject *originalFocusObject = (extra && extra->window) ? extra->window->focusObject() : nullptr;
6481
6482 QWidget *w = this;
6483 while (w) {
6484 // Just like setFocus(), we update (clear) the focus_child of our parents
6485 if (w->d_func()->focus_child == this)
6486 w->d_func()->focus_child = nullptr;
6487 w = w->parentWidget();
6488 }
6489
6490 // We've potentially cleared the focus_child of our parents, so we need
6491 // to report this to the rest of Qt. Note that the focus_child is not the same
6492 // thing as the application's focusWidget, which is why this piece of code is
6493 // not inside a hasFocus() block.
6494 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6495 emit extra->window->focusObjectChanged(extra->window->focusObject());
6496
6497 #if QT_CONFIG(graphicsview)
6498 const auto &topData = d_func()->extra;
6499 if (topData && topData->proxyWidget)
6500 topData->proxyWidget->clearFocus();
6501 #endif
6502
6503 if (hasFocus()) {
6504 // Update proxy state
6505 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6506 #ifndef QT_NO_ACCESSIBILITY
6507 QAccessibleEvent event(this, QAccessible::Focus);
6508 QAccessible::updateAccessibility(&event);
6509 #endif
6510 }
6511 }
6512
6513
6514 /*!
6515 \fn bool QWidget::focusNextChild()
6516
6517 Finds a new widget to give the keyboard focus to, as appropriate
6518 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6519 false if it can't.
6520
6521 \sa focusPreviousChild()
6522 */
6523
6524 /*!
6525 \fn bool QWidget::focusPreviousChild()
6526
6527 Finds a new widget to give the keyboard focus to, as appropriate
6528 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6529 or false if it can't.
6530
6531 \sa focusNextChild()
6532 */
6533
6534 /*!
6535 Finds a new widget to give the keyboard focus to, as appropriate
6536 for Tab and Shift+Tab, and returns \c true if it can find a new
6537 widget, or false if it can't.
6538
6539 If \a next is true, this function searches forward, if \a next
6540 is false, it searches backward.
6541
6542 Sometimes, you will want to reimplement this function. For
6543 example, a web browser might reimplement it to move its "current
6544 active link" forward or backward, and call
6545 focusNextPrevChild() only when it reaches the last or
6546 first link on the "page".
6547
6548 Child widgets call focusNextPrevChild() on their parent widgets,
6549 but only the window that contains the child widgets decides where
6550 to redirect focus. By reimplementing this function for an object,
6551 you thus gain control of focus traversal for all child widgets.
6552
6553 \sa focusNextChild(), focusPreviousChild()
6554 */
6555
focusNextPrevChild(bool next)6556 bool QWidget::focusNextPrevChild(bool next)
6557 {
6558 QWidget* p = parentWidget();
6559 bool isSubWindow = (windowType() == Qt::SubWindow);
6560 if (!isWindow() && !isSubWindow && p)
6561 return p->focusNextPrevChild(next);
6562 #if QT_CONFIG(graphicsview)
6563 Q_D(QWidget);
6564 if (d->extra && d->extra->proxyWidget)
6565 return d->extra->proxyWidget->focusNextPrevChild(next);
6566 #endif
6567
6568 bool wrappingOccurred = false;
6569 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6570 &wrappingOccurred);
6571 if (!w) return false;
6572
6573 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6574
6575 /* If we are about to wrap the focus chain, give the platform
6576 * implementation a chance to alter the wrapping behavior. This is
6577 * especially needed when the window is embedded in a window created by
6578 * another process.
6579 */
6580 if (wrappingOccurred) {
6581 QWindow *window = windowHandle();
6582 if (window != nullptr) {
6583 QWindowPrivate *winp = qt_window_private(window);
6584
6585 if (winp->platformWindow != nullptr) {
6586 QFocusEvent event(QEvent::FocusIn, reason);
6587 event.ignore();
6588 winp->platformWindow->windowEvent(&event);
6589 if (event.isAccepted()) return true;
6590 }
6591 }
6592 }
6593
6594 w->setFocus(reason);
6595 return true;
6596 }
6597
6598 /*!
6599 Returns the last child of this widget that setFocus had been
6600 called on. For top level widgets this is the widget that will get
6601 focus in case this window gets activated
6602
6603 This is not the same as QApplication::focusWidget(), which returns
6604 the focus widget in the currently active window.
6605 */
6606
focusWidget() const6607 QWidget *QWidget::focusWidget() const
6608 {
6609 return const_cast<QWidget *>(d_func()->focus_child);
6610 }
6611
6612 /*!
6613 Returns the next widget in this widget's focus chain.
6614
6615 \sa previousInFocusChain()
6616 */
nextInFocusChain() const6617 QWidget *QWidget::nextInFocusChain() const
6618 {
6619 return const_cast<QWidget *>(d_func()->focus_next);
6620 }
6621
6622 /*!
6623 \brief The previousInFocusChain function returns the previous
6624 widget in this widget's focus chain.
6625
6626 \sa nextInFocusChain()
6627
6628 \since 4.6
6629 */
previousInFocusChain() const6630 QWidget *QWidget::previousInFocusChain() const
6631 {
6632 return const_cast<QWidget *>(d_func()->focus_prev);
6633 }
6634
6635 /*!
6636 \property QWidget::isActiveWindow
6637 \brief whether this widget's window is the active window
6638
6639 The active window is the window that contains the widget that has
6640 keyboard focus (The window may still have focus if it has no
6641 widgets or none of its widgets accepts keyboard focus).
6642
6643 When popup windows are visible, this property is \c true for both the
6644 active window \e and for the popup.
6645
6646 By default, this property is \c false.
6647
6648 \sa activateWindow(), QApplication::activeWindow()
6649 */
isActiveWindow() const6650 bool QWidget::isActiveWindow() const
6651 {
6652 QWidget *tlw = window();
6653 if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6654 return true;
6655
6656 #if QT_CONFIG(graphicsview)
6657 if (const auto &tlwExtra = tlw->d_func()->extra) {
6658 if (isVisible() && tlwExtra->proxyWidget)
6659 return tlwExtra->proxyWidget->isActiveWindow();
6660 }
6661 #endif
6662
6663 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6664 if(tlw->windowType() == Qt::Tool &&
6665 !tlw->isModal() &&
6666 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6667 return true;
6668 QWidget *w = QApplication::activeWindow();
6669 while(w && tlw->windowType() == Qt::Tool &&
6670 !w->isModal() && w->parentWidget()) {
6671 w = w->parentWidget()->window();
6672 if(w == tlw)
6673 return true;
6674 }
6675 }
6676
6677 // Check for an active window container
6678 if (QWindow *ww = QGuiApplication::focusWindow()) {
6679 while (ww) {
6680 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6681 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6682 if (qwc && qwc->topLevelWidget() == tlw)
6683 return true;
6684 ww = ww->parent();
6685 }
6686 }
6687
6688 // Check if platform adaptation thinks the window is active. This is necessary for
6689 // example in case of ActiveQt servers that are embedded into another application.
6690 // Those are separate processes that are not part of the parent application Qt window/widget
6691 // hierarchy, so they need to rely on native methods to determine if they are part of the
6692 // active window.
6693 if (const QWindow *w = tlw->windowHandle()) {
6694 if (w->handle())
6695 return w->handle()->isActive();
6696 }
6697
6698 return false;
6699 }
6700
6701 /*!
6702 Puts the \a second widget after the \a first widget in the focus order.
6703
6704 It effectively removes the \a second widget from its focus chain and
6705 inserts it after the \a first widget.
6706
6707 Note that since the tab order of the \a second widget is changed, you
6708 should order a chain like this:
6709
6710 \snippet code/src_gui_kernel_qwidget.cpp 9
6711
6712 \e not like this:
6713
6714 \snippet code/src_gui_kernel_qwidget.cpp 10
6715
6716 If \a first or \a second has a focus proxy, setTabOrder()
6717 correctly substitutes the proxy.
6718
6719 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
6720 a compound widget. When setting a tab order between one or two compound widgets, the
6721 local tab order inside each will be preserved. This means that if both widgets are
6722 compound widgets, the resulting tab order will be from the last child inside
6723 \a first, to the first child inside \a second.
6724
6725 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6726 */
setTabOrder(QWidget * first,QWidget * second)6727 void QWidget::setTabOrder(QWidget* first, QWidget *second)
6728 {
6729 if (!first || !second || first == second
6730 || first->focusPolicy() == Qt::NoFocus
6731 || second->focusPolicy() == Qt::NoFocus)
6732 return;
6733
6734 if (Q_UNLIKELY(first->window() != second->window())) {
6735 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
6736 return;
6737 }
6738
6739 auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild)
6740 {
6741 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
6742 // determines the last focus child for a widget, taking proxies and compound widgets into account.
6743 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
6744 // 'lastFocusChild' will be set to the target itself.
6745 lastFocusChild = target;
6746
6747 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
6748 if (!focusProxy || !target->isAncestorOf(focusProxy))
6749 return;
6750
6751 lastFocusChild = focusProxy;
6752
6753 for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
6754 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
6755 focusNext = focusNext->d_func()->focus_next) {
6756 if (focusNext->focusPolicy() != Qt::NoFocus)
6757 lastFocusChild = focusNext;
6758 }
6759 };
6760 auto setPrev = [](QWidget *w, QWidget *prev)
6761 {
6762 w->d_func()->focus_prev = prev;
6763 };
6764 auto setNext = [](QWidget *w, QWidget *next)
6765 {
6766 w->d_func()->focus_next = next;
6767 };
6768
6769 // remove the second widget from the chain
6770 QWidget *lastFocusChildOfSecond;
6771 determineLastFocusChild(second, lastFocusChildOfSecond);
6772 {
6773 QWidget *oldPrev = second->d_func()->focus_prev;
6774 QWidget *prevWithFocus = oldPrev;
6775 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
6776 prevWithFocus = prevWithFocus->d_func()->focus_prev;
6777 // only widgets between first and second -> all is fine
6778 if (prevWithFocus == first)
6779 return;
6780 QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
6781 setPrev(oldNext, oldPrev);
6782 setNext(oldPrev, oldNext);
6783 }
6784
6785 // insert the second widget into the chain
6786 QWidget *lastFocusChildOfFirst;
6787 determineLastFocusChild(first, lastFocusChildOfFirst);
6788 {
6789 QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
6790 setPrev(second, lastFocusChildOfFirst);
6791 setNext(lastFocusChildOfFirst, second);
6792 setPrev(oldNext, lastFocusChildOfSecond);
6793 setNext(lastFocusChildOfSecond, oldNext);
6794 }
6795 }
6796
6797 /*!\internal
6798
6799 Moves the relevant subwidgets of this widget from the \a oldtlw's
6800 tab chain to that of the new parent, if there's anything to move and
6801 we're really moving
6802
6803 This function is called from QWidget::reparent() *after* the widget
6804 has been reparented.
6805
6806 \sa reparent()
6807 */
6808
reparentFocusWidgets(QWidget * oldtlw)6809 void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
6810 {
6811 Q_Q(QWidget);
6812 if (oldtlw == q->window())
6813 return; // nothing to do
6814
6815 if(focus_child)
6816 focus_child->clearFocus();
6817
6818 // separate the focus chain into new (children of myself) and old (the rest)
6819 QWidget *firstOld = nullptr;
6820 //QWidget *firstNew = q; //invariant
6821 QWidget *o = nullptr; // last in the old list
6822 QWidget *n = q; // last in the new list
6823
6824 bool prevWasNew = true;
6825 QWidget *w = focus_next;
6826
6827 //Note: for efficiency, we do not maintain the list invariant inside the loop
6828 //we append items to the relevant list, and we optimize by not changing pointers
6829 //when subsequent items are going into the same list.
6830 while (w != q) {
6831 bool currentIsNew = q->isAncestorOf(w);
6832 if (currentIsNew) {
6833 if (!prevWasNew) {
6834 //prev was old -- append to new list
6835 n->d_func()->focus_next = w;
6836 w->d_func()->focus_prev = n;
6837 }
6838 n = w;
6839 } else {
6840 if (prevWasNew) {
6841 //prev was new -- append to old list, if there is one
6842 if (o) {
6843 o->d_func()->focus_next = w;
6844 w->d_func()->focus_prev = o;
6845 } else {
6846 // "create" the old list
6847 firstOld = w;
6848 }
6849 }
6850 o = w;
6851 }
6852 w = w->d_func()->focus_next;
6853 prevWasNew = currentIsNew;
6854 }
6855
6856 //repair the old list:
6857 if (firstOld) {
6858 o->d_func()->focus_next = firstOld;
6859 firstOld->d_func()->focus_prev = o;
6860 }
6861
6862 if (!q->isWindow()) {
6863 QWidget *topLevel = q->window();
6864 //insert new chain into toplevel's chain
6865
6866 QWidget *prev = topLevel->d_func()->focus_prev;
6867
6868 topLevel->d_func()->focus_prev = n;
6869 prev->d_func()->focus_next = q;
6870
6871 focus_prev = prev;
6872 n->d_func()->focus_next = topLevel;
6873 } else {
6874 //repair the new list
6875 n->d_func()->focus_next = q;
6876 focus_prev = n;
6877 }
6878
6879 }
6880
6881 /*!\internal
6882
6883 Measures the shortest distance from a point to a rect.
6884
6885 This function is called from QDesktopwidget::screen(QPoint) to find the
6886 closest screen for a point.
6887 In directional KeypadNavigation, it is called to find the closest
6888 widget to the current focus widget center.
6889 */
pointToRect(const QPoint & p,const QRect & r)6890 int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
6891 {
6892 int dx = 0;
6893 int dy = 0;
6894 if (p.x() < r.left())
6895 dx = r.left() - p.x();
6896 else if (p.x() > r.right())
6897 dx = p.x() - r.right();
6898 if (p.y() < r.top())
6899 dy = r.top() - p.y();
6900 else if (p.y() > r.bottom())
6901 dy = p.y() - r.bottom();
6902 return dx + dy;
6903 }
6904
6905 /*!
6906 \property QWidget::frameSize
6907 \brief the size of the widget including any window frame
6908
6909 By default, this property contains a value that depends on the user's
6910 platform and screen geometry.
6911 */
frameSize() const6912 QSize QWidget::frameSize() const
6913 {
6914 Q_D(const QWidget);
6915 if (isWindow() && !(windowType() == Qt::Popup)) {
6916 QRect fs = d->frameStrut();
6917 return QSize(data->crect.width() + fs.left() + fs.right(),
6918 data->crect.height() + fs.top() + fs.bottom());
6919 }
6920 return data->crect.size();
6921 }
6922
6923 /*! \fn void QWidget::move(int x, int y)
6924
6925 \overload
6926
6927 This corresponds to move(QPoint(\a x, \a y)).
6928 */
6929
move(const QPoint & p)6930 void QWidget::move(const QPoint &p)
6931 {
6932 Q_D(QWidget);
6933 setAttribute(Qt::WA_Moved);
6934 if (testAttribute(Qt::WA_WState_Created)) {
6935 if (isWindow())
6936 d->topData()->posIncludesFrame = false;
6937 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
6938 p.y() + geometry().y() - QWidget::y(),
6939 width(), height(), true);
6940 d->setDirtyOpaqueRegion();
6941 } else {
6942 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
6943 if (isWindow())
6944 d->topData()->posIncludesFrame = true;
6945 data->crect.moveTopLeft(p); // no frame yet
6946 setAttribute(Qt::WA_PendingMoveEvent);
6947 }
6948
6949 if (d->extra && d->extra->hasWindowContainer)
6950 QWindowContainer::parentWasMoved(this);
6951 }
6952
6953 // move() was invoked with Qt::WA_WState_Created not set (frame geometry
6954 // unknown), that is, crect has a position including the frame.
6955 // If we can determine the frame strut, fix that and clear the flag.
6956 // FIXME: This does not play well with window states other than
6957 // Qt::WindowNoState, as we depend on calling setGeometry() on the
6958 // platform window after fixing up the position so that the new
6959 // geometry is reflected in the platform window, but when the frame
6960 // comes in after the window has been shown (e.g. maximized), we're
6961 // not in a position to do that kind of fixup.
fixPosIncludesFrame()6962 void QWidgetPrivate::fixPosIncludesFrame()
6963 {
6964 Q_Q(QWidget);
6965 if (QTLWExtra *te = maybeTopData()) {
6966 if (te->posIncludesFrame) {
6967 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
6968 // example, in QGraphicsProxyWidget).
6969 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
6970 te->posIncludesFrame = 0;
6971 } else {
6972 if (q->windowHandle() && q->windowHandle()->handle()) {
6973 updateFrameStrut();
6974 if (!q->data->fstrut_dirty) {
6975 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
6976 te->posIncludesFrame = 0;
6977 }
6978 } // windowHandle()
6979 } // !WA_DontShowOnScreen
6980 } // posIncludesFrame
6981 } // QTLWExtra
6982 }
6983
6984 /*! \fn void QWidget::resize(int w, int h)
6985 \overload
6986
6987 This corresponds to resize(QSize(\a w, \a h)).
6988 */
6989
resize(const QSize & s)6990 void QWidget::resize(const QSize &s)
6991 {
6992 Q_D(QWidget);
6993 setAttribute(Qt::WA_Resized);
6994 if (testAttribute(Qt::WA_WState_Created)) {
6995 d->fixPosIncludesFrame();
6996 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
6997 d->setDirtyOpaqueRegion();
6998 } else {
6999 const auto oldRect = data->crect;
7000 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7001 if (oldRect != data->crect)
7002 setAttribute(Qt::WA_PendingResizeEvent);
7003 }
7004 }
7005
setGeometry(const QRect & r)7006 void QWidget::setGeometry(const QRect &r)
7007 {
7008 Q_D(QWidget);
7009 setAttribute(Qt::WA_Resized);
7010 setAttribute(Qt::WA_Moved);
7011 if (isWindow())
7012 d->topData()->posIncludesFrame = 0;
7013 if (testAttribute(Qt::WA_WState_Created)) {
7014 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7015 d->setDirtyOpaqueRegion();
7016 } else {
7017 const auto oldRect = data->crect;
7018 data->crect.setTopLeft(r.topLeft());
7019 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7020 if (oldRect != data->crect) {
7021 setAttribute(Qt::WA_PendingMoveEvent);
7022 setAttribute(Qt::WA_PendingResizeEvent);
7023 }
7024 }
7025
7026 if (d->extra && d->extra->hasWindowContainer)
7027 QWindowContainer::parentWasMoved(this);
7028 }
7029
setGeometry_sys(int x,int y,int w,int h,bool isMove)7030 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7031 {
7032 Q_Q(QWidget);
7033 if (extra) { // any size restrictions?
7034 w = qMin(w,extra->maxw);
7035 h = qMin(h,extra->maxh);
7036 w = qMax(w,extra->minw);
7037 h = qMax(h,extra->minh);
7038 }
7039
7040 if (q->isWindow() && q->windowHandle()) {
7041 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7042 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7043 x = 0;
7044 y = 0;
7045 w = q->windowHandle()->width();
7046 h = q->windowHandle()->height();
7047 }
7048 }
7049
7050 QPoint oldp = q->geometry().topLeft();
7051 QSize olds = q->size();
7052 QRect r(x, y, w, h);
7053
7054 bool isResize = olds != r.size();
7055 if (!isMove)
7056 isMove = oldp != r.topLeft();
7057
7058
7059 // We only care about stuff that changes the geometry, or may
7060 // cause the window manager to change its state
7061 if (r.size() == olds && oldp == r.topLeft())
7062 return;
7063
7064 if (!data.in_set_window_state) {
7065 q->data->window_state &= ~Qt::WindowMaximized;
7066 q->data->window_state &= ~Qt::WindowFullScreen;
7067 if (q->isWindow())
7068 topData()->normalGeometry = QRect(0, 0, -1, -1);
7069 }
7070
7071 QPoint oldPos = q->pos();
7072 data.crect = r;
7073
7074 bool needsShow = false;
7075
7076 if (q->isWindow() || q->windowHandle()) {
7077 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7078 q->setAttribute(Qt::WA_OutsideWSRange, true);
7079 if (q->isVisible())
7080 hide_sys();
7081 data.crect = QRect(x, y, w, h);
7082 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7083 q->setAttribute(Qt::WA_OutsideWSRange, false);
7084 needsShow = true;
7085 }
7086 }
7087
7088 if (q->isVisible()) {
7089 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7090 if (QWindow *win = q->windowHandle()) {
7091 if (q->isWindow()) {
7092 if (isResize && !isMove)
7093 win->resize(w, h);
7094 else if (isMove && !isResize)
7095 win->setPosition(x, y);
7096 else
7097 win->setGeometry(q->geometry());
7098 } else {
7099 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7100 win->setGeometry(QRect(posInNativeParent,r.size()));
7101 }
7102
7103 if (needsShow)
7104 show_sys();
7105 }
7106
7107 if (!q->isWindow()) {
7108 if (renderToTexture) {
7109 QRegion updateRegion(q->geometry());
7110 updateRegion += QRect(oldPos, olds);
7111 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7112 } else if (isMove && !isResize) {
7113 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7114 } else {
7115 invalidateBackingStore_resizeHelper(oldPos, olds);
7116 }
7117 }
7118 }
7119
7120 if (isMove) {
7121 QMoveEvent e(q->pos(), oldPos);
7122 QCoreApplication::sendEvent(q, &e);
7123 }
7124 if (isResize) {
7125 QResizeEvent e(r.size(), olds);
7126 QCoreApplication::sendEvent(q, &e);
7127 if (q->windowHandle())
7128 q->update();
7129 }
7130 } else { // not visible
7131 if (isMove && q->pos() != oldPos)
7132 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7133 if (isResize)
7134 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7135 }
7136
7137 }
7138
7139 /*!
7140 \since 4.2
7141 Saves the current geometry and state for top-level widgets.
7142
7143 To save the geometry when the window closes, you can
7144 implement a close event like this:
7145
7146 \snippet code/src_gui_kernel_qwidget.cpp 11
7147
7148 See the \l{Window Geometry} documentation for an overview of geometry
7149 issues with windows.
7150
7151 Use QMainWindow::saveState() to save the geometry and the state of
7152 toolbars and dock widgets.
7153
7154 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7155 */
saveGeometry() const7156 QByteArray QWidget::saveGeometry() const
7157 {
7158 QByteArray array;
7159 QDataStream stream(&array, QIODevice::WriteOnly);
7160 stream.setVersion(QDataStream::Qt_4_0);
7161 const quint32 magicNumber = 0x1D9D0CB;
7162 // Version history:
7163 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7164 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7165 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7166 quint16 majorVersion = 3;
7167 quint16 minorVersion = 0;
7168 const int screenNumber = QDesktopWidgetPrivate::screenNumber(this);
7169 stream << magicNumber
7170 << majorVersion
7171 << minorVersion
7172 << frameGeometry()
7173 << normalGeometry()
7174 << qint32(screenNumber)
7175 << quint8(windowState() & Qt::WindowMaximized)
7176 << quint8(windowState() & Qt::WindowFullScreen)
7177 << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()) // added in 2.0
7178 << geometry(); // added in 3.0
7179 return array;
7180 }
7181
checkRestoredGeometry(const QRect & availableGeometry,QRect * restoredGeometry,int frameHeight)7182 static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7183 int frameHeight)
7184 {
7185 if (!restoredGeometry->intersects(availableGeometry)) {
7186 restoredGeometry->moveBottom(qMin(restoredGeometry->bottom(), availableGeometry.bottom()));
7187 restoredGeometry->moveLeft(qMax(restoredGeometry->left(), availableGeometry.left()));
7188 restoredGeometry->moveRight(qMin(restoredGeometry->right(), availableGeometry.right()));
7189 }
7190 restoredGeometry->moveTop(qMax(restoredGeometry->top(), availableGeometry.top() + frameHeight));
7191 }
7192
7193 /*!
7194 \since 4.2
7195
7196 Restores the geometry and state of top-level widgets stored in the
7197 byte array \a geometry. Returns \c true on success; otherwise
7198 returns \c false.
7199
7200 If the restored geometry is off-screen, it will be modified to be
7201 inside the available screen geometry.
7202
7203 To restore geometry saved using QSettings, you can use code like
7204 this:
7205
7206 \snippet code/src_gui_kernel_qwidget.cpp 12
7207
7208 See the \l{Window Geometry} documentation for an overview of geometry
7209 issues with windows.
7210
7211 Use QMainWindow::restoreState() to restore the geometry and the
7212 state of toolbars and dock widgets.
7213
7214 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7215 */
restoreGeometry(const QByteArray & geometry)7216 bool QWidget::restoreGeometry(const QByteArray &geometry)
7217 {
7218 if (geometry.size() < 4)
7219 return false;
7220 QDataStream stream(geometry);
7221 stream.setVersion(QDataStream::Qt_4_0);
7222
7223 const quint32 magicNumber = 0x1D9D0CB;
7224 quint32 storedMagicNumber;
7225 stream >> storedMagicNumber;
7226 if (storedMagicNumber != magicNumber)
7227 return false;
7228
7229 const quint16 currentMajorVersion = 3;
7230 quint16 majorVersion = 0;
7231 quint16 minorVersion = 0;
7232
7233 stream >> majorVersion >> minorVersion;
7234
7235 if (majorVersion > currentMajorVersion)
7236 return false;
7237 // (Allow all minor versions.)
7238
7239 QRect restoredFrameGeometry;
7240 QRect restoredGeometry;
7241 QRect restoredNormalGeometry;
7242 qint32 restoredScreenNumber;
7243 quint8 maximized;
7244 quint8 fullScreen;
7245 qint32 restoredScreenWidth = 0;
7246
7247 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7248 >> restoredNormalGeometry
7249 >> restoredScreenNumber
7250 >> maximized
7251 >> fullScreen;
7252
7253 if (majorVersion > 1)
7254 stream >> restoredScreenWidth;
7255 if (majorVersion > 2)
7256 stream >> restoredGeometry;
7257
7258 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7259
7260 if (restoredScreenNumber >= QDesktopWidgetPrivate::numScreens())
7261 restoredScreenNumber = QDesktopWidgetPrivate::primaryScreen();
7262 const qreal screenWidthF = qreal(QDesktopWidgetPrivate::screenGeometry(restoredScreenNumber).width());
7263 // Sanity check bailing out when large variations of screen sizes occur due to
7264 // high DPI scaling or different levels of DPI awareness.
7265 if (restoredScreenWidth) {
7266 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7267 if (factor < 0.8 || factor > 1.25)
7268 return false;
7269 } else {
7270 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7271 // unless the size will be adapted by maximized or fullscreen.
7272 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7273 return false;
7274 }
7275
7276 const int frameHeight = 20;
7277
7278 if (!restoredNormalGeometry.isValid())
7279 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7280 if (!restoredNormalGeometry.isValid()) {
7281 // use the widget's adjustedSize if the sizeHint() doesn't help
7282 restoredNormalGeometry.setSize(restoredNormalGeometry
7283 .size()
7284 .expandedTo(d_func()->adjustedSize()));
7285 }
7286
7287 const QRect availableGeometry = QDesktopWidgetPrivate::availableGeometry(restoredScreenNumber);
7288
7289 // Modify the restored geometry if we are about to restore to coordinates
7290 // that would make the window "lost". This happens if:
7291 // - The restored geometry is completely oustside the available geometry
7292 // - The title bar is outside the available geometry.
7293
7294 checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7295 checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7296
7297 if (maximized || fullScreen) {
7298 // set geometry before setting the window state to make
7299 // sure the window is maximized to the right screen.
7300 Qt::WindowStates ws = windowState();
7301 #ifndef Q_OS_WIN
7302 setGeometry(restoredNormalGeometry);
7303 #else
7304 if (ws & Qt::WindowFullScreen) {
7305 // Full screen is not a real window state on Windows.
7306 move(availableGeometry.topLeft());
7307 } else if (ws & Qt::WindowMaximized) {
7308 // Setting a geometry on an already maximized window causes this to be
7309 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7310 // Move the window in normal state if needed.
7311 if (restoredScreenNumber != QDesktopWidgetPrivate::screenNumber(this)) {
7312 setWindowState(Qt::WindowNoState);
7313 setGeometry(restoredNormalGeometry);
7314 }
7315 } else {
7316 setGeometry(restoredNormalGeometry);
7317 }
7318 #endif // Q_OS_WIN
7319 if (maximized)
7320 ws |= Qt::WindowMaximized;
7321 if (fullScreen)
7322 ws |= Qt::WindowFullScreen;
7323 setWindowState(ws);
7324 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7325 } else {
7326 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7327 if (majorVersion > 2)
7328 setGeometry(restoredGeometry);
7329 else
7330 setGeometry(restoredNormalGeometry);
7331 }
7332 return true;
7333 }
7334
7335 /*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7336 \overload
7337
7338 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7339 */
7340
7341 /*!
7342 Sets the margins around the contents of the widget to have the sizes
7343 \a left, \a top, \a right, and \a bottom. The margins are used by
7344 the layout system, and may be used by subclasses to specify the area
7345 to draw in (e.g. excluding the frame).
7346
7347 Changing the margins will trigger a resizeEvent().
7348
7349 \sa contentsRect(), contentsMargins()
7350 */
setContentsMargins(int left,int top,int right,int bottom)7351 void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7352 {
7353 Q_D(QWidget);
7354 if (left == d->leftmargin && top == d->topmargin
7355 && right == d->rightmargin && bottom == d->bottommargin)
7356 return;
7357 d->leftmargin = left;
7358 d->topmargin = top;
7359 d->rightmargin = right;
7360 d->bottommargin = bottom;
7361
7362 d->updateContentsRect();
7363 }
7364
7365 /*!
7366 \overload
7367 \since 4.6
7368
7369 \brief The setContentsMargins function sets the margins around the
7370 widget's contents.
7371
7372 Sets the margins around the contents of the widget to have the
7373 sizes determined by \a margins. The margins are
7374 used by the layout system, and may be used by subclasses to
7375 specify the area to draw in (e.g. excluding the frame).
7376
7377 Changing the margins will trigger a resizeEvent().
7378
7379 \sa contentsRect(), contentsMargins()
7380 */
setContentsMargins(const QMargins & margins)7381 void QWidget::setContentsMargins(const QMargins &margins)
7382 {
7383 setContentsMargins(margins.left(), margins.top(),
7384 margins.right(), margins.bottom());
7385 }
7386
updateContentsRect()7387 void QWidgetPrivate::updateContentsRect()
7388 {
7389 Q_Q(QWidget);
7390
7391 if (layout)
7392 layout->update(); //force activate; will do updateGeometry
7393 else
7394 q->updateGeometry();
7395
7396 if (q->isVisible()) {
7397 q->update();
7398 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7399 QCoreApplication::sendEvent(q, &e);
7400 } else {
7401 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7402 }
7403
7404 QEvent e(QEvent::ContentsRectChange);
7405 QCoreApplication::sendEvent(q, &e);
7406 }
7407
7408 #if QT_DEPRECATED_SINCE(5, 14)
7409 /*!
7410 \obsolete
7411 Use contentsMargins().
7412
7413 Returns the widget's contents margins for \a left, \a top, \a
7414 right, and \a bottom.
7415
7416 \sa setContentsMargins(), contentsRect()
7417 */
getContentsMargins(int * left,int * top,int * right,int * bottom) const7418 void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) const
7419 {
7420 QMargins m = contentsMargins();
7421 if (left)
7422 *left = m.left();
7423 if (top)
7424 *top = m.top();
7425 if (right)
7426 *right = m.right();
7427 if (bottom)
7428 *bottom = m.bottom();
7429 }
7430 #endif
7431
7432 // FIXME: Move to qmargins.h for next minor Qt release
operator |(const QMargins & m1,const QMargins & m2)7433 QMargins operator|(const QMargins &m1, const QMargins &m2)
7434 {
7435 return QMargins(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()),
7436 qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom()));
7437 }
7438
7439 /*!
7440 \since 4.6
7441
7442 \brief The contentsMargins function returns the widget's contents margins.
7443
7444 \sa setContentsMargins(), contentsRect()
7445 */
contentsMargins() const7446 QMargins QWidget::contentsMargins() const
7447 {
7448 Q_D(const QWidget);
7449 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7450 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7451 userMargins | d->safeAreaMargins() : userMargins;
7452 }
7453
7454 /*!
7455 Returns the area inside the widget's margins.
7456
7457 \sa setContentsMargins(), contentsMargins()
7458 */
contentsRect() const7459 QRect QWidget::contentsRect() const
7460 {
7461 return rect() - contentsMargins();
7462 }
7463
safeAreaMargins() const7464 QMargins QWidgetPrivate::safeAreaMargins() const
7465 {
7466 Q_Q(const QWidget);
7467 QWidget *nativeWidget = q->window();
7468 if (!nativeWidget->windowHandle())
7469 return QMargins();
7470
7471 QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7472 if (!platformWindow)
7473 return QMargins();
7474
7475 QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7476
7477 if (!q->isWindow()) {
7478 // In theory the native parent widget already has a contents rect reflecting
7479 // the safe area of that widget, but we can't be sure that the widget or child
7480 // widgets of that widget have respected the contents rect when setting their
7481 // geometry, so we need to manually compute the safe area.
7482
7483 // Unless the native widget doesn't have any margins, in which case there's
7484 // nothing for us to compute.
7485 if (safeAreaMargins.isNull())
7486 return QMargins();
7487
7488 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7489 // set, then we know that the layout has already taken care of placing us inside the
7490 // safe area, by taking the contents rect of its parent widget into account.
7491 const QWidget *assumedSafeWidget = nullptr;
7492 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7493 QWidget *parentWidget = w->parentWidget();
7494 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7495 continue; // Layout not going to help us
7496
7497 QLayout *layout = parentWidget->layout();
7498 if (!layout)
7499 continue;
7500
7501 if (layout->geometry().isNull())
7502 continue; // Layout hasn't been activated yet
7503
7504 if (layout->indexOf(const_cast<QWidget *>(w)) < 0)
7505 continue; // Widget is not in layout
7506
7507 assumedSafeWidget = w;
7508 break;
7509 }
7510
7511 #if !defined(QT_DEBUG)
7512 if (assumedSafeWidget) {
7513 // We found a layout that we assume will take care of keeping us within the safe area
7514 // For debug builds we still map the safe area using the fallback logic, so that we
7515 // can detect any misbehaving layouts.
7516 return QMargins();
7517 }
7518 #endif
7519
7520 // In all other cases we need to map the safe area of the native parent to the widget.
7521 // This depends on the widget being positioned and sized already, which means the initial
7522 // layout will be wrong, but the layout will then adjust itself.
7523 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7524 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7525 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7526 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7527
7528 // Margins should never be negative
7529 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7530 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7531
7532 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7533 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7534 qWarning() << layout << "is laying out" << assumedSafeWidget
7535 << "outside of the contents rect of" << layout->parentWidget();
7536 return QMargins(); // Return empty margin to visually highlight the error
7537 }
7538 }
7539
7540 return safeAreaMargins;
7541 }
7542
7543 /*!
7544 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7545
7546 This signal is emitted when the widget's \l contextMenuPolicy is
7547 Qt::CustomContextMenu, and the user has requested a context menu on
7548 the widget. The position \a pos is the position of the context menu
7549 event that the widget receives. Normally this is in widget
7550 coordinates. The exception to this rule is QAbstractScrollArea and
7551 its subclasses that map the context menu event to coordinates of the
7552 \l{QAbstractScrollArea::viewport()}{viewport()}.
7553
7554
7555 \sa mapToGlobal(), QMenu, contextMenuPolicy
7556 */
7557
7558
7559 /*!
7560 \property QWidget::contextMenuPolicy
7561 \brief how the widget shows a context menu
7562
7563 The default value of this property is Qt::DefaultContextMenu,
7564 which means the contextMenuEvent() handler is called. Other values
7565 are Qt::NoContextMenu, Qt::PreventContextMenu,
7566 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7567 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7568 emitted.
7569
7570 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7571 */
7572
contextMenuPolicy() const7573 Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7574 {
7575 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7576 }
7577
setContextMenuPolicy(Qt::ContextMenuPolicy policy)7578 void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7579 {
7580 data->context_menu_policy = (uint) policy;
7581 }
7582
7583 /*!
7584 \property QWidget::focusPolicy
7585 \brief the way the widget accepts keyboard focus
7586
7587 The policy is Qt::TabFocus if the widget accepts keyboard
7588 focus by tabbing, Qt::ClickFocus if the widget accepts
7589 focus by clicking, Qt::StrongFocus if it accepts both, and
7590 Qt::NoFocus (the default) if it does not accept focus at
7591 all.
7592
7593 You must enable keyboard focus for a widget if it processes
7594 keyboard events. This is normally done from the widget's
7595 constructor. For instance, the QLineEdit constructor calls
7596 setFocusPolicy(Qt::StrongFocus).
7597
7598 If the widget has a focus proxy, then the focus policy will
7599 be propagated to it.
7600
7601 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7602 */
7603
7604
focusPolicy() const7605 Qt::FocusPolicy QWidget::focusPolicy() const
7606 {
7607 return (Qt::FocusPolicy)data->focus_policy;
7608 }
7609
setFocusPolicy(Qt::FocusPolicy policy)7610 void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7611 {
7612 data->focus_policy = (uint) policy;
7613 Q_D(QWidget);
7614 if (d->extra && d->extra->focus_proxy)
7615 d->extra->focus_proxy->setFocusPolicy(policy);
7616 }
7617
7618 /*!
7619 \property QWidget::updatesEnabled
7620 \brief whether updates are enabled
7621
7622 An updates enabled widget receives paint events and has a system
7623 background; a disabled widget does not. This also implies that
7624 calling update() and repaint() has no effect if updates are
7625 disabled.
7626
7627 By default, this property is \c true.
7628
7629 setUpdatesEnabled() is normally used to disable updates for a
7630 short period of time, for instance to avoid screen flicker during
7631 large changes. In Qt, widgets normally do not generate screen
7632 flicker, but on X11 the server might erase regions on the screen
7633 when widgets get hidden before they can be replaced by other
7634 widgets. Disabling updates solves this.
7635
7636 Example:
7637 \snippet code/src_gui_kernel_qwidget.cpp 13
7638
7639 Disabling a widget implicitly disables all its children. Enabling a widget
7640 enables all child widgets \e except top-level widgets or those that
7641 have been explicitly disabled. Re-enabling updates implicitly calls
7642 update() on the widget.
7643
7644 \sa paintEvent()
7645 */
setUpdatesEnabled(bool enable)7646 void QWidget::setUpdatesEnabled(bool enable)
7647 {
7648 Q_D(QWidget);
7649 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7650 d->setUpdatesEnabled_helper(enable);
7651 }
7652
7653 /*!
7654 Shows the widget and its child widgets.
7655
7656 This is equivalent to calling showFullScreen(), showMaximized(), or setVisible(true),
7657 depending on the platform's default behavior for the window flags.
7658
7659 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7660 showNormal(), isVisible(), windowFlags()
7661 */
show()7662 void QWidget::show()
7663 {
7664 Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
7665 if (defaultState == Qt::WindowFullScreen)
7666 showFullScreen();
7667 else if (defaultState == Qt::WindowMaximized)
7668 showMaximized();
7669 else
7670 setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7671 }
7672
7673 /*! \internal
7674
7675 Makes the widget visible in the isVisible() meaning of the word.
7676 It is only called for toplevels or widgets with visible parents.
7677 */
show_recursive()7678 void QWidgetPrivate::show_recursive()
7679 {
7680 Q_Q(QWidget);
7681 // polish if necessary
7682
7683 if (!q->testAttribute(Qt::WA_WState_Created))
7684 createRecursively();
7685 q->ensurePolished();
7686
7687 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7688 q->parentWidget()->d_func()->layout->activate();
7689 // activate our layout before we and our children become visible
7690 if (layout)
7691 layout->activate();
7692
7693 show_helper();
7694 }
7695
sendPendingMoveAndResizeEvents(bool recursive,bool disableUpdates)7696 void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7697 {
7698 Q_Q(QWidget);
7699
7700 disableUpdates = disableUpdates && q->updatesEnabled();
7701 if (disableUpdates)
7702 q->setAttribute(Qt::WA_UpdatesDisabled);
7703
7704 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7705 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7706 QCoreApplication::sendEvent(q, &e);
7707 q->setAttribute(Qt::WA_PendingMoveEvent, false);
7708 }
7709
7710 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7711 QResizeEvent e(data.crect.size(), QSize());
7712 QCoreApplication::sendEvent(q, &e);
7713 q->setAttribute(Qt::WA_PendingResizeEvent, false);
7714 }
7715
7716 if (disableUpdates)
7717 q->setAttribute(Qt::WA_UpdatesDisabled, false);
7718
7719 if (!recursive)
7720 return;
7721
7722 for (int i = 0; i < children.size(); ++i) {
7723 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
7724 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7725 }
7726 }
7727
activateChildLayoutsRecursively()7728 void QWidgetPrivate::activateChildLayoutsRecursively()
7729 {
7730 sendPendingMoveAndResizeEvents(false, true);
7731
7732 for (int i = 0; i < children.size(); ++i) {
7733 QWidget *child = qobject_cast<QWidget *>(children.at(i));
7734 if (!child || child->isHidden() || child->isWindow())
7735 continue;
7736
7737 child->ensurePolished();
7738
7739 // Activate child's layout
7740 QWidgetPrivate *childPrivate = child->d_func();
7741 if (childPrivate->layout)
7742 childPrivate->layout->activate();
7743
7744 // Pretend we're visible.
7745 const bool wasVisible = child->isVisible();
7746 if (!wasVisible)
7747 child->setAttribute(Qt::WA_WState_Visible);
7748
7749 // Do the same for all my children.
7750 childPrivate->activateChildLayoutsRecursively();
7751
7752 // We're not cheating anymore.
7753 if (!wasVisible)
7754 child->setAttribute(Qt::WA_WState_Visible, false);
7755 }
7756 }
7757
show_helper()7758 void QWidgetPrivate::show_helper()
7759 {
7760 Q_Q(QWidget);
7761 data.in_show = true; // qws optimization
7762 // make sure we receive pending move and resize events
7763 sendPendingMoveAndResizeEvents();
7764
7765 // become visible before showing all children
7766 q->setAttribute(Qt::WA_WState_Visible);
7767
7768 // finally show all children recursively
7769 showChildren(false);
7770
7771
7772
7773 const bool isWindow = q->isWindow();
7774 #if QT_CONFIG(graphicsview)
7775 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
7776 #else
7777 bool isEmbedded = false;
7778 #endif
7779
7780 // popup handling: new popups and tools need to be raised, and
7781 // existing popups must be closed. Also propagate the current
7782 // windows's KeyboardFocusChange status.
7783 if (isWindow && !isEmbedded) {
7784 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
7785 q->raise();
7786 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
7787 q->setAttribute(Qt::WA_KeyboardFocusChange);
7788 } else {
7789 while (QApplication::activePopupWidget()) {
7790 if (!QApplication::activePopupWidget()->close())
7791 break;
7792 }
7793 }
7794 }
7795
7796 // Automatic embedding of child windows of widgets already embedded into
7797 // QGraphicsProxyWidget when they are shown the first time.
7798 #if QT_CONFIG(graphicsview)
7799 if (isWindow) {
7800 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
7801 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
7802 if (ancestorProxy) {
7803 isEmbedded = true;
7804 ancestorProxy->d_func()->embedSubWindow(q);
7805 }
7806 }
7807 }
7808 #else
7809 Q_UNUSED(isEmbedded);
7810 #endif
7811
7812 // send the show event before showing the window
7813 QShowEvent showEvent;
7814 QCoreApplication::sendEvent(q, &showEvent);
7815
7816 show_sys();
7817
7818 if (!isEmbedded && q->windowType() == Qt::Popup)
7819 qApp->d_func()->openPopup(q);
7820
7821 #ifndef QT_NO_ACCESSIBILITY
7822 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
7823 QAccessibleEvent event(q, QAccessible::ObjectShow);
7824 QAccessible::updateAccessibility(&event);
7825 }
7826 #endif
7827
7828 if (QApplicationPrivate::hidden_focus_widget == q) {
7829 QApplicationPrivate::hidden_focus_widget = nullptr;
7830 q->setFocus(Qt::OtherFocusReason);
7831 }
7832
7833 // Process events when showing a Qt::SplashScreen widget before the event loop
7834 // is spinnning; otherwise it might not show up on particular platforms.
7835 // This makes QSplashScreen behave the same on all platforms.
7836 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
7837 QCoreApplication::processEvents();
7838
7839 data.in_show = false; // reset qws optimization
7840 }
7841
show_sys()7842 void QWidgetPrivate::show_sys()
7843 {
7844 Q_Q(QWidget);
7845
7846 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7847
7848 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7849 invalidateBackingStore(q->rect());
7850 q->setAttribute(Qt::WA_Mapped);
7851 // add our window the modal window list (native dialogs)
7852 if (window && q->isWindow()
7853 #if QT_CONFIG(graphicsview)
7854 && (!extra || !extra->proxyWidget)
7855 #endif
7856 && q->windowModality() != Qt::NonModal) {
7857 QGuiApplicationPrivate::showModalWindow(window);
7858 }
7859 return;
7860 }
7861
7862 if (renderToTexture && !q->isWindow())
7863 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
7864 else
7865 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
7866
7867 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
7868 || q->testAttribute(Qt::WA_OutsideWSRange)) {
7869 return;
7870 }
7871
7872 if (window) {
7873 if (q->isWindow())
7874 fixPosIncludesFrame();
7875 QRect geomRect = q->geometry();
7876 if (!q->isWindow()) {
7877 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
7878 geomRect.moveTopLeft(topLeftOfWindow);
7879 }
7880 const QRect windowRect = window->geometry();
7881 if (windowRect != geomRect) {
7882 if (q->testAttribute(Qt::WA_Moved)
7883 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
7884 window->setGeometry(geomRect);
7885 else
7886 window->resize(geomRect.size());
7887 }
7888
7889 #ifndef QT_NO_CURSOR
7890 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
7891 #endif
7892 invalidateBackingStore(q->rect());
7893 window->setNativeWindowVisibility(true);
7894 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
7895 if (window->isTopLevel()) {
7896 const QPoint crectTopLeft = q->data->crect.topLeft();
7897 const QPoint windowTopLeft = window->geometry().topLeft();
7898 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
7899 q->data->crect.moveTopLeft(windowTopLeft);
7900 }
7901 }
7902 }
7903
7904 /*!
7905 Hides the widget. This function is equivalent to
7906 setVisible(false).
7907
7908
7909 \note If you are working with QDialog or its subclasses and you invoke
7910 the show() function after this function, the dialog will be displayed in
7911 its original position.
7912
7913 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
7914 */
hide()7915 void QWidget::hide()
7916 {
7917 setVisible(false);
7918 }
7919
7920 /*!\internal
7921 */
hide_helper()7922 void QWidgetPrivate::hide_helper()
7923 {
7924 Q_Q(QWidget);
7925
7926 bool isEmbedded = false;
7927 #if QT_CONFIG(graphicsview)
7928 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
7929 #else
7930 Q_UNUSED(isEmbedded);
7931 #endif
7932
7933 if (!isEmbedded && (q->windowType() == Qt::Popup))
7934 qApp->d_func()->closePopup(q);
7935
7936 q->setAttribute(Qt::WA_Mapped, false);
7937 hide_sys();
7938
7939 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
7940
7941 if (wasVisible) {
7942 q->setAttribute(Qt::WA_WState_Visible, false);
7943
7944 }
7945
7946 QHideEvent hideEvent;
7947 QCoreApplication::sendEvent(q, &hideEvent);
7948 hideChildren(false);
7949
7950 // next bit tries to move the focus if the focus widget is now
7951 // hidden.
7952 if (wasVisible) {
7953 qApp->d_func()->sendSyntheticEnterLeave(q);
7954 QWidget *fw = QApplication::focusWidget();
7955 while (fw && !fw->isWindow()) {
7956 if (fw == q) {
7957 q->focusNextPrevChild(true);
7958 break;
7959 }
7960 fw = fw->parentWidget();
7961 }
7962 }
7963
7964 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
7965 repaintManager->removeDirtyWidget(q);
7966
7967 #ifndef QT_NO_ACCESSIBILITY
7968 if (wasVisible) {
7969 QAccessibleEvent event(q, QAccessible::ObjectHide);
7970 QAccessible::updateAccessibility(&event);
7971 }
7972 #endif
7973 }
7974
hide_sys()7975 void QWidgetPrivate::hide_sys()
7976 {
7977 Q_Q(QWidget);
7978
7979 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7980
7981 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7982 q->setAttribute(Qt::WA_Mapped, false);
7983 // remove our window from the modal window list (native dialogs)
7984 if (window && q->isWindow()
7985 #if QT_CONFIG(graphicsview)
7986 && (!extra || !extra->proxyWidget)
7987 #endif
7988 && q->windowModality() != Qt::NonModal) {
7989 QGuiApplicationPrivate::hideModalWindow(window);
7990 }
7991 // do not return here, if window non-zero, we must hide it
7992 }
7993
7994 deactivateWidgetCleanup();
7995
7996 if (!q->isWindow()) {
7997 QWidget *p = q->parentWidget();
7998 if (p &&p->isVisible()) {
7999 if (renderToTexture)
8000 p->d_func()->invalidateBackingStore(q->geometry());
8001 else
8002 invalidateBackingStore(q->rect());
8003 }
8004 } else {
8005 invalidateBackingStore(q->rect());
8006 }
8007
8008 if (window)
8009 window->setNativeWindowVisibility(false);
8010 }
8011
8012 /*!
8013 \fn bool QWidget::isHidden() const
8014
8015 Returns \c true if the widget is hidden, otherwise returns \c false.
8016
8017 A hidden widget will only become visible when show() is called on
8018 it. It will not be automatically shown when the parent is shown.
8019
8020 To check visibility, use !isVisible() instead (notice the exclamation mark).
8021
8022 isHidden() implies !isVisible(), but a widget can be not visible
8023 and not hidden at the same time. This is the case for widgets that are children of
8024 widgets that are not visible.
8025
8026
8027 Widgets are hidden if:
8028 \list
8029 \li they were created as independent windows,
8030 \li they were created as children of visible widgets,
8031 \li hide() or setVisible(false) was called.
8032 \endlist
8033 */
8034
setVisible(bool visible)8035 void QWidget::setVisible(bool visible)
8036 {
8037 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8038 return;
8039
8040 // Remember that setVisible was called explicitly
8041 setAttribute(Qt::WA_WState_ExplicitShowHide);
8042
8043 Q_D(QWidget);
8044 d->setVisible(visible);
8045 }
8046
8047 // This method is called from QWidgetWindow in response to QWindow::setVisible,
8048 // and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8049 // the other hand keeps track of WA_WState_ExplicitShowHide in addition.
setVisible(bool visible)8050 void QWidgetPrivate::setVisible(bool visible)
8051 {
8052 Q_Q(QWidget);
8053 if (visible) { // show
8054 // Designer uses a trick to make grabWidget work without showing
8055 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8056 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8057 q->parentWidget()->window()->d_func()->createRecursively();
8058
8059 //create toplevels but not children of non-visible parents
8060 QWidget *pw = q->parentWidget();
8061 if (!q->testAttribute(Qt::WA_WState_Created)
8062 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8063 q->create();
8064 }
8065
8066 bool wasResized = q->testAttribute(Qt::WA_Resized);
8067 Qt::WindowStates initialWindowState = q->windowState();
8068
8069 // polish if necessary
8070 q->ensurePolished();
8071
8072 // whether we need to inform the parent widget immediately
8073 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8074 // we are no longer hidden
8075 q->setAttribute(Qt::WA_WState_Hidden, false);
8076
8077 if (needUpdateGeometry)
8078 updateGeometry_helper(true);
8079
8080 // activate our layout before we and our children become visible
8081 if (layout)
8082 layout->activate();
8083
8084 if (!q->isWindow()) {
8085 QWidget *parent = q->parentWidget();
8086 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8087 parent->d_func()->layout->activate();
8088 if (parent->isWindow())
8089 break;
8090 parent = parent->parentWidget();
8091 }
8092 if (parent)
8093 parent->d_func()->setDirtyOpaqueRegion();
8094 }
8095
8096 // adjust size if necessary
8097 if (!wasResized
8098 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8099 if (q->isWindow()) {
8100 q->adjustSize();
8101 if (q->windowState() != initialWindowState)
8102 q->setWindowState(initialWindowState);
8103 } else {
8104 q->adjustSize();
8105 }
8106 q->setAttribute(Qt::WA_Resized, false);
8107 }
8108
8109 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8110
8111 if (q->isWindow() || q->parentWidget()->isVisible()) {
8112 show_helper();
8113
8114 qApp->d_func()->sendSyntheticEnterLeave(q);
8115 }
8116
8117 QEvent showToParentEvent(QEvent::ShowToParent);
8118 QCoreApplication::sendEvent(q, &showToParentEvent);
8119 } else { // hide
8120 if (QApplicationPrivate::hidden_focus_widget == q)
8121 QApplicationPrivate::hidden_focus_widget = nullptr;
8122
8123 // hw: The test on getOpaqueRegion() needs to be more intelligent
8124 // currently it doesn't work if the widget is hidden (the region will
8125 // be clipped). The real check should be testing the cached region
8126 // (and dirty flag) directly.
8127 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8128 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8129
8130 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8131 q->setAttribute(Qt::WA_WState_Hidden);
8132 if (q->testAttribute(Qt::WA_WState_Created))
8133 hide_helper();
8134 }
8135
8136 // invalidate layout similar to updateGeometry()
8137 if (!q->isWindow() && q->parentWidget()) {
8138 if (q->parentWidget()->d_func()->layout)
8139 q->parentWidget()->d_func()->layout->invalidate();
8140 else if (q->parentWidget()->isVisible())
8141 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8142 }
8143
8144 QEvent hideToParentEvent(QEvent::HideToParent);
8145 QCoreApplication::sendEvent(q, &hideToParentEvent);
8146 }
8147 }
8148
8149 /*!
8150 Convenience function, equivalent to setVisible(!\a hidden).
8151 */
setHidden(bool hidden)8152 void QWidget::setHidden(bool hidden)
8153 {
8154 setVisible(!hidden);
8155 }
8156
_q_showIfNotHidden()8157 void QWidgetPrivate::_q_showIfNotHidden()
8158 {
8159 Q_Q(QWidget);
8160 if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
8161 q->setVisible(true);
8162 }
8163
showChildren(bool spontaneous)8164 void QWidgetPrivate::showChildren(bool spontaneous)
8165 {
8166 QList<QObject*> childList = children;
8167 for (int i = 0; i < childList.size(); ++i) {
8168 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8169 if (widget && widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8170 widget->setAttribute(Qt::WA_WState_Hidden, false);
8171 if (!widget
8172 || widget->isWindow()
8173 || widget->testAttribute(Qt::WA_WState_Hidden))
8174 continue;
8175 if (spontaneous) {
8176 widget->setAttribute(Qt::WA_Mapped);
8177 widget->d_func()->showChildren(true);
8178 QShowEvent e;
8179 QApplication::sendSpontaneousEvent(widget, &e);
8180 } else {
8181 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8182 widget->d_func()->show_recursive();
8183 else
8184 widget->show();
8185 }
8186 }
8187 }
8188
hideChildren(bool spontaneous)8189 void QWidgetPrivate::hideChildren(bool spontaneous)
8190 {
8191 QList<QObject*> childList = children;
8192 for (int i = 0; i < childList.size(); ++i) {
8193 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8194 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8195 continue;
8196
8197 if (spontaneous)
8198 widget->setAttribute(Qt::WA_Mapped, false);
8199 else
8200 widget->setAttribute(Qt::WA_WState_Visible, false);
8201 widget->d_func()->hideChildren(spontaneous);
8202 QHideEvent e;
8203 if (spontaneous) {
8204 QApplication::sendSpontaneousEvent(widget, &e);
8205 } else {
8206 QCoreApplication::sendEvent(widget, &e);
8207 if (widget->internalWinId()
8208 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8209 // hide_sys() on an ancestor won't have any affect on this
8210 // widget, so it needs an explicit hide_sys() of its own
8211 widget->d_func()->hide_sys();
8212 }
8213 }
8214 qApp->d_func()->sendSyntheticEnterLeave(widget);
8215 #ifndef QT_NO_ACCESSIBILITY
8216 if (!spontaneous) {
8217 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8218 QAccessible::updateAccessibility(&event);
8219 }
8220 #endif
8221 }
8222 }
8223
close_helper(CloseMode mode)8224 bool QWidgetPrivate::close_helper(CloseMode mode)
8225 {
8226 if (data.is_closing)
8227 return true;
8228
8229 Q_Q(QWidget);
8230 data.is_closing = 1;
8231
8232 QPointer<QWidget> that = q;
8233 QPointer<QWidget> parentWidget = (q->parentWidget() && !QObjectPrivate::get(q->parentWidget())->wasDeleted) ? q->parentWidget() : nullptr;
8234
8235 bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
8236 if (mode != CloseNoEvent) {
8237 QCloseEvent e;
8238 if (mode == CloseWithSpontaneousEvent)
8239 QApplication::sendSpontaneousEvent(q, &e);
8240 else
8241 QCoreApplication::sendEvent(q, &e);
8242 if (!that.isNull() && !e.isAccepted()) {
8243 data.is_closing = 0;
8244 return false;
8245 }
8246 }
8247
8248 if (!that.isNull() && !q->isHidden())
8249 q->hide();
8250
8251 // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
8252 quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
8253
8254 if (quitOnClose) {
8255 /* if there is no non-withdrawn primary window left (except
8256 the ones without QuitOnClose), we emit the lastWindowClosed
8257 signal */
8258 QWidgetList list = QApplication::topLevelWidgets();
8259 bool lastWindowClosed = true;
8260 for (int i = 0; i < list.size(); ++i) {
8261 QWidget *w = list.at(i);
8262 if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
8263 continue;
8264 lastWindowClosed = false;
8265 break;
8266 }
8267 if (lastWindowClosed) {
8268 QGuiApplicationPrivate::emitLastWindowClosed();
8269 QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
8270 applicationPrivate->maybeQuit();
8271 }
8272 }
8273
8274
8275 if (!that.isNull()) {
8276 data.is_closing = 0;
8277 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8278 q->setAttribute(Qt::WA_DeleteOnClose, false);
8279 q->deleteLater();
8280 }
8281 }
8282 return true;
8283 }
8284
8285
8286 /*!
8287 Closes this widget. Returns \c true if the widget was closed;
8288 otherwise returns \c false.
8289
8290 First it sends the widget a QCloseEvent. The widget is
8291 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8292 the close event. If it \l{QEvent::ignore()}{ignores}
8293 the event, nothing happens. The default
8294 implementation of QWidget::closeEvent() accepts the close event.
8295
8296 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8297 is also deleted. A close events is delivered to the widget no
8298 matter if the widget is visible or not.
8299
8300 The \l QApplication::lastWindowClosed() signal is emitted when the
8301 last visible primary window (i.e. window with no parent) with the
8302 Qt::WA_QuitOnClose attribute set is closed. By default this
8303 attribute is set for all widgets except transient windows such as
8304 splash screens, tool windows, and popup menus.
8305
8306 */
8307
close()8308 bool QWidget::close()
8309 {
8310 return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
8311 }
8312
8313 /*!
8314 \property QWidget::visible
8315 \brief whether the widget is visible
8316
8317 Calling setVisible(true) or show() sets the widget to visible
8318 status if all its parent widgets up to the window are visible. If
8319 an ancestor is not visible, the widget won't become visible until
8320 all its ancestors are shown. If its size or position has changed,
8321 Qt guarantees that a widget gets move and resize events just
8322 before it is shown. If the widget has not been resized yet, Qt
8323 will adjust the widget's size to a useful default using
8324 adjustSize().
8325
8326 Calling setVisible(false) or hide() hides a widget explicitly. An
8327 explicitly hidden widget will never become visible, even if all
8328 its ancestors become visible, unless you show it.
8329
8330 A widget receives show and hide events when its visibility status
8331 changes. Between a hide and a show event, there is no need to
8332 waste CPU cycles preparing or displaying information to the user.
8333 A video application, for example, might simply stop generating new
8334 frames.
8335
8336 A widget that happens to be obscured by other windows on the
8337 screen is considered to be visible. The same applies to iconified
8338 windows and windows that exist on another virtual
8339 desktop (on platforms that support this concept). A widget
8340 receives spontaneous show and hide events when its mapping status
8341 is changed by the window system, e.g. a spontaneous hide event
8342 when the user minimizes the window, and a spontaneous show event
8343 when the window is restored again.
8344
8345 You almost never have to reimplement the setVisible() function. If
8346 you need to change some settings before a widget is shown, use
8347 showEvent() instead. If you need to do some delayed initialization
8348 use the Polish event delivered to the event() function.
8349
8350 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8351 showEvent(), hideEvent()
8352 */
8353
8354
8355 /*!
8356 Returns \c true if this widget would become visible if \a ancestor is
8357 shown; otherwise returns \c false.
8358
8359 The true case occurs if neither the widget itself nor any parent
8360 up to but excluding \a ancestor has been explicitly hidden.
8361
8362 This function will still return true if the widget is obscured by
8363 other windows on the screen, but could be physically visible if it
8364 or they were to be moved.
8365
8366 isVisibleTo(0) is identical to isVisible().
8367
8368 \sa show(), hide(), isVisible()
8369 */
8370
isVisibleTo(const QWidget * ancestor) const8371 bool QWidget::isVisibleTo(const QWidget *ancestor) const
8372 {
8373 if (!ancestor)
8374 return isVisible();
8375 const QWidget * w = this;
8376 while (!w->isHidden()
8377 && !w->isWindow()
8378 && w->parentWidget()
8379 && w->parentWidget() != ancestor)
8380 w = w->parentWidget();
8381 return !w->isHidden();
8382 }
8383
8384
8385 /*!
8386 Returns the unobscured region where paint events can occur.
8387
8388 For visible widgets, this is an approximation of the area not
8389 covered by other widgets; otherwise, this is an empty region.
8390
8391 The repaint() function calls this function if necessary, so in
8392 general you do not need to call it.
8393
8394 */
visibleRegion() const8395 QRegion QWidget::visibleRegion() const
8396 {
8397 Q_D(const QWidget);
8398
8399 QRect clipRect = d->clipRect();
8400 if (clipRect.isEmpty())
8401 return QRegion();
8402 QRegion r(clipRect);
8403 d->subtractOpaqueChildren(r, clipRect);
8404 d->subtractOpaqueSiblings(r);
8405 return r;
8406 }
8407
8408
adjustedSize() const8409 QSize QWidgetPrivate::adjustedSize() const
8410 {
8411 Q_Q(const QWidget);
8412
8413 QSize s = q->sizeHint();
8414
8415 if (q->isWindow()) {
8416 Qt::Orientations exp;
8417 if (layout) {
8418 if (layout->hasHeightForWidth())
8419 s.setHeight(layout->totalHeightForWidth(s.width()));
8420 exp = layout->expandingDirections();
8421 } else
8422 {
8423 if (q->sizePolicy().hasHeightForWidth())
8424 s.setHeight(q->heightForWidth(s.width()));
8425 exp = q->sizePolicy().expandingDirections();
8426 }
8427 if (exp & Qt::Horizontal)
8428 s.setWidth(qMax(s.width(), 200));
8429 if (exp & Qt::Vertical)
8430 s.setHeight(qMax(s.height(), 100));
8431
8432 QRect screen = QDesktopWidgetPrivate::screenGeometry(q->pos());
8433
8434 s.setWidth(qMin(s.width(), screen.width()*2/3));
8435 s.setHeight(qMin(s.height(), screen.height()*2/3));
8436
8437 if (QTLWExtra *extra = maybeTopData())
8438 extra->sizeAdjusted = true;
8439 }
8440
8441 if (!s.isValid()) {
8442 QRect r = q->childrenRect(); // get children rectangle
8443 if (r.isNull())
8444 return s;
8445 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8446 }
8447
8448 return s;
8449 }
8450
8451 /*!
8452 Adjusts the size of the widget to fit its contents.
8453
8454 This function uses sizeHint() if it is valid, i.e., the size hint's width
8455 and height are \>= 0. Otherwise, it sets the size to the children
8456 rectangle that covers all child widgets (the union of all child widget
8457 rectangles).
8458
8459 For windows, the screen size is also taken into account. If the sizeHint()
8460 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8461 {expanding}, the window will be at least (200, 100). The maximum size of
8462 a window is 2/3 of the screen's width and height.
8463
8464 \sa sizeHint(), childrenRect()
8465 */
8466
adjustSize()8467 void QWidget::adjustSize()
8468 {
8469 Q_D(QWidget);
8470 ensurePolished();
8471 QSize s = d->adjustedSize();
8472
8473 if (d->layout)
8474 d->layout->activate();
8475
8476 if (s.isValid())
8477 resize(s);
8478 }
8479
8480
8481 /*!
8482 \property QWidget::sizeHint
8483 \brief the recommended size for the widget
8484
8485 If the value of this property is an invalid size, no size is
8486 recommended.
8487
8488 The default implementation of sizeHint() returns an invalid size
8489 if there is no layout for this widget, and returns the layout's
8490 preferred size otherwise.
8491
8492 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8493 setMinimumSize(), updateGeometry()
8494 */
8495
sizeHint() const8496 QSize QWidget::sizeHint() const
8497 {
8498 Q_D(const QWidget);
8499 if (d->layout)
8500 return d->layout->totalSizeHint();
8501 return QSize(-1, -1);
8502 }
8503
8504 /*!
8505 \property QWidget::minimumSizeHint
8506 \brief the recommended minimum size for the widget
8507
8508 If the value of this property is an invalid size, no minimum size
8509 is recommended.
8510
8511 The default implementation of minimumSizeHint() returns an invalid
8512 size if there is no layout for this widget, and returns the
8513 layout's minimum size otherwise. Most built-in widgets reimplement
8514 minimumSizeHint().
8515
8516 \l QLayout will never resize a widget to a size smaller than the
8517 minimum size hint unless minimumSize() is set or the size policy is
8518 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8519 size hint will be ignored.
8520
8521 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8522 */
minimumSizeHint() const8523 QSize QWidget::minimumSizeHint() const
8524 {
8525 Q_D(const QWidget);
8526 if (d->layout)
8527 return d->layout->totalMinimumSize();
8528 return QSize(-1, -1);
8529 }
8530
8531
8532 /*!
8533 \fn QWidget *QWidget::parentWidget() const
8534
8535 Returns the parent of this widget, or \nullptr if it does not have any
8536 parent widget.
8537 */
8538
8539
8540 /*!
8541 Returns \c true if this widget is a parent, (or grandparent and so on
8542 to any level), of the given \a child, and both widgets are within
8543 the same window; otherwise returns \c false.
8544 */
8545
isAncestorOf(const QWidget * child) const8546 bool QWidget::isAncestorOf(const QWidget *child) const
8547 {
8548 while (child) {
8549 if (child == this)
8550 return true;
8551 if (child->isWindow())
8552 return false;
8553 child = child->parentWidget();
8554 }
8555 return false;
8556 }
8557
8558 /*****************************************************************************
8559 QWidget event handling
8560 *****************************************************************************/
8561
8562 /*!
8563 This is the main event handler; it handles event \a event. You can
8564 reimplement this function in a subclass, but we recommend using
8565 one of the specialized event handlers instead.
8566
8567 Key press and release events are treated differently from other
8568 events. event() checks for Tab and Shift+Tab and tries to move the
8569 focus appropriately. If there is no widget to move the focus to
8570 (or the key press is not Tab or Shift+Tab), event() calls
8571 keyPressEvent().
8572
8573 Mouse and tablet event handling is also slightly special: only
8574 when the widget is \l enabled, event() will call the specialized
8575 handlers such as mousePressEvent(); otherwise it will discard the
8576 event.
8577
8578 This function returns \c true if the event was recognized, otherwise
8579 it returns \c false. If the recognized event was accepted (see \l
8580 QEvent::accepted), any further processing such as event
8581 propagation to the parent widget stops.
8582
8583 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8584 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8585 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8586 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8587 QObject::event(), QObject::timerEvent()
8588 */
8589
event(QEvent * event)8590 bool QWidget::event(QEvent *event)
8591 {
8592 Q_D(QWidget);
8593
8594 // ignore mouse and key events when disabled
8595 if (!isEnabled()) {
8596 switch(event->type()) {
8597 case QEvent::TabletPress:
8598 case QEvent::TabletRelease:
8599 case QEvent::TabletMove:
8600 case QEvent::MouseButtonPress:
8601 case QEvent::MouseButtonRelease:
8602 case QEvent::MouseButtonDblClick:
8603 case QEvent::MouseMove:
8604 case QEvent::TouchBegin:
8605 case QEvent::TouchUpdate:
8606 case QEvent::TouchEnd:
8607 case QEvent::TouchCancel:
8608 case QEvent::ContextMenu:
8609 case QEvent::KeyPress:
8610 case QEvent::KeyRelease:
8611 #if QT_CONFIG(wheelevent)
8612 case QEvent::Wheel:
8613 #endif
8614 return false;
8615 default:
8616 break;
8617 }
8618 }
8619 switch (event->type()) {
8620 case QEvent::PlatformSurface: {
8621 // Sync up QWidget's view of whether or not the widget has been created
8622 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8623 case QPlatformSurfaceEvent::SurfaceCreated:
8624 if (!testAttribute(Qt::WA_WState_Created))
8625 create();
8626 break;
8627 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8628 if (testAttribute(Qt::WA_WState_Created)) {
8629 // Child windows have already been destroyed by QWindow,
8630 // so we skip them here.
8631 destroy(false, false);
8632 }
8633 break;
8634 }
8635 break;
8636 }
8637 case QEvent::MouseMove:
8638 mouseMoveEvent((QMouseEvent*)event);
8639 break;
8640
8641 case QEvent::MouseButtonPress:
8642 mousePressEvent((QMouseEvent*)event);
8643 break;
8644
8645 case QEvent::MouseButtonRelease:
8646 mouseReleaseEvent((QMouseEvent*)event);
8647 break;
8648
8649 case QEvent::MouseButtonDblClick:
8650 mouseDoubleClickEvent((QMouseEvent*)event);
8651 break;
8652 #if QT_CONFIG(wheelevent)
8653 case QEvent::Wheel:
8654 wheelEvent((QWheelEvent*)event);
8655 break;
8656 #endif
8657 #if QT_CONFIG(tabletevent)
8658 case QEvent::TabletMove:
8659 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
8660 break;
8661 Q_FALLTHROUGH();
8662 case QEvent::TabletPress:
8663 case QEvent::TabletRelease:
8664 tabletEvent((QTabletEvent*)event);
8665 break;
8666 #endif
8667 case QEvent::KeyPress: {
8668 QKeyEvent *k = (QKeyEvent *)event;
8669 bool res = false;
8670 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
8671 if (k->key() == Qt::Key_Backtab
8672 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
8673 res = focusNextPrevChild(false);
8674 else if (k->key() == Qt::Key_Tab)
8675 res = focusNextPrevChild(true);
8676 if (res)
8677 break;
8678 }
8679 keyPressEvent(k);
8680 #ifdef QT_KEYPAD_NAVIGATION
8681 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
8682 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
8683 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
8684 if (k->key() == Qt::Key_Up)
8685 res = focusNextPrevChild(false);
8686 else if (k->key() == Qt::Key_Down)
8687 res = focusNextPrevChild(true);
8688 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
8689 if (k->key() == Qt::Key_Up)
8690 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
8691 else if (k->key() == Qt::Key_Right)
8692 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
8693 else if (k->key() == Qt::Key_Down)
8694 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
8695 else if (k->key() == Qt::Key_Left)
8696 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
8697 }
8698 if (res) {
8699 k->accept();
8700 break;
8701 }
8702 }
8703 #endif
8704 #if QT_CONFIG(whatsthis)
8705 if (!k->isAccepted()
8706 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
8707 && d->whatsThis.size()) {
8708 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
8709 k->accept();
8710 }
8711 #endif
8712 }
8713 break;
8714
8715 case QEvent::KeyRelease:
8716 keyReleaseEvent((QKeyEvent*)event);
8717 Q_FALLTHROUGH();
8718 case QEvent::ShortcutOverride:
8719 break;
8720
8721 case QEvent::InputMethod:
8722 inputMethodEvent((QInputMethodEvent *) event);
8723 break;
8724
8725 case QEvent::InputMethodQuery:
8726 if (testAttribute(Qt::WA_InputMethodEnabled)) {
8727 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
8728 Qt::InputMethodQueries queries = query->queries();
8729 for (uint i = 0; i < 32; ++i) {
8730 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
8731 if (q) {
8732 QVariant v = inputMethodQuery(q);
8733 if (q == Qt::ImEnabled && !v.isValid() && isEnabled())
8734 v = QVariant(true); // special case for Qt4 compatibility
8735 query->setValue(q, v);
8736 }
8737 }
8738 query->accept();
8739 }
8740 break;
8741
8742 case QEvent::PolishRequest:
8743 ensurePolished();
8744 break;
8745
8746 case QEvent::Polish: {
8747 style()->polish(this);
8748 setAttribute(Qt::WA_WState_Polished);
8749 if (!QApplication::font(this).isCopyOf(QApplication::font()))
8750 d->resolveFont();
8751 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
8752 d->resolvePalette();
8753 }
8754 break;
8755
8756 case QEvent::ApplicationWindowIconChange:
8757 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
8758 d->setWindowIcon_sys();
8759 d->setWindowIcon_helper();
8760 }
8761 break;
8762 case QEvent::FocusIn:
8763 focusInEvent((QFocusEvent*)event);
8764 d->updateWidgetTransform(event);
8765 break;
8766
8767 case QEvent::FocusOut:
8768 focusOutEvent((QFocusEvent*)event);
8769 break;
8770
8771 case QEvent::Enter:
8772 #if QT_CONFIG(statustip)
8773 if (d->statusTip.size()) {
8774 QStatusTipEvent tip(d->statusTip);
8775 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8776 }
8777 #endif
8778 enterEvent(event);
8779 break;
8780
8781 case QEvent::Leave:
8782 #if QT_CONFIG(statustip)
8783 if (d->statusTip.size()) {
8784 QString empty;
8785 QStatusTipEvent tip(empty);
8786 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8787 }
8788 #endif
8789 leaveEvent(event);
8790 break;
8791
8792 case QEvent::HoverEnter:
8793 case QEvent::HoverLeave:
8794 update();
8795 break;
8796
8797 case QEvent::Paint:
8798 // At this point the event has to be delivered, regardless
8799 // whether the widget isVisible() or not because it
8800 // already went through the filters
8801 paintEvent((QPaintEvent*)event);
8802 break;
8803
8804 case QEvent::Move:
8805 moveEvent((QMoveEvent*)event);
8806 d->updateWidgetTransform(event);
8807 break;
8808
8809 case QEvent::Resize:
8810 resizeEvent((QResizeEvent*)event);
8811 d->updateWidgetTransform(event);
8812 break;
8813
8814 case QEvent::Close:
8815 closeEvent((QCloseEvent *)event);
8816 break;
8817
8818 #ifndef QT_NO_CONTEXTMENU
8819 case QEvent::ContextMenu:
8820 switch (data->context_menu_policy) {
8821 case Qt::PreventContextMenu:
8822 break;
8823 case Qt::DefaultContextMenu:
8824 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
8825 break;
8826 case Qt::CustomContextMenu:
8827 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
8828 break;
8829 #if QT_CONFIG(menu)
8830 case Qt::ActionsContextMenu:
8831 if (d->actions.count()) {
8832 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
8833 nullptr, this);
8834 break;
8835 }
8836 Q_FALLTHROUGH();
8837 #endif
8838 default:
8839 event->ignore();
8840 break;
8841 }
8842 break;
8843 #endif // QT_NO_CONTEXTMENU
8844
8845 #if QT_CONFIG(draganddrop)
8846 case QEvent::Drop:
8847 dropEvent((QDropEvent*) event);
8848 break;
8849
8850 case QEvent::DragEnter:
8851 dragEnterEvent((QDragEnterEvent*) event);
8852 break;
8853
8854 case QEvent::DragMove:
8855 dragMoveEvent((QDragMoveEvent*) event);
8856 break;
8857
8858 case QEvent::DragLeave:
8859 dragLeaveEvent((QDragLeaveEvent*) event);
8860 break;
8861 #endif
8862
8863 case QEvent::Show:
8864 showEvent((QShowEvent*) event);
8865 break;
8866
8867 case QEvent::Hide:
8868 hideEvent((QHideEvent*) event);
8869 break;
8870
8871 case QEvent::ShowWindowRequest:
8872 if (!isHidden())
8873 d->show_sys();
8874 break;
8875
8876 case QEvent::ApplicationFontChange:
8877 d->resolveFont();
8878 break;
8879 case QEvent::ApplicationPaletteChange:
8880 if (!(windowType() == Qt::Desktop))
8881 d->resolvePalette();
8882 break;
8883
8884 case QEvent::ToolBarChange:
8885 case QEvent::ActivationChange:
8886 case QEvent::EnabledChange:
8887 case QEvent::FontChange:
8888 case QEvent::StyleChange:
8889 case QEvent::PaletteChange:
8890 case QEvent::WindowTitleChange:
8891 case QEvent::IconTextChange:
8892 case QEvent::ModifiedChange:
8893 case QEvent::MouseTrackingChange:
8894 case QEvent::TabletTrackingChange:
8895 case QEvent::ParentChange:
8896 case QEvent::LocaleChange:
8897 case QEvent::MacSizeChange:
8898 case QEvent::ContentsRectChange:
8899 case QEvent::ThemeChange:
8900 case QEvent::ReadOnlyChange:
8901 changeEvent(event);
8902 break;
8903
8904 case QEvent::WindowStateChange: {
8905 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
8906 if (wasMinimized != isMinimized()) {
8907 QWidget *widget = const_cast<QWidget *>(this);
8908 if (wasMinimized) {
8909 // Always send the spontaneous events here, otherwise it can break the application!
8910 if (!d->childrenShownByExpose) {
8911 // Show widgets only when they are not yet shown by the expose event
8912 d->showChildren(true);
8913 QShowEvent showEvent;
8914 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
8915 }
8916 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
8917 } else {
8918 QHideEvent hideEvent;
8919 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
8920 d->hideChildren(true);
8921 d->childrenHiddenByWState = true;
8922 }
8923 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
8924 }
8925 changeEvent(event);
8926 }
8927 break;
8928
8929 case QEvent::WindowActivate:
8930 case QEvent::WindowDeactivate: {
8931 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
8932 update();
8933 QList<QObject*> childList = d->children;
8934 for (int i = 0; i < childList.size(); ++i) {
8935 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
8936 if (w && w->isVisible() && !w->isWindow())
8937 QCoreApplication::sendEvent(w, event);
8938 }
8939 break; }
8940
8941 case QEvent::LanguageChange:
8942 changeEvent(event);
8943 {
8944 QList<QObject*> childList = d->children;
8945 for (int i = 0; i < childList.size(); ++i) {
8946 QObject *o = childList.at(i);
8947 if (o)
8948 QCoreApplication::sendEvent(o, event);
8949 }
8950 }
8951 update();
8952 break;
8953
8954 case QEvent::ApplicationLayoutDirectionChange:
8955 d->resolveLayoutDirection();
8956 break;
8957
8958 case QEvent::LayoutDirectionChange:
8959 if (d->layout)
8960 d->layout->invalidate();
8961 update();
8962 changeEvent(event);
8963 break;
8964 case QEvent::UpdateRequest:
8965 d->syncBackingStore();
8966 break;
8967 case QEvent::UpdateLater:
8968 update(static_cast<QUpdateLaterEvent*>(event)->region());
8969 break;
8970 case QEvent::StyleAnimationUpdate:
8971 if (isVisible() && !window()->isMinimized()) {
8972 event->accept();
8973 update();
8974 }
8975 break;
8976
8977 case QEvent::WindowBlocked:
8978 case QEvent::WindowUnblocked:
8979 if (!d->children.isEmpty()) {
8980 QWidget *modalWidget = QApplication::activeModalWidget();
8981 for (int i = 0; i < d->children.size(); ++i) {
8982 QObject *o = d->children.at(i);
8983 if (o && o != modalWidget && o->isWidgetType()) {
8984 QWidget *w = static_cast<QWidget *>(o);
8985 // do not forward the event to child windows; QApplication does this for us
8986 if (!w->isWindow())
8987 QCoreApplication::sendEvent(w, event);
8988 }
8989 }
8990 }
8991 break;
8992 #ifndef QT_NO_TOOLTIP
8993 case QEvent::ToolTip:
8994 if (!d->toolTip.isEmpty())
8995 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
8996 else
8997 event->ignore();
8998 break;
8999 #endif
9000 #if QT_CONFIG(whatsthis)
9001 case QEvent::WhatsThis:
9002 if (d->whatsThis.size())
9003 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9004 else
9005 event->ignore();
9006 break;
9007 case QEvent::QueryWhatsThis:
9008 if (d->whatsThis.isEmpty())
9009 event->ignore();
9010 break;
9011 #endif
9012 case QEvent::EmbeddingControl:
9013 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9014 data->fstrut_dirty = false;
9015 break;
9016 #ifndef QT_NO_ACTION
9017 case QEvent::ActionAdded:
9018 case QEvent::ActionRemoved:
9019 case QEvent::ActionChanged:
9020 actionEvent((QActionEvent*)event);
9021 break;
9022 #endif
9023
9024 case QEvent::KeyboardLayoutChange:
9025 {
9026 changeEvent(event);
9027
9028 // inform children of the change
9029 QList<QObject*> childList = d->children;
9030 for (int i = 0; i < childList.size(); ++i) {
9031 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9032 if (w && w->isVisible() && !w->isWindow())
9033 QCoreApplication::sendEvent(w, event);
9034 }
9035 break;
9036 }
9037 case QEvent::TouchBegin:
9038 case QEvent::TouchUpdate:
9039 case QEvent::TouchEnd:
9040 case QEvent::TouchCancel:
9041 {
9042 event->ignore();
9043 break;
9044 }
9045 #ifndef QT_NO_GESTURES
9046 case QEvent::Gesture:
9047 event->ignore();
9048 break;
9049 #endif
9050 case QEvent::ScreenChangeInternal:
9051 if (const QTLWExtra *te = d->maybeTopData()) {
9052 const QWindow *win = te->window;
9053 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9054 }
9055 if (d->data.fnt.d->dpi != logicalDpiY())
9056 d->updateFont(d->data.fnt);
9057 #ifndef QT_NO_OPENGL
9058 d->renderToTextureReallyDirty = 1;
9059 #endif
9060 break;
9061 #ifndef QT_NO_PROPERTIES
9062 case QEvent::DynamicPropertyChange: {
9063 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9064 if (propName.length() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9065 uint value = property(propName.constData()).toUInt();
9066 if (!d->extra)
9067 d->createExtra();
9068 const char axis = propName.at(12);
9069 if (axis == 'X')
9070 d->extra->customDpiX = value;
9071 else if (axis == 'Y')
9072 d->extra->customDpiY = value;
9073 d->updateFont(d->data.fnt);
9074 }
9075 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9076 windowHandle()->setProperty(propName, property(propName));
9077 Q_FALLTHROUGH();
9078 }
9079 #endif
9080 default:
9081 return QObject::event(event);
9082 }
9083 return true;
9084 }
9085
9086 /*!
9087 This event handler can be reimplemented to handle state changes.
9088
9089 The state being changed in this event can be retrieved through the \a event
9090 supplied.
9091
9092 Change events include: QEvent::ToolBarChange,
9093 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9094 QEvent::StyleChange, QEvent::PaletteChange,
9095 QEvent::WindowTitleChange, QEvent::IconTextChange,
9096 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9097 QEvent::ParentChange, QEvent::WindowStateChange,
9098 QEvent::LanguageChange, QEvent::LocaleChange,
9099 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9100
9101 */
changeEvent(QEvent * event)9102 void QWidget::changeEvent(QEvent * event)
9103 {
9104 switch(event->type()) {
9105 case QEvent::EnabledChange: {
9106 update();
9107 #ifndef QT_NO_ACCESSIBILITY
9108 QAccessible::State s;
9109 s.disabled = true;
9110 QAccessibleStateChangeEvent event(this, s);
9111 QAccessible::updateAccessibility(&event);
9112 #endif
9113 break;
9114 }
9115
9116 case QEvent::FontChange:
9117 case QEvent::StyleChange: {
9118 Q_D(QWidget);
9119 update();
9120 updateGeometry();
9121 if (d->layout)
9122 d->layout->invalidate();
9123 break;
9124 }
9125
9126 case QEvent::PaletteChange:
9127 update();
9128 break;
9129
9130 case QEvent::ThemeChange:
9131 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9132 && qApp && !QCoreApplication::closingDown()) {
9133 if (testAttribute(Qt::WA_WState_Polished))
9134 QApplication::style()->unpolish(this);
9135 if (testAttribute(Qt::WA_WState_Polished))
9136 QApplication::style()->polish(this);
9137 QEvent styleChangedEvent(QEvent::StyleChange);
9138 QCoreApplication::sendEvent(this, &styleChangedEvent);
9139 if (isVisible())
9140 update();
9141 }
9142 break;
9143
9144 #ifdef Q_OS_MAC
9145 case QEvent::MacSizeChange:
9146 updateGeometry();
9147 break;
9148 #endif
9149
9150 default:
9151 break;
9152 }
9153 }
9154
9155 /*!
9156 This event handler, for event \a event, can be reimplemented in a
9157 subclass to receive mouse move events for the widget.
9158
9159 If mouse tracking is switched off, mouse move events only occur if
9160 a mouse button is pressed while the mouse is being moved. If mouse
9161 tracking is switched on, mouse move events occur even if no mouse
9162 button is pressed.
9163
9164 QMouseEvent::pos() reports the position of the mouse cursor,
9165 relative to this widget. For press and release events, the
9166 position is usually the same as the position of the last mouse
9167 move event, but it might be different if the user's hand shakes.
9168 This is a feature of the underlying window system, not Qt.
9169
9170 If you want to show a tooltip immediately, while the mouse is
9171 moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9172 and show them as a tooltip), you must first enable mouse tracking
9173 as described above. Then, to ensure that the tooltip is updated
9174 immediately, you must call QToolTip::showText() instead of
9175 setToolTip() in your implementation of mouseMoveEvent().
9176
9177 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9178 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9179 */
9180
mouseMoveEvent(QMouseEvent * event)9181 void QWidget::mouseMoveEvent(QMouseEvent *event)
9182 {
9183 event->ignore();
9184 }
9185
9186 /*!
9187 This event handler, for event \a event, can be reimplemented in a
9188 subclass to receive mouse press events for the widget.
9189
9190 If you create new widgets in the mousePressEvent() the
9191 mouseReleaseEvent() may not end up where you expect, depending on
9192 the underlying window system (or X11 window manager), the widgets'
9193 location and maybe more.
9194
9195 The default implementation implements the closing of popup widgets
9196 when you click outside the window. For other widget types it does
9197 nothing.
9198
9199 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9200 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9201 */
9202
mousePressEvent(QMouseEvent * event)9203 void QWidget::mousePressEvent(QMouseEvent *event)
9204 {
9205 event->ignore();
9206 if ((windowType() == Qt::Popup)) {
9207 event->accept();
9208 QWidget* w;
9209 while ((w = QApplication::activePopupWidget()) && w != this){
9210 w->close();
9211 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9212 w->hide(); // hide at least
9213 }
9214 if (!rect().contains(event->pos())){
9215 close();
9216 }
9217 }
9218 }
9219
9220 /*!
9221 This event handler, for event \a event, can be reimplemented in a
9222 subclass to receive mouse release events for the widget.
9223
9224 \sa mousePressEvent(), mouseDoubleClickEvent(),
9225 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9226 */
9227
mouseReleaseEvent(QMouseEvent * event)9228 void QWidget::mouseReleaseEvent(QMouseEvent *event)
9229 {
9230 event->ignore();
9231 }
9232
9233 /*!
9234 This event handler, for event \a event, can be reimplemented in a
9235 subclass to receive mouse double click events for the widget.
9236
9237 The default implementation calls mousePressEvent().
9238
9239 \note The widget will also receive mouse press and mouse release
9240 events in addition to the double click event. And if another widget
9241 that overlaps this widget disappears in response to press or
9242 release events, then this widget will only receive the double click
9243 event. It is up to the developer to ensure that the application
9244 interprets these events correctly.
9245
9246 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9247 event(), QMouseEvent
9248 */
9249
mouseDoubleClickEvent(QMouseEvent * event)9250 void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9251 {
9252 mousePressEvent(event);
9253 }
9254
9255 #if QT_CONFIG(wheelevent)
9256 /*!
9257 This event handler, for event \a event, can be reimplemented in a
9258 subclass to receive wheel events for the widget.
9259
9260 If you reimplement this handler, it is very important that you
9261 \l{QEvent}{ignore()} the event if you do not handle
9262 it, so that the widget's parent can interpret it.
9263
9264 The default implementation ignores the event.
9265
9266 \sa QEvent::ignore(), QEvent::accept(), event(),
9267 QWheelEvent
9268 */
9269
wheelEvent(QWheelEvent * event)9270 void QWidget::wheelEvent(QWheelEvent *event)
9271 {
9272 event->ignore();
9273 }
9274 #endif // QT_CONFIG(wheelevent)
9275
9276 #if QT_CONFIG(tabletevent)
9277 /*!
9278 This event handler, for event \a event, can be reimplemented in a
9279 subclass to receive tablet events for the widget.
9280
9281 If you reimplement this handler, it is very important that you
9282 \l{QEvent}{ignore()} the event if you do not handle
9283 it, so that the widget's parent can interpret it.
9284
9285 The default implementation ignores the event.
9286
9287 If tablet tracking is switched off, tablet move events only occur if the
9288 stylus is in contact with the tablet, or at least one stylus button is
9289 pressed, while the stylus is being moved. If tablet tracking is switched on,
9290 tablet move events occur even while the stylus is hovering in proximity of
9291 the tablet, with no buttons pressed.
9292
9293 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9294 QTabletEvent
9295 */
9296
tabletEvent(QTabletEvent * event)9297 void QWidget::tabletEvent(QTabletEvent *event)
9298 {
9299 event->ignore();
9300 }
9301 #endif // QT_CONFIG(tabletevent)
9302
9303 /*!
9304 This event handler, for event \a event, can be reimplemented in a
9305 subclass to receive key press events for the widget.
9306
9307 A widget must call setFocusPolicy() to accept focus initially and
9308 have focus in order to receive a key press event.
9309
9310 If you reimplement this handler, it is very important that you
9311 call the base class implementation if you do not act upon the key.
9312
9313 The default implementation closes popup widgets if the user
9314 presses the key sequence for QKeySequence::Cancel (typically the
9315 Escape key). Otherwise the event is ignored, so that the widget's
9316 parent can interpret it.
9317
9318 Note that QKeyEvent starts with isAccepted() == true, so you do not
9319 need to call QKeyEvent::accept() - just do not call the base class
9320 implementation if you act upon the key.
9321
9322 \sa keyReleaseEvent(), setFocusPolicy(),
9323 focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
9324 */
9325
keyPressEvent(QKeyEvent * event)9326 void QWidget::keyPressEvent(QKeyEvent *event)
9327 {
9328 #ifndef QT_NO_SHORTCUT
9329 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9330 event->accept();
9331 close();
9332 } else
9333 #endif
9334 {
9335 event->ignore();
9336 }
9337 }
9338
9339 /*!
9340 This event handler, for event \a event, can be reimplemented in a
9341 subclass to receive key release events for the widget.
9342
9343 A widget must \l{setFocusPolicy()}{accept focus}
9344 initially and \l{hasFocus()}{have focus} in order to
9345 receive a key release event.
9346
9347 If you reimplement this handler, it is very important that you
9348 call the base class implementation if you do not act upon the key.
9349
9350 The default implementation ignores the event, so that the widget's
9351 parent can interpret it.
9352
9353 Note that QKeyEvent starts with isAccepted() == true, so you do not
9354 need to call QKeyEvent::accept() - just do not call the base class
9355 implementation if you act upon the key.
9356
9357 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9358 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9359 */
9360
keyReleaseEvent(QKeyEvent * event)9361 void QWidget::keyReleaseEvent(QKeyEvent *event)
9362 {
9363 event->ignore();
9364 }
9365
9366 /*!
9367 \fn void QWidget::focusInEvent(QFocusEvent *event)
9368
9369 This event handler can be reimplemented in a subclass to receive
9370 keyboard focus events (focus received) for the widget. The event
9371 is passed in the \a event parameter
9372
9373 A widget normally must setFocusPolicy() to something other than
9374 Qt::NoFocus in order to receive focus events. (Note that the
9375 application programmer can call setFocus() on any widget, even
9376 those that do not normally accept focus.)
9377
9378 The default implementation updates the widget (except for windows
9379 that do not specify a focusPolicy()).
9380
9381 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9382 keyReleaseEvent(), event(), QFocusEvent
9383 */
9384
focusInEvent(QFocusEvent *)9385 void QWidget::focusInEvent(QFocusEvent *)
9386 {
9387 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9388 update();
9389 }
9390 }
9391
9392 /*!
9393 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9394
9395 This event handler can be reimplemented in a subclass to receive
9396 keyboard focus events (focus lost) for the widget. The events is
9397 passed in the \a event parameter.
9398
9399 A widget normally must setFocusPolicy() to something other than
9400 Qt::NoFocus in order to receive focus events. (Note that the
9401 application programmer can call setFocus() on any widget, even
9402 those that do not normally accept focus.)
9403
9404 The default implementation updates the widget (except for windows
9405 that do not specify a focusPolicy()).
9406
9407 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9408 keyReleaseEvent(), event(), QFocusEvent
9409 */
9410
focusOutEvent(QFocusEvent *)9411 void QWidget::focusOutEvent(QFocusEvent *)
9412 {
9413 if (focusPolicy() != Qt::NoFocus || !isWindow())
9414 update();
9415
9416 #if !defined(QT_PLATFORM_UIKIT)
9417 // FIXME: revisit autoSIP logic, QTBUG-42906
9418 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9419 QGuiApplication::inputMethod()->hide();
9420 #endif
9421 }
9422
9423 /*!
9424 \fn void QWidget::enterEvent(QEvent *event)
9425
9426 This event handler can be reimplemented in a subclass to receive
9427 widget enter events which are passed in the \a event parameter.
9428
9429 An event is sent to the widget when the mouse cursor enters the
9430 widget.
9431
9432 \sa leaveEvent(), mouseMoveEvent(), event()
9433 */
9434
enterEvent(QEvent *)9435 void QWidget::enterEvent(QEvent *)
9436 {
9437 }
9438
9439 // ### Qt 6: void QWidget::enterEvent(QEnterEvent *).
9440
9441 /*!
9442 \fn void QWidget::leaveEvent(QEvent *event)
9443
9444 This event handler can be reimplemented in a subclass to receive
9445 widget leave events which are passed in the \a event parameter.
9446
9447 A leave event is sent to the widget when the mouse cursor leaves
9448 the widget.
9449
9450 \sa enterEvent(), mouseMoveEvent(), event()
9451 */
9452
leaveEvent(QEvent *)9453 void QWidget::leaveEvent(QEvent *)
9454 {
9455 }
9456
9457 /*!
9458 \fn void QWidget::paintEvent(QPaintEvent *event)
9459
9460 This event handler can be reimplemented in a subclass to receive paint
9461 events passed in \a event.
9462
9463 A paint event is a request to repaint all or part of a widget. It can
9464 happen for one of the following reasons:
9465
9466 \list
9467 \li repaint() or update() was invoked,
9468 \li the widget was obscured and has now been uncovered, or
9469 \li many other reasons.
9470 \endlist
9471
9472 Many widgets can simply repaint their entire surface when asked to, but
9473 some slow widgets need to optimize by painting only the requested region:
9474 QPaintEvent::region(). This speed optimization does not change the result,
9475 as painting is clipped to that region during event processing. QListView
9476 and QTableView do this, for example.
9477
9478 Qt also tries to speed up painting by merging multiple paint events into
9479 one. When update() is called several times or the window system sends
9480 several paint events, Qt merges these events into one event with a larger
9481 region (see QRegion::united()). The repaint() function does not permit this
9482 optimization, so we suggest using update() whenever possible.
9483
9484 When the paint event occurs, the update region has normally been erased, so
9485 you are painting on the widget's background.
9486
9487 The background can be set using setBackgroundRole() and setPalette().
9488
9489 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9490 is no need to write double-buffering code in paintEvent() to avoid flicker.
9491
9492 \note Generally, you should refrain from calling update() or repaint()
9493 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9494 children inside a paintEvent() results in undefined behavior; the child may
9495 or may not get a paint event.
9496
9497 \warning If you are using a custom paint engine without Qt's backingstore,
9498 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9499 never be called; the backingstore will be used instead.
9500
9501 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9502 {Analog Clock Example}
9503 */
9504
paintEvent(QPaintEvent *)9505 void QWidget::paintEvent(QPaintEvent *)
9506 {
9507 }
9508
9509
9510 /*!
9511 \fn void QWidget::moveEvent(QMoveEvent *event)
9512
9513 This event handler can be reimplemented in a subclass to receive
9514 widget move events which are passed in the \a event parameter.
9515 When the widget receives this event, it is already at the new
9516 position.
9517
9518 The old position is accessible through QMoveEvent::oldPos().
9519
9520 \sa resizeEvent(), event(), move(), QMoveEvent
9521 */
9522
moveEvent(QMoveEvent *)9523 void QWidget::moveEvent(QMoveEvent *)
9524 {
9525 }
9526
9527
9528 /*!
9529 This event handler can be reimplemented in a subclass to receive
9530 widget resize events which are passed in the \a event parameter.
9531 When resizeEvent() is called, the widget already has its new
9532 geometry. The old size is accessible through
9533 QResizeEvent::oldSize().
9534
9535 The widget will be erased and receive a paint event immediately
9536 after processing the resize event. No drawing need be (or should
9537 be) done inside this handler.
9538
9539
9540 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9541 {Scribble Example}
9542 */
9543
resizeEvent(QResizeEvent *)9544 void QWidget::resizeEvent(QResizeEvent * /* event */)
9545 {
9546 }
9547
9548 #ifndef QT_NO_ACTION
9549 /*!
9550 \fn void QWidget::actionEvent(QActionEvent *event)
9551
9552 This event handler is called with the given \a event whenever the
9553 widget's actions are changed.
9554
9555 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9556 */
actionEvent(QActionEvent *)9557 void QWidget::actionEvent(QActionEvent *)
9558 {
9559
9560 }
9561 #endif
9562
9563 /*!
9564 This event handler is called with the given \a event when Qt receives a window
9565 close request for a top-level widget from the window system.
9566
9567 By default, the event is accepted and the widget is closed. You can reimplement
9568 this function to change the way the widget responds to window close requests.
9569 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9570 on all events.
9571
9572 Main window applications typically use reimplementations of this function to check
9573 whether the user's work has been saved and ask for permission before closing.
9574 For example, the \l{Application Example} uses a helper function to determine whether
9575 or not to close the window:
9576
9577 \snippet mainwindows/application/mainwindow.cpp 3
9578 \snippet mainwindows/application/mainwindow.cpp 4
9579
9580 \sa event(), hide(), close(), QCloseEvent, {Application Example}
9581 */
9582
closeEvent(QCloseEvent * event)9583 void QWidget::closeEvent(QCloseEvent *event)
9584 {
9585 event->accept();
9586 }
9587
9588 #ifndef QT_NO_CONTEXTMENU
9589 /*!
9590 This event handler, for event \a event, can be reimplemented in a
9591 subclass to receive widget context menu events.
9592
9593 The handler is called when the widget's \l contextMenuPolicy is
9594 Qt::DefaultContextMenu.
9595
9596 The default implementation ignores the context event.
9597 See the \l QContextMenuEvent documentation for more details.
9598
9599 \sa event(), QContextMenuEvent, customContextMenuRequested()
9600 */
9601
contextMenuEvent(QContextMenuEvent * event)9602 void QWidget::contextMenuEvent(QContextMenuEvent *event)
9603 {
9604 event->ignore();
9605 }
9606 #endif // QT_NO_CONTEXTMENU
9607
9608
9609 /*!
9610 This event handler, for event \a event, can be reimplemented in a
9611 subclass to receive Input Method composition events. This handler
9612 is called when the state of the input method changes.
9613
9614 Note that when creating custom text editing widgets, the
9615 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9616 (using the setAttribute() function) in order to receive input
9617 method events.
9618
9619 The default implementation calls event->ignore(), which rejects the
9620 Input Method event. See the \l QInputMethodEvent documentation for more
9621 details.
9622
9623 \sa event(), QInputMethodEvent
9624 */
inputMethodEvent(QInputMethodEvent * event)9625 void QWidget::inputMethodEvent(QInputMethodEvent *event)
9626 {
9627 event->ignore();
9628 }
9629
9630 /*!
9631 This method is only relevant for input widgets. It is used by the
9632 input method to query a set of properties of the widget to be
9633 able to support complex input method operations as support for
9634 surrounding text and reconversions.
9635
9636 \a query specifies which property is queried.
9637
9638 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9639 */
inputMethodQuery(Qt::InputMethodQuery query) const9640 QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9641 {
9642 switch(query) {
9643 case Qt::ImCursorRectangle:
9644 return QRect(width()/2, 0, 1, height());
9645 case Qt::ImFont:
9646 return font();
9647 case Qt::ImAnchorPosition:
9648 // Fallback.
9649 return inputMethodQuery(Qt::ImCursorPosition);
9650 case Qt::ImHints:
9651 return (int)inputMethodHints();
9652 case Qt::ImInputItemClipRectangle:
9653 return d_func()->clipRect();
9654 default:
9655 return QVariant();
9656 }
9657 }
9658
9659 /*!
9660 \property QWidget::inputMethodHints
9661 \brief What input method specific hints the widget has.
9662
9663 This is only relevant for input widgets. It is used by
9664 the input method to retrieve hints as to how the input method
9665 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9666 is set, the input method may change its visual components to reflect
9667 that only numbers can be entered.
9668
9669 \warning Some widgets require certain flags in order to work as
9670 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9671 instead of \c{w->setInputMethodHints(f)}.
9672
9673 \note The flags are only hints, so the particular input method
9674 implementation is free to ignore them. If you want to be
9675 sure that a certain type of characters are entered,
9676 you should also set a QValidator on the widget.
9677
9678 The default value is Qt::ImhNone.
9679
9680 \since 4.6
9681
9682 \sa inputMethodQuery()
9683 */
inputMethodHints() const9684 Qt::InputMethodHints QWidget::inputMethodHints() const
9685 {
9686 #ifndef QT_NO_IM
9687 const QWidgetPrivate *priv = d_func();
9688 while (priv->inheritsInputMethodHints) {
9689 priv = priv->q_func()->parentWidget()->d_func();
9690 Q_ASSERT(priv);
9691 }
9692 return priv->imHints;
9693 #else //QT_NO_IM
9694 return 0;
9695 #endif //QT_NO_IM
9696 }
9697
setInputMethodHints(Qt::InputMethodHints hints)9698 void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
9699 {
9700 #ifndef QT_NO_IM
9701 Q_D(QWidget);
9702 if (d->imHints == hints)
9703 return;
9704 d->imHints = hints;
9705 if (this == QGuiApplication::focusObject())
9706 QGuiApplication::inputMethod()->update(Qt::ImHints);
9707 #else
9708 Q_UNUSED(hints);
9709 #endif //QT_NO_IM
9710 }
9711
9712
9713 #if QT_CONFIG(draganddrop)
9714
9715 /*!
9716 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
9717
9718 This event handler is called when a drag is in progress and the
9719 mouse enters this widget. The event is passed in the \a event parameter.
9720
9721 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
9722 move events}.
9723
9724 See the \l{dnd.html}{Drag-and-drop documentation} for an
9725 overview of how to provide drag-and-drop in your application.
9726
9727 \sa QDrag, QDragEnterEvent
9728 */
dragEnterEvent(QDragEnterEvent *)9729 void QWidget::dragEnterEvent(QDragEnterEvent *)
9730 {
9731 }
9732
9733 /*!
9734 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
9735
9736 This event handler is called if a drag is in progress, and when
9737 any of the following conditions occur: the cursor enters this widget,
9738 the cursor moves within this widget, or a modifier key is pressed on
9739 the keyboard while this widget has the focus. The event is passed
9740 in the \a event parameter.
9741
9742 See the \l{dnd.html}{Drag-and-drop documentation} for an
9743 overview of how to provide drag-and-drop in your application.
9744
9745 \sa QDrag, QDragMoveEvent
9746 */
dragMoveEvent(QDragMoveEvent *)9747 void QWidget::dragMoveEvent(QDragMoveEvent *)
9748 {
9749 }
9750
9751 /*!
9752 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
9753
9754 This event handler is called when a drag is in progress and the
9755 mouse leaves this widget. The event is passed in the \a event
9756 parameter.
9757
9758 See the \l{dnd.html}{Drag-and-drop documentation} for an
9759 overview of how to provide drag-and-drop in your application.
9760
9761 \sa QDrag, QDragLeaveEvent
9762 */
dragLeaveEvent(QDragLeaveEvent *)9763 void QWidget::dragLeaveEvent(QDragLeaveEvent *)
9764 {
9765 }
9766
9767 /*!
9768 \fn void QWidget::dropEvent(QDropEvent *event)
9769
9770 This event handler is called when the drag is dropped on this
9771 widget. The event is passed in the \a event parameter.
9772
9773 See the \l{dnd.html}{Drag-and-drop documentation} for an
9774 overview of how to provide drag-and-drop in your application.
9775
9776 \sa QDrag, QDropEvent
9777 */
dropEvent(QDropEvent *)9778 void QWidget::dropEvent(QDropEvent *)
9779 {
9780 }
9781
9782 #endif // QT_CONFIG(draganddrop)
9783
9784 /*!
9785 \fn void QWidget::showEvent(QShowEvent *event)
9786
9787 This event handler can be reimplemented in a subclass to receive
9788 widget show events which are passed in the \a event parameter.
9789
9790 Non-spontaneous show events are sent to widgets immediately
9791 before they are shown. The spontaneous show events of windows are
9792 delivered afterwards.
9793
9794 Note: A widget receives spontaneous show and hide events when its
9795 mapping status is changed by the window system, e.g. a spontaneous
9796 hide event when the user minimizes the window, and a spontaneous
9797 show event when the window is restored again. After receiving a
9798 spontaneous hide event, a widget is still considered visible in
9799 the sense of isVisible().
9800
9801 \sa visible, event(), QShowEvent
9802 */
showEvent(QShowEvent *)9803 void QWidget::showEvent(QShowEvent *)
9804 {
9805 }
9806
9807 /*!
9808 \fn void QWidget::hideEvent(QHideEvent *event)
9809
9810 This event handler can be reimplemented in a subclass to receive
9811 widget hide events. The event is passed in the \a event parameter.
9812
9813 Hide events are sent to widgets immediately after they have been
9814 hidden.
9815
9816 Note: A widget receives spontaneous show and hide events when its
9817 mapping status is changed by the window system, e.g. a spontaneous
9818 hide event when the user minimizes the window, and a spontaneous
9819 show event when the window is restored again. After receiving a
9820 spontaneous hide event, a widget is still considered visible in
9821 the sense of isVisible().
9822
9823 \sa visible, event(), QHideEvent
9824 */
hideEvent(QHideEvent *)9825 void QWidget::hideEvent(QHideEvent *)
9826 {
9827 }
9828
9829 /*!
9830 This special event handler can be reimplemented in a subclass to
9831 receive native platform events identified by \a eventType
9832 which are passed in the \a message parameter.
9833
9834 In your reimplementation of this function, if you want to stop the
9835 event being handled by Qt, return true and set \a result. The \a result
9836 parameter has meaning only on Windows. If you return false, this native
9837 event is passed back to Qt, which translates the event into a Qt event
9838 and sends it to the widget.
9839
9840 \note Events are only delivered to this event handler if the widget
9841 has a native window handle.
9842
9843 \note This function superseedes the event filter functions
9844 x11Event(), winEvent() and macEvent() of Qt 4.
9845
9846 \sa QAbstractNativeEventFilter
9847
9848 \table
9849 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
9850 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
9851 \row \li macOS \li "NSEvent" \li NSEvent * \li
9852 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
9853 \endtable
9854 */
9855
9856 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
nativeEvent(const QByteArray & eventType,void * message,qintptr * result)9857 bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
9858 #else
9859 bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
9860 #endif
9861 {
9862 Q_UNUSED(eventType);
9863 Q_UNUSED(message);
9864 Q_UNUSED(result);
9865 return false;
9866 }
9867
9868 /*!
9869 Ensures that the widget and its children have been polished by
9870 QStyle (i.e., have a proper font and palette).
9871
9872 QWidget calls this function after it has been fully constructed
9873 but before it is shown the very first time. You can call this
9874 function if you want to ensure that the widget is polished before
9875 doing an operation, e.g., the correct font size might be needed in
9876 the widget's sizeHint() reimplementation. Note that this function
9877 \e is called from the default implementation of sizeHint().
9878
9879 Polishing is useful for final initialization that must happen after
9880 all constructors (from base classes as well as from subclasses)
9881 have been called.
9882
9883 If you need to change some settings when a widget is polished,
9884 reimplement event() and handle the QEvent::Polish event type.
9885
9886 \b{Note:} The function is declared const so that it can be called from
9887 other const functions (e.g., sizeHint()).
9888
9889 \sa event()
9890 */
ensurePolished() const9891 void QWidget::ensurePolished() const
9892 {
9893 Q_D(const QWidget);
9894
9895 const QMetaObject *m = metaObject();
9896 if (m == d->polished)
9897 return;
9898 d->polished = m;
9899
9900 QEvent e(QEvent::Polish);
9901 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
9902
9903 // polish children after 'this'
9904 QList<QObject*> children = d->children;
9905 for (int i = 0; i < children.size(); ++i) {
9906 QObject *o = children.at(i);
9907 if(!o->isWidgetType())
9908 continue;
9909 if (QWidget *w = qobject_cast<QWidget *>(o))
9910 w->ensurePolished();
9911 }
9912
9913 if (d->parent && d->sendChildEvents) {
9914 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
9915 QCoreApplication::sendEvent(d->parent, &e);
9916 }
9917 }
9918
9919 /*!
9920 Returns the mask currently set on a widget. If no mask is set the
9921 return value will be an empty region.
9922
9923 \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
9924 */
mask() const9925 QRegion QWidget::mask() const
9926 {
9927 Q_D(const QWidget);
9928 return d->extra ? d->extra->mask : QRegion();
9929 }
9930
9931 /*!
9932 Returns the layout manager that is installed on this widget, or \nullptr
9933 if no layout manager is installed.
9934
9935 The layout manager sets the geometry of the widget's children
9936 that have been added to the layout.
9937
9938 \sa setLayout(), sizePolicy(), {Layout Management}
9939 */
layout() const9940 QLayout *QWidget::layout() const
9941 {
9942 return d_func()->layout;
9943 }
9944
9945
9946 /*!
9947 \fn void QWidget::setLayout(QLayout *layout)
9948
9949 Sets the layout manager for this widget to \a layout.
9950
9951 If there already is a layout manager installed on this widget,
9952 QWidget won't let you install another. You must first delete the
9953 existing layout manager (returned by layout()) before you can
9954 call setLayout() with the new layout.
9955
9956 If \a layout is the layout manager on a different widget, setLayout()
9957 will reparent the layout and make it the layout manager for this widget.
9958
9959 Example:
9960
9961 \snippet layouts/layouts.cpp 24
9962
9963 An alternative to calling this function is to pass this widget to
9964 the layout's constructor.
9965
9966 The QWidget will take ownership of \a layout.
9967
9968 \sa layout(), {Layout Management}
9969 */
9970
setLayout(QLayout * l)9971 void QWidget::setLayout(QLayout *l)
9972 {
9973 if (Q_UNLIKELY(!l)) {
9974 qWarning("QWidget::setLayout: Cannot set layout to 0");
9975 return;
9976 }
9977 if (layout()) {
9978 if (Q_UNLIKELY(layout() != l))
9979 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
9980 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
9981 objectName().toLocal8Bit().data());
9982 return;
9983 }
9984
9985 QObject *oldParent = l->parent();
9986 if (oldParent && oldParent != this) {
9987 if (oldParent->isWidgetType()) {
9988 // Steal the layout off a widget parent. Takes effect when
9989 // morphing laid-out container widgets in Designer.
9990 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
9991 oldParentWidget->takeLayout();
9992 } else {
9993 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
9994 l->objectName().toLocal8Bit().data(), metaObject()->className(),
9995 objectName().toLocal8Bit().data());
9996 return;
9997 }
9998 }
9999
10000 Q_D(QWidget);
10001 l->d_func()->topLevel = true;
10002 d->layout = l;
10003 if (oldParent != this) {
10004 l->setParent(this);
10005 l->d_func()->reparentChildWidgets(this);
10006 l->invalidate();
10007 }
10008
10009 if (isWindow() && d->maybeTopData())
10010 d->topData()->sizeAdjusted = false;
10011 }
10012
10013 /*!
10014 \fn QLayout *QWidget::takeLayout()
10015
10016 Remove the layout from the widget.
10017 \since 4.5
10018 */
10019
takeLayout()10020 QLayout *QWidget::takeLayout()
10021 {
10022 Q_D(QWidget);
10023 QLayout *l = layout();
10024 if (!l)
10025 return nullptr;
10026 d->layout = nullptr;
10027 l->setParent(nullptr);
10028 return l;
10029 }
10030
10031 /*!
10032 \property QWidget::sizePolicy
10033 \brief the default layout behavior of the widget
10034
10035 If there is a QLayout that manages this widget's children, the
10036 size policy specified by that layout is used. If there is no such
10037 QLayout, the result of this function is used.
10038
10039 The default policy is Preferred/Preferred, which means that the
10040 widget can be freely resized, but prefers to be the size
10041 sizeHint() returns. Button-like widgets set the size policy to
10042 specify that they may stretch horizontally, but are fixed
10043 vertically. The same applies to lineedit controls (such as
10044 QLineEdit, QSpinBox or an editable QComboBox) and other
10045 horizontally orientated widgets (such as QProgressBar).
10046 QToolButton's are normally square, so they allow growth in both
10047 directions. Widgets that support different directions (such as
10048 QSlider, QScrollBar or QHeader) specify stretching in the
10049 respective direction only. Widgets that can provide scroll bars
10050 (usually subclasses of QScrollArea) tend to specify that they can
10051 use additional space, and that they can make do with less than
10052 sizeHint().
10053
10054 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10055 */
sizePolicy() const10056 QSizePolicy QWidget::sizePolicy() const
10057 {
10058 Q_D(const QWidget);
10059 return d->size_policy;
10060 }
10061
setSizePolicy(QSizePolicy policy)10062 void QWidget::setSizePolicy(QSizePolicy policy)
10063 {
10064 Q_D(QWidget);
10065 setAttribute(Qt::WA_WState_OwnSizePolicy);
10066 if (policy == d->size_policy)
10067 return;
10068
10069 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10070 d->retainSizeWhenHiddenChanged = 1;
10071
10072 d->size_policy = policy;
10073
10074 #if QT_CONFIG(graphicsview)
10075 if (const auto &extra = d->extra) {
10076 if (extra->proxyWidget)
10077 extra->proxyWidget->setSizePolicy(policy);
10078 }
10079 #endif
10080
10081 updateGeometry();
10082 d->retainSizeWhenHiddenChanged = 0;
10083
10084 if (isWindow() && d->maybeTopData())
10085 d->topData()->sizeAdjusted = false;
10086 }
10087
10088 /*!
10089 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10090 \overload
10091
10092 Sets the size policy of the widget to \a horizontal and \a
10093 vertical, with standard stretch and no height-for-width.
10094
10095 \sa QSizePolicy::QSizePolicy()
10096 */
10097
10098 /*!
10099 Returns the preferred height for this widget, given the width \a w.
10100
10101 If this widget has a layout, the default implementation returns
10102 the layout's preferred height. if there is no layout, the default
10103 implementation returns -1 indicating that the preferred height
10104 does not depend on the width.
10105 */
10106
heightForWidth(int w) const10107 int QWidget::heightForWidth(int w) const
10108 {
10109 if (layout() && layout()->hasHeightForWidth())
10110 return layout()->totalHeightForWidth(w);
10111 return -1;
10112 }
10113
10114
10115 /*!
10116 \since 5.0
10117
10118 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10119 */
hasHeightForWidth() const10120 bool QWidget::hasHeightForWidth() const
10121 {
10122 Q_D(const QWidget);
10123 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10124 }
10125
10126 /*!
10127 \fn QWidget *QWidget::childAt(int x, int y) const
10128
10129 Returns the visible child widget at the position (\a{x}, \a{y})
10130 in the widget's coordinate system. If there is no visible child
10131 widget at the specified position, the function returns \nullptr.
10132 */
10133
10134 /*!
10135 \overload
10136
10137 Returns the visible child widget at point \a p in the widget's own
10138 coordinate system.
10139 */
10140
childAt(const QPoint & p) const10141 QWidget *QWidget::childAt(const QPoint &p) const
10142 {
10143 return d_func()->childAt_helper(p, false);
10144 }
10145
childAt_helper(const QPoint & p,bool ignoreChildrenInDestructor) const10146 QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
10147 {
10148 if (children.isEmpty())
10149 return nullptr;
10150
10151 if (!pointInsideRectAndMask(p))
10152 return nullptr;
10153 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10154 }
10155
childAtRecursiveHelper(const QPoint & p,bool ignoreChildrenInDestructor) const10156 QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor) const
10157 {
10158 for (int i = children.size() - 1; i >= 0; --i) {
10159 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10160 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10161 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10162 continue;
10163 }
10164
10165 // Map the point 'p' from parent coordinates to child coordinates.
10166 QPoint childPoint = p;
10167 childPoint -= child->data->crect.topLeft();
10168
10169 // Check if the point hits the child.
10170 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10171 continue;
10172
10173 // Do the same for the child's descendants.
10174 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10175 return w;
10176
10177 // We have found our target; namely the child at position 'p'.
10178 return child;
10179 }
10180 return nullptr;
10181 }
10182
updateGeometry_helper(bool forceUpdate)10183 void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10184 {
10185 Q_Q(QWidget);
10186 if (widgetItem)
10187 widgetItem->invalidateSizeCache();
10188 QWidget *parent;
10189 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10190 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10191
10192 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10193 if (parent->d_func()->layout)
10194 parent->d_func()->layout->invalidate();
10195 else if (parent->isVisible())
10196 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10197 }
10198 }
10199 }
10200
10201 /*!
10202 Notifies the layout system that this widget has changed and may
10203 need to change geometry.
10204
10205 Call this function if the sizeHint() or sizePolicy() have changed.
10206
10207 For explicitly hidden widgets, updateGeometry() is a no-op. The
10208 layout system will be notified as soon as the widget is shown.
10209 */
10210
updateGeometry()10211 void QWidget::updateGeometry()
10212 {
10213 Q_D(QWidget);
10214 d->updateGeometry_helper(false);
10215 }
10216
10217 /*! \property QWidget::windowFlags
10218
10219 Window flags are a combination of a type (e.g. Qt::Dialog) and
10220 zero or more hints to the window system (e.g.
10221 Qt::FramelessWindowHint).
10222
10223 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10224 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10225 0) on the desktop. If the widget is a window and becomes a
10226 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10227 relative to its parent widget.
10228
10229 \note This function calls setParent() when changing the flags for
10230 a window, causing the widget to be hidden. You must call show() to make
10231 the widget visible again..
10232
10233 \sa windowType(), setWindowFlag(), {Window Flags Example}
10234 */
setWindowFlags(Qt::WindowFlags flags)10235 void QWidget::setWindowFlags(Qt::WindowFlags flags)
10236 {
10237 Q_D(QWidget);
10238 d->setWindowFlags(flags);
10239 }
10240
10241 /*!
10242 \since 5.9
10243
10244 Sets the window flag \a flag on this widget if \a on is true;
10245 otherwise clears the flag.
10246
10247 \sa setWindowFlags(), windowFlags(), windowType()
10248 */
setWindowFlag(Qt::WindowType flag,bool on)10249 void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10250 {
10251 Q_D(QWidget);
10252 if (on)
10253 d->setWindowFlags(data->window_flags | flag);
10254 else
10255 d->setWindowFlags(data->window_flags & ~flag);
10256 }
10257
10258 /*! \internal
10259
10260 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10261 */
setWindowFlags(Qt::WindowFlags flags)10262 void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10263 {
10264 Q_Q(QWidget);
10265 if (q->data->window_flags == flags)
10266 return;
10267
10268 if ((q->data->window_flags | flags) & Qt::Window) {
10269 // the old type was a window and/or the new type is a window
10270 QPoint oldPos = q->pos();
10271 bool visible = q->isVisible();
10272 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10273 q->setParent(q->parentWidget(), flags);
10274
10275 // if both types are windows or neither of them are, we restore
10276 // the old position
10277 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10278 q->move(oldPos);
10279 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10280 adjustQuitOnCloseAttribute();
10281 } else {
10282 q->data->window_flags = flags;
10283 }
10284 }
10285
10286 /*!
10287 Sets the window flags for the widget to \a flags,
10288 \e without telling the window system.
10289
10290 \warning Do not call this function unless you really know what
10291 you're doing.
10292
10293 \sa setWindowFlags()
10294 */
overrideWindowFlags(Qt::WindowFlags flags)10295 void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10296 {
10297 data->window_flags = flags;
10298 }
10299
10300 /*!
10301 \fn Qt::WindowType QWidget::windowType() const
10302
10303 Returns the window type of this widget. This is identical to
10304 windowFlags() & Qt::WindowType_Mask.
10305
10306 \sa windowFlags
10307 */
10308
10309 /*!
10310 Sets the parent of the widget to \a parent, and resets the window
10311 flags. The widget is moved to position (0, 0) in its new parent.
10312
10313 If the new parent widget is in a different window, the
10314 reparented widget and its children are appended to the end of the
10315 \l{setFocusPolicy()}{tab chain} of the new parent
10316 widget, in the same internal order as before. If one of the moved
10317 widgets had keyboard focus, setParent() calls clearFocus() for that
10318 widget.
10319
10320 If the new parent widget is in the same window as the
10321 old parent, setting the parent doesn't change the tab order or
10322 keyboard focus.
10323
10324 If the "new" parent widget is the old parent widget, this function
10325 does nothing.
10326
10327 \note The widget becomes invisible as part of changing its parent,
10328 even if it was previously visible. You must call show() to make the
10329 widget visible again.
10330
10331 \warning It is very unlikely that you will ever need this
10332 function. If you have a widget that changes its content
10333 dynamically, it is far easier to use \l QStackedWidget.
10334
10335 \sa setWindowFlags()
10336 */
setParent(QWidget * parent)10337 void QWidget::setParent(QWidget *parent)
10338 {
10339 if (parent == parentWidget())
10340 return;
10341 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10342 }
10343
10344 #ifndef QT_NO_OPENGL
sendWindowChangeToTextureChildrenRecursively(QWidget * widget)10345 static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget)
10346 {
10347 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10348 if (d->renderToTexture) {
10349 QEvent e(QEvent::WindowChangeInternal);
10350 QCoreApplication::sendEvent(widget, &e);
10351 }
10352
10353 for (int i = 0; i < d->children.size(); ++i) {
10354 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10355 if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
10356 sendWindowChangeToTextureChildrenRecursively(w);
10357 }
10358 }
10359 #endif
10360
10361 /*!
10362 \overload
10363
10364 This function also takes widget flags, \a f as an argument.
10365 */
10366
setParent(QWidget * parent,Qt::WindowFlags f)10367 void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10368 {
10369 Q_D(QWidget);
10370 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10371 #ifdef QT_DEBUG
10372 const auto checkForParentChildLoops = qScopeGuard([&](){
10373 int depth = 0;
10374 auto p = parentWidget();
10375 while (p) {
10376 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10377 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10378 "this is undefined behavior",
10379 this, metaObject()->className(), qPrintable(objectName()));
10380 }
10381 p = p->parentWidget();
10382 }
10383 });
10384 #endif
10385
10386 bool resized = testAttribute(Qt::WA_Resized);
10387 bool wasCreated = testAttribute(Qt::WA_WState_Created);
10388 QWidget *oldtlw = window();
10389
10390 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10391 d->data.fstrut_dirty = true;
10392
10393 QWidget *desktopWidget = nullptr;
10394 if (parent && parent->windowType() == Qt::Desktop)
10395 desktopWidget = parent;
10396 bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
10397
10398 if (newParent && parent && !desktopWidget) {
10399 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10400 parent->d_func()->enforceNativeChildren();
10401 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10402 setAttribute(Qt::WA_NativeWindow);
10403 }
10404
10405 if (wasCreated) {
10406 if (!testAttribute(Qt::WA_WState_Hidden)) {
10407 hide();
10408 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10409 }
10410 if (newParent) {
10411 QEvent e(QEvent::ParentAboutToChange);
10412 QCoreApplication::sendEvent(this, &e);
10413 }
10414 }
10415 if (newParent && isAncestorOf(focusWidget()))
10416 focusWidget()->clearFocus();
10417
10418 d->setParent_sys(parent, f);
10419
10420 if (desktopWidget)
10421 parent = nullptr;
10422
10423 #ifndef QT_NO_OPENGL
10424 if (d->textureChildSeen && parent) {
10425 // set the textureChildSeen flag up the whole parent chain
10426 QWidgetPrivate::get(parent)->setTextureChildSeen();
10427 }
10428 #endif
10429
10430 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10431 if (newParent)
10432 oldPaintManager->removeDirtyWidget(this);
10433 // Move the widget and all its static children from
10434 // the old backing store to the new one.
10435 oldPaintManager->moveStaticWidgets(this);
10436 }
10437
10438 // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
10439 if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation) && !testAttribute(Qt::WA_WState_Created))
10440 create();
10441
10442 d->reparentFocusWidgets(oldtlw);
10443 setAttribute(Qt::WA_Resized, resized);
10444
10445 const bool useStyleSheetPropagationInWidgetStyles =
10446 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10447
10448 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10449 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10450 // if the parent has a font set or inherited, then propagate the mask to the new child
10451 if (parent) {
10452 const auto pd = parent->d_func();
10453 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10454 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10455 }
10456 d->resolveFont();
10457 d->resolvePalette();
10458 }
10459 d->resolveLayoutDirection();
10460 d->resolveLocale();
10461
10462 // Note: GL widgets under WGL or EGL will always need a ParentChange
10463 // event to handle recreation/rebinding of the GL context, hence the
10464 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10465 // platforms).
10466 if (newParent
10467 #if defined(QT_OPENGL_ES)
10468 || (f & Qt::MSWindowsOwnDC)
10469 #endif
10470 ) {
10471 // propagate enabled updates enabled state to non-windows
10472 if (!isWindow()) {
10473 if (!testAttribute(Qt::WA_ForceDisabled))
10474 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10475 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10476 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10477 }
10478 d->inheritStyle();
10479
10480 // send and post remaining QObject events
10481 if (parent && d->sendChildEvents) {
10482 QChildEvent e(QEvent::ChildAdded, this);
10483 QCoreApplication::sendEvent(parent, &e);
10484 }
10485
10486 if (parent && d->sendChildEvents && d->polished) {
10487 QChildEvent e(QEvent::ChildPolished, this);
10488 QCoreApplication::sendEvent(parent, &e);
10489 }
10490
10491 QEvent e(QEvent::ParentChange);
10492 QCoreApplication::sendEvent(this, &e);
10493 }
10494 #ifndef QT_NO_OPENGL
10495 //renderToTexture widgets also need to know when their top-level window changes
10496 if (d->textureChildSeen && oldtlw != window()) {
10497 sendWindowChangeToTextureChildrenRecursively(this);
10498 }
10499 #endif
10500
10501 if (!wasCreated) {
10502 if (isWindow() || parentWidget()->isVisible())
10503 setAttribute(Qt::WA_WState_Hidden, true);
10504 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10505 setAttribute(Qt::WA_WState_Hidden, false);
10506 }
10507
10508 d->updateIsOpaque();
10509
10510 #if QT_CONFIG(graphicsview)
10511 // Embed the widget into a proxy if the parent is embedded.
10512 // ### Doesn't handle reparenting out of an embedded widget.
10513 if (oldtlw->graphicsProxyWidget()) {
10514 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10515 ancestorProxy->d_func()->unembedSubWindow(this);
10516 }
10517 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10518 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10519 ancestorProxy->d_func()->embedSubWindow(this);
10520 }
10521 #endif
10522
10523 if (d->extra && d->extra->hasWindowContainer)
10524 QWindowContainer::parentWasChanged(this);
10525 }
10526
setParent_sys(QWidget * newparent,Qt::WindowFlags f)10527 void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10528 {
10529 Q_Q(QWidget);
10530
10531 Qt::WindowFlags oldFlags = data.window_flags;
10532 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10533
10534 int targetScreen = -1;
10535 // Handle a request to move the widget to a particular screen
10536 if (newparent && newparent->windowType() == Qt::Desktop) {
10537 // make sure the widget is created on the same screen as the
10538 // programmer specified desktop widget
10539 const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(newparent);
10540 targetScreen = sw ? sw->screenNumber() : 0;
10541 newparent = nullptr;
10542 }
10543
10544 setWinId(0);
10545
10546 if (parent != newparent) {
10547 QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
10548 if (q->windowHandle()) {
10549 q->windowHandle()->setFlags(f);
10550 QWidget *parentWithWindow =
10551 newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
10552 if (parentWithWindow) {
10553 QWidget *topLevel = parentWithWindow->window();
10554 if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
10555 q->windowHandle()->setTransientParent(topLevel->windowHandle());
10556 q->windowHandle()->setParent(nullptr);
10557 } else {
10558 q->windowHandle()->setTransientParent(nullptr);
10559 q->windowHandle()->setParent(parentWithWindow->windowHandle());
10560 }
10561 } else {
10562 q->windowHandle()->setTransientParent(nullptr);
10563 q->windowHandle()->setParent(nullptr);
10564 }
10565 }
10566 }
10567
10568 if (!newparent) {
10569 f |= Qt::Window;
10570 if (targetScreen == -1) {
10571 if (parent)
10572 targetScreen = QDesktopWidgetPrivate::screenNumber(q->parentWidget()->window());
10573 }
10574 }
10575
10576 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
10577
10578 // Reparenting toplevel to child
10579 if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
10580 if (extra && extra->hasWindowContainer)
10581 QWindowContainer::toplevelAboutToBeDestroyed(q);
10582
10583 QWindow *newParentWindow = newparent->windowHandle();
10584 if (!newParentWindow)
10585 if (QWidget *npw = newparent->nativeParentWidget())
10586 newParentWindow = npw->windowHandle();
10587
10588 Q_FOREACH (QObject *child, q->windowHandle()->children()) {
10589 QWindow *childWindow = qobject_cast<QWindow *>(child);
10590 if (!childWindow)
10591 continue;
10592
10593 QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(childWindow);
10594 QWidget *childWidget = childWW ? childWW->widget() : nullptr;
10595 if (!childWW || (childWidget && childWidget->testAttribute(Qt::WA_NativeWindow)))
10596 childWindow->setParent(newParentWindow);
10597 }
10598 q->destroy();
10599 }
10600
10601 adjustFlags(f, q);
10602 data.window_flags = f;
10603 q->setAttribute(Qt::WA_WState_Created, false);
10604 q->setAttribute(Qt::WA_WState_Visible, false);
10605 q->setAttribute(Qt::WA_WState_Hidden, false);
10606
10607 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
10608 q->createWinId();
10609
10610 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
10611 q->setAttribute(Qt::WA_WState_Hidden);
10612 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
10613
10614 // move the window to the selected screen
10615 if (!newparent && targetScreen != -1) {
10616 // only if it is already created
10617 if (q->testAttribute(Qt::WA_WState_Created))
10618 q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
10619 else
10620 topData()->initialScreenIndex = targetScreen;
10621 }
10622 }
10623
10624 /*!
10625 Scrolls the widget including its children \a dx pixels to the
10626 right and \a dy downward. Both \a dx and \a dy may be negative.
10627
10628 After scrolling, the widgets will receive paint events for
10629 the areas that need to be repainted. For widgets that Qt knows to
10630 be opaque, this is only the newly exposed parts.
10631 For example, if an opaque widget is scrolled 8 pixels to the left,
10632 only an 8-pixel wide stripe at the right edge needs updating.
10633
10634 Since widgets propagate the contents of their parents by default,
10635 you need to set the \l autoFillBackground property, or use
10636 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
10637 a widget opaque.
10638
10639 For widgets that use contents propagation, a scroll will cause an
10640 update of the entire scroll area.
10641
10642 \sa {Transparency and Double Buffering}
10643 */
10644
scroll(int dx,int dy)10645 void QWidget::scroll(int dx, int dy)
10646 {
10647 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10648 return;
10649 if (dx == 0 && dy == 0)
10650 return;
10651 Q_D(QWidget);
10652 #if QT_CONFIG(graphicsview)
10653 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10654 // Graphics View maintains its own dirty region as a list of rects;
10655 // until we can connect item updates directly to the view, we must
10656 // separately add a translated dirty region.
10657 for (const QRect &rect : d->dirty)
10658 proxy->update(rect.translated(dx, dy));
10659 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
10660 return;
10661 }
10662 #endif
10663 d->setDirtyOpaqueRegion();
10664 d->scroll_sys(dx, dy);
10665 }
10666
scroll_sys(int dx,int dy)10667 void QWidgetPrivate::scroll_sys(int dx, int dy)
10668 {
10669 Q_Q(QWidget);
10670 scrollChildren(dx, dy);
10671 scrollRect(q->rect(), dx, dy);
10672 }
10673
10674 /*!
10675 \overload
10676
10677 This version only scrolls \a r and does not move the children of
10678 the widget.
10679
10680 If \a r is empty or invalid, the result is undefined.
10681
10682 \sa QScrollArea
10683 */
scroll(int dx,int dy,const QRect & r)10684 void QWidget::scroll(int dx, int dy, const QRect &r)
10685 {
10686
10687 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10688 return;
10689 if (dx == 0 && dy == 0)
10690 return;
10691 Q_D(QWidget);
10692 #if QT_CONFIG(graphicsview)
10693 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10694 // Graphics View maintains its own dirty region as a list of rects;
10695 // until we can connect item updates directly to the view, we must
10696 // separately add a translated dirty region.
10697 if (!d->dirty.isEmpty()) {
10698 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
10699 proxy->update(rect);
10700 }
10701 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
10702 return;
10703 }
10704 #endif
10705 d->scroll_sys(dx, dy, r);
10706 }
10707
scroll_sys(int dx,int dy,const QRect & r)10708 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
10709 {
10710 scrollRect(r, dx, dy);
10711 }
10712
10713 /*!
10714 Repaints the widget directly by calling paintEvent() immediately,
10715 unless updates are disabled or the widget is hidden.
10716
10717 We suggest only using repaint() if you need an immediate repaint,
10718 for example during animation. In almost all circumstances update()
10719 is better, as it permits Qt to optimize for speed and minimize
10720 flicker.
10721
10722 \warning If you call repaint() in a function which may itself be
10723 called from paintEvent(), you may get infinite recursion. The
10724 update() function never causes recursion.
10725
10726 \sa update(), paintEvent(), setUpdatesEnabled()
10727 */
10728
repaint()10729 void QWidget::repaint()
10730 {
10731 repaint(rect());
10732 }
10733
10734 /*! \overload
10735
10736 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
10737 the widget.
10738
10739 If \a w is negative, it is replaced with \c{width() - x}, and if
10740 \a h is negative, it is replaced width \c{height() - y}.
10741 */
repaint(int x,int y,int w,int h)10742 void QWidget::repaint(int x, int y, int w, int h)
10743 {
10744 if (x > data->crect.width() || y > data->crect.height())
10745 return;
10746
10747 if (w < 0)
10748 w = data->crect.width() - x;
10749 if (h < 0)
10750 h = data->crect.height() - y;
10751
10752 repaint(QRect(x, y, w, h));
10753 }
10754
10755 /*! \overload
10756
10757 This version repaints a rectangle \a rect inside the widget.
10758 */
repaint(const QRect & rect)10759 void QWidget::repaint(const QRect &rect)
10760 {
10761 Q_D(QWidget);
10762 d->repaint(rect);
10763 }
10764
10765 /*!
10766 \overload
10767
10768 This version repaints a region \a rgn inside the widget.
10769 */
repaint(const QRegion & rgn)10770 void QWidget::repaint(const QRegion &rgn)
10771 {
10772 Q_D(QWidget);
10773 d->repaint(rgn);
10774 }
10775
10776 template <typename T>
repaint(T r)10777 void QWidgetPrivate::repaint(T r)
10778 {
10779 Q_Q(QWidget);
10780
10781 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
10782 return;
10783
10784 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10785 if (tlwExtra && tlwExtra->backingStore)
10786 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
10787 }
10788
10789 /*!
10790 Updates the widget unless updates are disabled or the widget is
10791 hidden.
10792
10793 This function does not cause an immediate repaint; instead it
10794 schedules a paint event for processing when Qt returns to the main
10795 event loop. This permits Qt to optimize for more speed and less
10796 flicker than a call to repaint() does.
10797
10798 Calling update() several times normally results in just one
10799 paintEvent() call.
10800
10801 Qt normally erases the widget's area before the paintEvent() call.
10802 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
10803 responsible for painting all its pixels with an opaque color.
10804
10805 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
10806 */
update()10807 void QWidget::update()
10808 {
10809 update(rect());
10810 }
10811
10812 /*! \fn void QWidget::update(int x, int y, int w, int h)
10813 \overload
10814
10815 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
10816 the widget.
10817 */
10818
10819 /*!
10820 \overload
10821
10822 This version updates a rectangle \a rect inside the widget.
10823 */
update(const QRect & rect)10824 void QWidget::update(const QRect &rect)
10825 {
10826 Q_D(QWidget);
10827 d->update(rect);
10828 }
10829
10830 /*!
10831 \overload
10832
10833 This version repaints a region \a rgn inside the widget.
10834 */
update(const QRegion & rgn)10835 void QWidget::update(const QRegion &rgn)
10836 {
10837 Q_D(QWidget);
10838 d->update(rgn);
10839 }
10840
10841 template <typename T>
update(T r)10842 void QWidgetPrivate::update(T r)
10843 {
10844 Q_Q(QWidget);
10845
10846 if (!q->isVisible() || !q->updatesEnabled())
10847 return;
10848
10849 T clipped = r & q->rect();
10850
10851 if (clipped.isEmpty())
10852 return;
10853
10854 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
10855 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
10856 return;
10857 }
10858
10859 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10860 if (tlwExtra && tlwExtra->backingStore)
10861 tlwExtra->repaintManager->markDirty(clipped, q);
10862 }
10863
10864 /*!
10865 \internal
10866
10867 This just sets the corresponding attribute bit to 1 or 0
10868 */
setAttribute_internal(Qt::WidgetAttribute attribute,bool on,QWidgetData * data,QWidgetPrivate * d)10869 static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
10870 QWidgetPrivate *d)
10871 {
10872 if (attribute < int(8*sizeof(uint))) {
10873 if (on)
10874 data->widget_attributes |= (1<<attribute);
10875 else
10876 data->widget_attributes &= ~(1<<attribute);
10877 } else {
10878 const int x = attribute - 8*sizeof(uint);
10879 const int int_off = x / (8*sizeof(uint));
10880 if (on)
10881 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
10882 else
10883 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
10884 }
10885 }
10886
10887 #ifdef Q_OS_MAC
macUpdateSizeAttribute()10888 void QWidgetPrivate::macUpdateSizeAttribute()
10889 {
10890 Q_Q(QWidget);
10891 QEvent event(QEvent::MacSizeChange);
10892 QCoreApplication::sendEvent(q, &event);
10893 for (int i = 0; i < children.size(); ++i) {
10894 QWidget *w = qobject_cast<QWidget *>(children.at(i));
10895 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
10896 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
10897 && !w->testAttribute(Qt::WA_MacSmallSize)
10898 && !w->testAttribute(Qt::WA_MacNormalSize))
10899 w->d_func()->macUpdateSizeAttribute();
10900 }
10901 resolveFont();
10902 }
10903 #endif
10904
10905 /*!
10906 Sets the attribute \a attribute on this widget if \a on is true;
10907 otherwise clears the attribute.
10908
10909 \sa testAttribute()
10910 */
setAttribute(Qt::WidgetAttribute attribute,bool on)10911 void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
10912 {
10913 if (testAttribute(attribute) == on)
10914 return;
10915
10916 Q_D(QWidget);
10917 Q_STATIC_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
10918 "QWidget::setAttribute(WidgetAttribute, bool): "
10919 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
10920 #ifdef Q_OS_WIN
10921 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
10922 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
10923 // see ::paintEngine for details
10924 paintEngine();
10925 if (d->noPaintOnScreen)
10926 return;
10927 }
10928 #endif
10929
10930 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
10931 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
10932 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
10933 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
10934 return;
10935 }
10936
10937 setAttribute_internal(attribute, on, data, d);
10938
10939 switch (attribute) {
10940
10941 #if QT_CONFIG(draganddrop)
10942 case Qt::WA_AcceptDrops: {
10943 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
10944 setAttribute(Qt::WA_DropSiteRegistered, true);
10945 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
10946 setAttribute(Qt::WA_DropSiteRegistered, false);
10947 QEvent e(QEvent::AcceptDropsChange);
10948 QCoreApplication::sendEvent(this, &e);
10949 break;
10950 }
10951 case Qt::WA_DropSiteRegistered: {
10952 for (int i = 0; i < d->children.size(); ++i) {
10953 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10954 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
10955 w->setAttribute(Qt::WA_DropSiteRegistered, on);
10956 }
10957 break;
10958 }
10959 #endif
10960
10961 case Qt::WA_NoChildEventsForParent:
10962 d->sendChildEvents = !on;
10963 break;
10964 case Qt::WA_NoChildEventsFromChildren:
10965 d->receiveChildEvents = !on;
10966 break;
10967 case Qt::WA_MacNormalSize:
10968 case Qt::WA_MacSmallSize:
10969 case Qt::WA_MacMiniSize:
10970 #ifdef Q_OS_MAC
10971 {
10972 // We can only have one of these set at a time
10973 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
10974 Qt::WA_MacMiniSize };
10975 for (int i = 0; i < 3; ++i) {
10976 if (MacSizes[i] != attribute)
10977 setAttribute_internal(MacSizes[i], false, data, d);
10978 }
10979 d->macUpdateSizeAttribute();
10980 }
10981 #endif
10982 break;
10983 case Qt::WA_ShowModal:
10984 if (!on) {
10985 // reset modality type to NonModal when clearing WA_ShowModal
10986 data->window_modality = Qt::NonModal;
10987 } else if (data->window_modality == Qt::NonModal) {
10988 // determine the modality type if it hasn't been set prior
10989 // to setting WA_ShowModal. set the default to WindowModal
10990 // if we are the child of a group leader; otherwise use
10991 // ApplicationModal.
10992 QWidget *w = parentWidget();
10993 if (w)
10994 w = w->window();
10995 while (w && !w->testAttribute(Qt::WA_GroupLeader)) {
10996 w = w->parentWidget();
10997 if (w)
10998 w = w->window();
10999 }
11000 data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader))
11001 ? Qt::WindowModal
11002 : Qt::ApplicationModal;
11003 // Some window managers do not allow us to enter modality after the
11004 // window is visible.The window must be hidden before changing the
11005 // windowModality property and then reshown.
11006 }
11007 if (testAttribute(Qt::WA_WState_Created)) {
11008 // don't call setModal_sys() before create()
11009 d->setModal_sys();
11010 }
11011 break;
11012 case Qt::WA_MouseTracking: {
11013 QEvent e(QEvent::MouseTrackingChange);
11014 QCoreApplication::sendEvent(this, &e);
11015 break; }
11016 case Qt::WA_TabletTracking: {
11017 QEvent e(QEvent::TabletTrackingChange);
11018 QCoreApplication::sendEvent(this, &e);
11019 break; }
11020 case Qt::WA_NativeWindow: {
11021 d->createTLExtra();
11022 if (on)
11023 d->createTLSysExtra();
11024 #ifndef QT_NO_IM
11025 QWidget *focusWidget = d->effectiveFocusWidget();
11026 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11027 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11028 QGuiApplication::inputMethod()->commit();
11029 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11030 }
11031 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11032 parentWidget()->d_func()->enforceNativeChildren();
11033 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11034 d->createWinId();
11035 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11036 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11037 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11038 }
11039 #endif //QT_NO_IM
11040 break;
11041 }
11042 case Qt::WA_PaintOnScreen:
11043 d->updateIsOpaque();
11044 Q_FALLTHROUGH();
11045 case Qt::WA_OpaquePaintEvent:
11046 d->updateIsOpaque();
11047 break;
11048 case Qt::WA_NoSystemBackground:
11049 d->updateIsOpaque();
11050 Q_FALLTHROUGH();
11051 case Qt::WA_UpdatesDisabled:
11052 d->updateSystemBackground();
11053 break;
11054 case Qt::WA_TransparentForMouseEvents:
11055 break;
11056 case Qt::WA_InputMethodEnabled: {
11057 #ifndef QT_NO_IM
11058 if (QGuiApplication::focusObject() == this) {
11059 if (!on)
11060 QGuiApplication::inputMethod()->commit();
11061 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11062 }
11063 #endif //QT_NO_IM
11064 break;
11065 }
11066 case Qt::WA_WindowPropagation:
11067 d->resolvePalette();
11068 d->resolveFont();
11069 d->resolveLocale();
11070 break;
11071 case Qt::WA_DontShowOnScreen: {
11072 if (on && isVisible()) {
11073 // Make sure we keep the current state and only hide the widget
11074 // from the desktop. show_sys will only update platform specific
11075 // attributes at this point.
11076 d->hide_sys();
11077 d->show_sys();
11078 }
11079 break;
11080 }
11081
11082 case Qt::WA_X11NetWmWindowTypeDesktop:
11083 case Qt::WA_X11NetWmWindowTypeDock:
11084 case Qt::WA_X11NetWmWindowTypeToolBar:
11085 case Qt::WA_X11NetWmWindowTypeMenu:
11086 case Qt::WA_X11NetWmWindowTypeUtility:
11087 case Qt::WA_X11NetWmWindowTypeSplash:
11088 case Qt::WA_X11NetWmWindowTypeDialog:
11089 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11090 case Qt::WA_X11NetWmWindowTypePopupMenu:
11091 case Qt::WA_X11NetWmWindowTypeToolTip:
11092 case Qt::WA_X11NetWmWindowTypeNotification:
11093 case Qt::WA_X11NetWmWindowTypeCombo:
11094 case Qt::WA_X11NetWmWindowTypeDND:
11095 d->setNetWmWindowTypes();
11096 break;
11097
11098 case Qt::WA_StaticContents:
11099 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11100 if (on)
11101 repaintManager->addStaticWidget(this);
11102 else
11103 repaintManager->removeStaticWidget(this);
11104 }
11105 break;
11106 case Qt::WA_TranslucentBackground:
11107 if (on)
11108 setAttribute(Qt::WA_NoSystemBackground);
11109 d->updateIsTranslucent();
11110
11111 break;
11112 case Qt::WA_AcceptTouchEvents:
11113 break;
11114 default:
11115 break;
11116 }
11117 }
11118
11119 /*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11120
11121 Returns \c true if attribute \a attribute is set on this widget;
11122 otherwise returns \c false.
11123
11124 \sa setAttribute()
11125 */
testAttribute_helper(Qt::WidgetAttribute attribute) const11126 bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11127 {
11128 Q_D(const QWidget);
11129 const int x = attribute - 8*sizeof(uint);
11130 const int int_off = x / (8*sizeof(uint));
11131 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11132 }
11133
11134 /*!
11135 \property QWidget::windowOpacity
11136
11137 \brief The level of opacity for the window.
11138
11139 The valid range of opacity is from 1.0 (completely opaque) to
11140 0.0 (completely transparent).
11141
11142 By default the value of this property is 1.0.
11143
11144 This feature is available on Embedded Linux, \macos, Windows,
11145 and X11 platforms that support the Composite extension.
11146
11147 \note On X11 you need to have a composite manager running,
11148 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11149 supported by the window manager you are using.
11150
11151 \warning Changing this property from opaque to transparent might issue a
11152 paint event that needs to be processed before the window is displayed
11153 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11154 that semi-transparent windows update and resize significantly slower than
11155 opaque windows.
11156
11157 \sa setMask()
11158 */
windowOpacity() const11159 qreal QWidget::windowOpacity() const
11160 {
11161 Q_D(const QWidget);
11162 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11163 }
11164
setWindowOpacity(qreal opacity)11165 void QWidget::setWindowOpacity(qreal opacity)
11166 {
11167 Q_D(QWidget);
11168 if (!isWindow())
11169 return;
11170
11171 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11172 QTLWExtra *extra = d->topData();
11173 extra->opacity = uint(opacity * 255);
11174 setAttribute(Qt::WA_WState_WindowOpacitySet);
11175 d->setWindowOpacity_sys(opacity);
11176
11177 if (!testAttribute(Qt::WA_WState_Created))
11178 return;
11179
11180 #if QT_CONFIG(graphicsview)
11181 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11182 // Avoid invalidating the cache if set.
11183 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11184 proxy->update();
11185 else if (QGraphicsScene *scene = proxy->scene())
11186 scene->update(proxy->sceneBoundingRect());
11187 return;
11188 }
11189 #endif
11190 }
11191
setWindowOpacity_sys(qreal level)11192 void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11193 {
11194 Q_Q(QWidget);
11195 if (q->windowHandle())
11196 q->windowHandle()->setOpacity(level);
11197 }
11198
11199 /*!
11200 \property QWidget::windowModified
11201 \brief whether the document shown in the window has unsaved changes
11202
11203 A modified window is a window whose content has changed but has
11204 not been saved to disk. This flag will have different effects
11205 varied by the platform. On \macos the close button will have a
11206 modified look; on other platforms, the window title will have an
11207 '*' (asterisk).
11208
11209 The window title must contain a "[*]" placeholder, which
11210 indicates where the '*' should appear. Normally, it should appear
11211 right after the file name (e.g., "document1.txt[*] - Text
11212 Editor"). If the window isn't modified, the placeholder is simply
11213 removed.
11214
11215 Note that if a widget is set as modified, all its ancestors will
11216 also be set as modified. However, if you call \c
11217 {setWindowModified(false)} on a widget, this will not propagate to
11218 its parent because other children of the parent might have been
11219 modified.
11220
11221 \sa windowTitle, {Application Example}, {SDI Example}, {MDI Example}
11222 */
isWindowModified() const11223 bool QWidget::isWindowModified() const
11224 {
11225 return testAttribute(Qt::WA_WindowModified);
11226 }
11227
setWindowModified(bool mod)11228 void QWidget::setWindowModified(bool mod)
11229 {
11230 Q_D(QWidget);
11231 setAttribute(Qt::WA_WindowModified, mod);
11232
11233 d->setWindowModified_helper();
11234
11235 QEvent e(QEvent::ModifiedChange);
11236 QCoreApplication::sendEvent(this, &e);
11237 }
11238
setWindowModified_helper()11239 void QWidgetPrivate::setWindowModified_helper()
11240 {
11241 Q_Q(QWidget);
11242 QWindow *window = q->windowHandle();
11243 if (!window)
11244 return;
11245 QPlatformWindow *platformWindow = window->handle();
11246 if (!platformWindow)
11247 return;
11248 bool on = q->testAttribute(Qt::WA_WindowModified);
11249 if (!platformWindow->setWindowModified(on)) {
11250 if (Q_UNLIKELY(on && !q->windowTitle().contains(QLatin1String("[*]"))))
11251 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11252 setWindowTitle_helper(q->windowTitle());
11253 setWindowIconText_helper(q->windowIconText());
11254 }
11255 }
11256
11257 #ifndef QT_NO_TOOLTIP
11258 /*!
11259 \property QWidget::toolTip
11260
11261 \brief the widget's tooltip
11262
11263 Note that by default tooltips are only shown for widgets that are
11264 children of the active window. You can change this behavior by
11265 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11266 not on the widget with the tooltip.
11267
11268 If you want to control a tooltip's behavior, you can intercept the
11269 event() function and catch the QEvent::ToolTip event (e.g., if you
11270 want to customize the area for which the tooltip should be shown).
11271
11272 By default, this property contains an empty string.
11273
11274 \sa QToolTip, statusTip, whatsThis
11275 */
setToolTip(const QString & s)11276 void QWidget::setToolTip(const QString &s)
11277 {
11278 Q_D(QWidget);
11279 d->toolTip = s;
11280
11281 QEvent event(QEvent::ToolTipChange);
11282 QCoreApplication::sendEvent(this, &event);
11283 }
11284
toolTip() const11285 QString QWidget::toolTip() const
11286 {
11287 Q_D(const QWidget);
11288 return d->toolTip;
11289 }
11290
11291 /*!
11292 \property QWidget::toolTipDuration
11293 \brief the widget's tooltip duration
11294 \since 5.2
11295
11296 Specifies how long time the tooltip will be displayed, in milliseconds.
11297 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11298
11299 \sa toolTip
11300 */
11301
setToolTipDuration(int msec)11302 void QWidget::setToolTipDuration(int msec)
11303 {
11304 Q_D(QWidget);
11305 d->toolTipDuration = msec;
11306 }
11307
toolTipDuration() const11308 int QWidget::toolTipDuration() const
11309 {
11310 Q_D(const QWidget);
11311 return d->toolTipDuration;
11312 }
11313
11314 #endif // QT_NO_TOOLTIP
11315
11316
11317 #if QT_CONFIG(statustip)
11318 /*!
11319 \property QWidget::statusTip
11320 \brief the widget's status tip
11321
11322 By default, this property contains an empty string.
11323
11324 \sa toolTip, whatsThis
11325 */
setStatusTip(const QString & s)11326 void QWidget::setStatusTip(const QString &s)
11327 {
11328 Q_D(QWidget);
11329 d->statusTip = s;
11330 }
11331
statusTip() const11332 QString QWidget::statusTip() const
11333 {
11334 Q_D(const QWidget);
11335 return d->statusTip;
11336 }
11337 #endif // QT_CONFIG(statustip)
11338
11339 #if QT_CONFIG(whatsthis)
11340 /*!
11341 \property QWidget::whatsThis
11342
11343 \brief the widget's What's This help text.
11344
11345 By default, this property contains an empty string.
11346
11347 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11348 */
setWhatsThis(const QString & s)11349 void QWidget::setWhatsThis(const QString &s)
11350 {
11351 Q_D(QWidget);
11352 d->whatsThis = s;
11353 }
11354
whatsThis() const11355 QString QWidget::whatsThis() const
11356 {
11357 Q_D(const QWidget);
11358 return d->whatsThis;
11359 }
11360 #endif // QT_CONFIG(whatsthis)
11361
11362 #ifndef QT_NO_ACCESSIBILITY
11363 /*!
11364 \property QWidget::accessibleName
11365
11366 \brief the widget's name as seen by assistive technologies
11367
11368 This is the primary name by which assistive technology such as screen readers
11369 announce this widget. For most widgets setting this property is not required.
11370 For example for QPushButton the button's text will be used.
11371
11372 It is important to set this property when the widget does not provide any
11373 text. For example a button that only contains an icon needs to set this
11374 property to work with screen readers.
11375 The name should be short and equivalent to the visual information conveyed
11376 by the widget.
11377
11378 This property has to be \l{Internationalization with Qt}{localized}.
11379
11380 By default, this property contains an empty string.
11381
11382 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11383 */
setAccessibleName(const QString & name)11384 void QWidget::setAccessibleName(const QString &name)
11385 {
11386 Q_D(QWidget);
11387 d->accessibleName = name;
11388 QAccessibleEvent event(this, QAccessible::NameChanged);
11389 QAccessible::updateAccessibility(&event);
11390 }
11391
accessibleName() const11392 QString QWidget::accessibleName() const
11393 {
11394 Q_D(const QWidget);
11395 return d->accessibleName;
11396 }
11397
11398 /*!
11399 \property QWidget::accessibleDescription
11400
11401 \brief the widget's description as seen by assistive technologies
11402
11403 The accessible description of a widget should convey what a widget does.
11404 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11405 the description should give more context, such as \gui{Saves the current document}.
11406
11407 This property has to be \l{Internationalization with Qt}{localized}.
11408
11409 By default, this property contains an empty string and Qt falls back
11410 to using the tool tip to provide this information.
11411
11412 \sa QWidget::accessibleName, QAccessibleInterface::text()
11413 */
setAccessibleDescription(const QString & description)11414 void QWidget::setAccessibleDescription(const QString &description)
11415 {
11416 Q_D(QWidget);
11417 d->accessibleDescription = description;
11418 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11419 QAccessible::updateAccessibility(&event);
11420 }
11421
accessibleDescription() const11422 QString QWidget::accessibleDescription() const
11423 {
11424 Q_D(const QWidget);
11425 return d->accessibleDescription;
11426 }
11427 #endif // QT_NO_ACCESSIBILITY
11428
11429 #ifndef QT_NO_SHORTCUT
11430 /*!
11431 Adds a shortcut to Qt's shortcut system that watches for the given
11432 \a key sequence in the given \a context. If the \a context is
11433 Qt::ApplicationShortcut, the shortcut applies to the application as a
11434 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11435 or to the window itself, Qt::WindowShortcut.
11436
11437 If the same \a key sequence has been grabbed by several widgets,
11438 when the \a key sequence occurs a QEvent::Shortcut event is sent
11439 to all the widgets to which it applies in a non-deterministic
11440 order, but with the ``ambiguous'' flag set to true.
11441
11442 \warning You should not normally need to use this function;
11443 instead create \l{QAction}s with the shortcut key sequences you
11444 require (if you also want equivalent menu options and toolbar
11445 buttons), or create \l{QShortcut}s if you just need key sequences.
11446 Both QAction and QShortcut handle all the event filtering for you,
11447 and provide signals which are triggered when the user triggers the
11448 key sequence, so are much easier to use than this low-level
11449 function.
11450
11451 \sa releaseShortcut(), setShortcutEnabled()
11452 */
grabShortcut(const QKeySequence & key,Qt::ShortcutContext context)11453 int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11454 {
11455 Q_ASSERT(qApp);
11456 if (key.isEmpty())
11457 return 0;
11458 setAttribute(Qt::WA_GrabbedShortcut);
11459 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11460 }
11461
11462 /*!
11463 Removes the shortcut with the given \a id from Qt's shortcut
11464 system. The widget will no longer receive QEvent::Shortcut events
11465 for the shortcut's key sequence (unless it has other shortcuts
11466 with the same key sequence).
11467
11468 \warning You should not normally need to use this function since
11469 Qt's shortcut system removes shortcuts automatically when their
11470 parent widget is destroyed. It is best to use QAction or
11471 QShortcut to handle shortcuts, since they are easier to use than
11472 this low-level function. Note also that this is an expensive
11473 operation.
11474
11475 \sa grabShortcut(), setShortcutEnabled()
11476 */
releaseShortcut(int id)11477 void QWidget::releaseShortcut(int id)
11478 {
11479 Q_ASSERT(qApp);
11480 if (id)
11481 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11482 }
11483
11484 /*!
11485 If \a enable is true, the shortcut with the given \a id is
11486 enabled; otherwise the shortcut is disabled.
11487
11488 \warning You should not normally need to use this function since
11489 Qt's shortcut system enables/disables shortcuts automatically as
11490 widgets become hidden/visible and gain or lose focus. It is best
11491 to use QAction or QShortcut to handle shortcuts, since they are
11492 easier to use than this low-level function.
11493
11494 \sa grabShortcut(), releaseShortcut()
11495 */
setShortcutEnabled(int id,bool enable)11496 void QWidget::setShortcutEnabled(int id, bool enable)
11497 {
11498 Q_ASSERT(qApp);
11499 if (id)
11500 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11501 }
11502
11503 /*!
11504 \since 4.2
11505
11506 If \a enable is true, auto repeat of the shortcut with the
11507 given \a id is enabled; otherwise it is disabled.
11508
11509 \sa grabShortcut(), releaseShortcut()
11510 */
setShortcutAutoRepeat(int id,bool enable)11511 void QWidget::setShortcutAutoRepeat(int id, bool enable)
11512 {
11513 Q_ASSERT(qApp);
11514 if (id)
11515 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
11516 }
11517 #endif // QT_NO_SHORTCUT
11518
11519 /*!
11520 Updates the widget's micro focus.
11521 */
updateMicroFocus()11522 void QWidget::updateMicroFocus()
11523 {
11524 // updating everything since this is currently called for any kind of state change
11525 if (this == QGuiApplication::focusObject())
11526 QGuiApplication::inputMethod()->update(Qt::ImQueryAll);
11527 }
11528
11529 /*!
11530 Raises this widget to the top of the parent widget's stack.
11531
11532 After this call the widget will be visually in front of any
11533 overlapping sibling widgets.
11534
11535 \note When using activateWindow(), you can call this function to
11536 ensure that the window is stacked on top.
11537
11538 \sa lower(), stackUnder()
11539 */
11540
raise()11541 void QWidget::raise()
11542 {
11543 Q_D(QWidget);
11544 if (!isWindow()) {
11545 QWidget *p = parentWidget();
11546 const int parentChildCount = p->d_func()->children.size();
11547 if (parentChildCount < 2)
11548 return;
11549 const int from = p->d_func()->children.indexOf(this);
11550 Q_ASSERT(from >= 0);
11551 // Do nothing if the widget is already in correct stacking order _and_ created.
11552 if (from != parentChildCount -1)
11553 p->d_func()->children.move(from, parentChildCount - 1);
11554 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11555 create();
11556 else if (from == parentChildCount - 1)
11557 return;
11558
11559 QRegion region(rect());
11560 d->subtractOpaqueSiblings(region);
11561 d->invalidateBackingStore(region);
11562 }
11563 if (testAttribute(Qt::WA_WState_Created))
11564 d->raise_sys();
11565
11566 if (d->extra && d->extra->hasWindowContainer)
11567 QWindowContainer::parentWasRaised(this);
11568
11569 QEvent e(QEvent::ZOrderChange);
11570 QCoreApplication::sendEvent(this, &e);
11571 }
11572
raise_sys()11573 void QWidgetPrivate::raise_sys()
11574 {
11575 Q_Q(QWidget);
11576 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11577 q->windowHandle()->raise();
11578 } else if (renderToTexture) {
11579 if (QWidget *p = q->parentWidget()) {
11580 setDirtyOpaqueRegion();
11581 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11582 }
11583 }
11584 }
11585
11586 /*!
11587 Lowers the widget to the bottom of the parent widget's stack.
11588
11589 After this call the widget will be visually behind (and therefore
11590 obscured by) any overlapping sibling widgets.
11591
11592 \sa raise(), stackUnder()
11593 */
11594
lower()11595 void QWidget::lower()
11596 {
11597 Q_D(QWidget);
11598 if (!isWindow()) {
11599 QWidget *p = parentWidget();
11600 const int parentChildCount = p->d_func()->children.size();
11601 if (parentChildCount < 2)
11602 return;
11603 const int from = p->d_func()->children.indexOf(this);
11604 Q_ASSERT(from >= 0);
11605 // Do nothing if the widget is already in correct stacking order _and_ created.
11606 if (from != 0)
11607 p->d_func()->children.move(from, 0);
11608 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11609 create();
11610 else if (from == 0)
11611 return;
11612 }
11613 if (testAttribute(Qt::WA_WState_Created))
11614 d->lower_sys();
11615
11616 if (d->extra && d->extra->hasWindowContainer)
11617 QWindowContainer::parentWasLowered(this);
11618
11619 QEvent e(QEvent::ZOrderChange);
11620 QCoreApplication::sendEvent(this, &e);
11621 }
11622
lower_sys()11623 void QWidgetPrivate::lower_sys()
11624 {
11625 Q_Q(QWidget);
11626 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11627 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
11628 q->windowHandle()->lower();
11629 } else if (QWidget *p = q->parentWidget()) {
11630 setDirtyOpaqueRegion();
11631 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11632 }
11633 }
11634
11635 /*!
11636 Places the widget under \a w in the parent widget's stack.
11637
11638 To make this work, the widget itself and \a w must be siblings.
11639
11640 \sa raise(), lower()
11641 */
stackUnder(QWidget * w)11642 void QWidget::stackUnder(QWidget* w)
11643 {
11644 Q_D(QWidget);
11645 QWidget *p = parentWidget();
11646 if (!w || isWindow() || p != w->parentWidget() || this == w)
11647 return;
11648 if (p) {
11649 int from = p->d_func()->children.indexOf(this);
11650 int to = p->d_func()->children.indexOf(w);
11651 Q_ASSERT(from >= 0);
11652 Q_ASSERT(to >= 0);
11653 if (from < to)
11654 --to;
11655 // Do nothing if the widget is already in correct stacking order _and_ created.
11656 if (from != to)
11657 p->d_func()->children.move(from, to);
11658 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11659 create();
11660 else if (from == to)
11661 return;
11662 }
11663 if (testAttribute(Qt::WA_WState_Created))
11664 d->stackUnder_sys(w);
11665
11666 QEvent e(QEvent::ZOrderChange);
11667 QCoreApplication::sendEvent(this, &e);
11668 }
11669
stackUnder_sys(QWidget *)11670 void QWidgetPrivate::stackUnder_sys(QWidget*)
11671 {
11672 Q_Q(QWidget);
11673 if (QWidget *p = q->parentWidget()) {
11674 setDirtyOpaqueRegion();
11675 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11676 }
11677 }
11678
11679 /*!
11680 \fn bool QWidget::isTopLevel() const
11681 \obsolete
11682
11683 Use isWindow() instead.
11684 */
11685
11686 /*!
11687 \fn bool QWidget::isRightToLeft() const
11688 \internal
11689 */
11690
11691 /*!
11692 \fn bool QWidget::isLeftToRight() const
11693 \internal
11694 */
11695
11696 /*!
11697 \macro QWIDGETSIZE_MAX
11698 \relates QWidget
11699
11700 Defines the maximum size for a QWidget object.
11701
11702 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
11703 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
11704
11705 \sa QWidget::setMaximumSize()
11706 */
11707
11708 /*!
11709 \fn QWidget::setupUi(QWidget *widget)
11710
11711 Sets up the user interface for the specified \a widget.
11712
11713 \note This function is available with widgets that derive from user
11714 interface descriptions created using \l{uic}.
11715
11716 \sa {Using a Designer UI File in Your C++ Application}
11717 */
11718
frameStrut() const11719 QRect QWidgetPrivate::frameStrut() const
11720 {
11721 Q_Q(const QWidget);
11722 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(Qt::WA_DontShowOnScreen)) {
11723 // x2 = x1 + w - 1, so w/h = 1
11724 return QRect(0, 0, 1, 1);
11725 }
11726
11727 if (data.fstrut_dirty
11728 // ### Fix properly for 4.3
11729 && q->isVisible()
11730 && q->testAttribute(Qt::WA_WState_Created))
11731 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
11732
11733 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
11734 }
11735
updateFrameStrut()11736 void QWidgetPrivate::updateFrameStrut()
11737 {
11738 Q_Q(QWidget);
11739 if (q->data->fstrut_dirty) {
11740 if (QTLWExtra *te = maybeTopData()) {
11741 if (te->window && te->window->handle()) {
11742 const QMargins margins = te->window->frameMargins();
11743 if (!margins.isNull()) {
11744 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
11745 q->data->fstrut_dirty = false;
11746 }
11747 }
11748 }
11749 }
11750 }
11751
11752 #ifdef QT_KEYPAD_NAVIGATION
11753 /*!
11754 \internal
11755
11756 Changes the focus from the current focusWidget to a widget in
11757 the \a direction.
11758
11759 Returns \c true, if there was a widget in that direction
11760 */
navigateToDirection(Direction direction)11761 bool QWidgetPrivate::navigateToDirection(Direction direction)
11762 {
11763 QWidget *targetWidget = widgetInNavigationDirection(direction);
11764 if (targetWidget)
11765 targetWidget->setFocus();
11766 return (targetWidget != 0);
11767 }
11768
11769 /*!
11770 \internal
11771
11772 Searches for a widget that is positioned in the \a direction, starting
11773 from the current focusWidget.
11774
11775 Returns the pointer to a found widget or \nullptr, if there was no widget
11776 in that direction.
11777 */
widgetInNavigationDirection(Direction direction)11778 QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
11779 {
11780 const QWidget *sourceWidget = QApplication::focusWidget();
11781 if (!sourceWidget)
11782 return nullptr;
11783 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
11784 const int sourceX =
11785 (direction == DirectionNorth || direction == DirectionSouth) ?
11786 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
11787 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
11788 const int sourceY =
11789 (direction == DirectionEast || direction == DirectionWest) ?
11790 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
11791 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
11792 const QPoint sourcePoint(sourceX, sourceY);
11793 const QPoint sourceCenter = sourceRect.center();
11794 const QWidget *sourceWindow = sourceWidget->window();
11795
11796 QWidget *targetWidget = nullptr;
11797 int shortestDistance = INT_MAX;
11798
11799 const auto targetCandidates = QApplication::allWidgets();
11800 for (QWidget *targetCandidate : targetCandidates) {
11801
11802 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
11803
11804 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
11805 // but the owner of the proxy cannot.
11806 // Additionally, empty widgets should be ignored.
11807 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
11808 continue;
11809
11810 // Only navigate to a target widget that...
11811 if ( targetCandidate != sourceWidget
11812 // ...takes the focus,
11813 && targetCandidate->focusPolicy() & Qt::TabFocus
11814 // ...is above if DirectionNorth,
11815 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
11816 // ...is on the right if DirectionEast,
11817 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
11818 // ...is below if DirectionSouth,
11819 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
11820 // ...is on the left if DirectionWest,
11821 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
11822 // ...is enabled,
11823 && targetCandidate->isEnabled()
11824 // ...is visible,
11825 && targetCandidate->isVisible()
11826 // ...is in the same window,
11827 && targetCandidate->window() == sourceWindow) {
11828 const int targetCandidateDistance = pointToRect(sourcePoint, targetCandidateRect);
11829 if (targetCandidateDistance < shortestDistance) {
11830 shortestDistance = targetCandidateDistance;
11831 targetWidget = targetCandidate;
11832 }
11833 }
11834 }
11835 return targetWidget;
11836 }
11837
11838 /*!
11839 \internal
11840
11841 Tells us if it there is currently a reachable widget by keypad navigation in
11842 a certain \a orientation.
11843 If no navigation is possible, occurring key events in that \a orientation may
11844 be used to interact with the value in the focused widget, even though it
11845 currently has not the editFocus.
11846
11847 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
11848 */
canKeypadNavigate(Qt::Orientation orientation)11849 bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
11850 {
11851 return orientation == Qt::Horizontal?
11852 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
11853 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
11854 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
11855 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
11856 }
11857 /*!
11858 \internal
11859
11860 Checks, if the \a widget is inside a QTabWidget. If is is inside
11861 one, left/right key events will be used to switch between tabs in keypad
11862 navigation. If there is no QTabWidget, the horizontal key events can be used
11863 to
11864 interact with the value in the focused widget, even though it currently has
11865 not the editFocus.
11866
11867 \sa QWidget::hasEditFocus()
11868 */
inTabWidget(QWidget * widget)11869 bool QWidgetPrivate::inTabWidget(QWidget *widget)
11870 {
11871 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
11872 if (qobject_cast<const QTabWidget*>(tabWidget))
11873 return true;
11874 return false;
11875 }
11876 #endif
11877
11878 /*!
11879 \since 5.0
11880 \internal
11881
11882 Sets the backing store to be the \a store specified.
11883 The QWidget will take ownership of the \a store.
11884 */
setBackingStore(QBackingStore * store)11885 void QWidget::setBackingStore(QBackingStore *store)
11886 {
11887 // ### createWinId() ??
11888
11889 if (!isTopLevel())
11890 return;
11891
11892 Q_D(QWidget);
11893
11894 QTLWExtra *topData = d->topData();
11895 if (topData->backingStore == store)
11896 return;
11897
11898 QBackingStore *oldStore = topData->backingStore;
11899 deleteBackingStore(d);
11900 topData->backingStore = store;
11901
11902 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11903 if (!repaintManager)
11904 return;
11905
11906 if (isTopLevel()) {
11907 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
11908 delete repaintManager->backingStore();
11909 repaintManager->setBackingStore(store);
11910 }
11911 }
11912
11913 /*!
11914 \since 5.0
11915
11916 Returns the QBackingStore this widget will be drawn into.
11917 */
backingStore() const11918 QBackingStore *QWidget::backingStore() const
11919 {
11920 Q_D(const QWidget);
11921 QTLWExtra *extra = d->maybeTopData();
11922 if (extra && extra->backingStore)
11923 return extra->backingStore;
11924
11925 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11926 return repaintManager ? repaintManager->backingStore() : nullptr;
11927 }
11928
getLayoutItemMargins(int * left,int * top,int * right,int * bottom) const11929 void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
11930 {
11931 if (left)
11932 *left = (int)leftLayoutItemMargin;
11933 if (top)
11934 *top = (int)topLayoutItemMargin;
11935 if (right)
11936 *right = (int)rightLayoutItemMargin;
11937 if (bottom)
11938 *bottom = (int)bottomLayoutItemMargin;
11939 }
11940
setLayoutItemMargins(int left,int top,int right,int bottom)11941 void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
11942 {
11943 if (leftLayoutItemMargin == left
11944 && topLayoutItemMargin == top
11945 && rightLayoutItemMargin == right
11946 && bottomLayoutItemMargin == bottom)
11947 return;
11948
11949 Q_Q(QWidget);
11950 leftLayoutItemMargin = (signed char)left;
11951 topLayoutItemMargin = (signed char)top;
11952 rightLayoutItemMargin = (signed char)right;
11953 bottomLayoutItemMargin = (signed char)bottom;
11954 q->updateGeometry();
11955 }
11956
setLayoutItemMargins(QStyle::SubElement element,const QStyleOption * opt)11957 void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
11958 {
11959 Q_Q(QWidget);
11960 QStyleOption myOpt;
11961 if (!opt) {
11962 myOpt.initFrom(q);
11963 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
11964 opt = &myOpt;
11965 }
11966
11967 QRect liRect = q->style()->subElementRect(element, opt, q);
11968 if (liRect.isValid()) {
11969 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
11970 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
11971 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
11972 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
11973 } else {
11974 leftLayoutItemMargin = 0;
11975 topLayoutItemMargin = 0;
11976 rightLayoutItemMargin = 0;
11977 bottomLayoutItemMargin = 0;
11978 }
11979 }
11980 // resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
adjustQuitOnCloseAttribute()11981 void QWidgetPrivate::adjustQuitOnCloseAttribute()
11982 {
11983 Q_Q(QWidget);
11984
11985 if (!q->parentWidget()) {
11986 Qt::WindowType type = q->windowType();
11987 if (type == Qt::Widget || type == Qt::SubWindow)
11988 type = Qt::Window;
11989 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
11990 q->setAttribute(Qt::WA_QuitOnClose, false);
11991 }
11992 }
11993
shareContext() const11994 QOpenGLContext *QWidgetPrivate::shareContext() const
11995 {
11996 #ifdef QT_NO_OPENGL
11997 return 0;
11998 #else
11999 if (!extra || !extra->topextra || !extra->topextra->window)
12000 return nullptr;
12001
12002 if (!extra->topextra->shareContext) {
12003 auto ctx = qt_make_unique<QOpenGLContext>();
12004 ctx->setShareContext(qt_gl_global_share_context());
12005 ctx->setFormat(extra->topextra->window->format());
12006 ctx->setScreen(extra->topextra->window->screen());
12007 ctx->create();
12008 extra->topextra->shareContext = std::move(ctx);
12009 }
12010 return extra->topextra->shareContext.get();
12011 #endif // QT_NO_OPENGL
12012 }
12013
12014 #ifndef QT_NO_OPENGL
sendComposeStatus(QWidget * w,bool end)12015 void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12016 {
12017 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12018 if (!wd->textureChildSeen)
12019 return;
12020 if (end)
12021 wd->endCompose();
12022 else
12023 wd->beginCompose();
12024 for (int i = 0; i < wd->children.size(); ++i) {
12025 w = qobject_cast<QWidget *>(wd->children.at(i));
12026 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12027 sendComposeStatus(w, end);
12028 }
12029 }
12030 #endif // QT_NO_OPENGL
12031
qt_qwidget_data(QWidget * widget)12032 Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12033 {
12034 return widget->data;
12035 }
12036
qt_widget_private(QWidget * widget)12037 Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12038 {
12039 return widget->d_func();
12040 }
12041
12042
12043 #if QT_CONFIG(graphicsview)
12044 /*!
12045 \since 4.5
12046
12047 Returns the proxy widget for the corresponding embedded widget in a graphics
12048 view; otherwise returns \nullptr.
12049
12050 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12051 QGraphicsScene::addWidget()
12052 */
graphicsProxyWidget() const12053 QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12054 {
12055 Q_D(const QWidget);
12056 if (d->extra) {
12057 return d->extra->proxyWidget;
12058 }
12059 return nullptr;
12060 }
12061 #endif
12062
12063 #ifndef QT_NO_GESTURES
12064 /*!
12065 Subscribes the widget to a given \a gesture with specific \a flags.
12066
12067 \sa ungrabGesture(), QGestureEvent
12068 \since 4.6
12069 */
grabGesture(Qt::GestureType gesture,Qt::GestureFlags flags)12070 void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12071 {
12072 Q_D(QWidget);
12073 d->gestureContext.insert(gesture, flags);
12074 (void)QGestureManager::instance(); // create a gesture manager
12075 }
12076
12077 /*!
12078 Unsubscribes the widget from a given \a gesture type
12079
12080 \sa grabGesture(), QGestureEvent
12081 \since 4.6
12082 */
ungrabGesture(Qt::GestureType gesture)12083 void QWidget::ungrabGesture(Qt::GestureType gesture)
12084 {
12085 // if you modify this function, check the inlined version in ~QWidget, too
12086 Q_D(QWidget);
12087 if (d->gestureContext.remove(gesture)) {
12088 if (QGestureManager *manager = QGestureManager::instance())
12089 manager->cleanupCachedGestures(this, gesture);
12090 }
12091 }
12092 #endif // QT_NO_GESTURES
12093
12094 /*!
12095 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12096
12097 Frees up window system resources. Destroys the widget window if \a
12098 destroyWindow is true.
12099
12100 destroy() calls itself recursively for all the child widgets,
12101 passing \a destroySubWindows for the \a destroyWindow parameter.
12102 To have more control over destruction of subwidgets, destroy
12103 subwidgets selectively first.
12104
12105 This function is usually called from the QWidget destructor.
12106 */
destroy(bool destroyWindow,bool destroySubWindows)12107 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12108 {
12109 Q_D(QWidget);
12110
12111 d->aboutToDestroy();
12112 if (!isWindow() && parentWidget())
12113 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12114 d->deactivateWidgetCleanup();
12115
12116 if ((windowType() == Qt::Popup) && qApp)
12117 qApp->d_func()->closePopup(this);
12118
12119 if (this == QApplicationPrivate::active_window)
12120 QApplication::setActiveWindow(nullptr);
12121 if (QWidget::mouseGrabber() == this)
12122 releaseMouse();
12123 if (QWidget::keyboardGrabber() == this)
12124 releaseKeyboard();
12125
12126 setAttribute(Qt::WA_WState_Created, false);
12127
12128 if (windowType() != Qt::Desktop) {
12129 if (destroySubWindows) {
12130 QObjectList childList(children());
12131 for (int i = 0; i < childList.size(); i++) {
12132 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12133 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12134 if (widget->windowHandle()) {
12135 widget->destroy();
12136 }
12137 }
12138 }
12139 }
12140 if (destroyWindow) {
12141 d->deleteTLSysExtra();
12142 } else {
12143 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12144 d->hide_sys();
12145 }
12146 }
12147
12148 d->setWinId(0);
12149 }
12150 }
12151
12152 /*!
12153 \fn QPaintEngine *QWidget::paintEngine() const
12154
12155 Returns the widget's paint engine.
12156
12157 Note that this function should not be called explicitly by the
12158 user, since it's meant for reimplementation purposes only. The
12159 function is called by Qt internally, and the default
12160 implementation may not always return a valid pointer.
12161 */
paintEngine() const12162 QPaintEngine *QWidget::paintEngine() const
12163 {
12164 qWarning("QWidget::paintEngine: Should no longer be called");
12165
12166 #ifdef Q_OS_WIN
12167 // We set this bit which is checked in setAttribute for
12168 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12169 //
12170 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12171 // Windows which would mean suddenly their widgets stop working.
12172 //
12173 // 2. Users set paint on screen and subclass paintEngine() to
12174 // return 0, in which case we have a "hole" in the backingstore
12175 // allowing use of GDI or DirectX directly.
12176 //
12177 // 1 is WRONG, but to minimize silent failures, we have set this
12178 // bit to ignore the setAttribute call. 2. needs to be
12179 // supported because its our only means of embedding native
12180 // graphics stuff.
12181 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12182 #endif
12183
12184 return nullptr; //##### @@@
12185 }
12186
12187 // Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
canMapPosition(QWindow * window)12188 static inline bool canMapPosition(QWindow *window)
12189 {
12190 return window->handle() && !qt_window_private(window)->resizeEventPending;
12191 }
12192
12193 #if QT_CONFIG(graphicsview)
graphicsProxyWidget(const QWidget * w)12194 static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12195 {
12196 QGraphicsProxyWidget *result = nullptr;
12197 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12198 if (d->extra)
12199 result = d->extra->proxyWidget;
12200 return result;
12201 }
12202 #endif // QT_CONFIG(graphicsview)
12203
12204 struct MapToGlobalTransformResult {
12205 QTransform transform;
12206 QWindow *window;
12207 };
12208
mapToGlobalTransform(const QWidget * w)12209 static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12210 {
12211 MapToGlobalTransformResult result;
12212 result.window = nullptr;
12213 for ( ; w ; w = w->parentWidget()) {
12214 #if QT_CONFIG(graphicsview)
12215 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12216 if (const QGraphicsScene *scene = qgpw->scene()) {
12217 const QList <QGraphicsView *> views = scene->views();
12218 if (!views.isEmpty()) {
12219 result.transform *= qgpw->sceneTransform();
12220 result.transform *= views.first()->viewportTransform();
12221 w = views.first()->viewport();
12222 }
12223 }
12224 }
12225 #endif // QT_CONFIG(graphicsview)
12226 QWindow *window = w->windowHandle();
12227 if (window && canMapPosition(window)) {
12228 result.window = window;
12229 break;
12230 }
12231
12232 const QPoint topLeft = w->geometry().topLeft();
12233 result.transform.translate(topLeft.x(), topLeft.y());
12234 if (w->isWindow())
12235 break;
12236 }
12237 return result;
12238 }
12239
12240 /*!
12241 \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
12242
12243 Translates the widget coordinate \a pos to global screen
12244 coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
12245 the global coordinates of the top-left pixel of the widget.
12246
12247 \sa mapFromGlobal(), mapTo(), mapToParent()
12248 */
mapToGlobal(const QPoint & pos) const12249 QPoint QWidget::mapToGlobal(const QPoint &pos) const
12250 {
12251 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12252 const QPoint g = t.transform.map(pos);
12253 return t.window ? t.window->mapToGlobal(g) : g;
12254 }
12255
12256 /*!
12257 \fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12258
12259 Translates the global screen coordinate \a pos to widget
12260 coordinates.
12261
12262 \sa mapToGlobal(), mapFrom(), mapFromParent()
12263 */
mapFromGlobal(const QPoint & pos) const12264 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12265 {
12266 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12267 const QPoint windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12268 return t.transform.inverted().map(windowLocal);
12269 }
12270
12271 QWidget *qt_pressGrab = nullptr;
12272 QWidget *qt_mouseGrb = nullptr;
12273 static bool mouseGrabWithCursor = false;
12274 static QWidget *keyboardGrb = nullptr;
12275
grabberWindow(const QWidget * w)12276 static inline QWindow *grabberWindow(const QWidget *w)
12277 {
12278 QWindow *window = w->windowHandle();
12279 if (!window)
12280 if (const QWidget *nativeParent = w->nativeParentWidget())
12281 window = nativeParent->windowHandle();
12282 return window;
12283 }
12284
12285 #ifndef QT_NO_CURSOR
grabMouseForWidget(QWidget * widget,const QCursor * cursor=nullptr)12286 static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12287 #else
12288 static void grabMouseForWidget(QWidget *widget)
12289 #endif
12290 {
12291 if (qt_mouseGrb)
12292 qt_mouseGrb->releaseMouse();
12293
12294 mouseGrabWithCursor = false;
12295 if (QWindow *window = grabberWindow(widget)) {
12296 #ifndef QT_NO_CURSOR
12297 if (cursor) {
12298 mouseGrabWithCursor = true;
12299 QGuiApplication::setOverrideCursor(*cursor);
12300 }
12301 #endif // !QT_NO_CURSOR
12302 window->setMouseGrabEnabled(true);
12303 }
12304
12305 qt_mouseGrb = widget;
12306 qt_pressGrab = nullptr;
12307 }
12308
releaseMouseGrabOfWidget(QWidget * widget)12309 static void releaseMouseGrabOfWidget(QWidget *widget)
12310 {
12311 if (qt_mouseGrb == widget) {
12312 if (QWindow *window = grabberWindow(widget)) {
12313 #ifndef QT_NO_CURSOR
12314 if (mouseGrabWithCursor) {
12315 QGuiApplication::restoreOverrideCursor();
12316 mouseGrabWithCursor = false;
12317 }
12318 #endif // !QT_NO_CURSOR
12319 window->setMouseGrabEnabled(false);
12320 }
12321 }
12322 qt_mouseGrb = nullptr;
12323 }
12324
12325 /*!
12326 \fn void QWidget::grabMouse()
12327
12328 Grabs the mouse input.
12329
12330 This widget receives all mouse events until releaseMouse() is
12331 called; other widgets get no mouse events at all. Keyboard
12332 events are not affected. Use grabKeyboard() if you want to grab
12333 that.
12334
12335 \warning Bugs in mouse-grabbing applications very often lock the
12336 terminal. Use this function with extreme caution, and consider
12337 using the \c -nograb command line option while debugging.
12338
12339 It is almost never necessary to grab the mouse when using Qt, as
12340 Qt grabs and releases it sensibly. In particular, Qt grabs the
12341 mouse when a mouse button is pressed and keeps it until the last
12342 button is released.
12343
12344 \note Only visible widgets can grab mouse input. If isVisible()
12345 returns \c false for a widget, that widget cannot call grabMouse().
12346
12347 \note On Windows, grabMouse() only works when the mouse is inside a window
12348 owned by the process.
12349 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12350
12351 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12352 */
grabMouse()12353 void QWidget::grabMouse()
12354 {
12355 grabMouseForWidget(this);
12356 }
12357
12358 /*!
12359 \fn void QWidget::grabMouse(const QCursor &cursor)
12360 \overload grabMouse()
12361
12362 Grabs the mouse input and changes the cursor shape.
12363
12364 The cursor will assume shape \a cursor (for as long as the mouse
12365 focus is grabbed) and this widget will be the only one to receive
12366 mouse events until releaseMouse() is called().
12367
12368 \warning Grabbing the mouse might lock the terminal.
12369
12370 \note See the note in QWidget::grabMouse().
12371
12372 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12373 */
12374 #ifndef QT_NO_CURSOR
grabMouse(const QCursor & cursor)12375 void QWidget::grabMouse(const QCursor &cursor)
12376 {
12377 grabMouseForWidget(this, &cursor);
12378 }
12379 #endif
12380
stealMouseGrab(bool grab)12381 bool QWidgetPrivate::stealMouseGrab(bool grab)
12382 {
12383 // This is like a combination of grab/releaseMouse() but with error checking
12384 // and it has no effect on the result of mouseGrabber().
12385 Q_Q(QWidget);
12386 QWindow *window = grabberWindow(q);
12387 return window ? window->setMouseGrabEnabled(grab) : false;
12388 }
12389
12390 /*!
12391 \fn void QWidget::releaseMouse()
12392
12393 Releases the mouse grab.
12394
12395 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12396 */
releaseMouse()12397 void QWidget::releaseMouse()
12398 {
12399 releaseMouseGrabOfWidget(this);
12400 }
12401
12402 /*!
12403 \fn void QWidget::grabKeyboard()
12404
12405 Grabs the keyboard input.
12406
12407 This widget receives all keyboard events until releaseKeyboard()
12408 is called; other widgets get no keyboard events at all. Mouse
12409 events are not affected. Use grabMouse() if you want to grab that.
12410
12411 The focus widget is not affected, except that it doesn't receive
12412 any keyboard events. setFocus() moves the focus as usual, but the
12413 new focus widget receives keyboard events only after
12414 releaseKeyboard() is called.
12415
12416 If a different widget is currently grabbing keyboard input, that
12417 widget's grab is released first.
12418
12419 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12420 */
grabKeyboard()12421 void QWidget::grabKeyboard()
12422 {
12423 if (keyboardGrb)
12424 keyboardGrb->releaseKeyboard();
12425 if (QWindow *window = grabberWindow(this))
12426 window->setKeyboardGrabEnabled(true);
12427 keyboardGrb = this;
12428 }
12429
stealKeyboardGrab(bool grab)12430 bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12431 {
12432 // This is like a combination of grab/releaseKeyboard() but with error
12433 // checking and it has no effect on the result of keyboardGrabber().
12434 Q_Q(QWidget);
12435 QWindow *window = grabberWindow(q);
12436 return window ? window->setKeyboardGrabEnabled(grab) : false;
12437 }
12438
12439 /*!
12440 \fn void QWidget::releaseKeyboard()
12441
12442 Releases the keyboard grab.
12443
12444 \sa grabKeyboard(), grabMouse(), releaseMouse()
12445 */
releaseKeyboard()12446 void QWidget::releaseKeyboard()
12447 {
12448 if (keyboardGrb == this) {
12449 if (QWindow *window = grabberWindow(this))
12450 window->setKeyboardGrabEnabled(false);
12451 keyboardGrb = nullptr;
12452 }
12453 }
12454
12455 /*!
12456 \fn QWidget *QWidget::mouseGrabber()
12457
12458 Returns the widget that is currently grabbing the mouse input.
12459
12460 If no widget in this application is currently grabbing the mouse,
12461 \nullptr is returned.
12462
12463 \sa grabMouse(), keyboardGrabber()
12464 */
mouseGrabber()12465 QWidget *QWidget::mouseGrabber()
12466 {
12467 if (qt_mouseGrb)
12468 return qt_mouseGrb;
12469 return qt_pressGrab;
12470 }
12471
12472 /*!
12473 \fn QWidget *QWidget::keyboardGrabber()
12474
12475 Returns the widget that is currently grabbing the keyboard input.
12476
12477 If no widget in this application is currently grabbing the
12478 keyboard, \nullptr is returned.
12479
12480 \sa grabMouse(), mouseGrabber()
12481 */
keyboardGrabber()12482 QWidget *QWidget::keyboardGrabber()
12483 {
12484 return keyboardGrb;
12485 }
12486
12487 /*!
12488 \fn void QWidget::activateWindow()
12489
12490 Sets the top-level widget containing this widget to be the active
12491 window.
12492
12493 An active window is a visible top-level window that has the
12494 keyboard input focus.
12495
12496 This function performs the same operation as clicking the mouse on
12497 the title bar of a top-level window. On X11, the result depends on
12498 the Window Manager. If you want to ensure that the window is
12499 stacked on top as well you should also call raise(). Note that the
12500 window must be visible, otherwise activateWindow() has no effect.
12501
12502 On Windows, if you are calling this when the application is not
12503 currently the active one then it will not make it the active
12504 window. It will change the color of the taskbar entry to indicate
12505 that the window has changed in some way. This is because Microsoft
12506 does not allow an application to interrupt what the user is currently
12507 doing in another application.
12508
12509 \sa isActiveWindow(), window(), show(), QWindowsWindowFunctions::setWindowActivationBehavior()
12510 */
activateWindow()12511 void QWidget::activateWindow()
12512 {
12513 QWindow *const wnd = window()->windowHandle();
12514
12515 if (wnd)
12516 wnd->requestActivate();
12517 }
12518
12519 /*!
12520
12521 Internal implementation of the virtual QPaintDevice::metric()
12522 function.
12523
12524 \a m is the metric to get.
12525 */
metric(PaintDeviceMetric m) const12526 int QWidget::metric(PaintDeviceMetric m) const
12527 {
12528 QWindow *topLevelWindow = nullptr;
12529 QScreen *screen = nullptr;
12530 if (QWidget *topLevel = window()) {
12531 topLevelWindow = topLevel->windowHandle();
12532 if (topLevelWindow)
12533 screen = topLevelWindow->screen();
12534 }
12535 if (!screen && QGuiApplication::primaryScreen())
12536 screen = QGuiApplication::primaryScreen();
12537
12538 if (!screen) {
12539 if (m == PdmDpiX || m == PdmDpiY)
12540 return 72;
12541 return QPaintDevice::metric(m);
12542 }
12543 int val;
12544 if (m == PdmWidth) {
12545 val = data->crect.width();
12546 } else if (m == PdmWidthMM) {
12547 val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12548 } else if (m == PdmHeight) {
12549 val = data->crect.height();
12550 } else if (m == PdmHeightMM) {
12551 val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12552 } else if (m == PdmDepth) {
12553 return screen->depth();
12554 } else if (m == PdmDpiX) {
12555 for (const QWidget *p = this; p; p = p->parentWidget()) {
12556 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12557 return p->d_func()->extra->customDpiX;
12558 }
12559 return qRound(screen->logicalDotsPerInchX());
12560 } else if (m == PdmDpiY) {
12561 for (const QWidget *p = this; p; p = p->parentWidget()) {
12562 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12563 return p->d_func()->extra->customDpiY;
12564 }
12565 return qRound(screen->logicalDotsPerInchY());
12566 } else if (m == PdmPhysicalDpiX) {
12567 return qRound(screen->physicalDotsPerInchX());
12568 } else if (m == PdmPhysicalDpiY) {
12569 return qRound(screen->physicalDotsPerInchY());
12570 } else if (m == PdmDevicePixelRatio) {
12571 return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
12572 } else if (m == PdmDevicePixelRatioScaled) {
12573 return (QPaintDevice::devicePixelRatioFScale() *
12574 (topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio()));
12575 } else {
12576 val = QPaintDevice::metric(m);// XXX
12577 }
12578 return val;
12579 }
12580
12581 /*!
12582 Initializes the \a painter pen, background and font to the same as
12583 the given widget's. This function is called automatically when the
12584 painter is opened on a QWidget.
12585 */
initPainter(QPainter * painter) const12586 void QWidget::initPainter(QPainter *painter) const
12587 {
12588 const QPalette &pal = palette();
12589 painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1);
12590 painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
12591 QFont f(font(), const_cast<QWidget *>(this));
12592 painter->d_func()->state->deviceFont = f;
12593 painter->d_func()->state->font = f;
12594 }
12595
12596 /*!
12597 \internal
12598
12599 Do PaintDevice rendering with the specified \a offset.
12600 */
redirected(QPoint * offset) const12601 QPaintDevice *QWidget::redirected(QPoint *offset) const
12602 {
12603 return d_func()->redirected(offset);
12604 }
12605
12606 /*!
12607 \internal
12608
12609 A painter that is shared among other instances of QPainter.
12610 */
sharedPainter() const12611 QPainter *QWidget::sharedPainter() const
12612 {
12613 // Someone sent a paint event directly to the widget
12614 if (!d_func()->redirectDev)
12615 return nullptr;
12616
12617 QPainter *sp = d_func()->sharedPainter();
12618 if (!sp || !sp->isActive())
12619 return nullptr;
12620
12621 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12622 return nullptr;
12623
12624 return sp;
12625 }
12626
12627 /*!
12628 \fn void QWidget::setMask(const QRegion ®ion)
12629 \overload
12630
12631 Causes only the parts of the widget which overlap \a region to be
12632 visible. If the region includes pixels outside the rect() of the
12633 widget, window system controls in that area may or may not be
12634 visible, depending on the platform.
12635
12636 Note that this effect can be slow if the region is particularly
12637 complex.
12638
12639 \sa windowOpacity
12640 */
setMask(const QRegion & newMask)12641 void QWidget::setMask(const QRegion &newMask)
12642 {
12643 Q_D(QWidget);
12644
12645 d->createExtra();
12646 if (newMask == d->extra->mask)
12647 return;
12648
12649 #ifndef QT_NO_BACKINGSTORE
12650 const QRegion oldMask(d->extra->mask);
12651 #endif
12652
12653 d->extra->mask = newMask;
12654 d->extra->hasMask = !newMask.isEmpty();
12655
12656 if (!testAttribute(Qt::WA_WState_Created))
12657 return;
12658
12659 d->setMask_sys(newMask);
12660
12661 #ifndef QT_NO_BACKINGSTORE
12662 if (!isVisible())
12663 return;
12664
12665 if (!d->extra->hasMask) {
12666 // Mask was cleared; update newly exposed area.
12667 QRegion expose(rect());
12668 expose -= oldMask;
12669 if (!expose.isEmpty()) {
12670 d->setDirtyOpaqueRegion();
12671 update(expose);
12672 }
12673 return;
12674 }
12675
12676 if (!isWindow()) {
12677 // Update newly exposed area on the parent widget.
12678 QRegion parentExpose(rect());
12679 parentExpose -= newMask;
12680 if (!parentExpose.isEmpty()) {
12681 d->setDirtyOpaqueRegion();
12682 parentExpose.translate(data->crect.topLeft());
12683 parentWidget()->update(parentExpose);
12684 }
12685
12686 // Update newly exposed area on this widget
12687 if (!oldMask.isEmpty())
12688 update(newMask - oldMask);
12689 }
12690 #endif
12691 }
12692
setMask_sys(const QRegion & region)12693 void QWidgetPrivate::setMask_sys(const QRegion ®ion)
12694 {
12695 Q_Q(QWidget);
12696 if (QWindow *window = q->windowHandle())
12697 window->setMask(region);
12698 }
12699
12700 /*!
12701 \fn void QWidget::setMask(const QBitmap &bitmap)
12702
12703 Causes only the pixels of the widget for which \a bitmap has a
12704 corresponding 1 bit to be visible. If the region includes pixels
12705 outside the rect() of the widget, window system controls in that
12706 area may or may not be visible, depending on the platform.
12707
12708 Note that this effect can be slow if the region is particularly
12709 complex.
12710
12711 The following code shows how an image with an alpha channel can be
12712 used to generate a mask for a widget:
12713
12714 \snippet widget-mask/main.cpp 0
12715
12716 The label shown by this code is masked using the image it contains,
12717 giving the appearance that an irregularly-shaped image is being drawn
12718 directly onto the screen.
12719
12720 Masked widgets receive mouse events only on their visible
12721 portions.
12722
12723 \sa clearMask(), windowOpacity(), {Shaped Clock Example}
12724 */
setMask(const QBitmap & bitmap)12725 void QWidget::setMask(const QBitmap &bitmap)
12726 {
12727 setMask(QRegion(bitmap));
12728 }
12729
12730 /*!
12731 \fn void QWidget::clearMask()
12732
12733 Removes any mask set by setMask().
12734
12735 \sa setMask()
12736 */
clearMask()12737 void QWidget::clearMask()
12738 {
12739 Q_D(QWidget);
12740 if (!d->extra || !d->extra->hasMask)
12741 return;
12742 setMask(QRegion());
12743 }
12744
setWidgetParentHelper(QObject * widgetAsObject,QObject * newParent)12745 void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
12746 {
12747 Q_ASSERT(widgetAsObject->isWidgetType());
12748 Q_ASSERT(!newParent || newParent->isWidgetType());
12749 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
12750 widget->setParent(static_cast<QWidget*>(newParent));
12751 }
12752
setNetWmWindowTypes(bool skipIfMissing)12753 void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
12754 {
12755 Q_Q(QWidget);
12756
12757 if (!q->windowHandle())
12758 return;
12759
12760 int wmWindowType = 0;
12761 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
12762 wmWindowType |= QXcbWindowFunctions::Desktop;
12763 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
12764 wmWindowType |= QXcbWindowFunctions::Dock;
12765 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
12766 wmWindowType |= QXcbWindowFunctions::Toolbar;
12767 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
12768 wmWindowType |= QXcbWindowFunctions::Menu;
12769 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
12770 wmWindowType |= QXcbWindowFunctions::Utility;
12771 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
12772 wmWindowType |= QXcbWindowFunctions::Splash;
12773 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
12774 wmWindowType |= QXcbWindowFunctions::Dialog;
12775 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
12776 wmWindowType |= QXcbWindowFunctions::DropDownMenu;
12777 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
12778 wmWindowType |= QXcbWindowFunctions::PopupMenu;
12779 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
12780 wmWindowType |= QXcbWindowFunctions::Tooltip;
12781 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
12782 wmWindowType |= QXcbWindowFunctions::Notification;
12783 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
12784 wmWindowType |= QXcbWindowFunctions::Combo;
12785 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
12786 wmWindowType |= QXcbWindowFunctions::Dnd;
12787
12788 if (wmWindowType == 0 && skipIfMissing)
12789 return;
12790
12791 QXcbWindowFunctions::setWmWindowType(q->windowHandle(), static_cast<QXcbWindowFunctions::WmWindowType>(wmWindowType));
12792 }
12793
12794 #ifndef QT_NO_DEBUG_STREAM
12795
formatWidgetAttributes(QDebug debug,const QWidget * widget)12796 static inline void formatWidgetAttributes(QDebug debug, const QWidget *widget)
12797 {
12798 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
12799 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
12800 debug << ", attributes=[";
12801 int count = 0;
12802 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
12803 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
12804 if (count++)
12805 debug << ',';
12806 debug << me.valueToKey(a);
12807 }
12808 }
12809 debug << ']';
12810 }
12811
operator <<(QDebug debug,const QWidget * widget)12812 QDebug operator<<(QDebug debug, const QWidget *widget)
12813 {
12814 const QDebugStateSaver saver(debug);
12815 debug.nospace();
12816 if (widget) {
12817 debug << widget->metaObject()->className() << '(' << (const void *)widget;
12818 if (!widget->objectName().isEmpty())
12819 debug << ", name=" << widget->objectName();
12820 if (debug.verbosity() > 2) {
12821 const QRect geometry = widget->geometry();
12822 const QRect frameGeometry = widget->frameGeometry();
12823 if (widget->isVisible())
12824 debug << ", visible";
12825 if (!widget->isEnabled())
12826 debug << ", disabled";
12827 debug << ", states=" << widget->windowState()
12828 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
12829 formatWidgetAttributes(debug, widget);
12830 if (widget->isWindow())
12831 debug << ", window";
12832 debug << ", " << geometry.width() << 'x' << geometry.height()
12833 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
12834 if (frameGeometry != geometry) {
12835 const QMargins margins(geometry.x() - frameGeometry.x(),
12836 geometry.y() - frameGeometry.y(),
12837 frameGeometry.right() - geometry.right(),
12838 frameGeometry.bottom() - geometry.bottom());
12839 debug << ", margins=" << margins;
12840 }
12841 debug << ", devicePixelRatio=" << widget->devicePixelRatioF();
12842 if (const WId wid = widget->internalWinId())
12843 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
12844 }
12845 debug << ')';
12846 } else {
12847 debug << "QWidget(0x0)";
12848 }
12849 return debug;
12850 }
12851 #endif // !QT_NO_DEBUG_STREAM
12852
12853 QT_END_NAMESPACE
12854
12855 #include "moc_qwidget.cpp"
12856
12857