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