summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoawindow.mm
Commit message (Collapse)AuthorAgeFilesLines
* macOS: Expand and tighten plumbing of QWindow's requested color spaceTor Arne Vestbø2024-02-151-5/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A QWindow can have a requested target color space via its QSurfaceFormat. This allows users who know what color space their source material is in, or who do their own color matching, to ensure a consistent target color space. In the past we plumbed this to NSWindow's colorSpace property. This meant that you could only have one color space per top level, even if child windows were in play, and we could only set the color space if we were the ones creating the NSWindow, failing the color space request in cases where the window was embedded in a non-Qt window hierarchy. We now store the requested color space in our QNSView, and propagate it to both the IOSurfaces we use in QCALayerBackingStore, and to the view's layer, in case it's a CAMetalLayer. We also pick up any changes to the backing properties of the view, and ensure we update the color space accordingly. We still propagate the color space to NSWindow, as for OpenGL we don't use CAOpenGLLayer (which has a colorSpace property), but instead use NSOpenGLContext. This is not something we're going to change, so as a workaround we set the NSWindow color space, which does affect GL drawing via NSOpenGLContext. The granular color spaces we set on the IOSurfaces and CAMetalLayer will override the NSWindow state. Pick-to: 6.7 Change-Id: I5d9765d95140b8523ee09f70ff09a8c9400ffdc7 Reviewed-by: Pavel Dubsky <pavel.dubsky@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
* macOS: Deliver focus change events for foreign windowsTor Arne Vestbø2023-12-121-8/+2
| | | | | | | | | | If a foreign window becomes or loses focus window status, we should let QGuiApplication know about it. Pick-to: 6.7 Task-number: QTBUG-119287 Change-Id: I550d72fa13e1c38c9b89880857db9f9cbd7f6568 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't reset focus window to top level window when becoming keyTor Arne Vestbø2023-12-121-9/+18
| | | | | | | | | | | | | | | | | | | | | | | | | The NSWindow becomes the "key window" when it's the window that currently receives keyboard events. This happens when switching activation between windows of the same app, or when the app is made active, restoring the key window status. Since the keyWindow property only applies to top level windows we were skipping child windows when processing the event callback, but we then proceeded to pass the top level window() to handleFocusWindowChanged, instead of the QWindow of the key window's first responder (the view that receives key input sent to the top level key window). To fix this, we let each platform window send its own focus change event, if it's the first responder, instead of relying on the top level window to send it on behalf of possible child windows. This decoupling ensures that we also send focus changes when we're not part of a view hierarchy Qt controls. Task-number: QTBUG-119287 Fixes: QTBUG-119054 Pick-to: 6.7 6.6 6.5 Change-Id: Iac06fe800291e243432335169c52db7685e173df Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Rename QWSI::handleWindowActivated to QWSI::handleFocusWindowChangedTor Arne Vestbø2023-11-231-3/+3
| | | | | | | | | | | | | | | | | | | A single QWindow is QGuiApplication::focusWindow() at a time, and this window is typically also QWindow::isActive(), but other windows may also be QWindow::isActive(). For example, we treat any sibling or ancestor of the focusWindow as being QWindow::isActive() as well. In addition, in the case of non-QWindow child windows, we may have to query the platform for the activation state, which means we also need a way for the platform to reflect changes in this state through QWSI. The current API for this, QWSI::handleWindowActivated, is in practice a focus window change API, so as a first step let's rename it to better reflect what it's doing. Task-number: QTBUG-119287 Change-Id: I381baf8505dd13a4a829c961095a8d2ed120092b Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* Prevent reparenting of foreign window embedding containerTor Arne Vestbø2023-11-151-1/+4
| | | | | | | | | | | A foreign window used to embed a Qt window into it should not end up with changes to its own parent, as its only job is to give the embedded Qt window a parent handle. Pick-to: 6.6 Change-Id: If1bc89658fedf449d266bc0cc750c90b6a841a68 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
* Cocoa plugin: make sure popups' collection behavior knows about spacesTimur Pocheptsov2023-11-151-2/+3
| | | | | | | | | | | | | | | | It is possible to have several desktops on macOS, and even more - assign an app to one particular desktop. Then, moving such an app to a different desktop and using Qt's widgets like combobox may result in a strange behavior: since it's not a native 'combo button', we create a popup to show contents (list of items) of Qt's combobox and this popup may open on a 'wrong' desktop (the one to which the app is assigned to). To address this, combine the existing collection behavior for popups with NSWindowCollectionBehaviorMoveToActiveSpace. Pick-to: 6.6 6.5 Fixes: QTBUG-113507 Change-Id: Icbbc930fd1fc91089774340793e4bc452b939c1c Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Ensure foreign window can be reparented out of contained window againTor Arne Vestbø2023-11-131-4/+6
| | | | | | | | | A foreign window embedded into a Qt hierarchy must also support being removed from that window hierarchy. Pick-to: 6.6 Change-Id: Id4d08079ff19d67a8989937bc72602e8bd14b31b Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
* macOS: Clarify relation between occlusion state, hidden state, and exposeTor Arne Vestbø2023-11-121-5/+7
| | | | | | Pick-to: 6.5 6.6 Change-Id: I0e05332087fb3f876a9d2fadd9d7dcfd556d5734 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Work around key view loop crossing NSWindow boundariesTor Arne Vestbø2023-11-121-0/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | AppKit will in some cases set up the key view loop for child views, even if we don't set autorecalculatesKeyViewLoop, nor call recalculateKeyViewLoop ourselves. When a child window is promoted to a top level, AppKit will maintain the key view loop between the views, even if these views now cross NSWindows, even after we explicitly call recalculateKeyViewLoop. When the top level is then hidden, AppKit will complain when -[NSView _setHidden:setNeedsDisplay:] tries to transfer first responder by reading the nextValidKeyView, and it turns out to live in a different window. ERROR: Setting <View: 0x145e0cfd0> as the first responder for window <Window: 0x10f904de0>, but it is in a different window (<Window: 0x147104f00>)! This would eventually crash when the view is freed. The first responder will be set to nil. We mitigate this by a last second reset of the first responder, which is what AppKit also falls back to. It's unclear if the original situation of views having their nextKeyView pointing to views in other windows is kosher or not, but that's left for further investigations. Pick-to: 6.5 6.6 Change-Id: I63636afbba85abf73a38db9701f32656c42c59cc Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Check NSWindow as well when determining if setVisible can bail outTor Arne Vestbø2023-10-301-1/+1
| | | | | | | | | | | | | | | | In be268ae19731ab854931e43eea83e0e140ec2538 we made QCocoaWindow::setVisible idempotent by checking if NSView.hidden needed update. This failed to take into account the case when a window is moved from being a child window to a top level, where the window is still visible and the NSView's hidden state doesn't change, but we need to order in the NSWindow that we're now managing. We now check NSWindow.visible as well, if we're a top level window. Pick-to: 6.5 6.6 Change-Id: I94434d6ebfe2c9ece6eac7f83f17ead250ccc07a Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Don't refuse key window for direct transient parent of modal windowTor Arne Vestbø2023-10-251-2/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As explain in detail in 1bde2036051b3aaf5896ef1ff50c08c11ea1eba9, AppKit doesn't treat non-direct transient parents of a window modal window as being blocked by that modal window, but Qt does. To align with Qt, we worked around it by returning NO from canBecomeKeyWindow for windows that were blocked by a modal window. This however had an unintended side effect for native dialogs, due to the way we hide these dialogs. When a native dialog is closed, AppKit will look for another window to make key, and as part of that it checks canBecomeKeyWindow. The problem is that the modal blocked status has not been updated in QGuiApplicationPrivate at that point, so we tell AppKit it can't make the transient parent key. The modal blocked status is only updated once we hit QWidget::setVisible, at which point dialogs like QMessageBox and QColorDialog has already called setNativeDialogVisible(false) in its setVisible() override, triggering the close logic described above. To fix this properly we need to have the dialogs call the base class first when hiding, and then setNativeDialogVisible(), and also have the macOS native dialog helpers react to hide() by ordering out the window in case it didn't work at an earlier point. This kind of change is risky for Qt 6.5/6.6 however, so we opt for a simpler solution for now. By limiting the original workaround for non-direct transient parents not being blocked to just those transient parents, and only for window modal dialogs, we avoid the issue with failing to transfer key status. Task-number: QTBUG-104905 Fixes: QTBUG-118320 Pick-to: 6.6 6.5 Change-Id: Iabbca0b74a7db4e9821a9b60730d01fbad1425db Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Make QCocoaWindow::setVisible idempotentTor Arne Vestbø2023-10-251-0/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The implementation of QCocoaWindow::setVisible is not idempotent, as for modal windows it calls beginSheet/endSheet or starts/ends modal sessions, which will confuse the AppKit modal session stack. Once a window has been shown QWindowPrivate::setVisible hides/masks this issue, by returning early if the visibility has not changed, but during first show QWindowPrivate::setVisible will update the QWindow state, before creating the platform window. If the platform window then picks up the QWindow's visible state during creation, it will result in one QPlatformWindow::setVisible() call during creation, and another one via QWindowPrivate::setVisible after the platform window has been created. To fix this we can check the existing NSView.hidden state and skip the setVisible call if it's already up to date. But one complication is that our QCocoaWindow::setVisible has different behaviors depending on whether the window has been initialized yet or not, due to how handleGeometryChange skips sending geometry changes for uninitialized windows. So we need to also bail out if we're still initializing the window. This is fine, as we know we'll get a follow up setVisible call via QWindow, both when QWindow itself creates the platform window as part of setVisible, as well as when the user does a two step create and then show. For good measure we throw in a recursion check as well, in case some of the logic in QCocoaWindow::setVisible before we update NSView.hidden recurses back into QCocoaWindow::setVisible. Pick-to: 6.5 6.6 Change-Id: Ibdcf4859e58d6684aac4490126d35eb12fdd5943 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Explicitly mark NSView as needing display when unhiding itTor Arne Vestbø2023-10-241-0/+4
| | | | | | | | | | | AppKit doesn't do this automatically for us, and since we may have decided to not draw anything when the view was not exposed, we need to inform clients that its time to draw something now. Pick-to: 6.5 6.6 Change-Id: Ib2dd969632898ba5640d6848356acd1b97da652d Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Doris Verria <doris.verria@qt.io>
* macOS: Use [QNSWindow closeAndRelease] for closing and releasingTor Arne Vestbø2023-08-071-2/+1
| | | | | | | | Unifies code paths that end up closing and releasing the window. Pick-to: 6.6 Change-Id: Ie041079a22bbae0912df0406291c8146f02d0cd7 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Ensure foreign windows can be reparented via QWindow::setParent()Tor Arne Vestbø2023-08-031-4/+8
| | | | | | | | | | | | | | | | | | | In b64b0c7947f9f2b0ab4ed33fe526880f54e3981f we bailed out from QCocoaWindow::recreateWindowIfNeeded() for foreign windows, as we should not manage any NSWindows on their behalf. Unfortunately QCocoaWindow::recreateWindowIfNeeded() also took care of adding the view as a subview to the potential non top level view, which we do want for foreign views. Ideally we'd move the reparenting out of recreateWindowIfNeeded() and into QCocoaWindow::setParent(), but this is a more intrusive change, so for now just restore the original missing logic. Pick-to: 6.6 6.5 Change-Id: Ic35ebf94d4adc2f19cedb1cb6a5d0215a1c9c2b4 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* Fix typo in QCocoaWindow commentColin Snover2023-06-151-1/+1
| | | | | | | Pick-to: 6.6 6.5 Change-Id: Idea292bc2927ff9a534f06b054c26b4ab3ef1bea Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Disable minimize button for Qt::Dialog windows by defaultTor Arne Vestbø2023-06-031-0/+7
| | | | | | | | | | | Regression after 4c78ef80ca7573cd2eb054cdf1667837b43e6c58, where we moved the window titlebar button logic from QCocoaWindow's windowStyleMask function to updateTitleBarButtons. Fixes: QTBUG-114064 Pick-to: 6.5 Change-Id: Idb0870571e88fa2962af36decd9bc7b53c35664d Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Handle failure to create display link or invalid display linkTor Arne Vestbø2023-04-241-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | In some rare situations the display link may fail to create, or will be created in an uninitialized state: https://bugzilla.mozilla.org/show_bug.cgi?id=1201401#c123 When the latter happens the display link thread will crash in CVCGDisplayLink::getDisplayTimes(). Based on the Mozilla bug report, and subsequent patch, we can detect this situation via CVDisplayLinkGetCurrentCGDisplay(), so we follow the same approach, and then bail out: https://bugzilla.mozilla.org/show_bug.cgi?id=1201401#c158 Once we bail out we fall back to the timer based approach to delivering the update request. The next requestUpdate() will try to use the display link again, which will likely work this time around, as the display has had time to fully initialize. Pick-to: 6.5 Change-Id: Ib80fd792516d1e4e7f863a82755cbf00d1eb6c34 Reviewed-by: Robert Griebl <robert.griebl@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Synthesize cursor updates on QCocoaWindow::setWindowCursorTor Arne Vestbø2023-04-121-18/+20
| | | | | | | | | | | | | | | | | | | | | | | | The original issue for doing this was that invalidateCursorRectsForView would not result in an updateCursor callback in certain scenarios on macOS 11 and below. In macOS 13, improvements to how tracking areas work now result in also missing cursorUpdate calls when the mouse is pressed, which makes sense for tracking areas in general (you don't want a drag over a text field to reset the cursor to the I-bream), but not for our specific case of setting a cursor synchronously. To ensure the cursor is updated immediately, even if the mouse is pressed, we synthesize a updateCursor event, just like we did for the invalidateCursorRectsForView workaround. It's up to clients of QWindow to manage their setCursor calls to not happen during a drag operation, which we already manage in Qt Widgets. Pick-to: 6.5 6.2 Change-Id: I67d6e0f8e270b40da9879828455f4de943da7839 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* Pick up initial state of foreign windows instead of reflecting QWindowTor Arne Vestbø2023-03-281-12/+18
| | | | | | | | | | | | | | A foreign window can be used both for embedding a Qt window into a native window hierarchy, or for embedding a native window into a Qt window hierarchy. In the former case, we should not modify the foreign window in any way. Since the platform does not know anything about the intended use case at the time of the foreign window creation, it should avoid modifying the foreign window in any way, and should instead pick up the foreign window state and reflect that through QWindow. Pick-to: 6.5 Change-Id: Id2e39d101277ecebd656d615cea3e7f734a4b0a6 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't try to create or manage NSWindow of foreign windowsTor Arne Vestbø2023-03-281-0/+8
| | | | | | | | | | | A foreign window is a single NSView, and unlike our QNSView, where we in addition manage a NSWindow for top level windows we should treat the foreign window as just an NSView. It's not our place to neither create nor dispose of any NSWindows attached to the foreign window. Pick-to: 6.5 Change-Id: I88aa796c679be0489abf4999829d1378ba054bdc Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Simplify child window parenting in recreateWindowIfNeeded()Tor Arne Vestbø2023-03-281-3/+1
| | | | | | | | | The logic for this should ideally be handled in setParent(), but for now let's clean up the code a tiny bit. Pick-to: 6.5 Change-Id: Id2370d6704625038ab6b4fa246dea5d1c037371c Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Create NSView as initially hidden, to match QWindow behaviorTor Arne Vestbø2023-03-281-10/+5
| | | | | | | | | | | | | | | | | Initially attempted in 096b56f336e5bb994d46f073d55496d36d38e6b1, but that broke QQuickWindow::grabWindow(), which at the time was not prepared for grabbing non-visible windows. This is no longer an issue, as QQuickWindow::grabWindow() has fallback logic for non-renderable windows. QWidget::grab() also works fine, as it grabs from the backingstore directly. For top level windows we apply the visibility state to both the NSWindow (orderIn/Out), and to the NSView (hidden=YES/NO). Pick-to: 6.5 Change-Id: I617b292ca6bfba66e65b55941c5b002e415da88d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Apply QWindow properties to NSWindow when setting content viewTor Arne Vestbø2023-03-281-9/+1
| | | | | | | | | | | | | | | | | | | | | The main responsibility of QCocoaWindow::recreateWindowIfNeeded() is to decide if the platform window is top level or not, and if so needs an NSWindow or NSPanel accompanying it. Once that decision has been made, and we've created an NSWindow or NSPanel, and made the view the content view of this window, we need to apply the QWindow properties to the newly created NSWindow or NSPanel. But doing so in recreateWindowIfNeeded increases the complexity and responsibilities of the function, so we move the logic to [QNSWindow setContentView:] instead. This is analogous to applying the properties during [QNSWindow init], but since we are now the content view we can use the same code paths to apply the initial properties as we use when they are updated later on. Pick-to: 6.5 Change-Id: Idb4c812f4b22a029030bf4638357cf8628caea40 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Disable interaction for modally blocked transient parent windowsTor Arne Vestbø2023-03-201-4/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a window-modal window has a transient ancestor, Qt treats this ancestor window as modally blocked by the modal window, as if it had been a true non-transient parent of the modal window. Unfortunately, this is not how macOS natively behaves. Window-modal windows only block their direct parent, and AppKit will happily send events to any other top level window. This is different from how application modal windows work, where NSApplication will filter many events (but not all) in [[NSApplication _modalSession:sendEvent:]. Note that NSWindow.worksWhenModal has no effect in this situation, as that property is only considered by AppKit for application modal session are active (and NSApp.modalWidow returns non-nil). Instead of trying to replicate the event filtering that AppKit does, which would be fragile, we disable some of the effects these events could potentially have, by for example preventing modally blocked windows from becoming key, and temporarily disabling the close button in the title bar. One remaining issue is that, unlike with application modal windows, the modally blocked transient parents can still be ordered above the modal window. Fixing this requires informing the window server about the modally blocked state of the window, which we can't do using public APIs. Even returning NO from [NSWindow _allowsOrdering] is not sufficient. Task-number: QTBUG-104905 Pick-to: 6.5 Change-Id: I7e764a354f397ae6ef61304ca5442a4e1bb7589c Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Remove content border thickness members from QCocoaWindowTor Arne Vestbø2023-03-081-2/+2
| | | | | | | | | They were only set by QCocoaWindow::setContentBorderThickness(), which was removed in 19fc78e9672f4350a06790a9a0f0edba75244875. Pick-to: 6.5 Change-Id: Ia1b429c56c9627506023b76bddf878a4321d5f0b Reviewed-by: Doris Verria <doris.verria@qt.io>
* macOS: Class initialize QCocoaWindow membersTor Arne Vestbø2023-03-081-18/+1
| | | | | | Pick-to: 6.5 Change-Id: I76e107b676ce27526094f851ec23bb544689e32f Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Move setMask call out of recreateWindowIfNeededTor Arne Vestbø2023-03-081-2/+2
| | | | | | | | | It semantically applies during platform window initialization, and doesn't depend on the logic of choosing an appropriate NSWindow class. Pick-to: 6.5 Change-Id: Ia24a2deafc78ed4c79df766b6372ad64de2d0dde Reviewed-by: Doris Verria <doris.verria@qt.io>
* macOS: Don't set opacity on non-top level windows during NSWindow creationTor Arne Vestbø2023-03-081-4/+1
| | | | | | | | | | | | | | The opacity is a property of NSWindow. There's no point in pulling out the opacity from QWindowPrivate, as QWindow has a public accessor for it. And we don't need to guard the call with a check for non-1.0 opacity. If we want logic to avoid redundant calls to the platform APIs, they should be in the setter. Pick-to: 6.5 Change-Id: Ic9b8d1051f30d3b7e09dae14b9f22ca899d05865 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Remove QCocoaWindow::setContentBorderThicknessTor Arne Vestbø2023-02-151-10/+0
| | | | | | | | | | | | | Its only client was QMainWindow, but that use was removed in 3b8b47db6aaeb333f106cff57cc712b01d828302 and replaced with a call to setContentBorderEnabled. This effectively reverts 0caaf9966a8e4ea1e83de866020e61fd5ffaec1a. Pick-to: 6.5 Change-Id: Iaba4d5fd9256632b4a3b935e3fb30d7f5c39851e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Remove machinery for attaching NSToolBar to QWindowTor Arne Vestbø2023-02-151-20/+0
| | | | | | | | | | | | | | | | | It was only used by QMacToolBar in QtMacExtras, which no longer exists in Qt 6. Attaching a toolbar can be done manually via the NSWindow of the NSView retrieved from winId(). There are no public uses of the native interface in GitHub outside of Qt. Improvements we want to make to toolbars in QtWidgets and QtQuick in the future, possibly backed by native toolbars, would be done behind the scenes and would not need this API. This effectively reverts e8fd6b9604bac334404dc52daa63b9e6d9cd71d8. Pick-to: 6.5 Change-Id: I33b090fa19f9f3af029ae8c269efcf739a4b1b22 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Limit cursor update workaround to Monterey and belowTor Arne Vestbø2023-01-031-16/+18
| | | | | | | The AppKit issue has been fixed in Ventura. Change-Id: Ic2c0a0ed4ad52ef2d52410ec2c8ba061907cbe8e Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Send synthetic cursorUpdate events for utility windowsTor Arne Vestbø2023-01-031-3/+9
| | | | | | | | | | | | | In faffaa729282b435fb330e1c92523fc0df3fc051 we limited our cursor update workaround to key windows, but macOS also sends cursorUpdate events to non-key windows with the NSWindowStyleMaskUtilityWindow style mask, so we include this in our workaround logic from ae8e96d4c2fc43. We include NSWindowStyleMaskTitled in this check, as macOS seems to require a window to be titled to treat it as a utility window. Task-number: QTBUG-96374 Change-Id: I1c54da181acbe472c2f598fec37aeadada3956bb Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Don't set cursor for non-key windowsTor Arne Vestbø2022-12-131-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | The system behavior when using NSTrackingArea with NSTrackingCursorUpdate is that cursorUpdate is called whenever the mouse enters a key window. In response, we use [NSCursor set] to apply the QWindow's cursor that was set earlier though QCocoaWindow::setWindowCursor(). As a QWidget can manage a hierarchy of child widgets, each with their own cursor, we may see multiple calls to setWindowCursor() when hovering the mouse over a window. In ae8e96d4c2fc430ed6f71e422ef4aff2c7f15186 we worked around an AppKit bug where an override cursor would prevent our call to invalidateCursorRectsForView from resulting in a cursorUpdate call. But, in doing so, we ignored one of the documented behaviors of invalidateCursorRectsForView, namely that the cursor is only updated immediately if the window is currently the key window. As a result, we would call [NSCursor set] for non-key windows, which creates an inconsistent behavior. As long as we're not consistently supporting cursor updates for non-key windows we should align our workaround behavior with the existing behavior. Task-number: QTBUG-96374 Change-Id: I36e4c7802b177230a7e81133cd38557590f041b7 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* QCocoaWindow::windowStyleMask: make popups non-resizableTimur Pocheptsov2022-10-071-1/+3
| | | | | | | | | Otherwise, context menu can be resized. Pick-to: 6.4 6.2 Task-number: QTBUG-106925 Change-Id: I409d0113fd92ca89b14f068c391dd9c0ddb79ce7 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Report compound window state when state changesTor Arne Vestbø2022-09-201-12/+16
| | | | | | | | | | | Otherwise we lose the fact that the window is both maximized and minimized, if the minimize transition is asynchronous, as it is on macOS 13. Task-number: QTBUG-104210 Pick-to: 6.4 Change-Id: I76199e98927e6e4a0f379d78db0603faa80aa4b0 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Handle asynchronous deminiaturizing of windowsTor Arne Vestbø2022-09-201-3/+12
| | | | | | | | As of macOS 13 this operation is now asynchronous. Pick-to: 6.4 6.2 5.15 Change-Id: I9431e24803c53a3fa455707b20a6814290718766 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Return false from set(Keyboard/Mouse)GrabEnabledTor Arne Vestbø2022-09-131-18/+4
| | | | | | | | | | | | [ChangeLog][macOS] QWindow::setKeyboardGrabEnabled() and QWindow::setMouseGrabEnabled() now returns false, as the feature is not implemented on macOS yet. If you were relying on these functions to make the window key (activate it), please use QWindow::requestActivate() instead. Task-number: QTBUG-106597 Change-Id: I86d7d806080aae98c9aec5287adfcc8cb70d372a Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Mac: close popups opened on inactive application on relevant user actionVolker Hilsheimer2022-08-221-1/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On macOS, users can right-click into an inactive application to open a context menu without activating the application. Qt handles a number of events to close open popups (window deactivating or a mouse press outside the popup), but none of those will get called when the application is already inactive. So the popup might stay open (and on top of the window stack) when the user clicks into other applications, or activates another window. To fix this we need to watch for events outside of the Qt application on which we need to close the popup: when the user presses a mouse button, or activates another application using Cmd-Tab. But we don't want to monitor for key events, as that requires user permission. Use a global event monitor to watch for mouse presses, and an notification observer to watch for application activations, and respond by closing all popups (and removing the monitor and observer again). Use the monitor as well to watch for mouse moves, and pass only those events through the Qt event system so that mouse tracking in the menu works even if the application is inactive. This change brings back a version of the global event monitor we had in Qt 5.15. However, a press into our own menu will trigger the activation observer after the application became active, which would now close the menu. We don't want that, so we also need to remove the observer when the application becomes active (which makes sense anyway, as we will get regular events from then on). Pick-to: 6.4 6.3 6.2 Fixes: QTBUG-105474 Change-Id: I18573fcda09a46c27730bd670a795f4d467aab01 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Fix several more improperly placed #include mocThiago Macieira2022-08-041-2/+2
| | | | | | | | | | | | | Like commit qtbase/638893bea083b619b73b33a7dd5589fb2c4c4242. Script to find them: git grep -l '#include.*moc' \*.cpp \*.mm | \ xargs awk '/QT_BEGIN_NAMESPACE/ { i=1 } /QT_END_NAMESPACE/ { i=0 } /#include.*moc/ && i { print ARGV[ARGIND], $0 }' Pick-to: 6.4 Change-Id: I6f936da6f6e84d649f70fffd17058fd05cfc5c6d Reviewed-by: Fabian Kosmale <fabian.kosmale@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>
* Plugins: replace remaining uses of QLatin1String with QLatin1StringViewSona Kurazyan2022-05-041-1/+1
| | | | | | | Task-number: QTBUG-98434 Change-Id: If64c294033c114ae46dfc327c40da7f3c7a598f5 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* macOS: Clear NSOpenGLContext drawable when QNSView is about to go awayTor Arne Vestbø2021-11-161-0/+9
| | | | | | | | | | | | | | Calling doneCurrent() on a QCocoaGLContext only clears the current context, but doesns't reset the drawable (view) of the context. In most cases this is fine, but it has been observed to cause issues when using the software GL renderer on Big Sur and above. To be a good citizen we clear the drawable of any of our contexts that are tied to the NSView this about to be go away. Pick-to: 6.2 6.2.2 Change-Id: I8c845727c50871f30fbebc2ed62a7d0485651ecf Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* macOS: Correctly record normalGeometry in Cocoa pluginVolker Hilsheimer2021-10-141-0/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Cocoa sends QWidget the state-change notification after the window has been resized already, at which point we cannot store the normal geometry anymore. Handle zoom and full screen callbacks prior to the state changing to store the geometry in QCocoaWindow. We do not need to handle minimized state, as the window will still reflect the original geometry. Return the stored value from an override of QPlatformWindow::normalGeometry so that QWidget gets the correct values even though the new state is already active. Fix the tst_QWidget::normalGeometry test to make it pass on all platforms by waiting for the window to actually have transitioned to the new state before comparing geometries. Both macOS and Windows fully pass; on Xcb, deminimizing a window using setWindowState does not work, which is why the test was partially skipped (confirmed by visual testing). Move those problematic, complex test cases to the end so that most cases are covered on Xcb as well. Done-with: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Pick-to: 6.2 Change-Id: I518a5db9169b80e8fa25fe4fa2b50bd1ea0e6db3 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* cocoa: Fix typo in debug messagesJonas Kvinge2021-10-121-1/+1
| | | | | | Pick-to: 5.15 6.2 Change-Id: I0a4c344f2104241175a9bfce7cfc7128c3f7d3ed Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* qcocoa: Fix typos in source code commentsJonas Kvinge2021-10-121-4/+4
| | | | | | Pick-to: 6.2 5.15 Change-Id: Ide20e1d133891890a7673c8403ea91b489baa8f6 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* QCocoaWindow: Make window key if the app's modal window is hiddenDoris Verria2021-10-071-1/+3
| | | | | | | | | | | | | | | | | | | | On macOS, when showing a window, we decide if it should be made key and therefore active, if the app has no active modal session or if the window's worksWhenModal returns true. However, the window needs to be made key also when a modal window is present, but not visible. Add this condition when checking if the window needs to be made key. This makes the behavior consistent with what happens when a modal is minimized on macOS. The input focus is passed to the next window, and the window appears active, even if it can not be interacted with. Fixes: QTBUG-85574 Pick-to: 5.15 6.2 Change-Id: I204d4f912128f4a46840789fc2ee08e1b2716bfc Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: fix window deactivation when a popup is openVolker Hilsheimer2021-09-301-1/+6
| | | | | | | | | | | | | | | | | | | | | On macOS, we get explicit notifications when a window becomes or resigns the key, before we have had a chance to close open popups. The popup is then closed later, but the delivery of the WindowDeactivate event has already been aborted as QApplication interprets such notifications while in popup mode as delayed focus events. This leaves the focus widget still displaying focus even though its window is no longer active. Trying to activate the window again then does not correctly transfer focus. To fix this, close all popup explicitly when a window resigns key. Task-number: QTBUG-78750 Fixes: QTBUG-66513 Fixes: QTBUG-69710 Pick-to: 6.2 Change-Id: I590757c7d3532dbe4b5358a8e121ce8aa871a699 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: send enter/leave when a window opens/closesVolker Hilsheimer2021-09-241-0/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | Since macOS doesn't give us any event when a modal window opens, we need to do so ourselves explicitly so that the current mouse window gets a leave event when e.g. a popup opens, and an enter event when the popup closes again. The case for modal dialogs is partially handled by QGuiApplication already. Note: We cannot rely on the transientParent of the opening/closing window, as it's nullptr for QMenu windows even if the QMenu has a widget parent. Add a test for enter/leave events when a secondary window opens, covering both the dialog and the popup case. For the dialog case, we sometimes get two Enter events when the dailog closes, which we have to tolerate for now. To make the test pass on b2qt platforms, fix the offscreen plugin to explicitly send enter/leave events in the same way as Cocoa now does. Fixes: QTBUG-78970 Pick-to: 6.2 Change-Id: If45e43e625e8362c3502c740154f6a6a8962b9e9 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Handle window titlebar buttons independently from style maskTor Arne Vestbø2021-09-231-35/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Style masks such as NSWindowStyleMask{Resizable,Miniaturizable} affect whether the window has a title bar button for the action, but also whether the window can be resized or minimized through other means, for example if the window border can be dragged to resize. By decoupling the visibility and enablement of the title bar buttons from the style mask we can individually control the buttons, and leave the style mask set to enable behaviors we always want. We were already doing this for the NSWindowZoomButton. Unfortunately AppKit not only checks NSWindowStyleMaskMiniaturizable during a call to miniaturize, but also whether the title bar button is enabled. To allow minimizing windows without the titlebar button we detect the situation and give AppKit a NSWindowMiniaturizeButton that we haven't disabled. The alternative would be to temporarily enable the NSWindowMiniaturizeButton during the minimize, but this results in the button flashing yellow for the duration of the animation. Task-number: QTBUG-65637 Task-number: QTBUG-46882 Task-number: QTBUG-64994 Task-number: QTBUG-71485 Change-Id: I2c1a9564d8b7516476aa018b2820670199124bc2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>