summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
Commit message (Collapse)AuthorAgeFilesLines
* QWidget: fix render() in RTL modeChristian Ehrlicher4 days1-0/+3
| | | | | | | | | | | | | | | Rendering a widget to a paintdevice via QWidget::render() did not pass the LayoutDirection mode of the widget to the paintdevice which lead to wrong rendering of text. This is especially visible with the windows 11 style which does not draw some widgets directly on the screen but through a QGraphicsEffect on a QImage. Pick-to: 6.7 6.5 6.2 Fixes: QTBUG-124931 Change-Id: If2cfa326d2ca45c42e203a4ae91fd857afa5c69c Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
* QWindowPrivate::setFocusToTarget: Add focusReason parameterDoris Verria5 days2-3/+3
| | | | | | | | | The focusReason is also important when setting focus to the target, so ammend 8c44064f62b9e57dacdf1dbd8de57e07c938b9db and add this parameter to the virtual method. Change-Id: Id7800a366cbc1ce2ac26b3fec1e47ec9267a57bb Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Windows 11 style: simplify code to polish paletteVolker Hilsheimer9 days1-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | There are two cases in which we let the style polish a palette: - after merging the system palette and the style's standard palette - or when a widget-class specific palette gets set A style needs to know which colors of the palette it can safely overwrite with style-specific preferences. For that to work, we need to reset the resolve mask of the synthesized palette (first case) to 0 before polishing. Palettes set explicitly by application code will then have resolve bits set, and the polishing can respect those colors and not overwrite them. Simplify the polish() implementation then to check whether the respective color's resolve bit is set, and only overwrite it with the style's preferred color if the bit is clear. Move that logic into a macro for simplification. This amends b733d31f275d09ca81b5e347ca1e9b6c9b216cd4 and makes sure that colors that are set by the application explicitly don't get overridden by the style. Task-number: QTBUG-124490 Task-number: QTBUG-124286 Change-Id: I69e1e3da93f661ebdafee0b62adbb3d411322443 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* QWindowPrivate: Introduce virtual setFocusToTargetDoris Verria2024-04-272-1/+44
| | | | | | | | | | | | | | | | | When a window gains focus, the focus will be set to the focusWidget, if one exists, in the case of QWidgetWindow, and to the window's contentItem's subFocusItem, in the case of QQuickWindow. However, we want to be able to customize this as we may want to set the focus item/widget to the first, last, prev, or next, depending for example, on the reason the window got focus. Eg.: on a TabKey we want to focus the next focus object, on a BackTabKey the previous one, and so on. To be able to do this, add a virtual method in QWindowPrivate that sets focus to the specified item, and override for QWidgetWindowPrivate. Task-number: QTBUG-121789 Done-with: axel.spoerl@qt.io Change-Id: Ib5e17d6ff52c2323a4013c80bf411e92b4c8ce9b Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Widgets focus abstraction: Skip isFocusChainConsistent w/o logging catAxel Spoerl2024-04-261-1/+6
| | | | | | | | | | | | | | | | | | QWidgetPrivate::isFocusChainConsistent() iterates over QApplication::allWidgets() to identify and log inconsistencies. In applications with many widgets, this has a major performance impact. Disable the check and return true, unless the logging category qt.widgets.focus is enabled. Adapt tst_QWidget::focusAbstraction() to enable the logging category. This amends 58d5d4b7c2faaeaa2c2ccdabb3da6d37f9db880a. Fixes: QTBUG-124666 Change-Id: Ia487b381ab45b052638b189bf56acaf4353b1a37 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* QGestureManager: use gesture owner target if topLevelAt returns nullptrLiang Qi2024-04-221-1/+2
| | | | | | | | | | For security reason, Wayland doesn't provide global position for top level windows, so topLevelAt is not supported. Fixes: QTBUG-113404 Pick-to: 6.7 6.5 6.2 5.15 Change-Id: Id60b8b77a1843344db4d4e4c13382ad87adac806 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Set focus to the window container when contained window gains focusDoris Verria2024-04-223-35/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As it is, when a QWindowContainer's embedded window gains focus, the container doesn't report having focus and QApplication::focusWidget() will be nullptr. This is because when the embedded window gets focus, the container will clearFocus() on the old focus widget. To be able to set focus to the next focus widget (eg: as a result of a key tab event sent to the container's parent window), the container checks if its embedded window is already focused, and if so, forwards focus to its nextInFocusChain(). That is why it keeps track of the (old) focusWindow. The problem with the current behavior is that if we want to make focus navigation via key tabbing work and return focus *from within the window* back to the normal widget focus chain, the encapsulating widget needs to remember its focusWidget(), in this case the window container, in order to be able to set focus to the next/PrevInFocusChain(). That is why we now set the focus to the window container whenever its contained window gains focus. This means that QApplication::focusWidget() will be the window container if the contained window has focus. In this way, we don't have to call clearFocus() on the old focus widget, or keep track of focus windows, because calling setFocus() on the container will handle that. It is worth noting and probably documenting the following caveats: - even though the window container will be the qApp's focusWidget(), it won't directly handle keyboard events, but the contained window will - we won't be able to respect the window container's focusPolicy in this case, since the contained window will be activated from interactions inside it, no matter the container's focusPolicy [ChangeLog][QtWidgets][QWindowContainer] The window container will become focused if the contained window becomes focused. This implies that the QApplication::focusWidget() will be the window container if the contained window is the focus window. Task-number: QTBUG-121789 Change-Id: I1050afc59780f7189a0d8e8c95bff27f96f38dbc Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Add preliminary support for Qt for visionOSTor Arne Vestbø2024-04-181-1/+1
| | | | | | | | | | | | | | | | | | | | | | Qt already runs on Vision Pro as "Designed for iPad", using Qt for iOS. This change enables building Qt for visionOS directly, which opens the door to visionOS specific APIs and use-cases such as volumes and immersive spaces. The platform removes some APIs we depend on, notably UIScreen, so some code paths have been disabled or mocked to get something up and running. As our current window management approach on UIKit platforms depends on UIWindow and UIScreen there is currently no way to bring up QWindows. This will improve once we refactor our window management to use window scenes. To configure for visionOS, pass -platform macx-visionos-clang, and optionally add -sdk xrsimulator to build for the simulator. Change-Id: I4eda55fc3fd06e12d30a188928487cf68940ee07 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
* QWidget: Remove un-needed nullptr check for oldtlwTor Arne Vestbø2024-04-171-2/+3
| | | | | | | | | | | | | | | | | | Added in 1bd755465efa27294362925f55306f88f1800936 We already access oldtlw and oldtlw->d_func() in other places, and the source of oldtlw is a call to QWidget::window(), which returns the widget itself if it doesn't have a parent. This should also fix a CodeChecker issue where it thinks that the other unchecked accesses to oldtlw are suspicious. Add assert just in case, so we catch it explicitly if for some reason this assumption doesn't hold in the future. Pick-to: 6.7 6.5 Change-Id: Iefa9b2df6b25a993afe87e4ee90fe9d2075ebbd0 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Implement QWindowContainer::minimumSizeHint()Jan Arve Sæther2024-04-122-0/+9
| | | | | | | | | | | | It will return the minimumSize of the underlying QWindow. The container can then be put inside QLayouts without risking to be shrunk to a smaller size than the QWindow::minimumSize. Whenever the QWindow::minimumWidth or QWindow::minimumHeight changes, we call QWindowContainer::updateGeometry(), which will make the layout re-query QWindowContainer::minimumSizeHint() again. Task-number: QTBUG-121798 Change-Id: Ib7ece7d9d75f2e4964ca9042d8d8b95ce3b17739 Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* QLayout: Consume ChildRemoved event, when layout is disabledAxel Spoerl2024-04-101-2/+3
| | | | | | | | | | | | | | | QLayout::widgetEvent() returned early, when the layout was disabled. That suppressed ChildRemoved events and lead to a crash, when the layout was enabled again. Don't return early on ChildRemoved events. Add an autotest in tst_layout::removeWidget(). Fixes: QTBUG-124151 Pick-to: 6.7 6.5 6.2 Change-Id: Ib0a0bb73978d9fc2c9777d300cf38a8c4496b702 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Chris René Lerner <chris.lerner@qt.io>
* QWidget: fix link error in static buildZhao Yuhang2024-04-061-19/+19
| | | | | | | | | | | | QtQuick also uses "lcFocus" as a category name, which causes link errors in static builds when both QWidget and QtQuick are linked in one executable. Making it static is also a good solution, but here adding a "Widget" prefix seems more consistent. Change-Id: I0a6a02750bd347f62b67544b4044789612f0fa4d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* widgets: Invalidate RHI swapchain when window moves to new top levelTor Arne Vestbø2024-04-041-3/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a QWidget with an associated RHI swapchain (via its QWindow) is moved to a different top level window, that top level window has its own backing store, and QBackingStoreRhiSupport, which doesn't know anything about the fact that the window already has an associated swap chain in the original top level window's QBackingStoreRhiSupport. As having multiple swap chains for the same window is not supported on all RHI backends (Vulkan and DX in particular), we need to throw away the swap chain when detecting that the window is moved to a new top level. We do this by hooking into the existing WindowAboutToChangeInternal event delivery to renderToTexture children, which now delivers the event both to renderToTexture QWidget children as well as QWindows in the hierarchy. The condition of when to deliver the event has been updated to reflect whether the top level uses RHI for flushing, instead of only including renderToTexture children, as the former also includes setting QT_WIDGETS_RHI=1 explicitly. The event is then caught by QBackingStoreRhiSupportWindowWatcher, and handled the same way as for SurfaceAboutToBeDestroyed. Renaming qSendWindowChangeToTextureChildrenRecursively would make sense at this point, but to make cherry-picks easier we keep the current name for now. Fixes: QTBUG-120276 Pick-to: 6.7 6.5 Change-Id: Ic4c60e89be985f12a84e9f893c299e602b70851a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* Abstract QWidget focus chain managementAxel Spoerl2024-04-042-136/+455
| | | | | | | | | | | | | | | | | | | The focus chain in widgets is implemented as a double-linked list, using QWidgetPrivate::focus_next and focus_prev as pointers to the next/previous widget in the focus chain. These pointers are manipulated directly at many places, which is error prone and difficult to read. Build an abstraction layer and remove direct usage of focus_next and focus_prev. Provide functions to insert and remove widgets to/from the focus chain. Add a test function to tst_QWidget. Task-number: QTBUG-121478 Change-Id: Ide6379c0197137e420352a2976912f2de8a8b338 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Decouple rate-limiting of paint-on-screen widgets from top level widgetTor Arne Vestbø2024-04-041-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As part of eacd58d4e78e7238ba5fcca90ba960aaf3ebd263, a mechanism was added to prevent posting redundant UpdateRequest events to the top level widget, managed by QWidgetRepaintManager. The mechanism relied on a boolean that was set when posting an update request event, and reset when processing the event for the top level widget, as part of QWidgetRepaintManager::sync(). However, for paint-on-screen widgets, we don't post an update request to the top level, we post it to the paint-on-screen widget directly. And when processing that event, we don't paint the widget though the normal QWidgetRepaintManager machinery, but instead call the paint event via QWidgetPrivate::paintOnScreen(). As a result, an update() on a paint-on-screen widget would result in never receiving updates for non-paint-on-screen widgets, as we assumed there was no reason to send further update requests. We could fix this by clearing the updateRequestSent flag as part of the paintOnScreen() code path, but that's incorrect as the flag represents whether the top level QWidgetRepaintManager needs an update request event or not, and would lead to missed updates to normal widgets until the paint-on-screen widget finishes its update. Instead, we only set updateRequestSent if we're posting update requests for non-paint-on-screen widgets, which in practice means the top level widget. The paint on screen logic in QWidgetRepaintManager::markDirty still takes care of rate-limiting the update requests to the paint-on-screen widget, by comparing the dirty area of the widget. There is definite room for improvement here, especially in the direction of handling update requests via QWindow::requestUpdate instead of manually posted events, but for now this will have to do. Fixes: QTBUG-80167 Pick-to: 6.7 6.6 6.5 6.2 5.15 Change-Id: Ib5685de7ca2fd7cd7883a25bb7bc0255ea242d30 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* QApplication: use focus abstraction instead of QWidget::focus_next/prevAxel Spoerl2024-03-181-2/+2
| | | | | | | | | | | Focus abstraction in QWidgetPrivate makes direct access to QWidget::focus_next and focus_prev an antipattern. Remove usage. Task-number: QTBUG-121478 Change-Id: Iaab97024c20b97a0d9850dce43816a432d4bc7a1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Reparent QWindow children when reparenting QWidgetTor Arne Vestbø2024-03-142-39/+93
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a QWidget was reparented, we would take care to reparent its backing QWidgetWindow as well, into the nearest QWindow of the new QWidget parent. However we would only do this for the reparented widget itself, and not any of its child widgets. In the case where the widget has native children with their own QWindows, the widget itself may not (yet) be native, e.g. if it hasn't been shown yet, or if the user has set Qt::WA_DontCreateNativeAncestors. In these scenarios, we would be left with dangling QWindows, still hanging off their original QWindow parents, which would eventually lead to crashes. We now reparent both the QWindow of the reparented widget (as long as it's not about to be destroyed), and any QQWindow children we can reach. For each child hierarchy we can stop once we reach a QWindow, as the QWindow children of that window will follow along once we reparent the QWindow. QWindowContainer widgets don't usually have their own windowHandle(), but still manage a QWindow inside their parent widget hierarchy. These will not be reparented during QWidgetPrivate::setParent_sys(), but instead do their own reparenting later in QWidget::setParent via QWindowContainer::parentWasChanged(). The only exception to this is when the top level is about to be destroyed, in which case we let the window container know during QWidgetPrivate::setParent_sys(). Finally, although there should not be any leftover QWindows in the reparented widget once we have done the QWidgetWindow and QWindowContainer reparenting, we still do a pass over any remaining QWindows and reparent those too, since the original code included this as a possibility. We could make further improvements in this areas, such as moving the QWindowContainer::parentWasChanged() call, but the goal was to keep this change as minimal as possible so we can back-port it. Fixes: QTBUG-122747 Pick-to: 6.7.0 6.7 6.6 6.5 Change-Id: I4d1217fce4c3c48cf5f7bfbe9d561ab408ceebb2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QDialogButtonBox: Don't set focus in a dialog with StrongFocus childrenAxel Spoerl2024-03-072-0/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A QDialogButtonBox with the first accept button becoming default, didn't explicitly set focus on such a button in a QDialog. d44413d526ec12ed83acd7343c2005782178c7ad implemented this missing functionality. It set focus to the automatic default button, unless the QDialog had a focusWidget() set. That has caused a regression, in cases where - the QDialog has a QWidget child with a Qt::StrongFocus policy, and - the QDialog is not yet visible, so focusWidget() returns nullptr. Amend d44413d526ec12ed83acd7343c2005782178c7ad: Implement a helper in QWidgetPrivate, that returns true, if a child with a given focus policy is found. Do not set focus to a QDialogButtonBox's automatic default button, when - not located inside a QDialog, or - a focusWidget() exists, or - the dialog has QWidget child with Qt::StrongFocus, that is not a child of the QDialogButtonBox. Add an autotest function. Pick-to: 6.7 6.6 6.5 Fixes: QTBUG-121514 Fixes: QTBUG-120049 Change-Id: I3c65ae36b56657f9af4a3a4b42f9b66e8bc5c534 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Mention QChronoTimer in API docsAhmad Samir2024-03-031-2/+3
| | | | | Change-Id: Iaf9fb31994f1580b2051dbd0b1b8eef2a218aa39 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Disconnect QWindowContainer::focusWindowChanged on destructionTor Arne Vestbø2024-03-031-0/+3
| | | | | | | | | | | | | | | | | | Regression after 9e78256579e8dc704066a98cb4816a1aab0e7e3b. Apparently the string based connection syntax is more lenient, as with PMF-style connects, we (correctly) get: ASSERT failure in QWindowContainer: "Called object is not of the correct type (class destructor may have already run)" when the QWidget destructor closes the QWindow and we get a synchronous callback from the platform that we've lost the focus window. Pick-to: 6.7 Change-Id: I8f25b3b050e11913ec0f0941eaf831c88b4249f9 Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
* Add QWidgetPrivate::rhi() helper methodTor Arne Vestbø2024-03-013-8/+11
| | | | | | | | For accessing the RHI managed by the widget compositing machinery. Pick-to: 6.7 6.6 6.5 Change-Id: Ia3c1227cc2d9cfebe95611cad3dbcd7aa6f6f8c7 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Add QWidgetPrivate::closestParentWidgetWithWindowHandle helper methodTor Arne Vestbø2024-03-012-0/+20
| | | | | | | | | In contrast to nativeParentWidget(), we return the closest widget with a QWindow, even if this window has not been created yet. Pick-to: 6.7 6.6 6.5 Change-Id: Icac46297a6052a7a5698d752d4aa871bd5c2bdd8 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Remove QWindowPrivate::compositingTor Arne Vestbø2024-03-011-2/+0
| | | | | | | | | | | It was added for Android in a4f50269f82695fbd0dd344f87b4b355feff4333, for the case of QSurface::RasterGLSurface, but since 6.4 we no longer use QSurface::RasterGLSurface for composition. And the Android usage was removed in 2020ce5fd2478389c56f34742fdeee9cd24ca8a5. Pick-to: 6.7 6.6 6.5 Change-Id: I8dafe959c54e09b3a974253e15d184365141d559 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Fix -Wimplicit-fallthrough for clangTim Blechmann2024-03-012-0/+3
| | | | | | | | | | | | | | | | | | | Clang's `-Wimplicit-fallthrough` warnings are a little stricter than gcc's interpretation: switch (i) { case 0: foo(); case 4: break; } While gcc accepts the implicit fallthrough, if the following statement is a trivial `break`, clang will warn about it. Pick-to: 6.7 Change-Id: I38e0817f1bc034fbb552aeac21de1516edcbcbb0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QApplicationPrivate::dispatchEnterLeave: remove dead codeAxel Spoerl2024-02-291-13/+0
| | | | | | | | | Remove #ifdef 0 section added in 2011. Task-number: QTBUG-121478 Pick-to: 6.7 Change-Id: I2154cd5616e2695af89cf4fc5ec9d1b3ae5572d5 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* QWidgetRepaintManager: Use textureChildSeen to determine deferred updateTor Arne Vestbø2024-02-271-3/+3
| | | | | | | | | | | | We want to get rid of the QWindowPrivate::compositing member, as it is no longer needed for the Android backingstore, which it was first added for in a4f50269f82695fbd0dd344f87b4b355feff4333. We can use textureChildSeen instead to check if we're compositing. Pick-to: 6.7 Change-Id: If85b21f92c8253bf89543a7e81e03730023f8095 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Doc: Use QDOC_PROPERTY for QRhiWidget::autoRenderTargetPaul Wicking2024-02-262-3/+4
| | | | | | | | | | `autoRenderTarget` is a private bool that very much looks like it's used as a Q_PROPERTY. Use QDOC_PROPERTY for it to generate warning- free documentation. Pick-to: 6.7 Change-Id: Ia6255287f139ff23172c4fac96950e1a37eeef83 Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
* Correct license in widget/kernelLucie Gérard2024-02-153-3/+3
| | | | | | | | | | | | | | | | | | According to QUIP-18 [1], all module files should be LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only or LicenseRef-Qt-Commercial OR GPL-3.0-only LGPD and non-LGPL licenses should not be mixed in a given directory. The files in this patch now match the other files in the same directory and QUIP-18 rule. [1]: https://contribute.qt-project.org/quips/18 Pick-to: 6.7 Task-number: QTBUG-121787 Change-Id: Ied60c775fbae38d6edeabc669f782b39d02c28f4 Reviewed-by: Kai Köhne <kai.koehne@qt.io>
* QRhiWidget: Register cleanup callback also on first RHI initTor Arne Vestbø2024-02-141-13/+15
| | | | | | | | | | | | | | | | | The first time ensureRhi() is called we don't have an RHI yet, and will adopt the top level's repaint manager's RHI. We need to register a cleanup callback for this RHI, so that if it goes away, we will reset our RHI pointer to null, just like when we switch from one top level to another (and get a new potential RHI). Without the reset, we would be working with a stale QRhi pointer, which we in most cases updated via a call to ensureRhi(), that picked up the new QRhi, but for good measure we should reset it if we can. Pick-to: 6.7 Change-Id: Iac6d8787b636675bbcb4358e8f0baad26187b0e2 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* QRhiWidget: Tear down resources before window has changedTor Arne Vestbø2024-02-141-1/+1
| | | | | | | | | | | | | | | | | | | We were handling QEvent::WindowChangeInternal, but based on what the code is doing, what the comments say, and what QQuickWidget does, the right event should be WindowAboutToChangeInternal. This fixes a crash when reparenting a QRhiWidget into another widget, where we could call removeCleanupCallback() on an RHI that was already gone. The fact that we have a stale RHI pointer at WindowChangeInternal time is still problematic, and caused by our call to addCleanupCallback not happening as it should for the first call to ensureRhi(), but this will be fixed in a follow up. Pick-to: 6.7 Change-Id: I054120e97a24a1f74af44b2d251470792f03f7f3 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* Add QPlatformIntegration::BackingStoreStaticContents capabilityTor Arne Vestbø2024-02-131-5/+3
| | | | | | | | | | | | | | This was a feature in Qt 4, but the only platform that carried it over to Qt 5 was Windows, in ab76593f18396e693f24066592244ca95e135ea2, and that's still the situation. As a first step in possibly implementing this on more platforms, lets replace the hard-coded check in QWidgetRepaintManager::hasStaticContents with a proper QPlatformIntegration capability check in the only call site. Pick-to: 6.7 Change-Id: I2067109f45116cd8c62facf7224cd748f19e845b Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* QWidgetWindow: Don't meddle with WA_WState_{Hidden/ExplicitShowHide}Tor Arne Vestbø2024-02-121-14/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In ccd3bf0871b81dfc09bb469b161f32dfb47ee53e we introduced code that would ensure that our call to QWidgetPrivate::setVisible() from QWidgetWindow would not result in WA_WState_Hidden being set. This code was later modified in 51300566ffe2ece2455e1d0479a556c5dbb3bb8e to apply to widgets that were explicitly shown/hidden. Unfortunately, the reset of the Hidden and ExplicitShowHide attributes would in some cases result in the widget having only ExplicitShowHide after being hidden, which is an invalid state. It also resulted in the widget having both Visible, Hidden, and ExplicitShowHide, if first being hidden via QWidget, and then shown via QWindow, which in turn prevented the widget from being hidden via QWidget::hide(). As we no longer rely on the adjustments to Hidden/ExplicitShowHide to fix QTBUG-73021, we can remove the entire logic. Any setVisible call to QWidgetWindow will either come from outside, in which case we should respect that and set Visible/Hidden via QWidgetPrivate, or the setVisible call is a result of QWidget itself (or its parent) showing the QWidgetWindow, in which case the QWidget visible state is already up to date and we skip the QWidgetPrivate::setVisible call. Task-number: QTBUG-121398 Task-number: QTBUG-73021 Fixes: QTBUG-120316 Pick-to: 6.7 Change-Id: I3174ad66b7e10c55aa99b7cb433267632169ca8f Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* Ensure QWidget::destroy() events and attributes match hiding the widgetTor Arne Vestbø2024-02-121-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When destroying a widget via QWidget::destroy(), we clear WA_WState_Created, and then delete the QWidgetWindow, which in turn hides the widget. But QWidgetPrivate::setVisible(false) skips hide_helper() if the widget has not been created, which leaves out important events such as the hide event, and even more important, fails to clear WA_WState_Visible. As a result, the widget is left visible (and mapped), even if it has been destroyed. This is normally not a big issue for the main use of destroy(), namely destructing the widget, but for cases where destroy() and create() is used to recreate the widget this is important. We now unconditionally call hide_helper() if the widget is not already hidden. As a result, the widget will correctly be visible=false after a destroy(). This in turn means we need to re-apply the visible state after recreating the widget when we detect a mismatch in RHI configuration. Due to our meddling of the Hidden and ExplicitShowHide attributes in QWidgetWindow private, a QWidet::show() will not have any effect after being destroy(). This is okey for now, as destroy() is internal to a widget, and we make sure to either update WA_WState_Visible and WA_WState_Hidden (in QWidgetPrivate::setParent_sys), or use the QWidgetPrivate::setVisible() code path directly, which doesn't have that issue. The root problem will be fixed in a follow up. Pick-to: 6.7 Change-Id: I77cb88d75e57f0d9a31741161fb14d618a653291 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Restore window state of recreated top level widget, not closest QWindowTor Arne Vestbø2024-02-121-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When we recreate a top level QWidget due to the RHI config not matching, we need to re-apply the window state, as the state is lost on destroy(). But we should do this on the QWidget we are recreating, not on its closest QWindow. These are usually the same, so it didn't matter in practice for most cases (besides the more convoluted way of getting to the QWidget's window). But if the top level widget does not have a winId yet, the call to find the closest QWindow via QWidgetPrivate::windowHandle() will traverse from the top level widget to its transient parent widget, via nativeParentWidget, which is strange and likely a bug. As a result of that, we would store the window state of the transient parent widget, and then, once we had created() the new top level, we would apply the window state to the top level, which now had a winId. We can simplify all of this by just storing and applying the window state on the widget we are re-creating. There's no need to go via the closest QWindow for this. We do however need to set the window state on the widget's window, as going via QWidget will just bail out since the window state hasn't changed. Amends c88211d1e4ac12eb2ae4990703a4f73c7085d624 Fixes: QTBUG-119795 Pick-to: 6.7 6.6 6.5 Change-Id: I0ad6e7bbac5f29d095cc643e9a7094784e9a2122 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Harden WidgetAttributes debug stream operatorTor Arne Vestbø2024-02-021-9/+10
| | | | | | | | The call site may pass in a null-widget, so guard for that. Pick-to: 6.7 Change-Id: I631cb2fc105bad69faf3daaeac4b893457d27cc1 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Don't set ExplicitShowHide on children when showing parent widgetTor Arne Vestbø2024-02-012-23/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | As a result of using QWidget::setVisible to show the child widgets we would end up also setting ExplicitShowHide. This is not in line with the intent of ExplicitShowHide, which is to flag a widget as explicitly shown/hidden by the developer, which in turn prevents Qt Widgets from toggling WState_Hidden when the widget is reparented. By using QWidgetPrivate::setVisible instead, we can show the child without setting ExplicitShowHide. As side effect of this is that we no longer reset WA_WState_Hidden from QWidgetWindowPrivate::setVisible(). This is an issue when the setVisible call comes as a result of destroying the QWidgetWindow, as that is an implicit hide, and should not result in the widget having WA_WState_Hidden. QWidget handles this case in hideChildren by not calling QWidgetPrivate::setVisible -- instead doing its own reset of WA_WState_Visible. We don't want to untangle this just yet, so as a workaround we detect that the widget is already !isVisible(), thanks to hideChildren having hidden it, and then skip the call to QWidgetPrivate::setVisible that results from QWindow::destroy(). Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: Ib5b4d9c84f0569124c5f3ca2169cabff18934e2d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Add logging, clarifications, and tests for QWidget show/hide behaviorTor Arne Vestbø2024-02-013-10/+66
| | | | | | | Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: I94b4c90c3bd515279417c88497d7b9bd5a362eae Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Add QWidgetPrivate::isExplicitlyHidden() helper functionTor Arne Vestbø2024-01-314-5/+14
| | | | | | | | | To aid readability. Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: I3cb231584c2b7aee72e9f01c669fed1e01fbe475 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* qWaitForWindowFocused: Pass timeout as QDeadlineTimerTor Arne Vestbø2024-01-252-5/+5
| | | | | | | | | | | We should avoid int-based timeouts nowadays, and prefer std::chrono, or for timeouts where Forever is a valid state, QDeadlineTimer. Discovered during API header review. Pick-to: 6.7 Change-Id: Ia56a67084c7a2f989951755fed5ffc161ed8f79e Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QWidget: Clean up state that depends on QWindow from ~QWidgetWindow()Tor Arne Vestbø2024-01-232-27/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We were assuming that QWidget was in full control of QWidgetWindow destruction, via deleteTLSysExtra(), and that we could limit any cleanups to that function. But in some situations QWidgetWindow is destructed from other code paths, in which case we were left with dangling pointers to the QWidgetWindow in both QTLWExtra, as well as the backingstore. This can happen if there's a child widget hierarchy where there is not a 1:1 mapping between QWidgets and QWindows, for example if the window attribute WA_DontCreateNativeAncestors has been set. In this situation our normal recursion into children in QWidget::destroy() stops at the first widget without a window handle. When we then delete the top level QWindow, the QWindow destructor will delete any child QWindows, which includes our leaf QWidgetWindow. We should probably fix up QWidget::destroy to continue looking for children, even if we don't destroy the current child. But independently of that we should make sure the QWidgetWindow cleans up when it's being deleted, regardless of how it ended up there. There's further room to clean up the deleteTLSysExtra() function and friends, but that's been left for a later time. Fixes: QTBUG-120509 Pick-to: 6.7 6.6 6.6.2 6.5 Change-Id: Ib691df164d7c9c83cb464c0a6bf3bc2116e8ca43 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Do more QRhiWidget cleanups based on API reviewLaszlo Agocs2024-01-222-9/+9
| | | | | | Pick-to: 6.7 Change-Id: I339fb2ac2546b9d7b4b88cba89191e7a4311017f Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QMetaTypeModuleHelper: mark instances constexprMarc Mutz2024-01-191-1/+1
| | | | | | | | | | Static and thread-local objects should be constexpr or constinit if possible. Task-number: QTBUG-100485 Pick-to: 6.7 6.6 6.5 Change-Id: I29088798a50d6278252c9088e7c191c4214b2e5b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QMetaTypeModuleHelper: suppress cppcoreguidelines-virtual-class-destructorMarc Mutz2024-01-181-0/+1
| | | | | | | | | | | | | | | | | | | | Says clang-tidy: destructor of '(unnamed struct at qmetatype.cpp:966:14)' is public and non-virtual in file:src/corelib/kernel/qmetatype.cpp line:966 col:14 static const struct : QMetaTypeModuleHelper Yes, these classes are polymorphic (because the base class is). Yes, the destructor is non-virtual (because the base class' one isn't, but it's also protected, so fine). But these classes are not used as base classes, so suppress the warning. Pick-to: 6.7 6.6 6.5 6.2 Change-Id: I75be86bca36a4a0e93d72acb1a0d2fe0dca1c505 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Update QRhiWidget API based on review commentsLaszlo Agocs2024-01-183-62/+68
| | | | | | | | | | | | | | | | | | Spell out some API names in enum. Some functions are now protected. Remove property for autoRenderTarget. textureFormat -> colorBufferFormat. Used "fixed" instead of "explicit" and follow the above naming, so that explicitSize becomes fixedColorBufferSize. Pick-to: 6.7 Change-Id: I2fd6ad46033313a3febbb8846146021d5dd11010 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Widgets: pass widget to QStyle::pixelMetric()Christian Ehrlicher2024-01-161-1/+1
| | | | | | | | | | | | Make sure to pass the widget to QStyle::pixelMetric() as some styles might use this (e.g. the new windows styles) to determine the correct pixel metric. Pick-to: 6.7 6.6 6.5 6.2 Task-number: QTBUG-1857 Change-Id: I5c32f5af8b284749732b610e56b4e3d8c8ed1946 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: David Faure <david.faure@kdab.com>
* Widgets: Use pmf-style connectsChristian Ehrlicher2023-12-216-15/+15
| | | | | | | | | | Replace some more string-based connects with pmf-style to trigger a compiler error instead a runtime error if a signal or slot does no longer exists. Pick-to: 6.7 Change-Id: Ibc047cc935885a30ea58367fa97e9f962b87ca2c Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* QWindowContainer: Don't embed a QWidgetAxel Spoerl2023-12-211-0/+21
| | | | | | | | | | | | | | | | | | | | | | | | Embedding a QWidget in a window container (via its windowHandle()) may cause crashes, e.g. during drag & drop and when the application goes out of scope. If a QWidget->windowHandle() is attempted to be embedded in a window container, return the pointer to the widget instead of creating a container. Add an autotest. Update documentation. [ChangeLog][QtWidgets][QWindowContainer] If createWindowContainer() is called with a QWidgetWindow argument, return pointer to the widget instead of new container. Pick-to: 6.7 Fixes: QTBUG-119113 Change-Id: Id052a03be13adce05bbd025d86270d265dfb662e Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* QWidget: deliver DragLeave events symmetricallyVolker Hilsheimer2023-12-201-2/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | If a widget received a DragEnter event that it didn't accept, then the UnderMouse widget attribute gets set. But the drag manager never got a drag target, so the DragLeave event was never delivered, leaving the UnderMouse attribute set incorrectly. We always need to send DragLeave events to the receiver, even if the DragEnter or DragMove was not accepted. Otherwise we are not in balance, and the UnderMouse attribute will remain set. This is a change of behavior and a very old bug, so only fixing this in unreleased branches. Test case added to verify that explicitly generated drag events result in the correct enter/leave events. [ChangeLog][QtWidgets][QWidget] DragLeave events are now always sent to the widget the mouse is leaving, even if it didn't accept the DragEnter event. Fixes: QTBUG-50403 Pick-to: 6.7 Change-Id: I5eae49da000fb4fea81f1767f0e73a06a6b78975 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de> Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Sync QWindow visible state during QWidget destructionTor Arne Vestbø2023-12-201-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | A call to QWidget::destroy() will end up in QWindow::destroy(), which calls QWindow::setVisible(false). A call to QWindow::setVisible(false) on a widget's window will under normal circumstances end up in QWidgetPrivate::setVisible(), which in turn recurses back into QWindowPrivate::setVisible(), via QWidgetPrivate::hide_helper(), ensuring that the QWindow internal state is updated, visibleChanged emitted, and show/hide events sent. Durin QWidget::destroy() we end up in QWindow::destroy(), which calls QWindow::setVisible(false), but in this case the widget no longer has Qt::WA_WState_Created, so the hide_helper() call is skipped, and the corresponding QWindow is not kept in the loop. To work around this we could have checked for windowHandle() instead of Qt::WA_WState_Created before calling hide_helper(), but that had many other side effects, so we opt for a more targeted fix. Pick-to: 6.7 6.6 6.5 Change-Id: I68f80e5f7df9ee811afcd274a7ee4de31a110da5 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Set correct content size for tool tip labelSanthosh Kumar2023-12-151-3/+5
| | | | | | | | | | | | | | | | The tool tip content size uses an incorrect content margin, when it's constructed. This content margin has been reset to correct value when tool tip is positioned using placeTip(). But after that, the content size not been recalculated. This patch triggers updatesSize() to calculate content size with updated content margin values. Fixes: QTBUG-119752 Pick-to: 6.7 6.6 6.5 Change-Id: I454c8528505686f2724b897e4002f78f3049149a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>