Commit Graph

2344 Commits (ce33e476670c82bdf50344f4ab9bdbb17e6feaea)

Author SHA1 Message Date
Eirik Aavitsland a5953d20e2 Add QPaintDevice metric query to get precise fractional DPR value
For compatibility reasons, QPaintDevice needs to query subclasses for
device metrics as int values. To report fractional DPR values, they
have been multiplied with a large constant and divided back
afterwards. However, the loss of accuracy introduced by this, though
tiny, could still lead to rounding errors and painting artefacts when
the values where multiplied up for large coordinates.

Avoid this issue by adding a metric query that transports the full
floating point value encoded as two ints.

[ChangeLog][QtGui] Added new QPaintDevice metrics for querying
fractional device pixel ratios with high precision. Custom paintdevice
classes that support fractional DPRs are recommended to implement
support for these queries in metric(). Others can ignore them.

Fixes: QTBUG-124342
Change-Id: Ia6fa46e68e9fe981bdcbafb41daf080b4d1fb6d7
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2024-05-30 20:51:46 +02:00
Axel Spoerl 2d4993899f Widgets focus abstraction: Fix re-parenting
Focus abstraction in 58d5d4b7c2 was
supposed to be behavior-neutral. QWidgetPrivate::reparentFocusChildren
used QObject::findChildren() to find children inside and outside the
current focus chain. If the re-parented widget had only direct children
and the focus chain was equal to creation-order, the result was
identical to previous behavior.

When the re-parented widget had grandchildren, the behavior differred.
While not being detected by existing tests, it caused a regression.

Re-implement the previous logic: Iterate through the focus chain,
instead of relying on QObject::findChildren() returning a complete and
well-ordered list.

Modify tst_QWidget::focusChainOnReparent() in order to cover the
regression.

This amends 58d5d4b7c2.

Fixes: QTBUG-125257
Change-Id: Iff4f1d0d9b6117c50c8980dfb6eebfc6f6d4a710
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2024-05-23 01:12:32 +02:00
Michael Weghorn 25ab8ada10 a11y: Notify of name change when setting window title used as a11y name
When no explicit accessible name is set for a window,
QAccessibleWidget::text uses the window title instead for a
non-minimized window.

Send a QAccessible::NameChanged event when changing the
window title results in a change of the accessible name,
to ensure that the AT-SPI cache on Linux gets updated.

Extend tst_QAccessibility::mainWindowTest() to cover the scenario as well.

Note: The entire test function is skipped on platforms not supporting
window activation, e.g. Wayland.

Fixes: QTBUG-124192
Change-Id: I0fa7f683fb5969d6ba9878f6a506c4f192069799
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
2024-05-22 08:50:31 +02:00
Tor Arne Vestbø 35cdd8abf6 Widgets: Don't assume layout handles safe area margins if widget opts out
As an optimization when calculating the safe area margins for child
widgets we look at the parent hierarchy, and if we find a widget that
is in a layout, and that layout respects the widget's contents rect,
we assume the safe area margins are accounted for already.

But this relies on the widget the layout is operating on to not opt out
of the safe area margins affecting the contents rect. If it does, the
layout can't help us, and we need to fall back to computing the child
widget's safe area margins.

Task-number: QTBUG-125345
Change-Id: I2e2f7d292d2b2c3ecd2e2e95316c4d72b92db5d6
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
2024-05-16 20:17:06 +02:00
Volodymyr Zibarov 4585cacaa9 Add way to override when to show context menu
Add Qt::ContextMenuTrigger enum used with
QStyleHints::setContextMenuTrigger() to override default platform
behavior when to trigger context menu event.
The default is to show context menu on mouse press on
UNIX systems and on mouse release on Windows.

Give developer a possibility to override platform default behavior
to make cross platform application that behaves the same way on all
platforms

Task-number: QTBUG-93486
Change-Id: Ic832d3d8a7c355a8adb46868fff9cfd19988cf3c
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2024-05-13 22:32:34 +00:00
Christian Ehrlicher 5ea2481556 QWidget: fix render() in RTL mode
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>
2024-05-08 19:58:17 +02:00
Doris Verria 0678a8a00d QWindowPrivate::setFocusToTarget: Add focusReason parameter
The focusReason is also important when setting focus to the target, so
ammend 8c44064f62 and add this parameter
to the virtual method.

Change-Id: Id7800a366cbc1ce2ac26b3fec1e47ec9267a57bb
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2024-05-07 21:12:29 +02:00
Volker Hilsheimer 5cdac10b46 Windows 11 style: simplify code to polish palette
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 b733d31f27 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>
2024-05-03 14:04:51 +02:00
Doris Verria 8c44064f62 QWindowPrivate: Introduce virtual setFocusToTarget
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>
2024-04-27 20:13:20 +00:00
Axel Spoerl 913442a75a Widgets focus abstraction: Skip isFocusChainConsistent w/o logging cat
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 58d5d4b7c2.

Fixes: QTBUG-124666
Change-Id: Ia487b381ab45b052638b189bf56acaf4353b1a37
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
2024-04-26 17:26:07 +00:00
Liang Qi 10c3dd87d3 QGestureManager: use gesture owner target if topLevelAt returns nullptr
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>
2024-04-22 18:56:20 +02:00
Doris Verria f20be43b82 Set focus to the window container when contained window gains focus
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>
2024-04-22 16:01:01 +02:00
Tor Arne Vestbø d5bf42f75b Add preliminary support for Qt for visionOS
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>
2024-04-18 05:00:57 +02:00
Tor Arne Vestbø 0533d1d544 QWidget: Remove un-needed nullptr check for oldtlw
Added in 1bd755465e

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>
2024-04-17 20:41:36 +02:00
Jan Arve Sæther ddc80cc63d Implement QWindowContainer::minimumSizeHint()
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>
2024-04-12 17:12:18 +00:00
Axel Spoerl ef8e548cf1 QLayout: Consume ChildRemoved event, when layout is disabled
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>
2024-04-10 19:01:06 +00:00
Zhao Yuhang 079578eadd QWidget: fix link error in static build
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>
2024-04-06 13:14:25 +00:00
Tor Arne Vestbø 1bd755465e widgets: Invalidate RHI swapchain when window moves to new top level
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>
2024-04-04 21:42:14 +02:00
Axel Spoerl 58d5d4b7c2 Abstract QWidget focus chain management
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>
2024-04-04 16:13:29 +02:00
Tor Arne Vestbø 697e1b0397 Decouple rate-limiting of paint-on-screen widgets from top level widget
As part of eacd58d4e7, 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>
2024-04-04 01:26:56 +02:00
Axel Spoerl 268fa11eef QApplication: use focus abstraction instead of QWidget::focus_next/prev
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>
2024-03-18 17:21:22 +01:00
Tor Arne Vestbø c956eb8edd Reparent QWindow children when reparenting QWidget
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>
2024-03-14 13:50:36 +00:00
Axel Spoerl 78a3301372 QDialogButtonBox: Don't set focus in a dialog with StrongFocus children
A QDialogButtonBox with the first accept button becoming default, didn't
explicitly set focus on such a button in a QDialog.
d44413d526 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>
2024-03-07 23:00:33 +00:00
Ahmad Samir c610cfe328 Mention QChronoTimer in API docs
Change-Id: Iaf9fb31994f1580b2051dbd0b1b8eef2a218aa39
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-03-03 19:56:55 +02:00
Tor Arne Vestbø 7ff1285e7a Disconnect QWindowContainer::focusWindowChanged on destruction
Regression after 9e78256579.

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>
2024-03-03 17:07:55 +01:00
Tor Arne Vestbø f451b01791 Add QWidgetPrivate::rhi() helper method
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>
2024-03-01 20:41:30 +01:00
Tor Arne Vestbø b571634172 Add QWidgetPrivate::closestParentWidgetWithWindowHandle helper method
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>
2024-03-01 20:41:29 +01:00
Tor Arne Vestbø f517e85e90 Remove QWindowPrivate::compositing
It was added for Android in a4f50269f8,
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 2020ce5fd2.

Pick-to: 6.7 6.6 6.5
Change-Id: I8dafe959c54e09b3a974253e15d184365141d559
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
2024-03-01 20:41:29 +01:00
Tim Blechmann c26994ff15 Fix -Wimplicit-fallthrough for clang
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>
2024-03-01 03:04:06 +00:00
Axel Spoerl 2d1db53f9c QApplicationPrivate::dispatchEnterLeave: remove dead code
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>
2024-02-29 22:14:40 +01:00
Tor Arne Vestbø d31cc6dc7b QWidgetRepaintManager: Use textureChildSeen to determine deferred update
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 a4f50269f8.

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>
2024-02-27 16:18:06 +01:00
Paul Wicking 2fb8c2d5c3 Doc: Use QDOC_PROPERTY for QRhiWidget::autoRenderTarget
`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>
2024-02-26 18:59:02 +01:00
Lucie Gérard 039d51835f Correct license in widget/kernel
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>
2024-02-15 21:34:59 +01:00
Tor Arne Vestbø 986f8b361c QRhiWidget: Register cleanup callback also on first RHI init
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>
2024-02-14 18:51:29 +01:00
Tor Arne Vestbø 6fbbbef260 QRhiWidget: Tear down resources before window has changed
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>
2024-02-14 18:51:29 +01:00
Tor Arne Vestbø cce303b6a7 Add QPlatformIntegration::BackingStoreStaticContents capability
This was a feature in Qt 4, but the only platform that carried it over
to Qt 5 was Windows, in ab76593f18, 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>
2024-02-13 13:55:01 +01:00
Tor Arne Vestbø 1308f7e0b1 QWidgetWindow: Don't meddle with WA_WState_{Hidden/ExplicitShowHide}
In ccd3bf0871 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 51300566ff 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>
2024-02-12 21:09:18 +01:00
Tor Arne Vestbø 371d7ea19a Ensure QWidget::destroy() events and attributes match hiding the widget
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>
2024-02-12 21:09:18 +01:00
Tor Arne Vestbø aecedfed9a Restore window state of recreated top level widget, not closest QWindow
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 c88211d1e4

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>
2024-02-12 21:09:18 +01:00
Tor Arne Vestbø 97c02b80ae Harden WidgetAttributes debug stream operator
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>
2024-02-02 15:04:14 +01:00
Tor Arne Vestbø 5ba0982b28 Don't set ExplicitShowHide on children when showing parent widget
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>
2024-02-01 15:28:56 +01:00
Tor Arne Vestbø b393b26c70 Add logging, clarifications, and tests for QWidget show/hide behavior
Task-number: QTBUG-121398
Pick-to: 6.7
Change-Id: I94b4c90c3bd515279417c88497d7b9bd5a362eae
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
2024-02-01 15:28:56 +01:00
Tor Arne Vestbø 4634fbf34e Add QWidgetPrivate::isExplicitlyHidden() helper function
To aid readability.

Task-number: QTBUG-121398
Pick-to: 6.7
Change-Id: I3cb231584c2b7aee72e9f01c669fed1e01fbe475
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
2024-01-31 15:19:49 +01:00
Tor Arne Vestbø 3f2a9523a4 qWaitForWindowFocused: Pass timeout as QDeadlineTimer
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>
2024-01-25 18:37:47 +01:00
Tor Arne Vestbø 12203e94f5 QWidget: Clean up state that depends on QWindow from ~QWidgetWindow()
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>
2024-01-23 12:56:54 +00:00
Laszlo Agocs 80e7bcd368 Do more QRhiWidget cleanups based on API review
Pick-to: 6.7
Change-Id: I339fb2ac2546b9d7b4b88cba89191e7a4311017f
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2024-01-22 20:40:19 +01:00
Marc Mutz 88c3cd6e08 QMetaTypeModuleHelper: mark instances constexpr
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>
2024-01-19 10:15:25 +01:00
Marc Mutz 11d153ae1c QMetaTypeModuleHelper: suppress cppcoreguidelines-virtual-class-destructor
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>
2024-01-18 12:48:03 +01:00
Laszlo Agocs acebb97b58 Update QRhiWidget API based on review comments
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>
2024-01-18 12:48:03 +01:00
Christian Ehrlicher 43ce457cbd Widgets: pass widget to QStyle::pixelMetric()
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>
2024-01-16 00:01:43 +01:00