1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QWIDGET_P_H
41 #define QWIDGET_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists for the convenience
48 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
49 // file may change from version to version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtWidgets/private/qtwidgetsglobal_p.h>
55 #include "QtWidgets/qwidget.h"
56 #include "private/qobject_p.h"
57 #include "QtCore/qrect.h"
58 #include "QtCore/qlocale.h"
59 #include "QtCore/qset.h"
60 #include "QtGui/qregion.h"
61 #include "QtGui/qinputmethod.h"
62 #include "QtGui/qopengl.h"
63 #include "QtGui/qsurfaceformat.h"
64 #include "QtWidgets/qsizepolicy.h"
65 #include "QtWidgets/qstyle.h"
66 #include "QtWidgets/qapplication.h"
67 #if QT_CONFIG(graphicseffect)
68 #include <private/qgraphicseffect_p.h>
69 #endif
70 #if QT_CONFIG(graphicsview)
71 #include "QtWidgets/qgraphicsproxywidget.h"
72 #include "QtWidgets/qgraphicsscene.h"
73 #include "QtWidgets/qgraphicsview.h"
74 #endif
75 #include <private/qgesture_p.h>
76 #include <qpa/qplatformbackingstore.h>
77 
78 #include <vector>
79 #include <memory>
80 
81 QT_BEGIN_NAMESPACE
82 
83 Q_DECLARE_LOGGING_CATEGORY(lcWidgetPainting);
84 
85 // Extra QWidget data
86 //  - to minimize memory usage for members that are seldom used.
87 //  - top-level widgets have extra extra data to reduce cost further
88 class QWidgetWindow;
89 class QPaintEngine;
90 class QPixmap;
91 class QWidgetRepaintManager;
92 class QGraphicsProxyWidget;
93 class QWidgetItemV2;
94 class QOpenGLContext;
95 
96 class QStyle;
97 
98 class QUnifiedToolbarSurface;
99 
100 // implemented in qshortcut.cpp
101 bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context);
102 
103 class QUpdateLaterEvent : public QEvent
104 {
105 public:
QUpdateLaterEvent(const QRegion & paintRegion)106     explicit QUpdateLaterEvent(const QRegion& paintRegion)
107         : QEvent(UpdateLater), m_region(paintRegion)
108     {
109     }
110 
~QUpdateLaterEvent()111     ~QUpdateLaterEvent()
112     {
113     }
114 
region()115     inline const QRegion &region() const { return m_region; }
116 
117 protected:
118     QRegion m_region;
119 };
120 
121 struct QTLWExtra {
122     // *************************** Cross-platform variables *****************************
123 
124     // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
125     std::unique_ptr<QIcon> icon; // widget icon
126     std::unique_ptr<QWidgetRepaintManager> repaintManager;
127     QBackingStore *backingStore;
128     QPainter *sharedPainter;
129     QWidgetWindow *window;
130 #ifndef QT_NO_OPENGL
131     mutable std::unique_ptr<QOpenGLContext> shareContext;
132 #endif
133 
134     // Implicit pointers (shared_null).
135     QString caption; // widget caption
136     QString iconText; // widget icon text
137     QString role; // widget role
138     QString filePath; // widget file path
139 
140     // Other variables.
141     short incw, inch; // size increments
142     short basew, baseh; // base sizes
143      // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
144     QRect frameStrut;
145     QRect normalGeometry; // used by showMin/maximized/FullScreen
146     Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
147     // ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime
148     int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
149 
150 #ifndef QT_NO_OPENGL
151     std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures;
152 #endif
153 
154     // *************************** Cross-platform bit fields ****************************
155     uint opacity : 8;
156     uint posIncludesFrame : 1;
157     uint sizeAdjusted : 1;
158     uint embedded : 1;
159 };
160 
161 struct QWExtra {
162     // *************************** Cross-platform variables *****************************
163 
164     // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
165     void *glContext; // if the widget is hijacked by QGLWindowSurface
166     std::unique_ptr<QTLWExtra> topextra; // only useful for TLWs
167 #if QT_CONFIG(graphicsview)
168     QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
169 #endif
170 #ifndef QT_NO_CURSOR
171     std::unique_ptr<QCursor> curs;
172 #endif
173     QPointer<QStyle> style;
174     QPointer<QWidget> focus_proxy;
175 
176     // Implicit pointers (shared_empty/shared_null).
177     QRegion mask; // widget mask
178     QString styleSheet;
179 
180     // Other variables.
181     qint32 minw;
182     qint32 minh; // minimum size
183     qint32 maxw;
184     qint32 maxh; // maximum size
185     quint16 customDpiX;
186     quint16 customDpiY;
187     QSize staticContentsSize;
188 
189     // *************************** Cross-platform bit fields ****************************
190     uint explicitMinSize : 2;
191     uint explicitMaxSize : 2;
192     uint autoFillBackground : 1;
193     uint nativeChildrenForced : 1;
194     uint inRenderWithPainter : 1;
195     uint hasMask : 1;
196     uint hasWindowContainer : 1;
197 };
198 
199 /*!
200     \internal
201 
202     Returns \c true if \a p or any of its parents enable the
203     Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and
204     QWidget::setParent() to determine whether it's necessary to embed the
205     widget into a QGraphicsProxyWidget or not.
206 */
bypassGraphicsProxyWidget(const QWidget * p)207 static inline bool bypassGraphicsProxyWidget(const QWidget *p)
208 {
209     while (p) {
210         if (p->windowFlags() & Qt::BypassGraphicsProxyWidget)
211             return true;
212         p = p->parentWidget();
213     }
214     return false;
215 }
216 
217 class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate
218 {
219     Q_DECLARE_PUBLIC(QWidget)
220     Q_GADGET
221 
222 public:
223     // *************************** Cross-platform ***************************************
224     enum DrawWidgetFlag {
225         DrawAsRoot = 0x01,
226         DrawPaintOnScreen = 0x02,
227         DrawRecursive = 0x04,
228         DrawInvisible = 0x08,
229         DontSubtractOpaqueChildren = 0x10,
230         DontDrawOpaqueChildren = 0x20,
231         DontDrawNativeChildren = 0x40,
232         DontSetCompositionMode = 0x80
233     };
234     Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag)
235     Q_FLAG(DrawWidgetFlags)
236 
237     enum CloseMode {
238         CloseNoEvent,
239         CloseWithEvent,
240         CloseWithSpontaneousEvent
241     };
242     Q_ENUM(CloseMode)
243 
244     enum Direction {
245         DirectionNorth = 0x01,
246         DirectionEast = 0x10,
247         DirectionSouth = 0x02,
248         DirectionWest = 0x20
249     };
250     Q_ENUM(Direction)
251 
252     // Functions.
253     explicit QWidgetPrivate(int version = QObjectPrivateVersion);
254     ~QWidgetPrivate();
255 
get(QWidget * w)256     static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
get(const QWidget * w)257     static const QWidgetPrivate *get(const QWidget *w) { return w->d_func(); }
258 
259     QWExtra *extraData() const;
260     QTLWExtra *topData() const;
261     QTLWExtra *maybeTopData() const;
262     QPainter *sharedPainter() const;
263     void setSharedPainter(QPainter *painter);
264     QWidgetRepaintManager *maybeRepaintManager() const;
265 
266     enum class WindowHandleMode {
267         Direct,
268         Closest,
269         TopLevel
270     };
271     QWindow *windowHandle(WindowHandleMode mode = WindowHandleMode::Direct) const;
272 
273     QScreen *associatedScreen() const;
274 
275     template <typename T>
276     void repaint(T t);
277 
278     template <typename T>
279     void update(T t);
280 
281     void init(QWidget *desktopWidget, Qt::WindowFlags f);
282     void create();
283     void createRecursively();
284     void createWinId();
285 
286     bool setScreenForPoint(const QPoint &pos);
287     bool setScreen(QScreen *screen);
288 
289     void createTLExtra();
290     void createExtra();
291     void deleteExtra();
292     void createSysExtra();
293     void deleteSysExtra();
294     void createTLSysExtra();
295     void deleteTLSysExtra();
296     void updateSystemBackground();
297     void propagatePaletteChange();
298 
299     void setPalette_helper(const QPalette &);
300     void resolvePalette();
301     QPalette naturalWidgetPalette(uint inheritedMask) const;
302 
303     void setMask_sys(const QRegion &);
304 
305     void raise_sys();
306     void lower_sys();
307     void stackUnder_sys(QWidget *);
308 
309     QWidget *deepestFocusProxy() const;
310     void setFocus_sys();
311     void updateFocusChild();
312 
313     void updateFont(const QFont &);
setFont_helper(const QFont & font)314     inline void setFont_helper(const QFont &font) {
315         if (directFontResolveMask == font.resolve() && data.fnt == font)
316             return;
317         updateFont(font);
318     }
319     QFont localFont() const;
320     void resolveFont();
321     QFont naturalWidgetFont(uint inheritedMask) const;
322 
323     void setLayoutDirection_helper(Qt::LayoutDirection);
324     void resolveLayoutDirection();
325 
326     void setLocale_helper(const QLocale &l, bool forceUpdate = false);
327     void resolveLocale();
328 
329     void setStyle_helper(QStyle *newStyle, bool propagate);
330     void inheritStyle();
331 
332     void setUpdatesEnabled_helper(bool );
333 
334     bool updateBrushOrigin(QPainter *, const QBrush &brush) const;
335     void paintBackground(QPainter *, const QRegion &, DrawWidgetFlags flags = DrawAsRoot) const;
336     bool isAboutToShow() const;
337     QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
338     void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
339                        QWidget::RenderFlags renderFlags);
340     void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
341                 QWidget::RenderFlags renderFlags);
342     void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
343                     QPainter *sharedPainter = nullptr, QWidgetRepaintManager *repaintManager = nullptr);
344     void sendPaintEvent(const QRegion &toBePainted);
345 
346 
347     void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index,
348                                 const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
349                                 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager);
350 
351 #if QT_CONFIG(graphicsview)
352     static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin);
353 #endif
354     bool shouldPaintOnScreen() const;
355     void paintOnScreen(const QRegion &rgn);
356 
357     QRect clipRect() const;
358     QRegion clipRegion() const;
359     void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region);
360     void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
361     void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = nullptr,
362                                 bool alsoNonOpaque = false) const;
363     void clipToEffectiveMask(QRegion &region) const;
364     void updateIsOpaque();
365     void setOpaque(bool opaque);
366     void updateIsTranslucent();
367 #if QT_CONFIG(graphicseffect)
368     void invalidateGraphicsEffectsRecursively();
369 #endif // QT_CONFIG(graphicseffect)
370 
371     const QRegion &getOpaqueChildren() const;
372     void setDirtyOpaqueRegion();
373 
374     bool close_helper(CloseMode mode);
375 
376     void setWindowIcon_helper();
377     void setWindowIcon_sys();
378     void setWindowOpacity_sys(qreal opacity);
379     void adjustQuitOnCloseAttribute();
380 
381     void scrollChildren(int dx, int dy);
382     void moveRect(const QRect &, int dx, int dy);
383     void scrollRect(const QRect &, int dx, int dy);
384     void invalidateBackingStore_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
385 
386     template <class T>
387     void invalidateBackingStore(const T &);
388 
389     QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const;
390     void syncBackingStore();
391     void syncBackingStore(const QRegion &region);
392 
393     bool shouldDiscardSyncRequest() const;
394 
395     // tells the input method about the widgets transform
396     void updateWidgetTransform(QEvent *event);
397 
398     void reparentFocusWidgets(QWidget *oldtlw);
399 
400     static int pointToRect(const QPoint &p, const QRect &r);
401 
402     void setWinId(WId);
403     void showChildren(bool spontaneous);
404     void hideChildren(bool spontaneous);
405     void setParent_sys(QWidget *parent, Qt::WindowFlags);
406     void scroll_sys(int dx, int dy);
407     void scroll_sys(int dx, int dy, const QRect &r);
408     void deactivateWidgetCleanup();
409     void setGeometry_sys(int, int, int, int, bool);
410     void fixPosIncludesFrame();
411     void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
412     void activateChildLayoutsRecursively();
413     void show_recursive();
414     void show_helper();
415     void show_sys();
416     void hide_sys();
417     void hide_helper();
418     void _q_showIfNotHidden();
419     void setVisible(bool);
420 
421     void setEnabled_helper(bool);
422     static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = nullptr);
423 
424     void updateFrameStrut();
425     QRect frameStrut() const;
426 
427 #ifdef QT_KEYPAD_NAVIGATION
428     static bool navigateToDirection(Direction direction);
429     static QWidget *widgetInNavigationDirection(Direction direction);
430     static bool canKeypadNavigate(Qt::Orientation orientation);
431     static bool inTabWidget(QWidget *widget);
432 #endif
433 
434     void setWindowIconText_sys(const QString &cap);
435     void setWindowIconText_helper(const QString &cap);
436     void setWindowTitle_sys(const QString &cap);
437     void setWindowFilePath_sys(const QString &filePath);
438 
439 #ifndef QT_NO_CURSOR
440     void setCursor_sys(const QCursor &cursor);
441     void unsetCursor_sys();
442 #endif
443 
444     void setWindowTitle_helper(const QString &cap);
445     void setWindowFilePath_helper(const QString &filePath);
446     void setWindowModified_helper();
447     virtual void setWindowFlags(Qt::WindowFlags windowFlags);
448 
449     bool setMinimumSize_helper(int &minw, int &minh);
450     bool setMaximumSize_helper(int &maxw, int &maxh);
451     void setConstraints_sys();
452     bool pointInsideRectAndMask(const QPoint &) const;
453     QWidget *childAt_helper(const QPoint &, bool) const;
454     QWidget *childAtRecursiveHelper(const QPoint &p, bool) const;
455     void updateGeometry_helper(bool forceUpdate);
456 
457     void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const;
458     void setLayoutItemMargins(int left, int top, int right, int bottom);
459     void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = nullptr);
460 
461     void updateContentsRect();
462     QMargins safeAreaMargins() const;
463 
464     // aboutToDestroy() is called just before the contents of
465     // QWidget::destroy() is executed. It's used to signal QWidget
466     // sub-classes that their internals are about to be released.
aboutToDestroy()467     virtual void aboutToDestroy() {}
468 
effectiveFocusWidget()469     inline QWidget *effectiveFocusWidget() {
470         QWidget *w = q_func();
471         while (w->focusProxy())
472             w = w->focusProxy();
473         return w;
474     }
475 
476     void setModal_sys();
477 
478     // This is an helper function that return the available geometry for
479     // a widget and takes care is this one is in QGraphicsView.
480     // If the widget is not embed in a scene then the geometry available is
481     // null, we let QDesktopWidget decide for us.
screenGeometry(const QWidget * widget)482     static QRect screenGeometry(const QWidget *widget)
483     {
484         QRect screen;
485 #if QT_CONFIG(graphicsview)
486         QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
487         //It's embedded if it has an ancestor
488         if (ancestorProxy) {
489             if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != nullptr) {
490                 // One view, let be smart and return the viewport rect then the popup is aligned
491                 if (ancestorProxy->scene()->views().size() == 1) {
492                     QGraphicsView *view = ancestorProxy->scene()->views().at(0);
493                     screen = view->mapToScene(view->viewport()->rect()).boundingRect().toRect();
494                 } else {
495                     screen = ancestorProxy->scene()->sceneRect().toRect();
496                 }
497             }
498         }
499 #else
500         Q_UNUSED(widget);
501 #endif
502         return screen;
503     }
504 
setRedirected(QPaintDevice * replacement,const QPoint & offset)505     inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
506     {
507         Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
508         redirectDev = replacement;
509         redirectOffset = offset;
510     }
511 
redirected(QPoint * offset)512     inline QPaintDevice *redirected(QPoint *offset) const
513     {
514         if (offset)
515             *offset = redirectDev ? redirectOffset : QPoint();
516         return redirectDev;
517     }
518 
restoreRedirected()519     inline void restoreRedirected()
520     { redirectDev = nullptr; }
521 
enforceNativeChildren()522     inline void enforceNativeChildren()
523     {
524         if (!extra)
525             createExtra();
526 
527         if (extra->nativeChildrenForced)
528             return;
529         extra->nativeChildrenForced = 1;
530 
531         for (int i = 0; i < children.size(); ++i) {
532             if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
533                 child->setAttribute(Qt::WA_NativeWindow);
534         }
535     }
536 
nativeChildrenForced()537     inline bool nativeChildrenForced() const
538     {
539         return extra ? extra->nativeChildrenForced : false;
540     }
541 
effectiveRectFor(const QRegion & region)542     inline QRect effectiveRectFor(const QRegion &region) const
543     {
544         return effectiveRectFor(region.boundingRect());
545     }
546 
effectiveRectFor(const QRect & rect)547     inline QRect effectiveRectFor(const QRect &rect) const
548     {
549 #if QT_CONFIG(graphicseffect)
550         if (graphicsEffect && graphicsEffect->isEnabled())
551             return graphicsEffect->boundingRectFor(rect).toAlignedRect();
552 #endif // QT_CONFIG(graphicseffect)
553         return rect;
554     }
555 
556     QSize adjustedSize() const;
557 
handleSoftwareInputPanel(Qt::MouseButton button,bool clickCausedFocus)558     inline void handleSoftwareInputPanel(Qt::MouseButton button, bool clickCausedFocus)
559     {
560         Q_Q(QWidget);
561         if (button == Qt::LeftButton && qApp->autoSipEnabled()) {
562             QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
563                     q->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
564             if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
565                 QGuiApplication::inputMethod()->show();
566             }
567         }
568     }
569 
570     void setWSGeometry();
571 
mapToWS(const QPoint & p)572     inline QPoint mapToWS(const QPoint &p) const
573     { return p - data.wrect.topLeft(); }
574 
mapFromWS(const QPoint & p)575     inline QPoint mapFromWS(const QPoint &p) const
576     { return p + data.wrect.topLeft(); }
577 
mapToWS(const QRect & r)578     inline QRect mapToWS(const QRect &r) const
579     { return r.translated(-data.wrect.topLeft()); }
580 
mapFromWS(const QRect & r)581     inline QRect mapFromWS(const QRect &r) const
582     { return r.translated(data.wrect.topLeft()); }
583 
584     QOpenGLContext *shareContext() const;
585 
focusObject()586     virtual QObject *focusObject() { return nullptr; }
587 
588 #ifndef QT_NO_OPENGL
textureId()589     virtual GLuint textureId() const { return 0; }
textureListFlags()590     virtual QPlatformTextureList::Flags textureListFlags() {
591         Q_Q(QWidget);
592         return q->testAttribute(Qt::WA_AlwaysStackOnTop)
593             ? QPlatformTextureList::StacksOnTop
594             : QPlatformTextureList::Flags();
595     }
grabFramebuffer()596     virtual QImage grabFramebuffer() { return QImage(); }
beginBackingStorePainting()597     virtual void beginBackingStorePainting() { }
endBackingStorePainting()598     virtual void endBackingStorePainting() { }
beginCompose()599     virtual void beginCompose() { }
endCompose()600     virtual void endCompose() { }
setRenderToTexture()601     void setRenderToTexture() { renderToTexture = true; setTextureChildSeen(); }
setTextureChildSeen()602     void setTextureChildSeen()
603     {
604         Q_Q(QWidget);
605         if (textureChildSeen)
606             return;
607         textureChildSeen = 1;
608 
609         if (!q->isWindow()) {
610             QWidget *parent = q->parentWidget();
611             if (parent)
612                 get(parent)->setTextureChildSeen();
613         }
614     }
615     static void sendComposeStatus(QWidget *w, bool end);
616     // Called on setViewport().
initializeViewportFramebuffer()617     virtual void initializeViewportFramebuffer() { }
618     // When using a QOpenGLWidget as viewport with QAbstractScrollArea, resize events are
619     // filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget
620     // since the fbo must be resized. We need an alternative way to notify.
resizeViewportFramebuffer()621     virtual void resizeViewportFramebuffer() { }
622     // Called after each paint event.
resolveSamples()623     virtual void resolveSamples() { }
624 #endif
625 
626     static void setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent);
627 
628     // Variables.
629     // Regular pointers (keep them together to avoid gaps on 64 bit architectures).
630     std::unique_ptr<QWExtra> extra;
631     QWidget *focus_next;
632     QWidget *focus_prev;
633     QWidget *focus_child;
634     QLayout *layout;
635     QRegion *needsFlush;
636     QPaintDevice *redirectDev;
637     QWidgetItemV2 *widgetItem;
638     QPaintEngine *extraPaintEngine;
639     mutable const QMetaObject *polished;
640     QGraphicsEffect *graphicsEffect;
641     // All widgets are added into the allWidgets set. Once
642     // they receive a window id they are also added to the mapper.
643     // This should just ensure that all widgets are deleted by QApplication
644     static QWidgetMapper *mapper;
645     static QWidgetSet *allWidgets;
646 #if !defined(QT_NO_IM)
647     Qt::InputMethodHints imHints;
648 #endif
649 #ifdef QT_KEYPAD_NAVIGATION
650     static QPointer<QWidget> editingWidget;
651 #endif
652 
653     // Implicit pointers (shared_null/shared_empty).
654     QRegion opaqueChildren;
655     QRegion dirty;
656 #ifndef QT_NO_TOOLTIP
657     QString toolTip;
658     int toolTipDuration;
659 #endif
660 #if QT_CONFIG(statustip)
661     QString statusTip;
662 #endif
663 #if QT_CONFIG(whatsthis)
664     QString whatsThis;
665 #endif
666 #ifndef QT_NO_ACCESSIBILITY
667     QString accessibleName;
668     QString accessibleDescription;
669 #endif
670 
671     // Other variables.
672     uint directFontResolveMask;
673     uint inheritedFontResolveMask;
674     decltype(std::declval<QPalette>().resolve()) directPaletteResolveMask;
675     uint inheritedPaletteResolveMask;
676     short leftmargin;
677     short topmargin;
678     short rightmargin;
679     short bottommargin;
680     signed char leftLayoutItemMargin;
681     signed char topLayoutItemMargin;
682     signed char rightLayoutItemMargin;
683     signed char bottomLayoutItemMargin;
684     static int instanceCounter; // Current number of widget instances
685     static int maxInstances; // Maximum number of widget instances
686     Qt::HANDLE hd;
687     QWidgetData data;
688     QSizePolicy size_policy;
689     QLocale locale;
690     QPoint redirectOffset;
691 #ifndef QT_NO_ACTION
692     QList<QAction*> actions;
693 #endif
694 #ifndef QT_NO_GESTURES
695     QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
696 #endif
697 
698     // Bit fields.
699     uint high_attributes[4]; // the low ones are in QWidget::widget_attributes
700     QPalette::ColorRole fg_role : 8;
701     QPalette::ColorRole bg_role : 8;
702     uint dirtyOpaqueChildren : 1;
703     uint isOpaque : 1;
704     uint retainSizeWhenHiddenChanged : 1;
705     uint inDirtyList : 1;
706     uint isScrolled : 1;
707     uint isMoved : 1;
708     uint usesDoubleBufferedGLContext : 1;
709     uint mustHaveWindowHandle : 1;
710     uint renderToTexture : 1;
711     uint textureChildSeen : 1;
712 #ifndef QT_NO_IM
713     uint inheritsInputMethodHints : 1;
714 #endif
715 #ifndef QT_NO_OPENGL
716     uint renderToTextureReallyDirty : 1;
717     uint renderToTextureComposeActive : 1;
718 #endif
719     uint childrenHiddenByWState : 1;
720     uint childrenShownByExpose : 1;
721 
722     // *************************** Platform specific ************************************
723 #if defined(Q_OS_WIN)
724     uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine()
725 #elif defined(Q_OS_MAC)
726     void macUpdateSizeAttribute();
727 #endif
728     void setNetWmWindowTypes(bool skipIfMissing = false);
729 
730     bool stealKeyboardGrab(bool grab);
731     bool stealMouseGrab(bool grab);
732 };
733 
734 Q_DECLARE_OPERATORS_FOR_FLAGS(QWidgetPrivate::DrawWidgetFlags)
735 
736 struct QWidgetPaintContext
737 {
QWidgetPaintContextQWidgetPaintContext738     inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, QWidgetPrivate::DrawWidgetFlags f,
739                                QPainter *p, QWidgetRepaintManager *rpm)
740         : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), repaintManager(rpm), painter(nullptr) {}
741 
742     QPaintDevice *pdev;
743     QRegion rgn;
744     QPoint offset;
745     QWidgetPrivate::DrawWidgetFlags flags;
746     QPainter *sharedPainter;
747     QWidgetRepaintManager *repaintManager;
748     QPainter *painter;
749 };
750 
751 #if QT_CONFIG(graphicseffect)
752 class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
753 {
754 public:
QWidgetEffectSourcePrivate(QWidget * widget)755     QWidgetEffectSourcePrivate(QWidget *widget)
756         : QGraphicsEffectSourcePrivate(), m_widget(widget), context(nullptr), updateDueToGraphicsEffect(false)
757     {}
758 
detach()759     void detach() override
760     { m_widget->d_func()->graphicsEffect = nullptr; }
761 
graphicsItem()762     const QGraphicsItem *graphicsItem() const override
763     { return nullptr; }
764 
widget()765     const QWidget *widget() const override
766     { return m_widget; }
767 
update()768     void update() override
769     {
770         updateDueToGraphicsEffect = true;
771         m_widget->update();
772         updateDueToGraphicsEffect = false;
773     }
774 
isPixmap()775     bool isPixmap() const override
776     { return false; }
777 
effectBoundingRectChanged()778     void effectBoundingRectChanged() override
779     {
780         // ### This function should take a rect parameter; then we can avoid
781         // updating too much on the parent widget.
782         if (QWidget *parent = m_widget->parentWidget())
783             parent->update();
784         else
785             update();
786     }
787 
styleOption()788     const QStyleOption *styleOption() const override
789     { return nullptr; }
790 
deviceRect()791     QRect deviceRect() const override
792     { return m_widget->window()->rect(); }
793 
794     QRectF boundingRect(Qt::CoordinateSystem system) const override;
795     void draw(QPainter *p) override;
796     QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset,
797                    QGraphicsEffect::PixmapPadMode mode) const override;
798 
799     QWidget *m_widget;
800     QWidgetPaintContext *context;
801     QTransform lastEffectTransform;
802     bool updateDueToGraphicsEffect;
803 };
804 #endif // QT_CONFIG(graphicseffect)
805 
extraData()806 inline QWExtra *QWidgetPrivate::extraData() const
807 {
808     return extra.get();
809 }
810 
topData()811 inline QTLWExtra *QWidgetPrivate::topData() const
812 {
813     const_cast<QWidgetPrivate *>(this)->createTLExtra();
814     return extra->topextra.get();
815 }
816 
maybeTopData()817 inline QTLWExtra *QWidgetPrivate::maybeTopData() const
818 {
819     return extra ? extra->topextra.get() : nullptr;
820 }
821 
sharedPainter()822 inline QPainter *QWidgetPrivate::sharedPainter() const
823 {
824     Q_Q(const QWidget);
825     QTLWExtra *x = q->window()->d_func()->maybeTopData();
826     return x ? x->sharedPainter : nullptr;
827 }
828 
setSharedPainter(QPainter * painter)829 inline void QWidgetPrivate::setSharedPainter(QPainter *painter)
830 {
831     Q_Q(QWidget);
832     QTLWExtra *x = q->window()->d_func()->topData();
833     x->sharedPainter = painter;
834 }
835 
pointInsideRectAndMask(const QPoint & p)836 inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const
837 {
838     Q_Q(const QWidget);
839     return q->rect().contains(p) && (!extra || !extra->hasMask || q->testAttribute(Qt::WA_MouseNoMask)
840                                      || extra->mask.contains(p));
841 }
842 
maybeRepaintManager()843 inline QWidgetRepaintManager *QWidgetPrivate::maybeRepaintManager() const
844 {
845     Q_Q(const QWidget);
846     QTLWExtra *x = q->window()->d_func()->maybeTopData();
847     return x ? x->repaintManager.get() : nullptr;
848 }
849 
850 QT_END_NAMESPACE
851 
852 #endif // QWIDGET_P_H
853