summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
Commit message (Collapse)AuthorAgeFilesLines
...
* macOS: Respect QDir::Hidden for native file dialogsTor Arne Vestbø2023-06-301-2/+8
| | | | | | | | | The default for showsHiddenFiles is NO, so we were not showing hidden files unless the user toggled them via the keyboard shortcut. Pick-to: 6.5 6.6 Change-Id: I796144452cf8f5a6cc46f1ba6747affcd0a35879 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Avoid triggering TCC permission dialogs in file dialogsTor Arne Vestbø2023-06-301-35/+19
| | | | | | | | | | | | | | | | | | | | | | | In our NSOpenSavePanelDelegate we respond to panel:shouldEnableURL: by checking the file dialog's filter options. As part of this, we pulled out the file's attributes using [NSFileManager attributesOfItemAtPath:], but this API triggers the TCC (Transparency, Consent, and Control) machinery to ask the user for permission to access the path in question. We could replace the directory check with fileExistsAtPath:isDirectory:, but this would still leave the checks for writable/readable/executable. Luckily for us, the plumbing for QFileInfo uses lower level CoreFoundation APIs that don't have these issues (except for isBundle, which we should fix separately). This also means we can remove the custom isHiddenFileAtURL helper, as it was based on the same kCFURLIsHiddenKey as the QFileInfo plumbing. Fixes: QTBUG-114919 Pick-to: 6.5 6.6 Change-Id: I9ebefaeb1ef7bcc5bb9a1c5cd4b993ce230cf506 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Enable dirs in file dialogs, also when treating bundles as dirsTor Arne Vestbø2023-06-301-4/+3
| | | | | | | | | | | | | | | | | | In our NSOpenSavePanelDelegate we respond to panel:shouldEnableURL: with YES if it's a directory or symlink to a directory, which matches the native behavior. But the panel has a special flag to treat bundles as directories instead of files. We were checking this flag, but ignoring the case where it was actually set (which it normally is not), and as a result would go on to filter directory names as well. We now handle both cases, and only call [NSWorkspace isFilePackageAtPath:] if needed (when the treatsFilePackagesAsDirectories flag is not set). Pick-to: 6.5 6.6 6.2 Change-Id: I2b9a16ff99b4b643389acc042c032813f432ac59 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Propagate mouse enter/exit for windows embedded into foreign windowsTor Arne Vestbø2023-06-261-4/+26
| | | | | | | | | | | | | | | Similar to the isEmbedded() case, when the parent of a QWindow is a foreign window, created via QWindow::fromWinId(), we don't have a QNSView parent that will handle mouse enter/exit on our behalf. Longer term we probably want to fold this case into the isEmbedded() case, but as that function is used other places too this requires some more research, so for now let's fix hover events. Fixes: QTBUG-114605 Pick-to: 6.5 6.6 Change-Id: Ib61aefc84ed080417a6820a4a365555424b208be Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: work around getting invalid result from NSAlert::runModalVolker Hilsheimer2023-06-202-2/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | It is possible for an application to trigger the unexpected result of NSModalResponseContinue from our call to NSAlert::runModal, by showing and hiding a modal dialog first, and processing events explicitly. This at best only flashes the native message box, at worst it triggers an assert from our processResponse function evaluating that response value as impossible (via Q_UNREACHABLE). We should never call processResponse with NSModalResponseContinue, but instead keep the modal loop running and the dialog visible. So introduce a wrapper to NSAlert::runModal that keeps calling that method until we get a result other than NSModalResponseContinue. Writing an auto test for this failed; a simple test didn't reproduce the assert; trying to place the opening of the native message box into a lambda that would be called by the event loop (simulating the button press from the bug report's reproducer) resulted in the native message box never closing and the test blocking (and still not triggering the assert). Fixes: QTBUG-114546 Pick-to: 6.5 6.6 Change-Id: Iab25eff55c48b103287d1881ac355e6cdd190f7a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@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: Use submenuAction: as action for sub-menu menu itemsTimur Pocheptsov2023-06-132-1/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Having the generic qt_itemFired: as action would result in the whole submenu tree closing if an item with a sub-menu was clicked on. This is not how native applications behave. They respond by immediately opening the submenu, or do nothing if the menu is already open. By using submenuAction: as the selector we achieve the same behavior. A complication here is that for some reason we defer associating the submenu NSMenu to an NSMenuItem until QCocoaMenu::setAttachedItem(), instead of doing it in QCocoaMenuItem::setMenu(), or even as part of QCocoaMenuItem::sync(). As a result, AppKit's NSMenuValidation logic will conclude that the item does neither have a submenu, nor a valid target/selector combo to be validated, and will explicitly disable the item. This can be debugged by passing -NSTrackMenuValidation YES to the application. To work around this we explicitly enable the item once we have set a valid submenu for the item. Pick-to: 6.5 6.6 Fixes: QTBUG-114199 Change-Id: I7178e7687066b3fe082454c512ec9c7eab3bded4 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Don't assume DnD is handled via internal drag loopTor Arne Vestbø2023-06-071-2/+3
| | | | | | | | | | | | | | | | If we have only one item, we're not using beginDraggingSessionWithItems which requires us to manage our own drag loop, and instead use good old dragImage, which takes care of the drag loop on our behalf. In both cases we end up in draggingSession:endedAtPoint, so we need to explicitly check for the existence of a manually managed drag session. Amends 8a359343621fa83941946cb4e661b54ca7a1c4cc. Fixes: QTBUG-114236 Pick-to: 6.5 6.6 Change-Id: Ifa9110945e191c4ffebe099e3e4edf9c571ab376 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@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>
* Platform theme: fill QPalette::AccentColor with OS valueYuhang Zhao2023-06-011-0/+3
| | | | | | | | | | | The AccentColor role, added in Qt 6.6, is currently populated with a default value. This patch implements populating the brush with OS values for Windows and macOS. Change-Id: Ic243c3b8664d50db3a2096a034de6ba672d9e2d2 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* macOS: Fix assertion in accessibility implementation for treeviewsVolker Hilsheimer2023-05-222-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In QAccessible's widget implementations, trees are treated as tables, with a rowCount implementation that is based on the view's current item content. That item content is the view's content, not the model's, and it changes when tree branches are expanded. The Cocoa bridge for accessibility allocates arrays of row data structures based on the rowCount implementation. Those data structures need to be invalidated and recreated when the view's content changes. To do that, emit an accessibility event for a model reset when laying out items changes the size of the view's item array. We don't know what changed during that layout process to makes this any more granular. Amends 11ae55e918082e8fdfc0c88c21049e877cc47b5b, but the problem with the data structure being stale and incorrect would have been there before that chain of changes optimizing. It didn't trigger an assert, but probably resulted in incorrect data being reported. To make trees testable, we need to actually expose them as AXOutline to the macOS accessibility framework. Until now, they have been treated like plain QWidget, e.g. AXGroup. This made them in practice in- accessible. With this change, VoiceOver works much better (although not perfeclty yet). Also remove an assert that could be triggered by an accessibility client asking for a cell for an invalid index (which can be reproduced by navigating around in a tree, following debug warnings from QAccessibleTree::indexFromLogical: invalid index). Pick-to: 6.5 Change-Id: I7650342aa0dcd7925a94ae6a36de5a0b344c467d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Detect menu bar roles for untranslated menu titles as wellTor Arne Vestbø2023-05-161-29/+62
| | | | | | | | | | | | | | | | | | | | | | | If an application added an "About" menu action, and then loaded the qtbase translations, we would try to match the incoming menu title ("About") against QCoreApplication::translate("QCocoaMenuItem", "About"), which since qtbase provides translation in the QCocoaMenuItem context would fail, and we would not detect the menu item role successfully. For this to work, the application developer would need to add their own translations for every menu item, and these translations would have to match the QCocoaMenuItem translations in qtbase. By also comparing the menu titles against the untranslated heuristics we now account for the situation that the app has not translated its menu items. If the app does add translations of its menu items these still need to match the QCocoaMenuItem context translations. Change-Id: Ic2f019cd42b7e080187f9738840f84b0cec239df Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Replace [QNSView drawRect:] assert with warningTor Arne Vestbø2023-05-111-2/+4
| | | | | | | | | | | | AppKit will in some cases call this method, even if we are layer backed, just because we implement it. We should remove the implementation, but doing so requires us to also move from displayLayer to updateLayer for the layer backed drawing, which requires more testing. Pick-to: 6.5 Fixes: QTBUG-113500 Change-Id: I70bde34fdb433105d85ccea0514a5342e2c1e725 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Clear event dispatcher interrupt before running NSAlert modal sessionTor Arne Vestbø2023-05-101-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | If the event dispatcher is interrupted we propagate the interrupt to lower event loop levels, in case they too need to be interrupted. And we defer the actual interrupt of the NSApplication to the next time we process Qt events, to avoid AppKit dropping queued events on the floor. This logic relies on QCocoaEventDispatcher::processEvents() setting the interrupt flag to false, which signals that we should not continue to tear down any further event loops. Unfortunately, native run loops such as running application modal sessions, are not driven by QCocoaEventDispatcher::processEvents(), so we never reset the interrupt, and end up ending the session immediately. To work around this we need to explicitly clear the interrupt flag before starting native modal sessions. This also fixes the issue seen in QTBUG-111524 with showing native alerts from nested event loops. Fixes: QTBUG-112697 Task-number: QTBUG-111524 Pick-to: 6.5 6.5.1 Change-Id: I6aaec97011fd18c4a513c1dde3173b1cc4d50112 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't clam to support action messages from non-Qt menu itemsTor Arne Vestbø2023-05-042-54/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As described in 3bedeb837ef68e0062668406e7662ed9ffc5268a, the way menu items on macOS are typically set up they have an action, e.g. copy:, but no target, and the system then takes care of finding the right target at runtime, starting with the first responder, walking the responder chain, and then moving on to other NSWindows, before ending up in the NSApplication and its delegate. As we (still) don't have a mechanism in Qt to forward generic actions, such as the cut/copy/paste, or selectAll, so we rely on mapping the actions back to QCocoaNSMenuItem that we can trace back to a QPlatformMenuItem that we in turn emit activated() for. Normally this works fine, but in the case where the Qt app is embedded in a native UI, which has its own menu items with cut/copy/paste, we'll get callbacks into QNSView for actions triggered by a generic NSMenuItem. In that case, we need to bail out, but we want to do so in a way that lets AppKit continue to walk the responder chain. This is possible by implementing supplementalTargetForAction:sender:, where we have access to the sender. If sender doesn't match the expected QCocoaNSMenuItem we let AppKit find a better match up the chain. Since the target we return needs to ultimately respond to the selectors and/or forward them, we can't point the target back to ourselves, nor can we point it to the application delegate directly, as the menu items need to be validated in the context of the view, so a new per-view QNSViewMenuHelper class has been added to take the role of forwarding the menu actions. The logic for forwarding the resulting actions to the application delegate has been simplified and hardened a bit as well. A possible scenario with this new approach is that the Qt app has a line edit focused, and the user tries to activate the menu item for Paste, but the item is grayed out because we can not support the action. This is of course confusing for the user, but less so than having an active menu item that then doesn't do anything when activated. Another scenario is that a responder later in the chain does respond to the paste action, and the menu item will end up pasting into something that is not the first responder. This might also be confusing for the user, but it's generally recommended that implementers of actions like paste only allow the action if the view is the first responder, and this is something views have to deal with anyways, so it doesn't change anything that we're now bailing out earlier in not accepting the paste. One benefit of allowing AppKit to find a better target for the action is that if no target is found, and the user presses the key equivalent of the disabled menu item, the key event will be delivered as a normal keyDown to our QNSView, which we do forward, allowing the Qt app to respond to the action, even though the action came from a generic menu item. With our old approach this would not happen, as we would claim to support the action for our QNSView, but then drop it on the floor when AppKit tried to deliver it to us. Change-Id: I609db42df6a107a49e287f435e8808812c83d43e Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Don't leak QEventDispatcherUNIX during event dispatcher creationTor Arne Vestbø2023-04-292-4/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | During QCoreApplication initialization, we create the main thread's event dispatcher, which for a GUI app happens via QGuiApplicationPrivate's createEventDispatcher() override. This in turn relies on the platform integration to create the event dispatcher, but to do that it needs to create the platform integration first. And this might result in calling APIs that themselves initialize the main thread event dispatcher, such as QEventLoop, which non-lazily creates an event dispatcher for the thread. We already had a check to catch the platform integration setting the QCoreApplictionPrivate::eventDispatcher member, but not anything for checking the current thread data. On macOS this resulted in a leak of QEventDispatcherUNIX because QCocoaDrag contained a QEventLoop member. We now track the event loop temproarily via a pointer instead, like we do in other places. An alternative fix would be to defer the initialization of QCocoaDrag until QCocoaIntegration::drag() is called, but that would run the risk of something calling the function during platform initialization and we'd be back to the same problem. It's unclear why QEventLoop is not lazily ensuring the event dispatcher, and this might be a wider fix for similar issues. Pick-to: 6.5 Change-Id: I643010ddb09945936ce9b0b94de0df96f6fe218f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* macOS: Fix leak of application menu NSMenuItemTor Arne Vestbø2023-04-291-2/+2
| | | | | | | Pick-to: 6.5 6.2 Fixes: QTBUG-112697 Change-Id: I0fe62e5a66f57bb9b8c073e636be346e088e0986 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Handle failure to create display link or invalid display linkTor Arne Vestbø2023-04-243-6/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | 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: Localize title of edit menu's NSMenuItem via AppKitTor Arne Vestbø2023-04-241-4/+39
| | | | | | | | | | | | | | | | | | | | | | | | In 939b7bfe66221975d3a12a6d0a6dd14d9ad04344 we synced up the NSMenuItem's title to that of the corresponding NSMenu, as AppKit was observed to use the NSMenuItem title for its heuristics of when to add dictation and emoji entries to the menu. But AppKit's heuristics are based on the localized name of the edit menu, so we need to follow suit and look up AppKit's own localizations. This is of course fragile, as we're relying on this localization continuing to live in the InputManager table, but if that changes we'll just fall back to using the title from the NSMenu, as we did before. In addition, AppKit's heuristics also look for menu items in the menu that match selectors such as copy:, paste:, etc, so even if our lookup of the localized title fails, the additional heuristics would in most cases still succeed in detecting the edit menu. Task-number: QTBUG-53085 Task-number: QTBUG-79565 Pick-to: 6.5 Change-Id: I5e12973b86ab35f10a8f7434bcae8a4cf134ecfd Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* Revert "macOS: add default Edit menu items, if not added by AppKit"Tor Arne Vestbø2023-04-132-56/+0
| | | | | | | | | | | | | | | | | | | | | | This reverts commit d42cfeb84faf154b46f2811b2059946b396fcc12. Trying to help AppKit by adding the dictation and emoji edit menu items ourselves resulted in sometimes adding the entries twice, when we failed to detect the existing entries, or AppKit failed to detect our entries as a reason to not add its own. In addition, even if the entries we added were detected by AppKit and AppKit was smart enough to not add its own, our entries were relying on the developer to provide translation, instead of building on the translations that AppKit already provides. And the keyboard shortcut we set for our entries were not following system and user preferences for which keyboard combination should trigger the entries. Fixes: QTBUG-104709 Task-number: QTBUG-79565 Pick-to: 6.5 Change-Id: I3fabc41f85df917dbb669253ad441bccea8a5e35 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>
* Remove outdated comment about macOS cusorUpdateTor Arne Vestbø2023-04-121-4/+0
| | | | | | Pick-to: 6.5 Change-Id: Ic270e9800b56e4fa1027245bebc4cd08a58abb3f Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS Accessibility: flag all synthetic elements as unignoredVolker Hilsheimer2023-04-111-3/+4
| | | | | | | | | | | | | | | | This saves us a few more roundtrips. For rows and columns we could check if their accessibilityFrame instersects with the table and so ignore rows and columns that are outside of the view, but I'm observing weird corruptions in the list returned by NSAccessibilityUnignoredChildren when ignoring any objects. Task-number: QTBUG-34337 Pick-to: 6.5 Change-Id: Ia2d13fff463ff26abb39acfceafcfa0761171203 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* macOS Accessibility: Delay creation of table cell interfacesVolker Hilsheimer2023-04-111-18/+96
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since macOS requires us to return an array with elements as the children of a table's row. And it might ask for the children of many rows. This is very costly, and results in a lot of QAccessibleInterface instances being created unnecessary. Instead, use unassociated QMacAccessibleElements as place holders for cells, and place them in the column array of the QMacAccessibleElement that represents the respective row. Those placeholder elements have the synthesizedRole set to AXCell, and have the same axid as the table, for as long as there is no corresponding QAccessibleTableCell created. Until that point, they are in practice "managedByParent" just as the row and column elements. Since the place holder object knows about its column, row, and table, it can respond to many inquiries directly without needing to create the interface. Once the QAccessibleInterface for the cell is required for an already existing place holder, then we need to promote the place holder to an independent element. We reset the synthesizedRole to nil, and change the axid to the ID of the cell interface. However, the cell interface might have been created and assocated with an element before the placeholders were created when navigating through the children of a row. So when we create an element for a table cell, then we need to make sure that the table elements' corresponding row is also populated, with the new element in the right place. Pick-to: 6.5 Fixes: QTBUG-34337 Change-Id: Iff78e3b8335df8cf294fffb6579605bfeb8409ed Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS Accessibility: don't create an unnecessary interfaceVolker Hilsheimer2023-04-111-6/+3
| | | | | | | | | | We only need to compare elements to determine whether this element has focus. Task-number: QTBUG-34337 Pick-to: 6.5 Change-Id: Ic1388ac00381735acfbf1e5877a658f4bd534dfb Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS Accessibility: add an elementWithInterface helperVolker Hilsheimer2023-04-112-12/+17
| | | | | | | | | | | | | | | Instead of explicitly creating an ID from an interface and then asking for the element for the ID, ask for the element for the interface directly. In that helper we can also make sure that the created element is correctly configured if the interface for which it was created was for a table cell. Task-number: QTBUG-34337 Pick-to: 6.5 Change-Id: Id0f9247b0b50195301b293dcabb8925c3fc2d2cf Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS Accessibility: optimize table interface implementationVolker Hilsheimer2023-04-112-44/+58
| | | | | | | | | | | | | | Store row and column in the QMacAccessibilityElement when creating it so that we can avoid linearly looking for ourselves in the parent's data. Row elements have their m_rowIndex set, Column elements the m_columnIndex, and elements representing a cell have both set. Cells are not managed by the table. Task-number: QTBUG-34337 Pick-to: 6.5 Change-Id: I319fad1f1fda0cfa4c0b95e9e16c25c87df04351 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS Accessibility: code hygieneVolker Hilsheimer2023-04-112-130/+104
| | | | | | | | | | | | | | Make getting a QAccessibleInterface from a QMacAccessibilityElement a member function that also tests for the validity of the interface, and replace the respective code duplication. Remove unused member functions accessibilityMin/MaxValue. Task-number: QTBUG-34337 Pick-to: 6.5 Change-Id: Ie15cf0b71285e63cc485d87ced050dc541967c98 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Guard qopenglcontext_p.h with QT_NO_OPENGLAlexey Edelev2023-04-062-2/+8
| | | | | | | | | | | | | Fixes the macos build with the disabled opengl feature. Include inttypes.h that used to be implicitly included by qopenglcontext_p.h. It's needed for 'PRId64' macro. Amends: ef27cc126c38ff14360bebeeb3100671df9e4cf4 Pick-to: 6.5 Fixes: QTBUG-112656 Change-Id: I970329c4aacc70790f50e1ff3a57ab2aa6f6bff7 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
* macOS: Send Qt::NonClientAreaMouseMove for NSEventTypeMouseMoved in title barTor Arne Vestbø2023-03-311-3/+2
| | | | | | | | | | We were missing the NSEventTypeMouseMoved in resolving the event type for handleFrameStrutMouseEvent, resulting in passing on QEvent::None as the event type to QWSI. Pick-to: 6.5 6.2 Change-Id: I144b6459c5d4fda2839d25cd52ddb441dc7c3a47 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QWSI: Remove handleFrameStrutMouseEvent in favor of handleMouseEvent+typeTor Arne Vestbø2023-03-311-1/+1
| | | | | | | | | | | | | | | The handleMouseEvent function already takes a QEvent::Type, where clients pass in the corresponding mouse press/release/move type. The same applies to the handleFrameStrutMouseEvent. To avoid the chance that clients call these functions with a conflicting event type (handleFrameStrutMouseEvent with MouseButtonPress instead of NonClientAreaMouseButtonPress e.g.), we remove handleFrameStrutMouseEvent altogether and just let clients use the handleMouseEvent function directly with the correct event type. Change-Id: I4a0241c39aedac0d2d8d5163ba05cde72605959c Reviewed-by: Lars Knoll <lars@knoll.priv.no>
* 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-282-10/+12
| | | | | | | | | | | | | | | | | 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-282-9/+23
| | | | | | | | | | | | | | | | | | | | | 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: Skip DisplayLink updates when in live resizeLaszlo Agocs2023-03-231-0/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...and the view is using a CAMetalLayer and a non-default contents placement. (the default would be scaling/stretching of the content, that hides a lot of out-of-sync size problems during resize, but is not great for UIs so we never use that in practice) This achieves two things: - when presenting from the main thread with transactions (i.e. with parent patch in place), resizing the window will be even nicer, basically flicker free on the M1 Mini as well, - when presenting from outside the main thread, resizing becomes a lot smoother, even if the window background is still visible from time to time due to the size not catching up and due to Qt having to use NSViewLayerContentsPlacementTopLeft. Thus resizing Qt Quick-based windows, which use the threaded render loop by default and cannot use presentsWithTransaction, becomes a nicer experience than before, even if not always perfect. This comes at the expense of not animating during the live resize operation whenever the size is not changed (because only a resize triggers updates then, the CVDisplayLink-based updates are skipped in order to reduce flicker due to out of sync sizes) To force the old behavior, set QT_MAC_DISPLAY_LINK_UPDATE_IN_RESIZE. Task-number: QTBUG-107198 Change-Id: I796c3a74119510c62f7245b0ebbe78797d2df03e Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Disable interaction for modally blocked transient parent windowsTor Arne Vestbø2023-03-202-4/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: Bail out if handling cut/copy/paste action from non-Qt NSMenuItemTor Arne Vestbø2023-03-201-3/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The typical way to set up menus on macOS, which we follow, is to create NSMenuItems with an action selector set (copy:), but without a target. This will result in AppKit finding a target dynamically, starting with the first responder, walking the responder chain, and then moving on to other NSWindows, before ending up in the NSApplication and its delegate. Unfortunately, we don't have a mechanism in Qt to forward generic actions, such as the cut/copy/paste, or selectAll, so we rely on mapping the actions back to QCocoaNSMenuItem that we can trace back to a QPlatformMenuItem that we in turn emit activated() for. Normally this works fine, but in the case where the Qt app is embedded in a native UI, which has its own menu items with cut/copy/paste, we'll get callbacks into QNSView for actions triggered by a generic NSMenuItem. In that case, we need to bail out, but we must do so without calling [super forwardInvocation:invocation], as that will just try to invoke the action on ourselves again. It's unfortunately too late to try to redirect the action to another responder, that might have handled the action, and it's questionable whether that would be the behavior we'd want, as that would possibly result in e.g. pasting text into another window than the Qt one that currently has an active cursor in a text entry. Fixes: QTBUG-111916 Pick-to: 6.5 Change-Id: I56318e4f7efd779cd20bf577aec8c2de04a6a142 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Add logging category for menu machineryTor Arne Vestbø2023-03-208-27/+27
| | | | | | | | The machinery is quit fragile, so any logging will help here. Pick-to: 6.5 Change-Id: I1906c0e33b4afbf649a20bfe2aa7210b6822087e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Revert "QCocoaMenuBar: avoid duplication of 'special' entries in the 'Edit' ↵Timur Pocheptsov2023-03-171-16/+12
| | | | | | | | | | | | | | | | menu" This reverts commit 6c2387571a6ccace9edb600ce6798f75affd961d. Caused a regression when the edit menu did not have any entries from the system. Fixing that regression (out of bound index, crash), revealed that the original patch is simply not working anymore - items are still duplicated anyway. Fixes: QTBUG-111798 Pick-to: 6.5 Change-Id: Id4a88f30e2cf300bc63181c4bc7aa113a8b13ac6 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Remove workaround for worksWhenModal not being reevaluatedTor Arne Vestbø2023-03-131-39/+0
| | | | | | | | | | | | | | On macOS < 10.15 the worksWhenModal property of our NSWindow was read on window initialization and propagated to the window server, but never updated on the window server past that point, even if updating the worksWhenModal property on the NSWindow. Now that we no longer support macOS < 10.15, we can remove the workaround, that was using private APIs to talk to the window server directly. Pick-to: 6.5 Change-Id: Ide5a6d63cc471fd04748d1aa7f7915ccde2a1cdc Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Guard text input client from destroyed QCocoaWindowTor Arne Vestbø2023-03-132-13/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | The text input system on macOS may in some cases hold references to our QNSView, even after we've destroyed the corresponding QCocoaWindow. This happens e.g. when using the Keyboard Viewer to input text into a dialog, and then closing the dialog. In this situation we get text input callbacks such as selectedRange, attributedSubstringForProposedRange, firstRectForCharacterRange, and need to account for the lack of a valid platform window. This happens even if NSTextInputContext.currentInputContext has been updated to the input context of the parent window, and even if we explicitly deactivate the old input context and return nil for the input context of the now QCocoaWindow-less QNSView. We can combine this situation with the handling of a missing focus object, so that each callback doesn't need explicit platform window checks. Fixes: QTBUG-106369 Fixes: QTBUG-111183 Fixes: QTBUG-105250 Pick-to: 6.5 6.2 5.15 Change-Id: I5bc1b9667376c87221fe5007db162224c022c09f Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Plumb QMessageBox::setCheckBox() through QPlatformMessageDialogHelperTor Arne Vestbø2023-03-091-2/+29
| | | | | | | | | | | | | | | | | | | | | | | Without this plumbing we have no way of knowing if the QMessageBox has a checkbox set, and can't decide to skip the native dialog, leaving the user without the expected checkbox. As the suppression checkbox on macOS can be customized, we can use this plumbing to actually provide native dialog support for generic check boxes. This mechanism can also be used by QErrorMessage, which now matches behavior between native and non-native dialogs in terms of the label of the checkbox and its initial state. We might want to tweak this in the future, since user's might expect the suppression label and state to match the system default, but that's something we can expose from the platform theme if so, and should apply equally to the non-native dialog. Fixes: QTBUG-111803 Pick-to: 6.5.0 6.5 Change-Id: Ied9fc34383fe79fbd8437592ad1c1993b9396178 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Remove content border thickness members from QCocoaWindowTor Arne Vestbø2023-03-082-4/+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-082-34/+18
| | | | | | 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>
* macOS: Use non-native app modal message box from nested event loopsTor Arne Vestbø2023-03-071-0/+5
| | | | | | | | | | | The NSAlert does not stay open when ran from a nested event loop, so we need to fall back to the cross platform dialog. The window modal dialog does not have this issue. Fixes: QTBUG-111524 Pick-to: 6.5 6.5.0 Change-Id: I63fba0a092018bb19edeef78c06587455d752235 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* macOS: Send a filename QFileOpenEvent if invalid URL, deprecate openFileVolker Hilsheimer2023-03-021-1/+10
| | | | | | | | | | | | | | | | | | | | | | | | When the string we receive from the system doesn't parse into a valid QUrl (because QUrl requires a valid IDN), then we shouldn't send the QFileOpenEvent based on that invalid QUrl, but instead pass the string through as the file name. The file name is anyway not guaranteed to be path to a file that can be opened, as per the existence of QFileOpenEvent::open and the repective documentation stating: "some files cannot be opened by name, but require specific information stored in this event." However, that API is not useful at all, the implementation just opens the passed-in QFile, using the stored file name. There's no way to override this, and QFileOpenEvent is a locked class with all data stored inline. So we can't even redirect to a platform-implementation. Deprecate that function. Applications should interpret the string returned by file(), which might not be a path to a local file. Fixes: QTBUG-98384 Change-Id: Iff75489de9d7c5fc034f44c0bda4963b2efb1925 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>