summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidget.cpp
Commit message (Collapse)AuthorAgeFilesLines
* wayland: Add xx-session-management-v1 supportDavid Edmundson4 days1-4/+17
| | | | | | | | | | | | | | | | | | This is powered by the xx-session-manager which is tagged as experiemntal. This is guarded by an env variable. Application level session IDs are exposed via QSessionManager. The public API for windows is exposed via the existing QSessionManager and QWidget::setWindowRole. As it's not widely supported the documentation in QWidget is left untouched for now. [ChangeLog][Third-Party Code] New protocol synced from wayland-protocols Change-Id: Ibfbef86c6e75f8b95433cbba69ca10a5abea9e21 Reviewed-by: Vlad Zahorodnii <[email protected]>
* wasm: a11y - Implement support for disabled attributeEven Oscar Andersen2025-06-131-0/+17
| | | | | | Fixes: QTBUG-137449 Change-Id: I6aa07c7108b5ad14c12e6f24e71b8dda12fec483 Reviewed-by: Morten Johan Sørvig <[email protected]>
* Doc: Fix auto-links to deprecated functionsDavid Boddie2025-05-311-2/+2
| | | | | Change-Id: Id4456eef3440734add2d804d186966e253335b7c Reviewed-by: Richard Moe Gustavsen <[email protected]>
* QWidget: don't re-polish when style did not changeChristian Ehrlicher2025-05-201-1/+1
| | | | | | | | | | | | Don't call style->unpolish()/polish() when the old and new style did not change which might happen when setting a style sheet as this might create an infinite loop and the style (re)sets some window attribute. Bailing out early is not an option here as newStyle might be a nullptr so q->style() will fall back to the application default style. Pick-to: 6.9 Fixes: QTBUG-133332 Change-Id: Ifa9ee4fdfa64b2768337e2d90b7bbaac5f3fcd70 Reviewed-by: Richard Moe Gustavsen <[email protected]>
* Widgets/Stylesheets: compile without FEATURE_style_stylesheetChristian Ehrlicher2025-05-011-0/+2
| | | | | | | | | | | Make sure to not compile the stylesheet sources when FEATURE_style_stylesheet is disabled, also don't include the relevant headers in this case. Pick-to: 6.9 Fixes: QTBUG-136341 Change-Id: I4fc2de2fcba004b93140809ef79374401209f14a Reviewed-by: Axel Spoerl <[email protected]>
* Widgets/Stylesheets: Remove double negations for stylehseet featureChristian Ehrlicher2025-05-011-11/+11
| | | | | | | | | | Replace ifndef QT_NO_STYLE_STYLESHEET antipattern by if QT_CONFIG(style_stylesheet). Pick-to: 6.9 Task-number: QTBUG-136341 Change-Id: I8f5d5ff0b7b5cce010df167977214bc92a9443b7 Reviewed-by: Axel Spoerl <[email protected]>
* Only default top levels to Qt::WA_ContentsMarginsRespectsSafeAreaTor Arne Vestbø2025-03-181-2/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When safe area margins are in play, such as on iOS and Android, or on macOS in 6.8 and above when the NSWindowStyleMaskFullSizeContentView styleMask has been set (manually or via Qt::ExpandedClientAreaHint in 6.9), then widgets with a layout will by default try to avoid the non- safe areas. This worked well as a safe default, ensuring widget applications filled the entire window with its background color, while constraining the layout of children to the safe area. However, for those that explicitly want to put content in the non-safe areas, by setting Qt::WA_ContentsMarginsRespectsSafeArea to false, the story was a bit cumbersome, as we set the attribute to true by default for all widgets. Meaning, any child widget put into the non-safe areas that itself had a layout (such as a push button) would also need the Qt::WA_ContentsMarginsRespectsSafeArea = false override. We now default Qt::WA_ContentsMarginsRespectsSafeArea to true only for top level widgets on creation, and leave it up to the user to manage the attribute for the other use-cases, as they then need to be in full control. [ChangeLog][QtWidgets] The Qt::WA_ContentsMarginsRespectsSafeArea attribute is no longer set by default for non-top-level widgets. Top level widgets still default to Qt::WA_ContentsMarginsRespectsSafeArea=true, so children are laid out in the safe areas, but overriding the attribute for the top level now allows placing widgets in the non-safe areas without also setting the Qt::WA_ContentsMarginsRespectsSafeArea attribute to false for every descendant widget that overlaps the non-safe area. Task-number: QTBUG-133215 Pick-to: 6.9 6.8 Change-Id: I7b1d420d730ee896ec2fb61aadacd94473dc9681 Reviewed-by: Axel Spoerl <[email protected]>
* Add QAccessible::LocationChanged to QWidgetEven Oscar Andersen2025-03-111-0/+6
| | | | | | | | | Issue the event when geometry has changed to match QML. Task-number: QTBUG-115926 Pick-to: 6.9 6.8 Change-Id: I31d87a2b07c1cbdb31063bdbf146f21310103798 Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget: init `data` in ctor, not Private::init()Marc Mutz2025-03-041-2/+1
| | | | | | | | | | | | | | | This should fix Coverity's hallucination that QWidget::data is used uninitialized, or, after 58b9250aea0b1b41c8cbd1033149371a93a5b2c1, dereferenced while it's still nullptr. Coverity-Id: 475552 Coverity-Id: 475551 Coverity-Id: 475550 Coverity-Id: 475549 Coverity-Id: 396828 Pick-to: 6.9 6.8 6.5 Change-Id: I49705b8bc44082fc68a59c2c98c4e37a6d841b19 Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget: Don't offset the clip region for windows using effectsChristian Ehrlicher2025-03-041-1/+1
| | | | | | | | | | | | | When a top-level widget has a graphic effect applied, QWidgetPrivate::clipToEffectiveMask() must not use the parent widget for the mask calculation as this prevents the loop below from bailing out in the first loop (w->isWindow()) and might mess up the clip region when there is a widget with a mask in the parent chain. Pick-to: 6.9 6.8 Fixes: QTBUG-131893 Change-Id: I5d5777e730bee309db21ad5eb65387d19321ee6c Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget: DRY the ctors, use ctor delegationMarc Mutz2025-03-031-7/+1
| | | | | | | | | | | | | | | | | | Don't repeat the body in the two QWidgets ctors, call one from the other instead. This will help fighting Coverity's hallucination that QWidget::data is used uninitialized, or, after 58b9250aea0b1b41c8cbd1033149371a93a5b2c1, dereferenced while it's still nullptr. Coverity-Id: 475552 Coverity-Id: 475551 Coverity-Id: 475550 Coverity-Id: 475549 Coverity-Id: 396828 Pick-to: 6.9 6.8 6.5 Change-Id: I1f9a8b93871143b420b9c8f247e49d57510a2379 Reviewed-by: Volker Hilsheimer <[email protected]>
* Use QThread::isMainThread() in a few placesThiago Macieira2025-02-261-1/+1
| | | | | | | | | | | | | | | It's thread-safe, whereas trying to load qApp isn't in Qt 6.x (will be in 7.0) and dereferencing it to call QObject::thread() will probably never be. It's also faster, being a single function call instead of two or three. This is not an exhaustive search, it's just a few places I found while searching for QThread::instance(). Pick-to: 6.9 6.8 Change-Id: I3b4e1c75bb3966e2cd2dfffd79bfc8a40f6cf40b Reviewed-by: Ivan Solovev <[email protected]> Reviewed-by: Mårten Nordheim <[email protected]>
* QObjectPrivate: encode the version number in the constructor parametersThiago Macieira2025-01-271-11/+1
| | | | | | | | | | | | | | | | Instead of allowing the code to start and then possibly fail at runtime. This isn't a 100% sure solution because it's a function call. With lazy symbol binding on some OSes, the mistake won't be noticed until the function call is attempted. However, most OSes now resolve *all* calls at load time so they can mark the GOT (or equivalent) pages read-only, meaning the loading of the library will fail. qversiontagging_p.h is a more sure way in OSes / executable formats it works on. Change-Id: If7867a37256b7141001dfffd9bd299bb1bbd7c63 Reviewed-by: Marc Mutz <[email protected]>
* Use old position to set window position after recreationMorteza Jamshidi2025-01-221-0/+2
| | | | | | | | | Like window state and visibility, the window position should also remain the same after the window is recreated. Fixes: QTBUG-128790 Change-Id: Iad8599da7ef83eff6a93f7f071e6b452491a0d87 Reviewed-by: Tor Arne Vestbø <[email protected]>
* widget: clear WA_OutsideWSRange when needed in QWidgetPrivate::create()Liang Qi2025-01-161-3/+6
| | | | | | | | | which follows the behavior in QWidgetPrivate::setGeometry_sys(). Pick-to: 6.9 6.8 Fixes: QTBUG-129698 Change-Id: Ia85e9470111eea9e3392cdf38c3da2db232ef065 Reviewed-by: Tor Arne Vestbø <[email protected]>
* QWidget::mapTo()/mapFrom(): Do not crash if parent argument is invalidEirik Aavitsland2024-12-121-5/+8
| | | | | | | | | | | | | | | These functions iterate through the parent hierarchy until the widget given as argument is found. If never found, the code would assert (in debug mode) or just silently crash (in release mode). No need to bring down the entire application just because some widget coordinate calculation is off. Instead, just emit a qWarning and return cleanly. Task-number: QTBUG-132072 Pick-to: 6.9 6.8 Change-Id: I4d13f46037cdcf855f76e040f941a8a7050ab12b Reviewed-by: Richard Moe Gustavsen <[email protected]>
* Introduce Qt::ExpandedClientAreaHintTor Arne Vestbø2024-11-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <[email protected]> Reviewed-by: Wladimir Leuschner <[email protected]>
* QWidget: delete 'extra' in dtorChristian Ehrlicher2024-11-111-0/+1
| | | | | | | | | | | | | | | Call d->deleteExtra() in dtor of QWidget to make sure it's cleaned up before QWidgetPrivate calls it which might access the already deleted QWidget through deleteTLSysExtra() / QWindowContainer::toplevelAboutToBeDestroyed(q). Amends 006cbf658ea1f5986bbe1baafa7c146780320661. Pick-to: 6.8 6.8.1 Task-number: QTBUG-130932 Change-Id: I9109072a457cc01abd5d1b4e844a3ed3309d942b Reviewed-by: Tor Arne Vestbø <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget::mapTo/FromGlobal(): Fix transformation in case of ↵Friedemann Kleint2024-11-011-2/+3
| | | | | | | | | | | | QGraphicsItem::ItemIgnoresTransformations Extract a helper returning the transform from QGraphicsViewPrivate::mapToViewRect() and use that. Fixes: QTBUG-128913 Pick-to: 6.8 Change-Id: Idc31f653c23cd7d0e5bbb8af560f010f01ac4d4b Reviewed-by: Axel Spoerl <[email protected]>
* QWidget::mapTo/FromGlobal(): Fix transformation for QGraphicsView with offsetsFriedemann Kleint2024-11-011-2/+2
| | | | | | | | | | | | | Amends 474af0a61d6154006966a775d186687aa8881708. The code had an error showing when the QGraphicsView was not at 0,0 in the window. Pick-to: 6.8 Task-number: QTBUG-128913 Task-number: QTBUG-52507 Change-Id: Ic228cc7e71ef54dd23c946b9d90f9c45aac793d9 Reviewed-by: Axel Spoerl <[email protected]>
* widgets: Send Window{AboutToChange}Internal when top level used RHIInho Lee2024-10-021-3/+4
| | | | | | | | | | | | | | | | When calling setParent for a top-level widget that used RHI it's not enough to check if the widget's parent used RHI, as that's always going to be false. Missing this results in not sending textureChildren events for the reparented widget. Amends eb4cb719257d3b57cd801273d4011579d8c81714 Fixes: QTBUG-129299 Pick-to: 6.8 6.8.0 Change-Id: I632d8d63ec56243cd6da2b196ad9651c28128f0b Reviewed-by: Tor Arne Vestbø <[email protected]>
* QWidgetWindow: fix enter/leave events not sent due to fractional scalingDavid Faure2024-08-301-3/+16
| | | | | | | | | | | | | | | | If widget A starts at y=0 and widget B starts at y=19, when the mouse moves from y=15 to y=18.6667, the code was doing childAt(p) with a rounded QPoint y=19 and finding B, but then the relative coord for B was set to -0.33333 so B wasn't under the mouse and didn't get an enter event (and since it's now the "last receiver", it doesn't get one later either when y is bigger). Add QWidget::childAt(QPointF) to fix this. Fixes: QTBUG-128391 Pick-to: 6.8 Change-Id: I76d4b711a8297648780bdd079eb67405ab12be14 Reviewed-by: Volker Hilsheimer <[email protected]>
* a11y: Notify of implicit window title changeMichael Weghorn2024-08-231-14/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit 25ab8ada1019adf9e88addd47acb0924831edc5a implemented sending a QAccessible::NameChanged event when the window name is used as accessible name and is changed by calling QWidget::setWindowTitle. Besides explicitly setting a new window title that way, the title can also be changed less explicitly: If the window title contains a corresponding "[*]" placeholder, changing the QWidget::windowModified property also results in a changed window title, with no QAccessible::NameChanged being sent so far. Move the logic introduced in 25ab8ada1019adf9e88addd47acb0924831edc5a further down into QWidgetPrivate::setWindowTitle_sys so it covers that case as well. While at it, also adjust this to skip retrieving the accessible here after all if accessibility is not enabled. This also needs 5178606a98be57f6dc5f3dddc1fa0f1e16c933e5 (for xcb; corresponding qtwayland still pending in Gerrit) for the event to actually be sent for the QWidget::setWindowModified case, because oldAccessibleName in QWidgetPrivate::setWindowTitle_sys would previously already be evaluated to the new accessible name by qt_setWindowTitle_helperHelper instead of using the old window title still set on the window before the actual title gets updated. Fixes: QTBUG-128296 Change-Id: Iaf80cd4019b6bc7383f425b45ece51f322a9e1c4 Reviewed-by: Volker Hilsheimer <[email protected]>
* widgets: Persist window Qt::Popup state when reparenting parent widgetTor Arne Vestbø2024-08-031-10/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | As a result of c956eb8eddb1b3608d7e3d332fbe55df5ec41578 we are now reparenting QWindows managed by QWidgets when the widget itself or any of its parent widgets are reparented. When reparenting a child widget from being a child to a top level, or top level to child, we need to know the new top level state to determine if the QWindow should have a QWindow parent or not. As the window flags of the widget are in flux during the reparenting, we were using the new window flags of the reparented widget to determine this. However, for QWidget children of the widget that's being reparented we can't use the window flags of the reparented widget. We must use the flags of the child itself. These flags are not in flux, so we can use QWidget::windowFlags() directly. Failing to propagate the child widget window flags was causing us to lose the transient parent relationship to its parent QWindow for popup windows. Fixes: QTBUG-127641 Fixes: QTBUG-125149 Task-number: QTBUG-122747 Pick-to: 6.8 6.7 6.5 Change-Id: I6dbc5ff5ad019b0f9188516ff3d645e860a9627b Reviewed-by: Axel Spoerl <[email protected]> Reviewed-by: Volodymyr Zibarov <[email protected]>
* a11y: Don't notify about name/desc/id change if there was noneMichael Weghorn2024-07-191-0/+9
| | | | | | | | | | | | | | | | | | | | Return early if the setters are called with the same string as is already set for the accessible name, description or identifier. This avoids sending an event wrongly notifying about a change when there was actually none. Extend the `tst_QAccessibility::accessibleIdentifier` autotest accordingly to test that no event is triggered when setting the same ID again. Thanks to Jan Arve Sæther for suggesting that in the previous change introducing the accessibleIdentifier property. (Implemented in a separate commit as it is a preexisting issue for accessible name and description.) Change-Id: Id3af3f0c4769e93e4970be9db87734df9ef84212 Reviewed-by: Jan Arve Sæther <[email protected]>
* a11y: Add property for QWidget's accessible IDMichael Weghorn2024-07-191-0/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 9ec1de2528b871099d416d15592fcc5ef9242a64 added an Identifier role to QAccessible that can be used to provide an identfier for reliable identification by assistive technologies, e.g. in automated tests. As discussed in that commit's Gerrit change, add a corresponding accessibleIdentifier property to QWidget to allow easily setting a specific identifier for widgets, in the same way that an accessible name or description can be set. This provides more flexibility than the default logic that generates an identifier to be used in platform bridges that is based on the object or class names of the objects in the widget's subtree. (The only alternative so far to set a particular ID not including the "object path" would have been to provide a custom QAccessibleInterface implementation with a corresponding QAccessibleInterface::text implementation.) Add an autotest testing both, the default platform bridge logic and that the the newly added property overrides that. [ChangeLog][QtWidgets][QWidget] Add an accessibleId property that allows to easily set a particular accessible identifier for QWidgets that can be used by assistive technologies to identify the widget. Change-Id: If24e138c7d8fe4c78f25d3f0629a9520c352bacc Reviewed-by: Volker Hilsheimer <[email protected]>
* Call QWidget::setVisible, not QWidgetPrivate, when showing childrenTor Arne Vestbø2024-07-041-5/+17
| | | | | | | | | | | | | | | | | | | | | | | | As part of 5ba0982b2879a1a4c13bf97467b8e5ad296e57a2 we started calling QWidgetPrivate::setVisible instead of QWidget::setVisible when showing children, to avoid setting ExplicitShowHide. Unfortunately some widget subclasses wrongly override setVisible to do initialization, which resulted in these widgets not running their init code. The documentation clearly specifies to use showEvent or Polish for this use case, but to avoid a regression we temporarily set a flag that prevents QWidget::setVisible from setting the ExplicitShowHide attribute. We can not rely on simply unsetting ExplicitShowHide after our call to QWidget::setVisible, as the call might recurse into logic that checks ExplicitShowHide and wrongly determines that the show is explicit. Fixes: QTBUG-126721 Fixes: QTBUG-126218 Pick-to: 6.7 6.8 Change-Id: Ibf88340b68cb4fcb20ce3d8ec5b76de0fd2d2551 Reviewed-by: Volker Hilsheimer <[email protected]>
* Remove unused qt_pressGrab in qwidget.cppShawn Rutledge2024-07-011-5/+1
| | | | | | | | I can't find evidence that it has been anything other than nullptr since the 2011 "Qt by Nokia" commit at least. Change-Id: I191f35b1fc8ca06c5c28696fed5c44f1e8c30f59 Reviewed-by: Tor Arne Vestbø <[email protected]>
* Straighten out various logging categoriesUlf Hermann2024-06-191-2/+2
| | | | | | | | | | | | Either make them static or declare them in a header. We want them to be static wherever possible, in order to reduce the number of visible symbols. If they can't be static, however, they should at least be declared in only one place. Task-number: QTBUG-67692 Change-Id: I6f3b596ed4f0adc9873dd0a5f54f055a991a6207 Reviewed-by: Thiago Macieira <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* Let QWindowContainer know when its top level is about to be destroyedTor Arne Vestbø2024-06-181-0/+4
| | | | | | | | | | | | | | | | | | | | | | | When the top level window that a QWindowContainer is in is about to be destroyed the QWindowContainer must reparent the contained window into a dummy window, as otherwise the destruction of the top level will bring down the contained window as well. We were notifying the window container about this situation when the window container was moved from being a top level itself, to being a child widget, but did not have any logic for other ways the window container could lose its parent QWindow. An example of this was when RHI-needs would result in recreating the top revel with a different RHI backend. We now have a last minute call to toplevelAboutToBeDestroyed in QWidgetPrivate::deleteTLSysExtra(). Fixes: QTBUG-126303 Pick-to: 6.8 6.7 6.5 Change-Id: I5b14e156956ae76a8f53cac31904eaadee9e791f Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget: do not send hide events to hidden childrenGiuseppe D'Angelo2024-06-111-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The logic in QWidgetPrivate::hideChildren sends hide events to all of its children, including the ones that are already hidden (and thus have received already a hide event). This breaks some "event counting" logic in QGraphicsScene, which (since it can be displayed in multiple views) keeps track of how many hide/show events it has received. It is possible to break this counter by having it receive several hide events in a row, which won't be matched by the same number of show events. These extra hide events may be generated by adding a QGraphicsView into a QTabWidget (or QStackedWidget), hiding *that*, and then changing the current index -- which shows/hides the children. This makes the counter go negative and break. Furthermore, a hide event is received after the widget has been made invisible, therefore one can't check for "was I visible when I received this hide event?" This commit changes the logic in QWidgetPrivate::hideChildren so that we don't do anything if the a child was already not visible. [ChangeLog][QtWidgets][QWidget] Widgets which are already hidden no longer receive hide events if they're made hidden again (for instance because an ancestor gets hidden). Change-Id: I73061b9d8bf33911778c9c30df33dbe43e9deaa3 Fixes: QTBUG-53974 Reviewed-by: Richard Moe Gustavsen <[email protected]> Reviewed-by: Tor Arne Vestbø <[email protected]> Reviewed-by: David Faure <[email protected]>
* QStyleSheet/QProxyStyle: Avoid deref after setWindowFlags in polishWladimir Leuschner2024-06-051-1/+3
| | | | | | | | | | | | | | When invoking setWindowFlags with a QStyleSheet and QProxyStyle set, a repolish is recursivly done creating a second QStyleSheetStyle in QWidgetPrivate::inheritStyle due to not cleared WA_SetStyle window flag. This leads to a use-after-free in the then following recursive call to QStyle::polish. This patch uses the previously create QStyleSheetStyle in the case that there is already a QStyleSheetStyle for the proxy. Fixes: QTBUG-125513 Pick-to: 6.8 6.7 Change-Id: I841bf68143e893d74ab7373b7a3d3d4ee2bce514 Reviewed-by: Richard Moe Gustavsen <[email protected]>
* widgets: Use per-surface-format RHI support and compositorTor Arne Vestbø2024-06-011-45/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The RHI support and compositor in QPlatformBackingStore were tied to the surface format of the top level window owning the backing store. This meant that inserting an RHI-enabled widget (QRhiWidget, QOpenGLWidget, QQuickWidget, QWebEngineView) into the widget hierarchy required recreating the top level window with a matching surface format that could support the RHI composition. It also meant that we could not have two RHI enabled widgets with different surface format requirements (Metal and OpenGL for example) in the same top level widget hierarchy. The recreation of the window had various visual side effects, such as temporarily switching out of full screen state, or the widget rendering a frame of black, as well as more serious problems such as not correctly restoring the window geometry. In addition, if client code had pulled out the winId() of the window, and did not invalidate these references on window destruction via QEvent::WinIdChange or QEvent::PlatformSurface, the client would reference stale window handles. Although this is a programming error (QWidget::winId() specifically mentions this requirement), we should avoid recreation if we can. We were already supporting flushing the backingstore to individual native child widgets, but always did so via a single RHI managed by the platform backingstore. By expanding QPlatformBackingStore to keep one set of RHI support and compositor per surface format, we can refine the logic in QWidget and QWidgetRepaintManager to not require recreating the top level. Native child widgets are then flushed independently, including any RHI textures and raster content that overlaps with the widget. We still assume that a single RHI support and compositor can be be used for multiple windows, as long as those windows have the same surface format. In the future, if needed, we can refine this to use one set per surface format e.g. Fixes: QTBUG-119221 Fixes: QTBUG-121181 Fixes: QTBUG-120096 Task-number: QTBUG-115652 Task-number: QTBUG-108344 Task-number: QTBUG-113557 Task-number: QTBUG-119309 Change-Id: I2635ed3d20c2fb76eab3b8130007dd656a0b93e5 Reviewed-by: Laszlo Agocs <[email protected]>
* Add QPaintDevice metric query to get precise fractional DPR valueEirik Aavitsland2024-05-301-0/+4
| | | | | | | | | | | | | | | | | | | | | 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ø <[email protected]>
* Widgets focus abstraction: Fix re-parentingAxel Spoerl2024-05-231-26/+54
| | | | | | | | | | | | | | | | | | | | | | | | | Focus abstraction in 58d5d4b7c2faaeaa2c2ccdabb3da6d37f9db880a 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 58d5d4b7c2faaeaa2c2ccdabb3da6d37f9db880a. Fixes: QTBUG-125257 Change-Id: Iff4f1d0d9b6117c50c8980dfb6eebfc6f6d4a710 Reviewed-by: Volker Hilsheimer <[email protected]>
* a11y: Notify of name change when setting window title used as a11y nameMichael Weghorn2024-05-221-0/+14
| | | | | | | | | | | | | | | | | | | 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 <[email protected]>
* Widgets: Don't assume layout handles safe area margins if widget opts outTor Arne Vestbø2024-05-161-2/+6
| | | | | | | | | | | | | | | | 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 <[email protected]>
* QWidget: fix render() in RTL modeChristian Ehrlicher2024-05-081-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 <[email protected]> Reviewed-by: Wladimir Leuschner <[email protected]>
* 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 <[email protected]>
* Set focus to the window container when contained window gains focusDoris Verria2024-04-221-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]> Reviewed-by: Laszlo Agocs <[email protected]>
* Abstract QWidget focus chain managementAxel Spoerl2024-04-041-136/+420
| | | | | | | | | | | | | | | | | | | 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 <[email protected]>
* Reparent QWindow children when reparenting QWidgetTor Arne Vestbø2024-03-141-39/+91
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 <[email protected]>
* QDialogButtonBox: Don't set focus in a dialog with StrongFocus childrenAxel Spoerl2024-03-071-0/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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ø <[email protected]>
* Add QWidgetPrivate::rhi() helper methodTor Arne Vestbø2024-03-011-0/+8
| | | | | | | | 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 <[email protected]>
* Add QWidgetPrivate::closestParentWidgetWithWindowHandle helper methodTor Arne Vestbø2024-03-011-0/+18
| | | | | | | | | 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 <[email protected]>
* 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 <[email protected]> Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Richard Moe Gustavsen <[email protected]>