summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Fix crash in QWidgetWindow::handleMouseEventJoerg Bornemann8 days1-0/+4
| | | | | | | | | | | | | | | | | User code that calls qApp->processEvents(); in context menu actions could lead to accesses of deleted memory. The reason was that the QWidgetWindow object was deleted as an effect of the event delivery in handleMouseEvents, and later accesses to object members in this method crashed. Pick-to: 6.8 6.10 Fixes: QTBUG-138419 Fixes: QTBUG-140132 Change-Id: Ia61e4380b29333875de9e1202c363d99d3f79e2a Reviewed-by: Oliver Wolff <[email protected]> Reviewed-by: Friedemann Kleint <[email protected]>
* CRA review: src/widgets/kernel/*MohammadHossein Qanbari2025-09-231-0/+1
| | | | | | | | | | | | No critical security level found for these reviewed files. QApplication, QWidget and QSizePolicy files are reviewed in separate patches. QUIP: 23 Fixes: QTBUG-135741 Pick-to: 6.10 6.8 Change-Id: Iee10987c9a99606bc0a4c1faeeed354be53076bb Reviewed-by: Volker Hilsheimer <[email protected]>
* Restore QContextMenuEvent for a popupNodir Temirkhodjaev2025-07-081-0/+14
| | | | | | | | | | | Amends e4ef0f03e6f1fddc397980fd7fbf6f6b829f16d9 Fixes: QTBUG-134757 Pick-to: 6.8 6.9 6.10 Change-Id: Ibb1c069be20057160c404efe9b6afc3ca7d6c15b Reviewed-by: Nodir Temirkhodjaev <[email protected]> Reviewed-by: Shawn Rutledge <[email protected]> Reviewed-by: Richard Moe Gustavsen <[email protected]>
* QWidgetWindow: fix UB (invalid downcast) in Private::handleDragEnterEvent()Marc Mutz2025-03-261-2/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The handleDragEnterEvent() function is not only called for QEvent::DragEnter, but also, in handleDragMoveEvent(), for QEvent::DragMove, in which case the fully-derived event passed as an argument is a QDragMoveEvent, and not its subclass QDragEnterEvent. Code in Qt seems to assume that it's ok to cast an object down to a more-derived class than the most-derived dynamic type, as long as no extra state is being added between the two, but C++ does not chare that view. Says UBSan: qwidgetwindow.cpp:1000:38: runtime error: downcast of address 0x7ffe7b34c6e0 which does not point to an object of type 'QDragEnterEvent' 0x7ffe7b34c6e0: note: object is of type 'QDragMoveEvent' 00 00 00 00 e0 62 70 42 aa 7f 00 00 3d 00 00 00 00 00 00 00 00 00 00 00 00 c0 58 40 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDragMoveEvent' Furtunately, handleDragEnterEvent() doesn't actually need its argument to be a QDragEnterEvent; QDragMoveEvent suffices, so we can just change the argument type back to QDragMoveEvent and remove the cast in handleDragMoveEvent(). Add a bit of \internal docs to describe the discrepancy between the function's name and argument type. Amends f8944a7f07112c85dc4f66848cabb490514cd28e. Picking all the way, because this is risk-less: Either the code compiles and then it works as before (minus the UB), or it doesn't compile. Pick-to: 6.9 6.8 6.5 5.15 Change-Id: I5be53b023d389902b43e9a896d074edea1c4ff2d Reviewed-by: Axel Spoerl <[email protected]>
* Don't pass along expose events for destroying QWidgetsTor Arne Vestbø2025-01-261-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | When closing a popup window on macOS, and the NSView needs display, for example due to the frame geometry having changed, the system will ask our NSView to display one last frame, via NSOrderOutAnimationProxyWindow initWithSnapshotOfWindow. If this happens during the close() that the QWidget destructor does, we no longer have a QWidget subclass to handle the corresponding paint event, so we'll end up flushing an empty frame, using that for the animation transition instead of the last valid frame of the widget. Worse, if the top level is using RHI to flush, the texture list might be stale, as there is currently no plumbing for a widget to tell QWidgetRepaintManager about it deleting a texture that was previously picked up and placed in the QPlatformTextureList. When this happens we end up crashing on dereferencing the stale texture. To mitigate these issues we now skip the expose event if the widget is already in ~QWidget. This potentially means the close animation will use a stale frame, but we can live with that. Pick-to: 6.9 6.8 6.5 Change-Id: Iabe1d97019923ee3a1a86039630095d00c966156 Reviewed-by: Volker Hilsheimer <[email protected]>
* Avoid dangling d-pointer deref in QWidgetWindow::handleMouseEventShawn Rutledge2025-01-201-0/+8
| | | | | | | | | | | | | | | | If you drag-and-drop a OpenGLWidget in Designer, the main window gets re-created when the OpenGLWidget is instantiated. So in general (in rare cases), at the end of QWidgetWindow::handleMouseEvent() we might have a different window, and therefore can't reliably call QWindowPrivate::maybeSynthesizeContextMenuEvent() without checking for a valid pointer. Amends 84a5f50c7766c99f62b22bb4388137e0aa8dd13d Pick-to: 6.9 Fixes: QTBUG-132912 Change-Id: I7b220b4daceab988aadabf9427ef6b2d5624e00d Reviewed-by: Friedemann Kleint <[email protected]>
* QWidgetWindow: send QContextMenuEvent even after accepted mouse pressShawn Rutledge2024-12-101-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | It would be more consistent if we could rely on the accepted state of the original QMouseEvent to decide whether to follow up with a QContextMenuEvent; but not all Qt widgets call ignore() on unhandled mouse events, both in Qt and in external libraries and applications (including some from KDE). So we should at least wait until Qt 7 to make this a requirement. It seems sensible to move the check into QWindow::event() rather than trying to distinguish the window type in maybeSynthesizeContextMenuEvent(). We merely output a categorized log message to indicate when the legacy behavior is in effect. Amends 84a5f50c7766c99f62b22bb4388137e0aa8dd13d [ChangeLog][QtWidgets] If your QWidget subclass depends on receiving QContextMenuEvent, and also handles mouse events directly, we recommend that you call ignore() on unhandled mouse events (such as right-button events). In Qt 7, we plan to stop sending QContextMenuEvent if the triggering mouse event is accepted. Fixes: QTBUG-132066 Pick-to: 6.9 Change-Id: I454813dab4c387112f161fc28a0ee94570013afa Reviewed-by: Volker Hilsheimer <[email protected]> Reviewed-by: Mitch Curtis <[email protected]>
* Move QContextMenuEvent synthesis from QWidgetWindow to QWindowShawn Rutledge2024-12-071-31/+32
| | | | | | | | | | | | | | | | | | | | | | | | ...and only if the original mouse event is not accepted. To that end, QGraphicsView must setAccepted(false) if the graphics scene did not accept the QGraphicsSceneMouseEvent. So a widget or a Qt Quick item or handler can handle the mouse events directly, to provide a consistent context-menu experience across platforms (for example to handle the press-drag-release gesture), but the fallback pattern follows the platform behavior. QWidgetWindow::handleMouseEvent() picks the receiver in its own way: often a leaf widget. It sets qt_last_mouse_receiver, so QWidgetWindow::handleContextMenuEvent() can deliver a mouse-originating QContextMenuEvent to the same receiver. A keyboard-originating QContextMenuEvent is delivered to the focus widget instead, as before. As a drive-by: fix an awkward word in qCDebug output. Task-number: QTBUG-93486 Change-Id: I4c1499120851a899acf2d7d4adaedaf9f42c3126 Reviewed-by: Mitch Curtis <[email protected]> Reviewed-by: Jan Arve Sæther <[email protected]>
* fix QApplciation with a QML popupWindowLiu Heng2024-11-301-7/+4
| | | | | | | | | | | | | Since 6.8, QML has popupWindow. When in popupModeMode, it does not necessarily have a popupWidget. Not checking whether popWidget is nullptr will cause the program to crash. Fixes: QTBUG-131664 Pick-to: 6.8 Change-Id: I624b62ef7185f0ab35215c2c34b0d6e9c80539a0 Reviewed-by: Tor Arne Vestbø <[email protected]>
* Add public QWindow API for safe area marginsTor Arne Vestbø2024-11-251-7/+4
| | | | | | | | | | | | | The margins are exposed as a simple QMargins, as this is covers the primary use-cases sufficiently at this point. A Q_PROPERTY is not added, as this would conflict with the explicit Qt Quick API that will also be added. Task-number: QTBUG-125374 Change-Id: I504c3000473de0b09272aa5a3e58ebf9a41aa942 Reviewed-by: Volker Hilsheimer <[email protected]> Reviewed-by: Assam Boudjelthia <[email protected]>
* Fix ubsan warning of illegal cast and illegal method callAllan Sandfeld Jensen2024-11-131-2/+2
| | | | | | | | | Avoid casting an event to a type it does not have. Instead use a static accessor class. Pick-to: 6.8 Task-number: QTBUG-99563 Change-Id: Ideb11779b1510cd10a27fb8bc40bcc8e4849bf15 Reviewed-by: Marc Mutz <[email protected]>
* Restore event replay when a popup is closed by mouse press outsideShawn Rutledge2024-11-051-0/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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]>
* widgets: Defer repaint on screen/dpr change to expose/update requestTor Arne Vestbø2024-10-291-9/+23
| | | | | | | | | | | | | | | | | | | | | | | | 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-031-15/+16
| | | | | | | | | | | | | | | | | | | 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]>
* QWidgetWindow: fix enter/leave events not sent due to fractional scalingDavid Faure2024-08-301-8/+8
| | | | | | | | | | | | | | | | 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]>
* 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]>
* widgets: Use per-surface-format RHI support and compositorTor Arne Vestbø2024-06-011-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-311-55/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 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]>
* QWindowPrivate::setFocusToTarget: Add focusReason parameterDoris Verria2024-05-071-2/+2
| | | | | | | | | 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]>
* QWindowPrivate: Introduce virtual setFocusToTargetDoris Verria2024-04-271-0/+33
| | | | | | | | | | | | | | | | | 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]>
* QWidgetWindow: Don't meddle with WA_WState_{Hidden/ExplicitShowHide}Tor Arne Vestbø2024-02-121-14/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In ccd3bf0871b81dfc09bb469b161f32dfb47ee53e we introduced code that would ensure that our call to QWidgetPrivate::setVisible() from QWidgetWindow would not result in WA_WState_Hidden being set. This code was later modified in 51300566ffe2ece2455e1d0479a556c5dbb3bb8e to apply to widgets that were explicitly shown/hidden. Unfortunately, the reset of the Hidden and ExplicitShowHide attributes would in some cases result in the widget having only ExplicitShowHide after being hidden, which is an invalid state. It also resulted in the widget having both Visible, Hidden, and ExplicitShowHide, if first being hidden via QWidget, and then shown via QWindow, which in turn prevented the widget from being hidden via QWidget::hide(). As we no longer rely on the adjustments to Hidden/ExplicitShowHide to fix QTBUG-73021, we can remove the entire logic. Any setVisible call to QWidgetWindow will either come from outside, in which case we should respect that and set Visible/Hidden via QWidgetPrivate, or the setVisible call is a result of QWidget itself (or its parent) showing the QWidgetWindow, in which case the QWidget visible state is already up to date and we skip the QWidgetPrivate::setVisible call. Task-number: QTBUG-121398 Task-number: QTBUG-73021 Fixes: QTBUG-120316 Pick-to: 6.7 Change-Id: I3174ad66b7e10c55aa99b7cb433267632169ca8f Reviewed-by: Richard Moe Gustavsen <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
* Don't set ExplicitShowHide on children when showing parent widgetTor Arne Vestbø2024-02-011-22/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 <[email protected]> Reviewed-by: Axel Spoerl <[email protected]>
* Add logging, clarifications, and tests for QWidget show/hide behaviorTor Arne Vestbø2024-02-011-0/+5
| | | | | | | Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: I94b4c90c3bd515279417c88497d7b9bd5a362eae Reviewed-by: Axel Spoerl <[email protected]>
* QWidget: Clean up state that depends on QWindow from ~QWidgetWindow()Tor Arne Vestbø2024-01-231-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 <[email protected]>
* Sync QWindow visible state during QWidget destructionTor Arne Vestbø2023-12-201-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | A call to QWidget::destroy() will end up in QWindow::destroy(), which calls QWindow::setVisible(false). A call to QWindow::setVisible(false) on a widget's window will under normal circumstances end up in QWidgetPrivate::setVisible(), which in turn recurses back into QWindowPrivate::setVisible(), via QWidgetPrivate::hide_helper(), ensuring that the QWindow internal state is updated, visibleChanged emitted, and show/hide events sent. Durin QWidget::destroy() we end up in QWindow::destroy(), which calls QWindow::setVisible(false), but in this case the widget no longer has Qt::WA_WState_Created, so the hide_helper() call is skipped, and the corresponding QWindow is not kept in the loop. To work around this we could have checked for windowHandle() instead of Qt::WA_WState_Created before calling hide_helper(), but that had many other side effects, so we opt for a more targeted fix. Pick-to: 6.7 6.6 6.5 Change-Id: I68f80e5f7df9ee811afcd274a7ee4de31a110da5 Reviewed-by: Richard Moe Gustavsen <[email protected]>
* QWidgetWindow: pass QPointF to QMouseEventChristian Ehrlicher2023-11-081-6/+6
| | | | | | | | | | | | | QWidgetWindow::handleMouseEvent() passed a QPoint to QMouseEvent which might result in a wrong result on high-dpi displays. Since the incoming event has a correct QPointF coordinate, use this for the QMouseEvent Pick-to: 6.6 Fixes: QTBUG-106262 Change-Id: Idbfdab19220cb06aa0a28eef4e6ab4cab1035d97 Reviewed-by: Richard Moe Gustavsen <[email protected]> Reviewed-by: Tor Arne Vestbø <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* Fix connections in QWidgetWindowDavid Edmundson2023-02-151-1/+1
| | | | | | | | | | A recent update moved handleScreenChange out of being a private slot. Porting to the new syntax fixes the warning and moves to a compile-time check. Pick-to: 6.5 Change-Id: Ibd85c6caf7dca051d669250a94a82fbddbd3435d Reviewed-by: Volker Hilsheimer <[email protected]>
* Introduce events for Window device pixel ratio changesDavid Edmundson2023-02-131-4/+18
| | | | | | | | | | | | | | | | | | | | | | | | | There is a mix between screen device pixel ratio. Currently we store the property on a per-window basis, but the change notifications are still on a per screen basis which can fall apart on edge cases. On wayland we are getting per window DPR changes without as useful screen change events so it's important to fix. It also has potential to clean up the Windows backend in the future where the backend is currently papering over the two concepts. This patch introduces two new events: A QWindowSystemInterface to trigger a window DPR change independently of a screen change. An event to notify windows the new DPR rather than needing to track signals on the screen. This happens either when the window dpr changes or implicitly through a screen change. This can deprecate an existing event ScreenChangeInternal so the value is reused and renamed for clarity. Change-Id: I637a07fd4520ba3184ccc2c987c29d8d23a65ad3 Reviewed-by: Tor Arne Vestbø <[email protected]>
* Deliver tablet events to the toplevel widget if there is no childVolker Hilsheimer2022-12-021-4/+3
| | | | | | | | | | | | | | | | | | | | | QWidgetWindow dispatched only tablet presses to the toplevel widget if no child was found at the position; other events, such as hover events, were discarded. The tabletTracking test case even documented that shortcoming in a comment. Fix that by falling back to the toplevel widget for any event. As before, only press events initialize the tablet grabbing target widget. Remove the now unneeded parent widget from the test case, and move the test class into the only test function that uses it. Amends ea615b421b76668332a3029ad31fa725b5bb9e58 and 8fd6cef3724b2d676c5f6ae235956192d85eac39. Pick-to: 6.4 Fixes: QTBUG-108747 Change-Id: I79050f1e063931e439945f64b50712dcc1ecb18c Reviewed-by: Shawn Rutledge <[email protected]>
* Propagate the event acceptance correctly with context menu on RMBMikolaj Boc2022-09-071-0/+2
| | | | | | | | | | The context menu event created in QWidgetWindow::handleMouseEvent does not forward its acceptance flag on which a client may rely. Task-number: QTBUG-106389 Backport-to: 6.4 6.4.0 Change-Id: I17a53ebd23b4ae0a2721c629f3ecc7aeec56233d Reviewed-by: Tor Arne Vestbø <[email protected]>
* Do not use QExposedEvent::region() in internal codeIvan Solovev2022-07-131-5/+2
| | | | | | | Task-number: QTBUG-104857 Pick-to: 6.4 6.3 6.2 Change-Id: I5ee41802ecc4d6291aaaa1f0efddd20027c1c1e4 Reviewed-by: Volker Hilsheimer <[email protected]>
* Harden drag and drop handling in widget windowLaszlo Agocs2022-07-011-7/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | User code in an event handler can do arbitrary things, including operations that lead to destroying the QWidgetWindow. An example is what the autotest does: reparenting the top-level widget to under another top-level upon the drop. Internally this leads to destroying the drop target's QWidgetWindow as the widget is now a child, not a top-level. In fact some of the existing drag and drop handling code seems to be prepared to handle the case of having the drag target widget destroyed in the user's event handler during a drag-move. But none of it is prepared for having the QWidgetWindow destroyed upon returning from forwardEvent(). The associated bug report has the same root cause, it is just popping up now via the new 6.4 behavior: adding a QOpenGLWidget to a widget hierarchy upon a drop leads to getting a new QWidgetWindow (if the window only had regular raster widgets before). To solve this, avoid touching members on 'this' after the forwardEvent(). It looks like the handlers for mouse events follow this pattern already, no member data is touched after forwarding events (not sure if that is intentional or just incidental but it is the safe solution, even if this is not feasible everywhere, but ideally input events should take this into account). Fixes: QTBUG-104596 Pick-to: 6.4 6.3 6.2 Change-Id: I96c704cadcd799fc5619b776e939dfdf313a27dd Reviewed-by: Shawn Rutledge <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* Replace QT_NO_ACCESSIBILITY with QT_CONFIG(accessibility)Allan Sandfeld Jensen2022-06-151-3/+3
| | | | | | | Pick-to: 6.4 Change-Id: Iee4bd8970810be1b23bdba65a74de912401dca65 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Marc Mutz <[email protected]>
* Use SPDX license identifiersLucie Gérard2022-05-161-38/+2
| | | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Task-number: QTBUG-67283 Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Lars Knoll <[email protected]> Reviewed-by: Jörg Bornemann <[email protected]>
* QtWidgets: use _L1 for for creating Latin-1 string literalsSona Kurazyan2022-05-021-2/+4
| | | | | | Task-number: QTBUG-98434 Change-Id: I310ea8f19d73a79d985ebfb8bfbff7a02c424360 Reviewed-by: Volker Hilsheimer <[email protected]>
* Compose render-to-texture widgets through QRhiLaszlo Agocs2022-03-111-16/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QPlatformTextureList holds a QRhiTexture instead of GLuint. A QPlatformBackingStore now optionally can own a QRhi and a QRhiSwapChain for the associated window. Non-GL rendering must use this QRhi everywhere, whereas GL (QOpenGLWidget) can choose to still rely on resource sharing between contexts. A widget tells that it wants QRhi and the desired configuration in a new virtual function in QWidgetPrivate returning a QPlatformBackingStoreRhiConfig. This is evaluated (among a top-level's all children) upon create() before creating the repaint manager and the QWidgetWindow. In QOpenGLWidget what do request is obvious: it will request an OpenGL-based QRhi. QQuickWidget (or a potential future QRhiWidget) will be more interesting: it needs to honor the standard Qt Quick env.vars. and QQuickWindow APIs (or, in whatever way the user configured the QRhiWidget), and so will set up the config struct accordingly. In addition, the rhiconfig and surface type is (re)evaluated when (re)parenting a widget to a new tlw. If needed, this will now trigger a destroy - create on the tlw. This should be be safe to do in setParent. When multiple child widgets report an enabled rhiconfig, the first one (the first child encountered) wins. So e.g. attempting to have a QOpenGLWidget and a Vulkan-based QQuickWidget in the same top-level window will fail one of the widgets (it likely won't render). RasterGLSurface is no longer used by widgets. Rather, the appropriate surface type is chosen. The rhi support in the backingstore is usable without widgets as well. To make rhiFlush() functional, one needs to call setRhiConfig() after creating the QBackingStore. (like QWidget does to top-level windows) Most of the QT_NO_OPENGL ifdefs are eliminated all over the place. Everything with QRhi is unconditional code at compile time, except the actual initialization. Having to plumb the widget tlw's shareContext (or, now, the QRhi) through QWindowPrivate is no longer needed. The old approach does not scale: to implement composeAndFlush (now rhiFlush) we need more than just a QRhi object, and this way we no longer pollute everything starting from the widget level (QWidget's topextra -> QWidgetWindow -> QWindowPrivate) just to send data around. The BackingStoreOpenGLSupport interface and the QtGui - QtOpenGL split is all gone. Instead, there is a QBackingStoreDefaultCompositor in QtGui which is what the default implementations of composeAndFlush and toTexture call. (overriding composeAndFlush and co. f.ex. in eglfs should continue working mostly as-is, apart from adapting to the texture list changes and getting the native OpenGL texture id out of the QRhiTexture) As QQuickWidget is way too complicated to just port as-is, an rhi manual test (rhiwidget) is introduced as a first step, in ordewr to exercise a simple, custom render-to-texture widget that does something using a (not necessarily OpenGL-backed) QRhi and acts as fully functional QWidget (modeled after QOpenGLWidget). This can also form the foundation of a potential future QRhiWidget. It is also possible to force the QRhi-based flushing always, regardless of the presence of render-to-texture widgets. To exercise this, set the env.var. QT_WIDGETS_RHI=1. This picks a platform-specific default, and can be overridden with QT_WIDGETS_RHI_BACKEND. (in sync with Qt Quick) This can eventually be extended to query the platform plugin as well to check if the platform plugin prefers to always do flushes with a 3D API. QOpenGLWidget should work like before from the user's perspective, while internally it has to do some things differently to play nice and prevent regressions with the new rendering architecture. To exercise this better, the qopenglwidget example gets a new tab-based view (that could perhaps replace the example's main window later on?). The openglwidget manual test is made compatible with Qt 6, and gets a counterpart in form of the dockedopenglwidget manual test, which is a modified version of the cube example that features dock widgets. This is relevant in particular because render-to-texture widgets within a QDockWidget has its own specific quirks, with logic taking this into account, hence testing is essential. For existing applications there are two important consequences with this patch in place: - Once the rhi-based composition is enabled, it stays active for the lifetime of the top-level window. - Dynamically creating and parenting the first render-to-texture widget to an already created tlw will destroy and recreate the tlw (and the underlying window). The visible effects of this depend on the platform. (e.g. the window may disappear and reappear on some, whereas with other windowing systems it is not noticeable at all - this is not really different from similar situtions with reparenting or when moving windows between screens, so should be acceptable in practice) - On iOS raster windows are flushed with Metal (and rhi) from now on (previously this was through OpenGL by making flush() call composeAndFlush(). Change-Id: Id05bd0f7a26fa845f8b7ad8eedda3b0e78ab7a4e Reviewed-by: Tor Arne Vestbø <[email protected]>
* Make QGuiApplicationPrivate::lastCursorPosition.toPoint() safe to useShawn Rutledge2022-02-221-1/+1
| | | | | | | | | | | | | | | | | | | QGuiApplicationPrivate::lastCursorPosition is initialized with qInf(); so before Qt has seen a mouse move event, attempting to convert to QPoint is an error. It's best to have one place where we do the qIsInf() check rather than several (and otherwise prefer using the QPointF as-is rather than converting to QPoint at all). Introduce a helper class that contains a QPointF, and provides a safe conversion to QPoint, as well as simple accessors for clients using QPointF. Fixes: QTBUG-52472 Task-number: QTBUG-45045 Change-Id: I83fad1bfb658e03fa876344552f1d5bb751d9f81 Pick-to: 6.2 6.3 Reviewed-by: Marc Mutz <[email protected]> Reviewed-by: Shawn Rutledge <[email protected]>
* Deliver context menu event with correct coordinates to widgets in popupsVolker Hilsheimer2021-12-221-1/+2
| | | | | | | | | | | | | | If a popup is open, Qt delivers events to the popup child under the mouse, so we need to correctly translate the local position of the context menu event to that child's coordate system. This is already done correctly for regular mouse events, so use the same logic here. Fixes: QTBUG-99371 Pick-to: 6.2 6.3 5.15 Change-Id: Ief24c755e76d4d1aa2304b06662ed26ae309f684 Reviewed-by: Tor Arne Vestbø <[email protected]>
* Centralize maybeLastWindowClosed checking in QWindowTor Arne Vestbø2021-10-201-10/+15
| | | | | | | | | | | | | | | | | Instead of plumbing QWidgetWindow close events via handleCloseEvent, we just implement closeEvent directly. This allows QWindow do save the state of the window/widget before the close event, so that we know whether we should trigger lastWindowClosed handling, even if the window was deleted as a result of the close event. This also relieves QGuiApplication and QApplication from dealing with the close logic in their notify functions, so that these functions can focus on the propagation of events -- not how the event is handled. Change-Id: I8b586b53a53b1df1d8630c1acb635c60f191bb4b Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* Deduplicate lastWindowClosed handlingTor Arne Vestbø2021-10-161-26/+8
| | | | | | | | | | | | | | | | | | | | | | | Whenever a window was closed, we had logic to check if it was the last window, and if so emitted lastWindowClosed and then tried to quit the application. But the automatic quit process also checked if there were any remaining windows, as this process could be triggered as a result of a QEventLoopLocker going out of scope. The two paths now share the same logic for determining if there are any remaining windows. The docs have been updated to reflect the original intent of the logic, dealing only with primary windows (top levels without a transient parent). This was how both the original code paths implemented their logic. For historical reasons the Qt::WA_QuitOnClose attribute is closely tied to the lastWindowClosed signal, and isn't merely limited to controlling whether we try an automatic quit when the last window closes. For now this behavior has been kept, but the docs have been updated to clarify how the attribute is handled in practice. Change-Id: If3d06b065236aad2e59e9091cac3146bc4cf79f6 Reviewed-by: Doris Verria <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* widgets: Fix typos in source code commentsJonas Kvinge2021-10-151-1/+1
| | | | | | Pick-to: 6.2 Change-Id: I22f71a53b0f7f0698450123343e25548c889c3e2 Reviewed-by: Richard Moe Gustavsen <[email protected]>
* Fix closing and showing a window with a native childVolker Hilsheimer2021-10-071-2/+5
| | | | | | | | | | | | | | | | | | | Closing a window with a native child results in the native child's QWidgetWindow being closed. That explicitly calls setVisible(false) on the child, which will still have the ExplicitShowHide attribute set from the initial (explicit) show. Even though we then reset the ExplicitShowHide, the WState_Hidden attribute will still be set, so Qt considers the window to have been hidden, and not show it again when the parent becomes visible. Add a test case. Fixes: QTBUG-96286 Fixes: QTBUG-79012 Fixes: QTBUG-71519 Change-Id: I482e6d5236c959d82ce66798176b259a3176972c Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Oliver Wolff <[email protected]>
* macOS: Remove special cases in enter/leave event handlingVolker Hilsheimer2021-09-241-4/+2
| | | | | | | | | | The Cocoa QPA plugin no longer tracks popups, but dispatches enter/leave events when popups show and hide. So the special handling in tests and QWidgetWindow can go away now. Change-Id: Ib6ef00689de231996e5e57ecdd8fd0d4c861d68b Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Tor Arne Vestbø <[email protected]>
* Deduplicate maybeQuitOnLastWindowClosed handlingTor Arne Vestbø2021-09-171-0/+34
| | | | | | | | | | | | | | | | | | The functionality now lives in QGuiApplication, and is triggered by QGuiApplication and QApplication after dispatching the close event to the window. The slight difference between how a Qt GUI and Qt Widget app determines if a window should contribute to the close-on-quit behavior has been abstracted into a QWindowPrivate helper. The additional checks that were in place for skipping out of the whole maybeQuitOnLastWindowClosed machinery have been kept. Task-number: QTBUG-53286 Change-Id: I81bd474755f9adb3a2b082621e5ecaa1c4726808 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Volker Hilsheimer <[email protected]>
* Don't exclude WA_DontShowOnScreen widgets for QWidgetWindow event processingTor Arne Vestbø2021-09-131-8/+8
| | | | | | | | | | | | | | | | | | The Qt::WA_DontShowOnScreen widget attribute does not limit whether a widget will be created (have a QWindow and corresponding QPlatformWindow). It only limits whether the widget will be shown. As a result, we need to respect and process incoming events on a QWindow level, just as any other window. Any considerations that may apply because of WA_DontShowOnScreen should happen further down in the event delivery. For example for the issue in 74aae00a4e8e70845e8092abbefa7830c386e66b, where QWidgetWindow::handleExposeEvent() cleared the WA_Mapped flag which was set by QWidgetPrivate::show_sys(). Change-Id: I187ebe14ea84538a3715f1d09fb1ba1ce93fcc82 Reviewed-by: Volker Hilsheimer <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
* Split up close handling in QWidget into a pre and post stepTor Arne Vestbø2021-09-071-2/+2
| | | | | | | | | | If we are the one initiating the close (from Qt Widget land), we want to mark the widget as closing as early as possible. Clarified the role of close_helper by renaming it to handleClose. Change-Id: Iae250a0ae1583d743c59e99fcb99fdf18d2a1882 Reviewed-by: Volker Hilsheimer <[email protected]>
* QWidget: close the QWindow in QWidget::closeVolker Hilsheimer2021-09-021-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | We want to close the window, end full screen mode on macOS, and free platform resources. This is all done by QWindow::close. QWindow::close closes the platform window, triggering a closeEvent to QWidgetWindow, which then calls QWidgetPrivate::close_helper. This way, closing a window via QWidget::close, QWindow::close, or interactively by the user are all equivalent. The QCloseEvent generated by the widget needs to be spontaneous for window-system generated events (i.e. the user clicked the close button), and non-spontaneous if the window closes because of a call to QWindow::close. To keep track of whether the event originated in an explicit call to QWindow::close, add a boolean to the QWindowPrivate. Add a test case that verifies that the window resources is destroyed, and that events are delivered as they should. Done-with: Morten Johan Sørvig <[email protected]> Fixes: QTBUG-46701 Pick-to: 6.2 Change-Id: Iacb6a2c8d5e880b16b0c8f0c9257ed94bed36f5b Reviewed-by: Tor Arne Vestbø <[email protected]>
* Refactor QApplication::translateRawTouchEvent to take a QTouchEvent*Volker Hilsheimer2021-08-261-3/+1
| | | | | | | | | | | | Both call sites just pass the data from an existing QTouchEvent through, so just pass the QTouchEvent through instead. Amends 20d4f45a132606f7a910050d468519108486e9cf. Pick-to: 6.2 Change-Id: If3b9508b83311889b58e109e7f64743985b8b178 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Shawn Rutledge <[email protected]>
* Windows: Fix dialog moving up after closing/reshowingFriedemann Kleint2021-01-151-1/+5
| | | | | | | | | | | | A resize event delivered after closing the platform window was causing the stored frame margins to be cleared. Bail out of QWidgetWindow::updateMargins() if the platform window is null. Pick-to: 5.15 Fixes: QTBUG-79147 Change-Id: Iebbc90c3cccafa209cd720baedf45affb3f3c2b8 Reviewed-by: Richard Moe Gustavsen <[email protected]>