summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
Commit message (Collapse)AuthorAgeFilesLines
* QWidgetWindow: Don't meddle with WA_WState_{Hidden/ExplicitShowHide}Tor Arne Vestbø2024-02-121-14/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In ccd3bf0871b81dfc09bb469b161f32dfb47ee53e we introduced code that would ensure that our call to QWidgetPrivate::setVisible() from QWidgetWindow would not result in WA_WState_Hidden being set. This code was later modified in 51300566ffe2ece2455e1d0479a556c5dbb3bb8e to apply to widgets that were explicitly shown/hidden. Unfortunately, the reset of the Hidden and ExplicitShowHide attributes would in some cases result in the widget having only ExplicitShowHide after being hidden, which is an invalid state. It also resulted in the widget having both Visible, Hidden, and ExplicitShowHide, if first being hidden via QWidget, and then shown via QWindow, which in turn prevented the widget from being hidden via QWidget::hide(). As we no longer rely on the adjustments to Hidden/ExplicitShowHide to fix QTBUG-73021, we can remove the entire logic. Any setVisible call to QWidgetWindow will either come from outside, in which case we should respect that and set Visible/Hidden via QWidgetPrivate, or the setVisible call is a result of QWidget itself (or its parent) showing the QWidgetWindow, in which case the QWidget visible state is already up to date and we skip the QWidgetPrivate::setVisible call. Task-number: QTBUG-121398 Task-number: QTBUG-73021 Fixes: QTBUG-120316 Pick-to: 6.7 Change-Id: I3174ad66b7e10c55aa99b7cb433267632169ca8f Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Add logging, clarifications, and tests for QWidget show/hide behaviorTor Arne Vestbø2024-02-011-0/+5
| | | | | | | Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: I94b4c90c3bd515279417c88497d7b9bd5a362eae Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* 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 <volker.hilsheimer@qt.io>
* Sync QWindow visible state during QWidget destructionTor Arne Vestbø2023-12-201-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | A call to QWidget::destroy() will end up in QWindow::destroy(), which calls QWindow::setVisible(false). A call to QWindow::setVisible(false) on a widget's window will under normal circumstances end up in QWidgetPrivate::setVisible(), which in turn recurses back into QWindowPrivate::setVisible(), via QWidgetPrivate::hide_helper(), ensuring that the QWindow internal state is updated, visibleChanged emitted, and show/hide events sent. Durin QWidget::destroy() we end up in QWindow::destroy(), which calls QWindow::setVisible(false), but in this case the widget no longer has Qt::WA_WState_Created, so the hide_helper() call is skipped, and the corresponding QWindow is not kept in the loop. To work around this we could have checked for windowHandle() instead of Qt::WA_WState_Created before calling hide_helper(), but that had many other side effects, so we opt for a more targeted fix. Pick-to: 6.7 6.6 6.5 Change-Id: I68f80e5f7df9ee811afcd274a7ee4de31a110da5 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* 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 <richard.gustavsen@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* 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 <volker.hilsheimer@qt.io>
* 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ø <tor.arne.vestbo@qt.io>
* 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 <shawn.rutledge@qt.io>
* 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ø <tor.arne.vestbo@qt.io>
* 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 <volker.hilsheimer@qt.io>
* 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 <shawn.rutledge@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
* 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 <volker.hilsheimer@qt.io>
* 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ø <tor.arne.vestbo@qt.io>
* 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 <marc.mutz@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* 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ø <tor.arne.vestbo@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* 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 <doris.verria@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* widgets: Fix typos in source code commentsJonas Kvinge2021-10-151-1/+1
| | | | | | Pick-to: 6.2 Change-Id: I22f71a53b0f7f0698450123343e25548c889c3e2 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* 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 <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* 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 <volker.hilsheimer@qt.io>
* 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 <morten.sorvig@qt.io> Fixes: QTBUG-46701 Pick-to: 6.2 Change-Id: Iacb6a2c8d5e880b16b0c8f0c9257ed94bed36f5b Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* 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 <qt_ci_bot@qt-project.org> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* 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 <richard.gustavsen@qt.io>
* QWidget: mark obsolete function isTopLevel() as deprecatedChristian Ehrlicher2020-12-091-1/+1
| | | | | | | | QWidget::isTopLevel() is deprecated and can be replaced 1:1 with isWindow(). Sadly it's was not marked with Q_DECL_DEPRECATED in 5.15 Change-Id: I4508fbde41927f3b82e47a75011179548325029d Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
* QtWidgets: Propagate event device when translating mouse eventsFriedemann Kleint2020-11-271-2/+4
| | | | | | | | | | | There are a few places left over, for example the QTextEdit creating mouse events in a timer and notably QGraphicsView. Task-number: QTBUG-88678 Task-number: QTBUG-46412 Pick-to: 6.0 Change-Id: I7ed23911be3b86b4b39fb478b947ec3b7a60761f Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
* Adjust code format, add space after 'if'Zhang Sheng2020-11-161-1/+1
| | | | | | Change-Id: Ice081c891ff7f4b766f49dd4bd5cf18c30237acf Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: hjk <hjk@qt.io>
* Track grab state in QPointingDevicePrivate::activePointsShawn Rutledge2020-09-161-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QQuickEventPoint instances were very long-lived and got reused from one event to the next. That was initially done because they were "heavy" QObjects; but it also became useful to store state in them between events. But this is in conflict with the ubiquitous event replay code that assumes it's OK to hold an event instance (especially a QMouseEvent) for any length of time, and then send it to some widget, item or window. Clearly QEventPoints must be stored in the QPointerEvent, if we are to avoid the need for workarounds to keep such old code working. And now they have d-pointers, so copying is cheap. But replay code will need to detach() their QEventPoints now. QEventPoint is useful as an object to hold state, but we now store the truly persistent state separately in an EventPointData struct, in QPointingDevicePrivate::activePoints. Incoming events merely update the persistent points, then we deliver those instead. Thus when event handler code modifies state, it will be remembered even when the delivery is done and the QPA event is destroyed. This gets us a step closer to supporting multiple simultaneous mice. Within pointer events, the points are moved up to QPointerEvent itself: QList<QEventPoint> m_points; This means pointCount(), point(int i) and points() can be non-virtual. However in any QSinglePointEvent, the list only contains one point. We hope that pessimization is worthwhile for the sake of removing virtual functions, simplifying code in event classes themselves, and enabling the use of the range-for loop over points() with any kind of QPointerEvent, not just QTouchEvent. points() is a nicer API for the sake of range-for looping; but point() is more suited to being non-const. In QML it's expected to be OK to emit a signal with a QPointerEvent by value: that will involve copying the event. But QEventPoint instances are explicitly shared, so calling setAccepted() modifies the instance in activePoints (EventPointData.eventPoint.d->accept); and the grabbers are stored separately and thus preserved between events. In code such as MouseArea { onPressed: mouse.accepted = false } we can either continue to emit the QQuickMouseEvent wrapper or perhaps QEvent::setAccepted() could become virtual and set the eventpoint's accepted flag instead, so that it will survive after the event copy that QML sees is discarded. The grabChanged() signal is useful to keep QQuickWindow informed when items or handlers change exclusive or passive grabbers. When a release happens at a different location than the last move event, Qt synthesizes an additional move. But it would be "boring" if QEventPoint::lastXPosition() accessors in any released eventpoint always returned the same as the current QEventPoint::xPosition()s just because of that; and it would mean that the velocity() must always be zero on release, which would make it hard to use the final velocity to drive an animation. So now we expect the lastPositions to be different than current positions in a released eventpoint. De-inline some functions whose implementations might be subject to change later on. Improve documentation. Since we have an accessor for pressTimestamp(), we might as well add one for timestamp() too. That way users get enough information to calculate instantaneous velocity, since the plan is for velocity() to be somewhat smoothed. Change-Id: I2733d847139a1b1bea33c00275459dcd2a145ffc Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Introduce QWindow::paintEvent with QPA plumbingTor Arne Vestbø2020-08-261-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The explicit paint event on QtGui and QPA level allows us to untangle the expose event, which today has at least 3 different meanings. It also allows us to follow the platform more closely in its semantics of when painting can happen. On some platforms a paint can come in before a window is exposed, e.g. to prepare the first frame. On others a paint can come in after a window has been de-exposed, to save a snapshot of the window for use in an application switcher or similar. The expose keeps its semantics of being a barrier signaling that the application can now render at will, for example in a threaded render loop. There are two compatibility code paths in this patch: 1. For platform plugins that do not yet report the PaintEvents capability, QtGui will synthesize paint events on the platform's behalf, based on the existing expose events coming from the platform. 2. For applications that do not yet implement paintEvent, QtGui will send expose events instead, ensuring the same behavior as before. For now none of the platform plugins deliver paint events natively, so the first compatibility code path is always active. Task-numnber: QTBUG-82676 Change-Id: I0fbe0d4cf451d6a1f07f5eab8d376a6c8a53ce8c Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
* Change QWindow/QWidget::map(To/From)(Global/Parent) to operate in floatFriedemann Kleint2020-07-141-5/+5
| | | | | | | | | | | | | | | Change the functions to operate in float and add the QPoint versions as overload calling them. This is more in-line with the event accessors using float and allows for removing some workarounds using a delta when converting touch points. Leave QPlatformWindow::map(To/From)Global() as is for now and add helpers for float. Change-Id: I2d46b8dbda8adff26539e358074b55073dc80b6f Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Refactor pointer event hierarchyShawn Rutledge2020-07-101-6/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some goals that have hopefully been achieved are: - make QPointerEvent and QEventPoint resemble their Qt Quick counterparts to such an extent that we can remove those wrappers and go back to delivering the original events in Qt Quick - make QEventPoint much smaller than QTouchEvent::TouchPoint, with no pimpl - remove most public setters - reduce the usage of complex constructors that take many arguments - don't repeat ourselves: move accessors and storage upwards rather than having redundant ones in subclasses - standardize the set of accessors in QPointerEvent - maintain source compatibility as much as possible: do not require modifying event-handling code in any QWidget subclass To avoid public setters we now introduce a few QMutable* subclasses. This is a bit like the Builder pattern except that it doesn't involve constructing a separate disposable object: the main event type can be cast to the mutable type at any time to enable modifications, iff the code is linked with gui-private. Therefore event classes can have less-"complete" constructors, because internal Qt code can use setters the same way it could use the ones in QTouchEvent before; and the event classes don't need many friends. Even some read-accessors can be kept private unless we are sure we want to expose them. Task-number: QTBUG-46266 Fixes: QTBUG-72173 Change-Id: I740e4e40165b7bc41223d38b200bbc2b403e07b6 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Add ; to Q_UNUSEDLars Schmertmann2020-07-071-2/+2
| | | | | | | | This is required to remove the ; from the macro with Qt 6. Task-number: QTBUG-82978 Change-Id: I3f0b6717956ca8fa486bed9817b89dfa19f5e0e1 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
* Remove unused virtual method QWindowPrivate::allowClickThroughVolker Hilsheimer2020-07-071-6/+0
| | | | | | | Always returned true, also in the QWidgetWindowPrivate override. Change-Id: I01d11ae6f85882b52ce397125f994eea663ffcb5 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Fix delivery of MouseMove events to newly opened popup windowsVolker Hilsheimer2020-07-011-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | Amend d934fd7f54eae24ea3f719890e2c4dbbc445049d, which was too naive in assuming that any change to the popup stack while a popup had been pressed into should result in mouse move events to be delivered without buttons. Instead, add a new flag that is set explicitly when the qt_popup_down widget is closed, and remove buttons from the move move events only when that flag is set. Add the sorely missing test case as well, even if we have to accept that not all behavior can be tested reliably. Ie. on macOS, the simulated mouse event differs from the event we do get from the QPA plugin or the system; on Xcb, some of the behavior depends on the window manager. This is something we could try to clean up for Qt 6. Change-Id: Ibf0a0a6fb7d401915057365788947e5a35aa20c3 Fixes: QTBUG-84926 Task-number: QTBUG-82538 Pick-to: 5.15 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Liang Qi <liang.qi@qt.io>
* Introduce QInputDevice hierarchy; replace QTouchDeviceShawn Rutledge2020-06-161-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We have seen during the Qt 5 series that QMouseEvent::source() does not provide enough information: if it is synthesized, it could have come from any device for which mouse events are synthesized, not only from a touchscreen. By providing in every QInputEvent as complete information about the actual source device as possible, we will enable very fine-tuned behavior in the object that handles each event. Further, we would like to support multiple keyboards, pointing devices, and named groups of devices that are known as "seats" in Wayland. In Qt 5, QPA plugins registered each touchscreen as it was discovered. Now we extend this pattern to all input devices. This new requirement can be implemented gradually; for now, if a QTWSI input event is received wtihout a device pointer, a default "core" device will be created on-the-fly, and a warning emitted. In Qt 5, QTouchEvent::TouchPoint::id() was forced to be unique even when multiple devices were in use simultaneously. Now that each event identifies the device it came from, this hack is no longer needed. A stub of the new QPointerEvent is added; it will be developed further in subsequent patches. [ChangeLog][QtGui][QInputEvent] Every QInputEvent now carries a pointer to an instance of QInputDevice, or the subclass QPointingDevice in case of mouse, touch and tablet events. Each platform plugin is expected to create the device instances, register them, and provide valid pointers with all input events. If this is not done, warnings are emitted and default devices are created as necessary. When the device has accurate information, it provides the opportunity to fine-tune behavior depending on device type and capabilities: for example if a QMouseEvent is synthesized from a touchscreen, the recipient can see which touchscreen it came from. Each device also has a seatName to distinguish users on multi-user windowing systems. Touchpoint IDs are no longer unique on their own, but the combination of ID and device is. Fixes: QTBUG-46412 Fixes: QTBUG-72167 Task-number: QTBUG-69433 Task-number: QTBUG-52430 Change-Id: I933fb2b86182efa722037b7a33e404c5daf5292a Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Replace calls to deprecated QEvent accessor functionsShawn Rutledge2020-06-081-33/+33
| | | | | | | Many of these were generated by clazy using the new qevent-accessors check. Change-Id: Ie17af17f50fdc9f47d7859d267c14568cc350fd0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Fix to crash in QWindow::event when delete this called on closeEventMiika Pernu2020-06-041-2/+6
| | | | | | | | | | | | | Starting from Qt 5.11 QWindow::event is called after QDialog::closeEvent which would cause a crash if "delete this" was called on closeEvent. The commit that changed this was e0b5ff4ad583befbecbcbe462998e3ed80899531. Added a check before QWindow::event call utilizing QPointer to prevent the function call in case object is destroyed by a user in close event handler. Change-Id: I64a4a0f3271714e55bf7e806177f0d8b39b67fa3 Fixes: QTBUG-84222 Pick-to: 5.15 5.12 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Remove obsolete storage, constructors and accessors in QEvent subclassesShawn Rutledge2020-05-121-4/+0
| | | | | Change-Id: I5c51244031ff40f1972106ad4fe27010c8be1193 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Remove dead code from src/widgetsVolker Hilsheimer2020-05-111-4/+0
| | | | | | | | Code that's removed via QT_VERSION(6, 0, 0) check is already no longer compiled. Change-Id: I70865f330a6260ac2e9cf2770d599a5b6f7bb7d4 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
* macOS: Remove all use of deprecated Q_OS_OSX defineTor Arne Vestbø2020-04-031-2/+2
| | | | | Change-Id: I49c285604694c93d37c9d1c7cd6d3b1509858319 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Merge remote-tracking branch 'origin/5.14' into 5.15Liang Qi2020-03-311-3/+5
|\ | | | | | | | | | | | | Conflicts: tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp Change-Id: Ifaa56153f5f0d687a6b4d94f84fcfa1e1751afd2
| * Send MouseMove events without buttons if the press closed the popupVolker Hilsheimer2020-03-301-3/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With nested popup widgets, pressing a mouse button on the lower popup will close the active popup. MouseMove events that are generated before the button is released again should not have that button included, as it is likely to result in incorrect state handling in the widget. This change removes all buttons from the MouseMove event, which is the second best option. This is mostly consistent with the behavior when closing a popup and no other popup remains. The widget underneath will get MouseMove events without the respective button included. This change doesn't include a fix for the final release event, which should ideally also not be delivered to the remaining popup, as it never got a corresponding press event. Qt has already reset the states in which it stores which widget received the press event at the time the release is generated, such as qt_button_down and qt_popup_down. So we can't separate a release grabbed by a newly opened popup (which we want) from a release to the popup that became active after closing (which we don't want). However, widgets can more easily work around this issue, and the risk of breaking things by changing the code further becomes too high. Change-Id: I603bbdbc7e7355952d96ab77c5e2d2f1e6f94987 Fixes: QTBUG-82538 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* | widgets: Sync client rect of paint-on-screen widgets during resizeTor Arne Vestbø2020-03-271-4/+4
| | | | | | | | | | | | | | | | | | | | | | Paint events are delivered with the client rect of the widget, and this applies to paint-on-screen widgets as well. The same goes for how the widget repaint manager tracks dirty rects. Internally we were also calling paintOnScreen() with client rects, so the use of geometry() in the resize handler was likely a bug/oversight. Change-Id: I1312ccf77218d1162e0971e4cbabaa80f49c852c Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* | widgets: Remove unused member QTLWExtra::inTopLevelResizeTor Arne Vestbø2020-03-191-1/+1
| | | | | | | | | | | | | | | | | | It was introduced in Qt 4.4 (e150f6a6e619) to work around slow resizes on Windows and X11 due to excessive painting, but has since been removed when old dead code never ported to QPA was removed in a2337f79ffd229. Change-Id: Ic14e714a02edb4194a445a6bb0759b601799fdc6 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
* | Avoid using deprecated QTabletEvent::device() methodAllan Sandfeld Jensen2020-02-281-1/+1
| | | | | | | | | | | | | | | | It was renamed to QTabletEvent::deviceType() in 882f340f62b8dc34633f5f296be12243b6e8999d. Change-Id: I070404bfc9a04144ae3565bfa3cc3a016040a07d Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>