ios/CollaboraOnlineWebViewKeyboardManager/CollaboraOnlineWebViewKeyboardManager.m | 22 +++++- ios/Mobile/DocumentViewController.mm | 27 +++++++ loleaflet/html/loleaflet.html.m4 | 15 ++++ loleaflet/src/layer/marker/TextInput.js | 35 ++++++++-- 4 files changed, 86 insertions(+), 13 deletions(-)
New commits: commit 91041961f3f2841b50c3f74fa05761ac338181da Author: Tor Lillqvist <t...@collabora.com> AuthorDate: Tue Sep 1 16:58:17 2020 +0300 Commit: Tor Lillqvist <t...@collabora.com> CommitDate: Wed Sep 2 19:38:42 2020 +0200 tdf#133284: Improve hardware and on-screen keyboard in the iOS app This is a quite complicated change that should both fix tdf#133284 (cursor keys on a hardware keyboard do not work in a spreadsheet document) and also improve the interaction with CollaboraOnlineWebViewKeyboardManager that manages the on-screen keyboard. We need to jump through complicated hoops in order to get the hardware cursor keys handled right after loading a spreadsheet document. In the CollaboraOnlineWebViewKeyboardManager case we try harder to keep loleaflet's _textArea buffer in sync with what the UITextView in CollaboraOnlineWebViewKeyboardManager uses to provide suggestions above the on-screen keyboard. Also merges in related changes from today to CollaboraOnlineWebViewKeyboardManager. Change-Id: Ic4acb54bd4e815aa8bfb2bf40b08493446ae5ab0 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101878 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tor Lillqvist <t...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101953 diff --git a/ios/CollaboraOnlineWebViewKeyboardManager/CollaboraOnlineWebViewKeyboardManager.m b/ios/CollaboraOnlineWebViewKeyboardManager/CollaboraOnlineWebViewKeyboardManager.m index 561b726d6..fd1bcaff3 100644 --- a/ios/CollaboraOnlineWebViewKeyboardManager/CollaboraOnlineWebViewKeyboardManager.m +++ b/ios/CollaboraOnlineWebViewKeyboardManager/CollaboraOnlineWebViewKeyboardManager.m @@ -79,6 +79,18 @@ NSMutableString *quotedText = [NSMutableString string]; + int location = range.location; + + if (location < self.text.length && location + range.length == self.text.length) { + // To guard against possible mismatch between our self.text and the _textArea.value in + // TextInput.js, we indicate deletion or replacement from the end with negative location. + location = location - self.text.length; + } + else if (range.location == 0 && range.length == 0 && text.length == 0) { + // Backspace without anything known about preceding text + location = -1; + } + for (unsigned i = 0; i < text.length; i++) { const unichar c = [text characterAtIndex:i]; if (c == '\'' || c == '\\') { @@ -93,7 +105,7 @@ NSMutableString *message = [NSMutableString string]; - [message appendFormat:@"{id: 'COKbdMgr', command: 'replaceText', location: %lu, length: %lu, text: '", range.location, range.length]; + [message appendFormat:@"{id: 'COKbdMgr', command: 'replaceText', location: %d, length: %lu, text: '", location, range.length]; [message appendString:quotedText]; [message appendString:@"'}"]; @@ -209,15 +221,15 @@ // will be added. control.autocapitalizationType = UITextAutocapitalizationTypeNone; - control.text = text; - control.selectedRange = NSMakeRange(location, 0); - lastCommandIsHide = NO; [self->webView addSubview:control]; NSLog(@"COKbdMgr: Added _COWVKMKeyInputControl to webView"); [control becomeFirstResponder]; } + control.text = text; + control.selectedRange = NSMakeRange(location, 0); + } - (void)hideKeyboard { @@ -253,6 +265,8 @@ NSString *text = message.body[@"text"]; NSNumber *location = message.body[@"location"]; NSLog(@"COKbdMgr: command=display type=%@ text=%@ location=%@", type, text, location); + if (text == nil) + text = @""; [self displayKeyboardOfType:type withText:text at:(location != nil ? [location unsignedIntegerValue] : UINT_MAX)]; } else if ([stringCommand isEqualToString:@"hide"]) { lastCommandIsHide = YES; diff --git a/ios/Mobile/DocumentViewController.mm b/ios/Mobile/DocumentViewController.mm index cefd23c9e..eab598c2a 100644 --- a/ios/Mobile/DocumentViewController.mm +++ b/ios/Mobile/DocumentViewController.mm @@ -105,8 +105,10 @@ static IMP standardImpOfInputAccessoryView = nil; // contents is handled fully in JavaScript, the WebView has no knowledge of that.) self.webView.scrollView.delegate = self; - keyboardManager = - [[CollaboraOnlineWebViewKeyboardManager alloc] initForWebView:self.webView]; + if (!isExternalKeyboardAttached()) { + keyboardManager = + [[CollaboraOnlineWebViewKeyboardManager alloc] initForWebView:self.webView]; + } [self.view addSubview:self.webView]; @@ -447,6 +449,27 @@ static IMP standardImpOfInputAccessoryView = nil; std::remove(printFile.c_str()); }]; + return; + } else if ([message.body isEqualToString:@"FOCUSIFHWKBD"]) { + if (isExternalKeyboardAttached()) { + NSString *hwKeyboardMagic = @"{" + " if (window.MagicToGetHWKeyboardWorking) {" + " window.MagicToGetHWKeyboardWorking();" + " }" + "}"; + [self.webView evaluateJavaScript:hwKeyboardMagic + completionHandler:^(id _Nullable obj, NSError * _Nullable error) + { + if (error) { + LOG_ERR("Error after " << [hwKeyboardMagic UTF8String] << ": " << [[error localizedDescription] UTF8String]); + NSString *jsException = error.userInfo[@"WKJavaScriptExceptionMessage"]; + if (jsException != nil) + LOG_ERR("JavaScript exception: " << [jsException UTF8String]); + } + } + ]; + } + return; } else if ([message.body hasPrefix:@"HYPERLINK"]) { NSArray *messageBodyItems = [message.body componentsSeparatedByString:@" "]; diff --git a/loleaflet/html/loleaflet.html.m4 b/loleaflet/html/loleaflet.html.m4 index 9f42ed9f9..2a53e2603 100644 --- a/loleaflet/html/loleaflet.html.m4 +++ b/loleaflet/html/loleaflet.html.m4 @@ -69,7 +69,20 @@ m4_ifelse(ANDROIDAPP,[true], ) if (window.ThisIsTheiOSApp) { - window.addEventListener("keydown", function(e) { e.preventDefault(); }); + window.addEventListener('keydown', function(e) { + if (e.metaKey) { + e.preventDefault(); + } + if (window.MagicKeyDownHandler) + window.MagicKeyDownHandler(e); + }); + window.addEventListener('keyup', function(e) { + if (e.metaKey) { + e.preventDefault(); + } + if (window.MagicKeyUpHandler) + window.MagicKeyUpHandler(e); + }); } var Base64ToArrayBuffer = function(base64Str) { diff --git a/loleaflet/src/layer/marker/TextInput.js b/loleaflet/src/layer/marker/TextInput.js index 418ffd7d1..42ebdbf34 100644 --- a/loleaflet/src/layer/marker/TextInput.js +++ b/loleaflet/src/layer/marker/TextInput.js @@ -102,10 +102,28 @@ L.TextInput = L.Layer.extend({ this._onFocusBlur({ type: 'focus' }); } + if (window.ThisIsTheiOSApp) { + var that = this; + window.MagicToGetHWKeyboardWorking = function() { + var that2 = that; + window.MagicKeyDownHandler = function(e) { + that2._onKeyDown(e); + }; + window.MagicKeyUpHandler = function(e) { + that2._onKeyUp(e); + }; + }; + window.postMobileMessage('FOCUSIFHWKBD'); + } + L.DomEvent.on(this._map.getContainer(), 'mousedown touchstart', this._abortComposition, this); }, onRemove: function() { + window.MagicToGetHWKeyboardWorking = null; + window.MagicKeyDownHandler = null; + window.MagicKeyUpHandler = null; + if (this._container) { this.getPane().removeChild(this._container); } @@ -226,10 +244,16 @@ L.TextInput = L.Layer.extend({ throw errorMessage; } - if (that._textArea.value.length == 2 && message.length == 0 && message.text.length == 0) { - that._removeTextContent(1, 0); - } else { - that._textArea.value = that._textArea.value.slice(0, message.location + 1) + message.text + that._textArea.value.slice(message.location + 1 + message.length); + if (message.location < 0) { + if (that._textArea.value.length > 2) { + that._textArea.value = that._textArea.value.slice(0, message.location - 1) + that._textArea.value.slice(-1); + that._onInput({}); + } else { + that._removeTextContent(-message.location, 0); + } + } + if (message.text.length > 0) { + that._textArea.value = that._textArea.value.slice(0, -1) + message.text + that._textArea.value.slice(-1); that._onInput({}); } } else { @@ -239,8 +263,7 @@ L.TextInput = L.Layer.extend({ } }; - // We don't know the seed text to feed CollaboraOnlineWebViewKeyboardManager - window.webkit.messageHandlers.CollaboraOnlineWebViewKeyboardManager.postMessage({command: 'display'}); + window.webkit.messageHandlers.CollaboraOnlineWebViewKeyboardManager.postMessage({command: 'display', text: this._textArea.value.slice(1, -1)}); this._onFocusBlur({type: 'focus'}); return; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits