summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
Commit message (Collapse)AuthorAgeFilesLines
...
* Restore event replay when a popup is closed by mouse press outsideShawn Rutledge2024-11-053-0/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | If a popup (such as a context menu or combobox) is open, and the user presses any mouse button outside the popup, Windows users expect the mouse event to be sent to whatever is under the mouse, while the popup closes. (So the popup must close on press, not on release.) QPlatformIntegration::ReplayMousePressOutsidePopup requests this platform-specific behavior in general, and the WA_NoMouseReplay attribute can disable it on specific widgets. e4ef0f03e6f1fddc397980fd7fbf6f6b829f16d9 removed this feature which was added to Qt 5 in 1f456b4cbb93e3fea699878d117900b703146213, based on doubt that we really needed it: and if we did, maybe we would need it in QtGui. But so far it seems the main excuse for doing it this way is that popups are sometimes opened with exec(). If the nested event loop handles the mouse press completely, and the QPA event is discarded, the outer loop has no chance of seeing it after exec() finishes. In Qt Quick, we don't use exec(); so let's assume that this continues to be needed only for widgets. At least we don't use extern sharing of a global bool in this version. Fixes: QTBUG-130138 Pick-to: 6.8 Change-Id: I95b5d24ee9bc8608655ed5c585d1d91a891fbad3 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: Defer repaint on screen/dpr change to expose/update requestTor Arne Vestbø2024-10-292-10/+24
| | | | | | | | | | | | | | | | | | | | | | | | When a window is moved from one screen to another, or the DPR of the screen changes, the QPA layer may emit a screen or DPR change event for the QWindow. This event, just like resize events, is not a request to paint the window. It's information to the window that may or may not result in the window requiring a repaint. If so, the window should request an update explicitly. If the platform itself determines that a screen or DPR change will require a repaint, it will deliver an expose event explicitly. Both the expose event and update request will be synchronized with the platform's drawing cycle, as opposed to drawing from a callback such as resize events or screen/DPR change events. Task-number: QTBUG-114873 Change-Id: I2fb78f177d84800f43764c36e85b554acce65a00 Reviewed-by: Oliver Wolff <[email protected]> Reviewed-by: David Edmundson <[email protected]> Reviewed-by: Axel Spoerl <[email protected]>
* QWidgetWindow::setFocusToTarget: Respect focus policies and proxiesDoris Verria2024-10-032-15/+18
| | | | | | | | | | | | | | | | | | | When calling QWidgetWindowPrivate::setFocusToTarget with Prev or Next target parameter, we were just setting focus to the next/prevInFocusChain() of the window's focusWidget(). This will bypass focus proxies and focus policies of the widget, which is wrong as it can end up giving eg: tab focus to a widget that does not have such focus policy. To fix, we should instead call QWidget::focusNextPrevChild which determines the right next/prev in the TAB focus chain. As this is a protected member of QWidget, implement a "wrapper" for it in QWidgetWindow which is a friend class of QWidget. Pick-to: 6.8 Task-number: QTBUG-121789 Change-Id: I1f4f5d85e7552926580906fdef6f0a456fe7486c Reviewed-by: Axel Spoerl <[email protected]> Reviewed-by: MohammadHossein Qanbari <[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]>
* QTapAndHoldGesture: port to QBasicTimer instead of handling timer IDsAhmad Samir2024-09-132-19/+12
| | | | | Change-Id: I132696340d46b906a61412222529ad51fc988390 Reviewed-by: Richard Moe Gustavsen <[email protected]>
* QWindowContainer: Respect WA_DontCreateNativeAncestorsPaul Olav Tvete2024-09-031-0/+2
| | | | | | | | | | | | | | | | | QWindowContainer forces a native window if it has a scroll area or an MDI area as an ancestor. This breaks if WA_DontCreateNativeAncestors is set, because the window container logic assumes that either there are no native widgets in the parent chain, or all of them are native. To avoid this problem, don't turn the window container native if it has the WA_DontCreateNativeAncestors attribute set. Task-number: QTBUG-128029 Pick-to: 6.8 Change-Id: Ifca50c9abd7175a0af5b62b196a86a463a11be31 Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]> Reviewed-by: Tor Arne Vestbø <[email protected]> Reviewed-by: David Edmundson <[email protected]>
* QWidgetWindow: fix enter/leave events not sent due to fractional scalingDavid Faure2024-08-306-21/+38
| | | | | | | | | | | | | | | | 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]>
* Make QWidgetPrivate::setVisible virtualTor Arne Vestbø2024-08-121-1/+1
| | | | | | | | | | | | | | | | | | | | Initially the function was used as a helper function for QWidget, implemented in da55a1b04121abd44d9c72e0c7cba7d72f16d4f2. But with e0bb9e81ab1a9d71f2893844ea82430467422e21 we started overriding it e.g. QDialog. This "worked" because QDialog itself would call the private helper, but left a footgun when called via a plain QWidget pointer, as we did in 5ba0982b2879a1a4c13bf97467b8e5ad296e57a2. That specific instance of the problem was solved by the change in fc4c6fb5f6bd6bd63b13f1f8b5b7a7289a5fd230, but the trap still exists. To ensure we can use the function in a polymorphic context in the future we make it virtual. Task-number: QTBUG-127806 Pick-to: 6.8 Change-Id: Ic0810c5439b1e696cfbf199e701f41217acc5742 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]>
* QWidget: Store initialScreen as QPointerDavid Edmundson2024-08-021-1/+1
| | | | | | | | | | | | | | | A Toplevel QWidget can hold a pointer to the screen where it will eventually show contents, before a QWidgetWindow is created which then takes precedence. The screen member of QWindows is always kept up-to-date when a screen is removed, but not the contents of a toplevel window. If a widget has setScreen called but is never shown, it has potentially dangling pointer which can cause issues in the future. Pick-to: 6.8 6.7 6.5 Change-Id: Ia7c80549e8b3c90a75cdde745487e87ecddaca63 Reviewed-by: Volker Hilsheimer <[email protected]>
* widgets: fix build using PCH with disabled featuresVladimir Belyavsky2024-08-021-2/+6
| | | | | | | | | | | | Fix build using PCH when -DFEATURE_abstractbutton=OFF and/or -DFEATURE_abstractslider=OFF Pick-to: 6.8 6.7 6.5 Change-Id: Ifdb8d6454c242cf98f5effcd2708ef797c99a26d Reviewed-by: Friedemann Kleint <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* gestures: fix build when -DFEATURE_scrollarea=OFFVladimir Belyavsky2024-08-021-1/+3
| | | | | | Pick-to: 6.8 6.7 6.5 Change-Id: I1c6089875024b2cb4e3787bf7dcc2f7e8e441bd2 Reviewed-by: Volker Hilsheimer <[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-193-0/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-042-5/+18
| | | | | | | | | | | | | | | | | | | | | | | | 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]>
* Revert "QGestureManager: use gesture owner target if topLevelAt returns nullptr"Liang Qi2024-07-011-2/+1
| | | | | | | | | | | | | | | This reverts commit 10c3dd87d3bc2e84d4f477888622f5fc7ed5d502. QtWidgets depends on the old QApplication::topLevelAt() behavior too much, especially for the single top level window case. It's not easy to be decoupled in this way. Task-number: QTBUG-113404 Task-number: QTBUG-125878 Task-number: QTBUG-126313 Pick-to: 6.8 6.7 6.5 Change-Id: Ica9753bfc85f54ef24ff3db12ea954b06b50b1f0 Reviewed-by: Volker Hilsheimer <[email protected]>
* Fix use after destruct for QWidgetWindowEven Oscar Andersen2024-07-011-0/+3
| | | | | | | | | | | | | | | | | | The call to destroy() happened in QWindow destructor, after ̃QWidgetWindow destructor had run. This is to late since destroy calls setVisible which ends up in QWidgetWindowPrivate which accesses QWidgetWindow. Calling destroy from ̃the QWidgetWindow destructor makes sure the object is still alive when setVisible is called. Tested manually by running the documentviewer demo as given in the bug Fixes: QTBUG-126456 Pick-to: 6.8 6.7 6.5 Change-Id: I2ca0384c453d59c5ffb9f3588d592701bebf3aa8 Reviewed-by: Tor Arne Vestbø <[email protected]>
* Straighten out various logging categoriesUlf Hermann2024-06-193-4/+4
| | | | | | | | | | | | 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]>
* Remove redundant qtimer.h includesAhmad Samir2024-06-113-3/+5
| | | | | | | | | | | | | | If QTimer isn't used in the file where it's included, remove the include. Fix files that depended on transitive includes. QMacPanGestureRecognizer: drive by change: classes inheriting from QObject should have Q_OBJECT macro in the definition. Change-Id: Ia8d71f4195a1ca643c9fcb14db41877413348d98 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Thiago Macieira <[email protected]> Reviewed-by: Edward Welbourne <[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-014-101/+104
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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]>
* Move popup management from QApplication to QGuiApplicationShawn Rutledge2024-05-313-115/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We need to be able to have true popup windows in Qt Quick and Controls, including handling the press-drag-release sequence to select one entry from a menu or combobox. After the mouse press, a new window is created. On some platforms (such as xcb), the new window gets window system grabs of both keyboard and mouse (QApplicationPrivate::openPopup() calls grabForPopup() and it actually works); while on others, the pre-existing window continues to get the whole sequence of mouse events until the release. In the latter case, Qt needs to forward events from the original window to the popup. Until now, the list of popups was QApplicationPrivate::popupWidgets. Now we track the open popups as a list of QWindows rather than QWidgets, in QGuiApplicationPrivate::popup_list, and add a set of static functions to manage that list. Functions such as QApplication::activePopupWidget() QApplicationPrivate::openPopup() and closePopup() are rewritten to make requests to QGuiApplicationPrivate. 276943c8b791ba5897dcdb1ecfda780ac33a090b made QGuiApplicationPrivate::closeAllPopups() virtual. That is now reverted, because we're putting QGuiApplication in charge of popup management and trying to minimize widget-specific behavior. So far, QApplicationPrivate::closePopup() is still overridden to take care of focus changes. So far, QtGui does not take care of closing popups when the user clicks outside: the active popup window gets those events, and needs to close itself if the click occurs outside. An attempt to move this logic raised some issues with legacy widget test cases. Using a touchscreen to press on QMenuBar and open a QMenu, drag to a menu item and release, is temporarily broken for now. The plan is to fix it in a subsequent patch. Task-number: QTBUG-68080 Task-number: QTBUG-69777 Change-Id: I02b5034987b5ee8909917d305f414c8b0db9c7f5 Reviewed-by: Richard Moe Gustavsen <[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]>
* Add way to override when to show context menuVolodymyr Zibarov2024-05-131-6/+3
| | | | | | | | | | | | | | | | 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ø <[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]>
* QWindowPrivate::setFocusToTarget: Add focusReason parameterDoris Verria2024-05-072-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 <[email protected]>
* Windows 11 style: simplify code to polish paletteVolker Hilsheimer2024-05-031-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 <[email protected]>
* 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: [email protected] Change-Id: Ib5e17d6ff52c2323a4013c80bf411e92b4c8ce9b Reviewed-by: Shawn Rutledge <[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]>
* 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ø <[email protected]>
* 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 <[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]>
* 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 <[email protected]> Reviewed-by: Axel Spoerl <[email protected]>
* 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 <[email protected]> Reviewed-by: Chris René Lerner <[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-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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>