summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
Commit message (Collapse)AuthorAgeFilesLines
* macOS: Handle window titlebar buttons independently from style maskTor Arne Vestbø2021-09-233-36/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Cocoa: Don't call makeKeyAndOrderFront for native app-modal dialogsDoris Verria2021-09-232-9/+8
| | | | | | | | | | | | | | | | | | | | | | | | We show non-modal and Qt::WindowModal native dialogs as modeless panels by calling makeKeyAndOrderFront on the panel. When we exec() a dialog on the other hand, we start a modal event loop by calling runModalForWindow. This method will display the dialog and make it a key window before running the modal event loop. So we don't need to and shouldn't call makeKeyAndOrderFront explicitly before that. Doing so will make Cocoa lose the reference to the previous active window (as it maintains only one level of previous active window) and wrongly choose the main window as key after the dialog closes. Avoiding the call to showModelessPanel for Qt::ApplicationModal dialogs fixes it. Also, in order to display a modal when show() is called and app modality is set via setModality, display it as a modeless dialog as well. This keeps the same behavior we have currently, but it is still not the right way to handle it as we don't respect the modality set by the user. A clean-up of that logic to come in a follow-up commit. Fixes: QTBUG-42661 Pick-to: 5.15 6.1 6.2 Change-Id: I8f33e3866b191d775a64a5d9ec3dd65736114e62 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Change NSTrackingArea to use NSTrackingActiveAlwaysRichard Moe Gustavsen2021-09-234-38/+94
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The current implementation configured NSTrackingArea to be active while the application was active (NSTrackingActiveInActiveApp). But because of a bug in AppKit, the tracking area would sometimes stop being updated, with the result that no mouse events was being sent from AppKit. One way to trigger this bug would be to deactivate the app using cmd+tab (fast enough so that the task switcher is not showing), and reactivate it again using a mouse click. To work around this issue, this patch will instead configure the tracking area to always listen for tracking events, even when the application is inactive (NSTrackingActiveAlways). By doing so, we bypass the apparently broken behavior in AppKit related to activation. The downside is that we then also get tracking events while the application is inactive, which is against how Qt should work. So we therefore need to now check if the application is active before we forward any tracking events to QWSI. With NSTrackingActiveAlways we no longer get enter/leave events from AppKit when the application is activated/deactivated and the mouse stays on top of the application, so we now also need to handle this explicitly from the application delegate. Since we already need to keep track of which QWindow is under the mouse to be able to send out enter/leave from mouse moves, we use the same variable (s_windowUnderMouse) for this purpose as well. Because of QTBUG-35109, there was already a code path in QCocoaWindow that sent out an enter event when a window became key. This is no longer needed now that we send out enter/leave when the application is activated/deactivated. It's also questionable if sending an enter event based on a window's key status is correct, since we in Qt should also send out enter events for inactive windows. So we remove this code path since it interferes with (both the old and) the new implementation. Fixes: QTBUG-36926 Task-number: QTBUG-94447 Change-Id: I5c1105bc3102925c9c65964b4a7d1e02efd01735 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Fix logic for determining NSWindowStyleMaskTitled/BorderlessTor Arne Vestbø2021-09-221-11/+32
| | | | | | | | | | | | | | | | We were working under the assumption that the NSWindowStyleMaskBorderless style mask excluded all others, on account of having the value 0. But in practice this does not seem to be the case, and you can combine the mask with many of the other masks. The only mask that is mutually exclusive with the borderless mask is NSWindowStyleMaskTitled (with a value of 1). Clarify this be restructuring QCocoaWindow::windowStyleMask(). Task-number: QTBUG-71485 Change-Id: I4bbd603fd2373c11f76e84b72a2a60aa2356b032 Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Øystein Heskestad <oystein.heskestad@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't re-send key event through input method on focus object changeTor Arne Vestbø2021-09-211-9/+0
| | | | | | | | | | | | | | | | | | | | | | | In 0c2ca26cd9583092f3ade7b18bc2423336a6202b we started re-sending the key event through the input method when we detected a focus object change, to support the use-case of QAbstractItemView opening an editor and changing focus in response to the first QEvent::InputMethod event. Unfortunately this doesn't work as a general approach, because we don't know what the reason was for the change in focus object. For example, a client might respond to a Qt::Key_Return press by changing the focus to the next input element, and re-sending the key event would in that case insert a new-line in the new focus object -- counter to the expectations of the client. Since we can't know the reason for the changed focus object we can't assume re-sending the key event is safe. Task-number: QTBUG-54848 Fixes: QTBUG-96726 Pick-to: 6.2 6.2.0 Change-Id: Iea8b166385925cd1a05ef62d5cf763638d9f8a67 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Remove remnant of popup closing logic from Cocoa pluginVolker Hilsheimer2021-09-182-30/+0
| | | | | | | | This monitor call back is never called when a popup is open and there's mouse action. Change-Id: I6c45b600ebea16e5fd6c5b3af66fd1242973d747 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Add QPlatformTheme::Appearance for detecting light/dark modesMitch Curtis2021-09-172-0/+6
| | | | | | | | | And implement it on Windows and macOS. Fixes: QTBUG-83908 Fixes: QTBUG-94859 Change-Id: I7b0c062adf5d4dbaefa64c862ab8ab1348809d71 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: convert mask region to native geometryMorten Johan Sørvig2021-09-152-2/+3
| | | | | | | | | | | QWindow::mask() returns a region in device independent geometry which can’t be used directly by the platform plugin. Pick-to: 6.2 5.15 Task-number: QTBUG-94770 Change-Id: I76279bc74cfabe315178327938f485f4447568be Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: don't block CMD+H while a popup is openVolker Hilsheimer2021-09-151-7/+2
| | | | | | | | | | | | | | | | | The shortcut hides the application, which works in native apps such as Xcode or Safari also while a popup menu (or combobox drop down) is open. This essentially reverts 29104c85db53e7c0c0aaf3fe78f84b737fce4886, which introduced the blocking of CMD+H to prevent the popup stack in the Cocoa plugin from going out of sync. With that stack gone after the previous commits, this is no longer a problem. Task-number: QTBUG-82626 Task-number: QTBUG-96450 Task-number: QTBUG-58727 Pick-to: 6.2 Change-Id: I35603d971741f03b793b7839b183b7ab37200647 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: remove the popup stack from QCocoaIntegrationVolker Hilsheimer2021-09-155-77/+2
| | | | | | | | | Since popup handling is now done exclusively by Q(Gui)Application, we don't need to keep track of the popup stack in the Cocoa plugin anymore. Fixes: QTBUG-96450 Change-Id: I869f36f52bc2210b6c92efd9425502de4122c553 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: remove mouse and key grabbing logic from Cocoa pluginVolker Hilsheimer2021-09-152-15/+0
| | | | | | | | | | For QGuiApplication with QWindow, no other QPA plugins do so, and for QApplication with QWidgets, QApplication implements popup functionality consistently. Task-number: QTBUG-96450 Change-Id: I47489296e0e470d8948ca7858d0a2608c58b2975 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Remove duplicate code closing popups on window interactionVolker Hilsheimer2021-09-154-36/+0
| | | | | | | | | | | | | | | | | | | After 70b94eea10d7af83cced09296755a8af28e167b5, all popups are closed on mouseDown within the window frame. As with native applications, the popup is closed on press, and before the press is delivered to the frame (ie before the jewel is shown as depressed). The previous notification handlers for window moving, minimizing, and closing can now be removed, together with the alternative implementation of closePopups that relies on the Cocoa plugin maintaining its own popup stack. This reverts 048e66a11d87845eaba9e8cf23de3fb4acac924d. Task-number: QTBUG-96450 Task-number: QTBUG-77833 Change-Id: I165f3caa64bf9a7b4c4d5455ca33e87029d75f73 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Use QGuiApplication popup APIs in Cocoa pluginVolker Hilsheimer2021-09-151-4/+3
| | | | | | | | | This removes more dependencies to the Cocoa plugin managing its own popup stack. Task-number: QTBUG-96450 Change-Id: Id01577739af525a34728f27b790b9aaac29705f2 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Compute NSWindow background color without checking styleMaskTor Arne Vestbø2021-09-152-6/+14
| | | | | | | | | | | | | | | | | | | | | | | | The check for styleMask == NSWindowStyleMaskBorderless to decide whether to clear the NSWindow background was broken, as NSWindowStyleMaskBorderless has the value 0, but is only supposed to be compared to its companion NSWindowStyleMaskTitled (with value 1). A window can perfectly well be NSWindowStyleMaskBorderless and NSWindowStyleMaskMiniaturizable e.g., so by comparing directly to NSWindowStyleMaskBorderless instead of masking to the first bit first we ended up making miniaturizable windows non-translucent. We now check the Qt::FramelessWindowHint directly, and also whether the window is opaque. Ideally we'd have QWindow flags that could plumb WA_NoSystemBackground from Qt Widgets, as well as a background color property on QWindow to control the system background, but in the meantime we'll have to use the FramelessWindowHint heuristic. The QWidget docs have been updated to reflect this. Task-number: QTBUG-95042 Pick-to: 6.2 Change-Id: I0d40eecace60883c205ebb8c76cef1092cdf1144 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
* macOS: Move handleMouseEvent: to MouseAPI categoryTor Arne Vestbø2021-09-141-53/+53
| | | | | | | Fixes warning of method definition not found. Change-Id: I87866785d1564e29fc356c033ae8cf972548ea7f Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't close popups in Cocoa plugin for most mouse eventsVolker Hilsheimer2021-09-133-10/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | QWidget and QApplication handle popup closing for most events at the right time for the Qt-internal state logic. On other platforms popup QWindows are never closed automatically when clicking outside. So don't close any popups in the Cocoa plugin either, and let the Qt logic take care of it. This ensures that window activation is done at the right time, that Qt's modal popup stack is consistent, and that mouse replay for events closing a popup works. There are however two exceptions: mouse events in the window frame don't produce a QMouseEvent for Qt; and mouse events in a modally blocked (by Cocoa) window don't reach Qt at all. For those case, the logic in QWidget and QApplication is not enough. For the former, leave the change introduced in 70b94eea10d7af83cced092967 to explicitly close popups for LMB down in the frame. This still needs to happen before the event is delivered. For the latter case, deliver the event explicitly to Qt when we discover that the target window is modally blocked while a popup is active. The handleMouseEvent implementation then takes care of the redirect to the active popup, and Qt will further respect the modal stack in the QApplication::isWindowBlocked implementation. Change-Id: I578eb5e6aebc897a0ff1f69bc5c53bcaa05d138d Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: don't replay mouse presses that closed a popupVolker Hilsheimer2021-09-131-0/+2
| | | | | | | | | | | | | | On macOS, we only follow the native behavior to not replay mouse presses outside of a popup because we close popups in the QPA plugin before any popup-specific logic in QApplication kicks in, so a press that closed a popup is never seen by Qt at all. Before we can remove the popup closing code from the QPA plugin, implement the existing platform style hint for Cocoa to prevent mouse press replays. Change-Id: I2328f706ba148ece2d0e3fb4e71fe9123ab5e205 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: process all activation events synchronouslyMorten Johan Sørvig2021-09-101-1/+2
| | | | | | | | | | | | Commit ed483346 changed the main code path to deliver activation events synchronously, however it looks like an additional code path was missed. Use SynchronousDelivery also in becomeFirstResponder. Pick-to: 6.2 Change-Id: I9061868b0dd0db0252f281e3a974cffe795af38f Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Move pointingDeviceFor helper to top of fileVolker Hilsheimer2021-09-081-30/+30
| | | | | | | | | It's confusing to have it in the middle of the code implementing the various interfaces. Make review of follow up patches easier by moving it out of the way. Change-Id: I10f6e8f7642ec0cb14ae31b14a023c6a9ef455d9 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Cocoa: Make sure we can display multiple sheets for the same NSWindowDoris Verria2021-09-071-1/+5
| | | | | | | | | | | | | | | On macOS, to display a modal with Qt::WindowModality set, or of type Qt::Sheet, we call beginSheet:completinHandler:. However, this method won't display the specified sheet unless the current active one is dismissed, which is a different behavior than what we expect for this case. Use beginCriticalSheet:completionHandler: whenever we already have an active sheet attached to the NSWindow, which allows us to display multiple sheets for the same window. Fixes: QTBUG-91059 Pick-to: 5.15 6.1 6.2 Change-Id: I86bdbcbd63758edbbc48a8aade0178917dcb0e5b Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Report preedit cursor position and cursor visibility correctlyTor Arne Vestbø2021-09-061-2/+9
| | | | | | | | | | | | | | | | Unfortunately QInputMethodEvent::Cursor defines length == 0 as the cursor being hidden, and length > 0 as being visible. This is the opposite of what native macOS application do. A future improvement here would be to base the QInputMethodEvent logic on QStyle::SH_BlinkCursorWhenTextSelected, which we already respect for normal selections. That would also allow us to use QInputMethodEvent::Cursor to set the preedit selection, which we currently have to fake via QInputMethodEvent::TextFormat. Pick-to: 6.2 Change-Id: I75b5d8c5403283a0988355e440a98b4df35ec995 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Don't rely on invalidateCursorRectsForView when mouse is over viewTor Arne Vestbø2021-09-031-0/+14
| | | | | | | | | | | | | | | | | | | | | | Calling invalidateCursorRectsForView will normally result in a updateCursor callback, where we then set the current cursor using [NSCursor set]. But if an override cursor is set by AppKit, which happens for example when hovering over a resizable window's theme frame, then AppKit ignores the call to invalidateCursorRectsForView. And it will not consult the view when the override cursor is unset again, which results in the cursor being reset back to the default arrow cursor instead of the cursor that was set when we initiated the invalidateCursorRectsForView call. We need to hit-test to confirm that the mouse is over the view, as there might be child views in the mix that also have custom cursors, and we don't want to activate the parent view's cursor unless we're actually over that view. Fixes: QTBUG-81552 Fixes: QTBUG-96003 Pick-to: 6.2 5.15 Change-Id: I52573ab7be82f28c6a1cf686bd4b133551cfe98b Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* cocoa: use TouchPad deviceType for trackpadShawn Rutledge2021-09-031-0/+1
| | | | | | | | | | | WheelHandler { acceptedDevices: PointerDevice.TouchPad } doesn't react unless we use the right type. Amends 69c833dae91d004b48f815e0156d6caeb4cdb491 Pick-to: 6.2 Change-Id: I813de096b87f3af4dfcf5510abc0d0bd9c15b689 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Hide mouse cursor when initiating IM enabled text inputTor Arne Vestbø2021-08-271-0/+13
| | | | | | | Fixes: QTBUG-72744 Pick-to: 6.2 Change-Id: I952710e88a11fd00498562c9011461a010f02f7b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Correctly implement attributedSubstringForProposedRangeTor Arne Vestbø2021-08-271-6/+36
| | | | | | | | | | | | | | | | The substring range refers to the entire text of the focus object, not just the selection. As there is no way to pull out the entire text via input method queries we do the best we can via ImTextBeforeCursor and ImTextAfterCursor. Returning the correct substring enables input method features such as backtracking into already committed text with the Hiragana IM, as well as the Keyboard Viewer's 'Current Text' toolbar. Pick-to: 6.2 Change-Id: I53286ef1e8e7c5fba37858dda7317ae74d95b528 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Assume input method handles key eventTor Arne Vestbø2021-08-272-12/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When input methods are enabled for the focus object we send key events through interpretKeyEvents, which will involve the input method in the key event processing. The input method will get back to us with callbacks such as insertText, setMarkedText, or doCommandBySelector. In the case of insertText, when the inserted text matches the originating key event's text, we opt to not send the text as an QInputMethodEvent, and instead fall back to sending it as a normal QKeyEvent. The reason for this is that Qt's IM protocol was designed to handle composited text, so sending non-composited (but IM-initiated) text input as IM events is unexpected (see 2d05d3bd2815c220474b3c07bf3f2ef7417d3070). However, we cannot assume that the input method will always call us back with one of the above mentioned methods. The input method can very well eat the event as part of its own operation. This happens for example when pressing and holding 'a' in a US English keyboard layout, which will pop up an input panel for the various accents available. Or it may happen when using the AquaSKK third party IM, which uses the 'l' key to switch the input mode to latin without producing any characters. To allow these input methods the freedom to control the processing of key events we need to reverse the logic for when we send key events as QKeyEvent. We now assume that the IM will handle the event, and only trigger QKeyEvent in two cases where we explicitly were called back by the IM, but decided that a QKeyEvent is needed: - If the IM calls insertText and we consider the text simple text - If the IM calls doCommandBySelector and we can't find a matching selector for the command. We only implement insertNewline and cancel, so in all other cases we want to pass on the key event to let the focus object handle it, for example for 'Select All' and similar key combinations. Fixes: QTBUG-46300 Fixes: QTBUG-71394 Pick-to: 6.2 Inspired-by: Vladimir Belyavsky Change-Id: I9a73a8e1baa2ebe0c5df1166a9ec3d9843632bb1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Handle replacement range during marking of textTor Arne Vestbø2021-08-271-0/+16
| | | | | | | | | | | | The input method may include already committed text when marking text, in which case the replacement range reflects the position and length of the existing text. We handle this the same way we do replacement ranges in insertText. Pick-to: 6.2 Change-Id: I148e4701318a59c7e0d9441d157199d7c8606f43 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Handle IM insertNewline by sending synthetic Qt::Key_ReturnTor Arne Vestbø2021-08-273-8/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Depending on the input method, pressing enter may result in simply dismissing the input method editor, without confirming the composition. For example with Hiragana, pressing 'a', then 'Tab', and then 'Enter'. In other cases it may confirm the composition as well, for example with Hiragana, pressing 'a' and then 'Enter'. And in some cases the IME will produce an explicit new line, for example with US English, pressing '~' and then 'Enter', or with 2-Set Korean, pressing 'a', then 'j', and then 'Enter'. Semantically, the input method has then asked us to insert a newline, and we should probably do so via an QInputMethodEvent, either directly or via [self insertText:@"\r"]. This is also how NSTextView handles the command. But, if we did, we would bypass all the code in Qt (and clients) that assume that pressing the return key results in a key event, for example the QLineEdit::returnPressed logic. To ensure that clients will still see the Qt::Key_Return key event, we send it as a normal key event. But, we can not fall back to handleKeyEvent for this, as the original key event may have text that reflects the combination of the inserted text and the newline, e.g. "~\r". We have already inserted the composition, so we need to follow up with a single newline event. Task-number: QTBUG-39125 Pick-to: 6.2 Change-Id: If1e95687e6d5b06011692175a325f457b0b8a72f Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Factor out key event handling into helper structTor Arne Vestbø2021-08-272-72/+140
| | | | | | | | | | | This allows us to share code between handleKeyEvent: and flagsChanged: for parsing the incoming NSEvent, and allows for sending key events from other call sites in the future without duplicating the parsing and sending logic. Pick-to: 6.2 Change-Id: Ic63f740523496a9432e439663a20f78b5bc234c5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Return early from key handler if shortcut was handledTor Arne Vestbø2021-08-271-7/+3
| | | | | | | | The code paths after accepting a shortcut event can never be hit. Pick-to: 6.2 Change-Id: Ida77417adb8fcfd25a4b20c4eb86056b3769f014 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Check NSEvent.characters to determine dead key stateTor Arne Vestbø2021-08-271-2/+3
| | | | | | | | | | | | | | We map NSEvent.characters to text that we pass on in our QKeyEvent, but for Qt 4 compatibility we explicitly skip function keys and arrow keys, as the text these events produce are control characters. See 4dbce2a469608194527188a136baa3e812caf361. However, these keys are not dead keys, so we can't use the resolved text we're planning to pass on to Qt to determine if they are. Pick-to: 6.2 Change-Id: Ib59f0489ae014379c699600f14634c55161ccc8a Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Use current NSEvent to determine if IM text matches key eventTor Arne Vestbø2021-08-273-13/+17
| | | | | | | | | Gives us one less state member to worry about in the IM machinery. Task-number: QTBUG-35700 Pick-to: 6.2 Change-Id: Iaa06b29015f9b9594b8107b74a8931f076a26e12 Reviewed-by: Liang Qi <liang.qi@qt.io>
* macOS: Modernize and clean up key event handlingTor Arne Vestbø2021-08-261-54/+56
| | | | | | | | | | | | | - Pass key event type as QEvent::Type - Use proper type for NSEventModifierFlags - Use modern Objective-C property access in key handler - Modernize flagsChanged implementation using ranged-for - Use explicit Qt::Key type in key handling - Add FIXME comments for dubious code Pick-to: 6.2 Change-Id: I533e0a5685108dc3cdccd2b276b4eb7a729d172e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Move replacement range calculations into helper methodsTor Arne Vestbø2021-08-261-35/+70
| | | | | | | | We're going to need this logic for marked text as well. Pick-to: 6.2 Change-Id: I461024c3df0c4956c794f16d1cb31fc6b0efe4c5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Correctly compute marked and selected text range, and use for insertionTor Arne Vestbø2021-08-241-17/+111
| | | | | | | | | | | | | | | | | | | The NSTextInputClient protocol expects marked (composed) and selected text ranges to be relative to the document, not to the current editing block as Qt typically expects. Luckily we can use the absolute cursor position to compute an absolute offset that we can apply to any other positions, such as the selection. Now that we are computing the ranges correctly we can also use them during text insertion, when the incoming replacementRange is not valid. We then transform and sanitize the replacement range to the format that Qt expects for QInputMethodEvent::setCommitString(). Pick-to: 6.2 Change-Id: I4cb2f7c63adb92e407f38af05adce539c9bed7e2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Highlight selected part of preedit using platform theme paletteTor Arne Vestbø2021-08-231-5/+17
| | | | | | | | | | | | | | | | | | | | | | | | QInputMethodEvent::Selection unfortunately doesn't apply to the preedit text, and QInputMethodEvent::Cursor which does, doesn't support setting a selection. Until we've introduced attributes that allow us to propagate the preedit selection semantically we resort to styling the selection via the TextFormat attribute, so that the preedit selection is visible to the user. This allows us to remove the fallback we had for thick and double underline styles, where we mapped those to the wiggly underline style. This was needed to distinguish the selected cluster when composing CJK, but looked out of place. One disadvantage of faking the selection via text format is that we will not update the selection color on theme change, e.g. when switching from light to dark mode, but this is a minor issue that we can live with until we've introduced a proper QInputMethodEvent attribute for the preedit selection. Pick-to: 6.2 Change-Id: I1c45c310107697962e328a4db908d29d2358f756 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Handle more NSUnderlineStyles during text compositionTor Arne Vestbø2021-08-211-2/+22
| | | | | | Pick-to: 6.2 Change-Id: I2a6cf612506d19736eab007f687a03f6d6595b62 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Respect default marked text attributesTor Arne Vestbø2021-08-211-31/+37
| | | | | | | | | | | | | | | | | | | | When the marked text was not an attributed string with built in styling we used to fall back to a hard-coded underline style. We now pick up the default marked text style via the markedTextAttributes property of a temporarily created NSView, which by default is a yellow background color. The implementation in NSView respects text system configuration toggles such as NSMarkedTextAttribute and NSMarkedTextColor, so by setting the user default NSMarkedTextAttribute to "Underline" the marked text will look like our old hard-coded default. This can be done in many ways, including passing `-NSMarkedTextAttribute Underline` on the command line, or by QSettings::setValue("NSMarkedTextAttribute", "Underline"); Pick-to: 6.2 Change-Id: Iede74836ed1449e77018c13733a675f8e9d84f7d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Clean up code style in [QNSView setMarkedText:]Tor Arne Vestbø2021-08-211-23/+23
| | | | | | Pick-to: 6.2 Change-Id: I8a901ac81b64e6fc9bd7fe9ea4e3eaa6257118ce Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Ensure we provide a preedit format for non-attributed stringsTor Arne Vestbø2021-08-211-3/+1
| | | | | | | | | | The logic was not taking into account that we were always adding an QInputMethodEvent::Cursor attribute, so we would never hit the fallback code. Pick-to: 6.2 Change-Id: I25bd725025152241a55e3fea60444c20e27db4f9 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Simplify validAttributesForMarkedTextTor Arne Vestbø2021-08-211-10/+1
| | | | | | | | | | We don't need to condition this on IM enablement. The attributes are only used if we are actually marking text, which only happens for IM enabled views. Pick-to: 6.2 Change-Id: I47377cf53cf2bf44a1d9513d317f82c73f083fa3 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Correct QNSPanelContentsWrapper @end marker placementTor Arne Vestbø2021-08-201-1/+2
| | | | | | | | | The incorrect "scoping" of q_IOObjectRetain and q_IOObjectRelease luckily did not affect their functionality as QIOType helpers. Pick-to: 6.2 Change-Id: I9b9c2312464c7e6f8e2d2a5856e35efa99ec0c41 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QCocoaTheme: add ButtonText color to standard paletteRichard Moe Gustavsen2021-08-201-1/+2
| | | | | | | | | | | | | | | | The standard palette had no value set for ButtonText. The result was the we drew button text in QtQuickControls2 using Text color instead, which would be wrong in dark mode, and result in a dark color instead of white. Note: Widgets hardcode the color "white" directly in the mac style, and was not affected by the missing value. Fixes: QTBUG-89177 Pick-to: 6.2 6.1 Change-Id: Ie2d99bfac9fcc70d45e5bd40ea45becf3fd70d87 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
* macOS: close popups on mousedown within the window frameVolker Hilsheimer2021-08-193-34/+53
| | | | | | | | | | | | | | | | On macOS, we close active popups when handling mouse-down events in the NSView, but not for such events in the window frame. This allows users to close a window that has a context menu open via the window's close button, which then leaves open popups behind. Factor the popup-closing code out into a dedicated method that we can call from within the NSWindow::sendEvent implementation for mouse down events. Fixes: QTBUG-30522 Pick-to: 6.2 6.1 5.15 Change-Id: I9c354efc449cfefff3ed84fa34b1cd8a0da3b4a7 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* macOS: Expand QNSView complex text documentationTor Arne Vestbø2021-08-191-1/+58
| | | | | | Pick-to: 6.2 Change-Id: Iceb146d7aafb869a80cebe50e27c3bc98e67ebe1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Tweak method argument names in QNSView complex text implementationTor Arne Vestbø2021-08-191-19/+19
| | | | | | Pick-to: 6.2 Change-Id: I6a7ec683ffe9c18a89326b3e53b4a907cb9a9512 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Restructure QNSView complex text implementationTor Arne Vestbø2021-08-191-85/+89
| | | | | | | | | For better overview of the flow and functionality of the NSTextInputClient protocol. Pick-to: 6.2 Change-Id: I8658405c7ff4ae762bfe3e4c11f9a157ae2b9a09 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Reorder QNSView instance variablesTor Arne Vestbø2021-08-191-14/+23
| | | | | | Pick-to: 6.2 Change-Id: Icde9ee6744290f88eaa2ac197c40ba412543b122 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Update QCocoaInputContext documentationTor Arne Vestbø2021-08-191-6/+4
| | | | | | Pick-to: 6.2 Change-Id: I5ae5fe51ddc1512f2627dbc972fbb95360d7ea24 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* macOS: Implement QPlatformInputContext::setFocusObject()Tor Arne Vestbø2021-08-192-13/+3
| | | | | | | | Instead of handling the update manually. Pick-to: 6.2 Change-Id: Iffb28d893146f5d3f6eae8e8c43aaf7fa5281516 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>