aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xbmc/dialogs/GUIDialogKeyboardTouch.cpp4
-rw-r--r--xbmc/platform/darwin/ios-common/CMakeLists.txt12
-rw-r--r--xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.h33
-rw-r--r--xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.mm108
-rw-r--r--xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.h32
-rw-r--r--xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.mm161
-rw-r--r--xbmc/platform/darwin/ios-common/IOSKeyboard.h29
-rw-r--r--xbmc/platform/darwin/ios-common/IOSKeyboard.mm100
-rw-r--r--xbmc/platform/darwin/ios-common/IOSKeyboardView.h40
-rw-r--r--xbmc/platform/darwin/ios-common/IOSKeyboardView.mm351
-rw-r--r--xbmc/platform/darwin/ios/CMakeLists.txt2
-rw-r--r--xbmc/platform/darwin/ios/IOSKeyboardView.h17
-rw-r--r--xbmc/platform/darwin/ios/IOSKeyboardView.mm146
13 files changed, 507 insertions, 528 deletions
diff --git a/xbmc/dialogs/GUIDialogKeyboardTouch.cpp b/xbmc/dialogs/GUIDialogKeyboardTouch.cpp
index a05999d00d..e9511cec1a 100644
--- a/xbmc/dialogs/GUIDialogKeyboardTouch.cpp
+++ b/xbmc/dialogs/GUIDialogKeyboardTouch.cpp
@@ -8,7 +8,7 @@
#include "GUIDialogKeyboardTouch.h"
#if defined(TARGET_DARWIN_EMBEDDED)
-#include "platform/darwin/ios-common/IOSKeyboard.h"
+#include "platform/darwin/ios-common/DarwinEmbedKeyboard.h"
#endif
CGUIDialogKeyboardTouch::CGUIDialogKeyboardTouch()
@@ -22,7 +22,7 @@ CGUIDialogKeyboardTouch::CGUIDialogKeyboardTouch()
bool CGUIDialogKeyboardTouch::ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput)
{
#if defined(TARGET_DARWIN_EMBEDDED)
- m_keyboard.reset(new CIOSKeyboard());
+ m_keyboard.reset(new CDarwinEmbedKeyboard());
#endif
if (!m_keyboard)
diff --git a/xbmc/platform/darwin/ios-common/CMakeLists.txt b/xbmc/platform/darwin/ios-common/CMakeLists.txt
index 5c6533d5bc..1a1749c379 100644
--- a/xbmc/platform/darwin/ios-common/CMakeLists.txt
+++ b/xbmc/platform/darwin/ios-common/CMakeLists.txt
@@ -1,11 +1,11 @@
set(SOURCES AnnounceReceiver.mm
- DarwinEmbedNowPlayingInfoManager.mm
- IOSKeyboard.mm
- IOSKeyboardView.mm)
+ DarwinEmbedKeyboard.mm
+ DarwinEmbedKeyboardView.mm
+ DarwinEmbedNowPlayingInfoManager.mm)
set(HEADERS AnnounceReceiver.h
- DarwinEmbedNowPlayingInfoManager.h
- IOSKeyboard.h
- IOSKeyboardView.h)
+ DarwinEmbedKeyboard.h
+ DarwinEmbedKeyboardView.h
+ DarwinEmbedNowPlayingInfoManager.h)
core_add_library(platform_ios-common)
diff --git a/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.h b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.h
new file mode 100644
index 0000000000..386f1bb42c
--- /dev/null
+++ b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "guilib/GUIKeyboard.h"
+
+struct CDarwinEmbedKeyboardImpl;
+
+class CDarwinEmbedKeyboard : public CGUIKeyboard
+{
+public:
+ CDarwinEmbedKeyboard();
+ bool ShowAndGetInput(char_callback_t pCallback,
+ const std::string& initialString,
+ std::string& typedString,
+ const std::string& heading,
+ bool bHiddenInput) override;
+ void Cancel() override;
+ void fireCallback(const std::string& str);
+ void invalidateCallback();
+ bool SetTextToKeyboard(const std::string& text, bool closeKeyboard = false) override;
+
+private:
+ char_callback_t m_pCharCallback = nullptr;
+ bool m_canceled = false;
+ std::unique_ptr<CDarwinEmbedKeyboardImpl> m_impl;
+};
diff --git a/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.mm b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.mm
new file mode 100644
index 0000000000..e0d61050ce
--- /dev/null
+++ b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboard.mm
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "DarwinEmbedKeyboard.h"
+
+#include "platform/darwin/ios-common/DarwinEmbedKeyboardView.h"
+#include "platform/darwin/ios/IOSKeyboardView.h"
+#include "platform/darwin/ios/XBMCController.h"
+
+struct CDarwinEmbedKeyboardImpl
+{
+ IOSKeyboardView* g_pKeyboard = nil;
+};
+
+CDarwinEmbedKeyboard::CDarwinEmbedKeyboard()
+ : CGUIKeyboard(), m_impl{std::make_unique<CDarwinEmbedKeyboardImpl>()}
+{
+}
+
+bool CDarwinEmbedKeyboard::ShowAndGetInput(char_callback_t pCallback,
+ const std::string& initialString,
+ std::string& typedString,
+ const std::string& heading,
+ bool bHiddenInput)
+{
+ // we are in xbmc main thread or python module thread.
+ @autoreleasepool
+ {
+ @synchronized([KeyboardView class])
+ {
+ // in case twice open keyboard.
+ if (m_impl->g_pKeyboard)
+ return false;
+
+ //! @Todo generalise this block for platform
+ //create the keyboardview
+ IOSKeyboardView* __block keyboardView;
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ // assume we are only drawn on the mainscreen ever!
+ auto keyboardFrame = [g_xbmcController fullscreenSubviewFrame];
+ keyboardView = [[IOSKeyboardView alloc] initWithFrame:keyboardFrame];
+ });
+ ////////////////////////////////////////////
+ if (!keyboardView)
+ return false;
+ m_impl->g_pKeyboard = keyboardView;
+
+ // inform the controller that the native keyboard is active
+ // basically as long as m_impl->g_pKeyboard exists...
+ [g_xbmcController nativeKeyboardActive:true];
+ }
+
+ m_pCharCallback = pCallback;
+
+ // init keyboard stuff
+ SetTextToKeyboard(initialString);
+ [m_impl->g_pKeyboard setHidden:bHiddenInput];
+ [m_impl->g_pKeyboard setHeading:@(heading.c_str())];
+ m_impl->g_pKeyboard.darwinEmbedKeyboard = this; // for calling back
+ bool confirmed = false;
+ if (!m_canceled)
+ {
+ [m_impl->g_pKeyboard setCancelFlag:&m_canceled];
+ [m_impl->g_pKeyboard activate]; // blocks and shows keyboard
+ // user is done - get resulted text and confirmation
+ confirmed = [m_impl->g_pKeyboard isConfirmed];
+ if (confirmed)
+ typedString = m_impl->g_pKeyboard.text.UTF8String;
+ }
+ @synchronized([KeyboardView class])
+ {
+ m_impl->g_pKeyboard = nil;
+ [g_xbmcController nativeKeyboardActive:false];
+ }
+ return confirmed;
+ }
+}
+
+void CDarwinEmbedKeyboard::Cancel()
+{
+ m_canceled = true;
+}
+
+bool CDarwinEmbedKeyboard::SetTextToKeyboard(const std::string& text,
+ bool closeKeyboard /* = false */)
+{
+ if (!m_impl->g_pKeyboard)
+ return false;
+ [m_impl->g_pKeyboard setKeyboardText:@(text.c_str()) closeKeyboard:closeKeyboard ? YES : NO];
+ return true;
+}
+
+//wrap our callback between objc and c++
+void CDarwinEmbedKeyboard::fireCallback(const std::string& str)
+{
+ if (m_pCharCallback)
+ m_pCharCallback(this, str);
+}
+
+void CDarwinEmbedKeyboard::invalidateCallback()
+{
+ m_pCharCallback = nullptr;
+}
diff --git a/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.h b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.h
new file mode 100644
index 0000000000..a50b616d8d
--- /dev/null
+++ b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "platform/darwin/ios-common/DarwinEmbedKeyboard.h"
+
+#import <UIKit/UIKit.h>
+
+@interface KeyboardView : UIView <UITextFieldDelegate>
+{
+ bool* m_canceled;
+ BOOL m_deactivated;
+ UITextField* __weak m_inputTextField;
+}
+
+@property(getter=isConfirmed) BOOL confirmed;
+@property(assign) CDarwinEmbedKeyboard* darwinEmbedKeyboard;
+@property(nonatomic, readonly) NSString* text;
+
+- (void)setHeading:(NSString*)heading;
+- (void)setHidden:(BOOL)hidden;
+- (void)activate;
+- (void)deactivate;
+- (void)setKeyboardText:(NSString*)aText closeKeyboard:(BOOL)closeKeyboard;
+- (void)textChanged:(NSNotification*)aNotification;
+- (void)setCancelFlag:(bool*)cancelFlag;
+
+@end
diff --git a/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.mm b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.mm
new file mode 100644
index 0000000000..c0365c614a
--- /dev/null
+++ b/xbmc/platform/darwin/ios-common/DarwinEmbedKeyboardView.mm
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#import "DarwinEmbedKeyboardView.h"
+
+#include "Application.h"
+#include "guilib/GUIKeyboardFactory.h"
+#include "threads/Event.h"
+#include "utils/log.h"
+
+#import "platform/darwin/ios/XBMCController.h"
+
+static CEvent keyboardFinishedEvent;
+
+@implementation KeyboardView
+
+@synthesize confirmed = m_confirmed;
+@synthesize darwinEmbedKeyboard = m_darwinEmbedKeyboard;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (!self)
+ return nil;
+
+ m_canceled = nullptr;
+ m_deactivated = NO;
+
+ auto textField = [UITextField new];
+ textField.translatesAutoresizingMaskIntoConstraints = NO;
+ textField.clearButtonMode = UITextFieldViewModeAlways;
+ textField.borderStyle = UITextBorderStyleNone;
+ textField.returnKeyType = UIReturnKeyDone;
+ textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ textField.backgroundColor = UIColor.whiteColor;
+ textField.delegate = self;
+ [self addSubview:textField];
+ m_inputTextField = textField;
+
+ self.userInteractionEnabled = YES;
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(textChanged:)
+ name:UITextFieldTextDidChangeNotification
+ object:m_inputTextField];
+ return self;
+}
+
+- (void)textFieldDidEndEditing:(UITextField*)textField
+{
+ [self deactivate];
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField*)textField
+{
+ m_confirmed = YES;
+ return YES;
+}
+
+- (NSString*)text
+{
+ NSString __block* result;
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ result = m_inputTextField.text;
+ });
+ return result;
+}
+
+- (void)activate
+{
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [g_xbmcController activateKeyboard:self];
+ [self layoutIfNeeded];
+ [m_inputTextField becomeFirstResponder];
+ keyboardFinishedEvent.Reset();
+ });
+
+ // we are waiting on the user finishing the keyboard
+ while (!keyboardFinishedEvent.WaitMSec(500))
+ {
+ if (nullptr != m_canceled && *m_canceled)
+ {
+ [self deactivate];
+ m_canceled = nullptr;
+ }
+ }
+}
+
+- (void)deactivate
+{
+ m_deactivated = YES;
+
+ // invalidate our callback object
+ if (m_darwinEmbedKeyboard)
+ {
+ m_darwinEmbedKeyboard->invalidateCallback();
+ m_darwinEmbedKeyboard = nil;
+ }
+ // give back the control to whoever
+ [m_inputTextField resignFirstResponder];
+
+ // delay closing view until text field finishes resigning first responder
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // always called in the mainloop context
+ // detach the keyboard view from our main controller
+ [g_xbmcController deactivateKeyboard:self];
+
+ // no more notification we want to receive.
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ keyboardFinishedEvent.Set();
+ });
+}
+
+- (void)setKeyboardText:(NSString*)aText closeKeyboard:(BOOL)closeKeyboard
+{
+ CLog::Log(LOGDEBUG, "{}: {}, {}", __PRETTY_FUNCTION__, aText.UTF8String, closeKeyboard);
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ m_inputTextField.text = aText;
+ [self textChanged:nil];
+ });
+
+ if (closeKeyboard)
+ {
+ m_confirmed = YES;
+ [self deactivate];
+ }
+}
+
+- (void)setHeading:(NSString*)heading
+{
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ m_inputTextField.placeholder = heading;
+ });
+}
+
+- (void)setHidden:(BOOL)hidden
+{
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ m_inputTextField.secureTextEntry = hidden;
+ });
+}
+
+- (void)textChanged:(NSNotification*)aNotification
+{
+ if (m_darwinEmbedKeyboard)
+ m_darwinEmbedKeyboard->fireCallback(m_inputTextField.text.UTF8String);
+}
+
+- (void)setCancelFlag:(bool*)cancelFlag
+{
+ m_canceled = cancelFlag;
+}
+
+@end
diff --git a/xbmc/platform/darwin/ios-common/IOSKeyboard.h b/xbmc/platform/darwin/ios-common/IOSKeyboard.h
deleted file mode 100644
index 74e5166bd7..0000000000
--- a/xbmc/platform/darwin/ios-common/IOSKeyboard.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012-2018 Team Kodi
- * This file is part of Kodi - https://kodi.tv
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- * See LICENSES/README.md for more information.
- */
-
-#pragma once
-
-#include "guilib/GUIKeyboard.h"
-
-class CIOSKeyboardImpl;
-
-class CIOSKeyboard : public CGUIKeyboard
-{
- public:
- CIOSKeyboard();
- bool ShowAndGetInput(char_callback_t pCallback, const std::string& initialString, std::string& typedString, const std::string& heading, bool bHiddenInput) override;
- void Cancel() override;
- void fireCallback(const std::string &str);
- void invalidateCallback() {m_pCharCallback = nullptr;}
- bool SetTextToKeyboard(const std::string& text, bool closeKeyboard = false) override;
-
- private:
- char_callback_t m_pCharCallback;
- bool m_bCanceled;
- std::unique_ptr<CIOSKeyboardImpl> m_impl;
-};
diff --git a/xbmc/platform/darwin/ios-common/IOSKeyboard.mm b/xbmc/platform/darwin/ios-common/IOSKeyboard.mm
deleted file mode 100644
index c76572ba5c..0000000000
--- a/xbmc/platform/darwin/ios-common/IOSKeyboard.mm
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2012-2018 Team Kodi
- * This file is part of Kodi - https://kodi.tv
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- * See LICENSES/README.md for more information.
- */
-
-#include "platform/darwin/ios-common/IOSKeyboard.h"
-
-#include "platform/darwin/NSLogDebugHelpers.h"
-#include "platform/darwin/ios-common/IOSKeyboardView.h"
-#include "platform/darwin/ios/XBMCController.h"
-
-class CIOSKeyboardImpl
-{
-public:
- KeyboardView* g_pIosKeyboard = nil;
-};
-
-CIOSKeyboard::CIOSKeyboard()
- : CGUIKeyboard()
- , m_pCharCallback{nullptr}
- , m_bCanceled{false}
- , m_impl{new CIOSKeyboardImpl}
-{
-}
-
-bool CIOSKeyboard::ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput)
-{
- // we are in xbmc main thread or python module thread.
- @autoreleasepool
- {
- @synchronized([KeyboardView class])
- {
- // in case twice open keyboard.
- if (m_impl->g_pIosKeyboard)
- return false;
-
- // assume we are only drawn on the mainscreen ever!
- auto keyboardFrame = [g_xbmcController fullscreenSubviewFrame];
-
- //create the keyboardview
- m_impl->g_pIosKeyboard = [[KeyboardView alloc] initWithFrame:keyboardFrame];
- if (!m_impl->g_pIosKeyboard)
- return false;
-
- // inform the controller that the native keyboard is active
- // basically as long as m_impl->g_pIosKeyboard exists...
- [g_xbmcController nativeKeyboardActive:true];
- }
-
- m_pCharCallback = pCallback;
-
- // init keyboard stuff
- SetTextToKeyboard(initialString);
- [m_impl->g_pIosKeyboard setHidden:bHiddenInput];
- [m_impl->g_pIosKeyboard setHeading:[NSString stringWithUTF8String:heading.c_str()]];
- [m_impl->g_pIosKeyboard registerKeyboard:this]; // for calling back
- bool confirmed = false;
- if (!m_bCanceled)
- {
- [m_impl->g_pIosKeyboard setCancelFlag:&m_bCanceled];
- [m_impl->g_pIosKeyboard activate]; // blocks and shows keyboard
- // user is done - get resulted text and confirmation
- confirmed = m_impl->g_pIosKeyboard.isConfirmed;
- if (confirmed)
- typedString = [m_impl->g_pIosKeyboard.text UTF8String];
- }
- @synchronized([KeyboardView class])
- {
- m_impl->g_pIosKeyboard = nil;
- [g_xbmcController nativeKeyboardActive:false];
- }
- return confirmed;
- }
-}
-
-void CIOSKeyboard::Cancel()
-{
- m_bCanceled = true;
-}
-
-bool CIOSKeyboard::SetTextToKeyboard(const std::string &text, bool closeKeyboard /* = false */)
-{
- if (!m_impl->g_pIosKeyboard)
- return false;
- [m_impl->g_pIosKeyboard setKeyboardText:[NSString stringWithUTF8String:text.c_str()]
- closeKeyboard:closeKeyboard ? YES : NO];
- return true;
-}
-
-//wrap our callback between objc and c++
-void CIOSKeyboard::fireCallback(const std::string &str)
-{
- if(m_pCharCallback)
- {
- m_pCharCallback(this, str);
- }
-}
diff --git a/xbmc/platform/darwin/ios-common/IOSKeyboardView.h b/xbmc/platform/darwin/ios-common/IOSKeyboardView.h
deleted file mode 100644
index 1ddec3ac32..0000000000
--- a/xbmc/platform/darwin/ios-common/IOSKeyboardView.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012-2018 Team Kodi
- * This file is part of Kodi - https://kodi.tv
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- * See LICENSES/README.md for more information.
- */
-
-#include "platform/darwin/ios-common/IOSKeyboard.h"
-
-#import <UIKit/UIKit.h>
-
-@interface KeyboardView : UIView <UITextFieldDelegate>
-{
- NSMutableString *text;
- BOOL _confirmed;
- CIOSKeyboard *_iosKeyboard;
- bool *_canceled;
- BOOL _deactivated;
- UITextField *_textField;
- UITextField *_heading;
- int _keyboardIsShowing; // 0: not, 1: will show, 2: showing
- CGRect _kbRect;
-}
-
-@property(nonatomic, strong) NSMutableString* text;
-@property (getter = isConfirmed) BOOL _confirmed;
-@property (assign, setter = registerKeyboard:) CIOSKeyboard *_iosKeyboard;
-@property CGRect _frame;
-
-- (void) setHeading:(NSString *)heading;
-- (void) setHidden:(BOOL)hidden;
-- (void) activate;
-- (void) deactivate;
-- (void) setKeyboardText:(NSString*)aText closeKeyboard:(BOOL)closeKeyboard;
-- (void) textChanged:(NSNotification*)aNotification;
-- (void) setCancelFlag:(bool *)cancelFlag;
-- (void) doDeactivate:(NSDictionary *)dict;
-- (id)initWithFrameInternal;
-@end
diff --git a/xbmc/platform/darwin/ios-common/IOSKeyboardView.mm b/xbmc/platform/darwin/ios-common/IOSKeyboardView.mm
deleted file mode 100644
index 84d69325b1..0000000000
--- a/xbmc/platform/darwin/ios-common/IOSKeyboardView.mm
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2012-2018 Team Kodi
- * This file is part of Kodi - https://kodi.tv
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- * See LICENSES/README.md for more information.
- */
-
-#import "platform/darwin/ios-common/IOSKeyboardView.h"
-
-#include "Application.h"
-#include "guilib/GUIKeyboardFactory.h"
-#include "threads/Event.h"
-
-#import "platform/darwin/NSLogDebugHelpers.h"
-#import "platform/darwin/ios-common/IOSKeyboard.h"
-#import "platform/darwin/ios/IOSScreenManager.h"
-#import "platform/darwin/ios/XBMCController.h"
-
-static CEvent keyboardFinishedEvent;
-
-#define INPUT_BOX_HEIGHT 30
-#define SPACE_BETWEEN_INPUT_AND_KEYBOARD 0
-
-@implementation KeyboardView
-@synthesize text;
-@synthesize _confirmed;
-@synthesize _iosKeyboard;
-@synthesize _frame;
-
-- (id)initWithFrame:(CGRect)frame
-{
- _frame = frame;
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(initWithFrameInternal) withObject:nil waitUntilDone:YES];
- }
- else
- {
- self = [self initWithFrameInternal];
- }
- return self;
-}
-
-- (id)initWithFrameInternal
-{
- CGRect frame = _frame;
- self = [super initWithFrame:frame];
- if (self)
- {
- _iosKeyboard = nil;
- _keyboardIsShowing = 0;
- _confirmed = NO;
- _canceled = NULL;
- _deactivated = NO;
-
- self.text = [NSMutableString stringWithString:@""];
-
- // default input box position above the half screen.
- CGRect textFieldFrame = CGRectMake(frame.size.width/2,
- frame.size.height/2-INPUT_BOX_HEIGHT-SPACE_BETWEEN_INPUT_AND_KEYBOARD,
- frame.size.width/2,
- INPUT_BOX_HEIGHT);
- _textField = [[UITextField alloc] initWithFrame:textFieldFrame];
- _textField.clearButtonMode = UITextFieldViewModeAlways;
- // UITextBorderStyleRoundedRect; - with round rect we can't control backgroundcolor
- _textField.borderStyle = UITextBorderStyleNone;
- _textField.returnKeyType = UIReturnKeyDone;
- _textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
- _textField.backgroundColor = [UIColor whiteColor];
- _textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
- _textField.delegate = self;
-
- CGRect labelFrame = textFieldFrame;
- labelFrame.origin.x = 0;
- _heading = [[UITextField alloc] initWithFrame:labelFrame];
- _heading.borderStyle = UITextBorderStyleNone;
- _heading.backgroundColor = [UIColor whiteColor];
- _heading.adjustsFontSizeToFitWidth = YES;
- _heading.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
- _heading.enabled = NO;
-
- [self addSubview:_heading];
- [self addSubview:_textField];
-
- self.userInteractionEnabled = YES;
-
- [self setAlpha:0.9];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(textChanged:)
- name:UITextFieldTextDidChangeNotification
- object:_textField];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardDidHide:)
- name:UIKeyboardDidHideNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardDidChangeFrame:)
- name:UIKeyboardDidChangeFrameNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardWillShow:)
- name:UIKeyboardWillShowNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardDidShow:)
- name:UIKeyboardDidShowNotification
- object:nil];
- }
- return self;
-}
-
-- (void)layoutSubviews
-{
- CGFloat headingW = 0;
- if (_heading.text and _heading.text.length > 0)
- {
- CGSize headingSize = [_heading.text sizeWithAttributes: @{NSFontAttributeName: [UIFont systemFontOfSize:[UIFont systemFontSize]]}];
- headingW = MIN(self.bounds.size.width/2, headingSize.width+30);
- }
-
- CGFloat y = _kbRect.origin.y - INPUT_BOX_HEIGHT - SPACE_BETWEEN_INPUT_AND_KEYBOARD;
-
- _heading.frame = CGRectMake(0, y, headingW, INPUT_BOX_HEIGHT);
- _textField.frame = CGRectMake(headingW, y, self.bounds.size.width-headingW, INPUT_BOX_HEIGHT);
-}
-
--(void)keyboardWillShow:(NSNotification *) notification{
- NSDictionary* info = [notification userInfo];
- CGRect kbRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- LOG(@"keyboardWillShow: keyboard frame: %@", NSStringFromCGRect(kbRect));
- _kbRect = kbRect;
- [self setNeedsLayout];
- _keyboardIsShowing = 1;
-}
-
--(void)keyboardDidShow:(NSNotification *) notification{
- LOG(@"keyboardDidShow: deactivated: %d", _deactivated);
- _keyboardIsShowing = 2;
- if (_deactivated)
- [self doDeactivate:nil];
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-{
- PRINT_SIGNATURE();
- [_textField resignFirstResponder];
-}
-
-- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
-{
- LOG(@"%s: keyboard IsShowing %d", __PRETTY_FUNCTION__, _keyboardIsShowing);
- // Do not break the keyboard show up process, else we will lost
- // keyboard did hide notification.
- return _keyboardIsShowing != 1;
-}
-
-- (void)textFieldDidEndEditing:(UITextField *)textField
-{
- PRINT_SIGNATURE();
- [self deactivate];
-}
-
--(BOOL)textFieldShouldReturn:(UITextField *)textField{
- PRINT_SIGNATURE();
- _confirmed = YES;
- [_textField resignFirstResponder];
- return YES;
-}
-
-- (void)keyboardDidChangeFrame:(id)sender
-{
-}
-
-- (void)keyboardDidHide:(id)sender
-{
- PRINT_SIGNATURE();
-
- _keyboardIsShowing = 0;
-
- if (_textField.editing)
- {
- LOG(@"kb hide when editing, it could be a language switch");
- return;
- }
-
- [self deactivate];
-}
-
-- (void) doActivate:(NSDictionary *)dict
-{
- PRINT_SIGNATURE();
- [g_xbmcController activateKeyboard:self];
- [_textField becomeFirstResponder];
- [self setNeedsLayout];
- keyboardFinishedEvent.Reset();
-}
-
-- (void)activate
-{
- PRINT_SIGNATURE();
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(doActivate:) withObject:nil waitUntilDone:YES];
- }
- else
- {
- // this would be fatal! We never should be called from the ios mainthread
- return;
- }
-
- // we are waiting on the user finishing the keyboard
- while(!keyboardFinishedEvent.WaitMSec(500))
- {
- if (NULL != _canceled && *_canceled)
- {
- [self deactivate];
- _canceled = NULL;
- }
- }
-}
-
-- (void) doDeactivate:(NSDictionary *)dict
-{
- LOG(@"%s: keyboard IsShowing %d", __PRETTY_FUNCTION__, _keyboardIsShowing);
- _deactivated = YES;
-
- // Do not break keyboard show up process, if so there's a bug of ios4 will not
- // notify us keyboard hide.
- if (_keyboardIsShowing == 1)
- return;
-
- // invalidate our callback object
- if(_iosKeyboard)
- {
- _iosKeyboard->invalidateCallback();
- _iosKeyboard = nil;
- }
- // give back the control to whoever
- [_textField resignFirstResponder];
-
- // delay closing view until text field finishes resigning first responder
- dispatch_async(dispatch_get_main_queue(), ^{
- // always called in the mainloop context
- // detach the keyboard view from our main controller
- [g_xbmcController deactivateKeyboard:self];
-
- // no more notification we want to receive.
- [[NSNotificationCenter defaultCenter] removeObserver: self];
-
- keyboardFinishedEvent.Set();
- });
-}
-
-- (void) deactivate
-{
- PRINT_SIGNATURE();
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(doDeactivate:) withObject:nil waitUntilDone:YES];
- }
- else
- {
- [self doDeactivate:nil];
- }
-}
-
-- (void) setKeyboardText:(NSString*)aText closeKeyboard:(BOOL)closeKeyboard
-{
- LOG(@"%s: %@, %d", __PRETTY_FUNCTION__, aText, closeKeyboard);
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(setDefault:) withObject:aText waitUntilDone:YES];
- }
- else
- {
- [self setDefault:aText];
- }
- if (closeKeyboard)
- {
- _confirmed = YES;
- [self deactivate];
- }
-}
-
-- (void) setHeading:(NSString *)heading
-{
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(setHeadingInternal:) withObject:heading waitUntilDone:YES];
- }
- else
- {
- [self setHeadingInternal:heading];
- }
-}
-
-- (void) setHeadingInternal:(NSString *)heading
-{
- if (heading && heading.length > 0) {
- _heading.text = [NSString stringWithFormat:@" %@:", heading];
- }
- else {
- _heading.text = nil;
- }
-}
-
-- (void) setDefault:(NSString *)defaultText
-{
- [_textField setText:defaultText];
- [self textChanged:nil];
-}
-
-- (void) setHiddenInternal:(NSNumber *)hidden
-{
- BOOL hiddenBool = [hidden boolValue];
- [_textField setSecureTextEntry:hiddenBool];
-}
-
-- (void) setHidden:(BOOL)hidden
-{
- NSNumber *passedValue = [NSNumber numberWithBool:hidden];
-
- if([NSThread currentThread] != [NSThread mainThread])
- {
- [self performSelectorOnMainThread:@selector(setHiddenInternal:) withObject:passedValue waitUntilDone:YES];
- }
- else
- {
- [self setHiddenInternal:passedValue];
- }
-}
-
-- (void) textChanged:(NSNotification*)aNotification
-{
- if (![self.text isEqualToString:_textField.text])
- {
- [self.text setString:_textField.text];
- if (_iosKeyboard)
- {
- _iosKeyboard->fireCallback([self.text UTF8String]);
- }
- }
-}
-
-- (void) setCancelFlag:(bool *)cancelFlag
-{
- _canceled = cancelFlag;
-}
-
-@end
diff --git a/xbmc/platform/darwin/ios/CMakeLists.txt b/xbmc/platform/darwin/ios/CMakeLists.txt
index 6214b00bb7..516fe43d62 100644
--- a/xbmc/platform/darwin/ios/CMakeLists.txt
+++ b/xbmc/platform/darwin/ios/CMakeLists.txt
@@ -1,12 +1,14 @@
set(SOURCES CPUInfoIos.cpp
IOSEAGLView.mm
IOSExternalTouchController.mm
+ IOSKeyboardView.mm
IOSScreenManager.mm
XBMCController.mm)
set(HEADERS CPUInfoIos.h
IOSEAGLView.h
IOSExternalTouchController.h
+ IOSKeyboardView.h
IOSScreenManager.h
XBMCApplication.h
XBMCController.h)
diff --git a/xbmc/platform/darwin/ios/IOSKeyboardView.h b/xbmc/platform/darwin/ios/IOSKeyboardView.h
new file mode 100644
index 0000000000..f5e3a61591
--- /dev/null
+++ b/xbmc/platform/darwin/ios/IOSKeyboardView.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019- Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#import "platform/darwin/ios-common/DarwinEmbedKeyboardView.h"
+
+@interface IOSKeyboardView : KeyboardView
+
+// use -initWithFrame:
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
+@end
diff --git a/xbmc/platform/darwin/ios/IOSKeyboardView.mm b/xbmc/platform/darwin/ios/IOSKeyboardView.mm
new file mode 100644
index 0000000000..74ec08a705
--- /dev/null
+++ b/xbmc/platform/darwin/ios/IOSKeyboardView.mm
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019- Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#import "IOSKeyboardView.h"
+
+#import "utils/log.h"
+
+static const CGFloat INPUT_BOX_HEIGHT = 30;
+
+@interface IOSKeyboardView ()
+@property(nonatomic, weak) UIView* textFieldContainer;
+@property(nonatomic, weak) NSLayoutConstraint* containerBottomConstraint;
+@property(nonatomic, assign, getter=isKeyboardVisible) bool keyboardVisible;
+@end
+
+@implementation IOSKeyboardView
+
+@synthesize textFieldContainer = m_textFieldContainer;
+@synthesize containerBottomConstraint = m_containerBottomConstraint;
+@synthesize keyboardVisible = m_keyboardVisible;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (!self)
+ return nil;
+
+ m_keyboardVisible = false;
+
+ self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
+
+ auto notificationCenter = NSNotificationCenter.defaultCenter;
+ [notificationCenter addObserver:self
+ selector:@selector(keyboardDidHide:)
+ name:UIKeyboardDidHideNotification
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(keyboardDidChangeFrame:)
+ name:UIKeyboardDidChangeFrameNotification
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(keyboardWillShow:)
+ name:UIKeyboardWillShowNotification
+ object:nil];
+ [notificationCenter addObserver:self
+ selector:@selector(keyboardDidShow:)
+ name:UIKeyboardDidShowNotification
+ object:nil];
+
+ [self addGestureRecognizer:[[UITapGestureRecognizer alloc]
+ initWithTarget:m_inputTextField
+ action:@selector(resignFirstResponder)]];
+
+ auto textFieldContainer = [UIView new];
+ textFieldContainer.translatesAutoresizingMaskIntoConstraints = NO;
+ textFieldContainer.backgroundColor = UIColor.whiteColor;
+ [textFieldContainer addSubview:m_inputTextField];
+ [self addSubview:textFieldContainer];
+ m_textFieldContainer = textFieldContainer;
+
+ auto bottomConstraint = [textFieldContainer.bottomAnchor constraintEqualToAnchor:self.topAnchor];
+ m_containerBottomConstraint = bottomConstraint;
+
+ [NSLayoutConstraint activateConstraints:@[
+ bottomConstraint,
+ [textFieldContainer.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
+ [textFieldContainer.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
+ [textFieldContainer.heightAnchor constraintEqualToConstant:INPUT_BOX_HEIGHT],
+
+ [m_inputTextField.widthAnchor constraintEqualToAnchor:textFieldContainer.widthAnchor
+ multiplier:0.5],
+ [m_inputTextField.centerXAnchor constraintEqualToAnchor:textFieldContainer.centerXAnchor],
+ [m_inputTextField.topAnchor constraintEqualToAnchor:textFieldContainer.topAnchor],
+ [m_inputTextField.bottomAnchor constraintEqualToAnchor:textFieldContainer.bottomAnchor],
+ ]];
+
+ return self;
+}
+
+- (void)keyboardWillShow:(NSNotification*)notification
+{
+ CLog::Log(LOGDEBUG, "{} {}", __PRETTY_FUNCTION__, notification.userInfo.description.UTF8String);
+ if (!self.isKeyboardVisible)
+ self.textFieldContainer.hidden = YES;
+}
+
+- (void)keyboardDidShow:(NSNotification*)notification
+{
+ CLog::Log(LOGDEBUG, "{} deactivated: {}, {}", __PRETTY_FUNCTION__, m_deactivated,
+ notification.userInfo.description.UTF8String);
+ self.keyboardVisible = true;
+ self.textFieldContainer.hidden = NO;
+
+ if (m_deactivated)
+ [self deactivate];
+}
+
+- (BOOL)textFieldShouldEndEditing:(UITextField*)textField
+{
+ CLog::Log(LOGDEBUG, "{}: keyboard IsShowing {}", __PRETTY_FUNCTION__, self.isKeyboardVisible);
+ return YES;
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField*)textField
+{
+ auto result = [super textFieldShouldReturn:textField];
+ if (result)
+ [textField resignFirstResponder];
+ return result;
+}
+
+- (void)keyboardDidChangeFrame:(NSNotification*)notification
+{
+ auto keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
+ // although converting isn't really necessary in our case, as the holder view occupies
+ // the whole screen, technically it's more correct
+ auto convertedFrame = [self convertRect:keyboardFrame
+ fromCoordinateSpace:UIScreen.mainScreen.coordinateSpace];
+ self.containerBottomConstraint.constant = CGRectGetMinY(convertedFrame);
+ [self layoutIfNeeded];
+}
+
+- (void)keyboardDidHide:(id)sender
+{
+ if (m_inputTextField.editing)
+ {
+ CLog::Log(LOGDEBUG, "kb hide when editing, it could be a language switch");
+ return;
+ }
+
+ self.keyboardVisible = false;
+ [self deactivate];
+}
+
+- (void)deactivate
+{
+ CLog::Log(LOGDEBUG, "{}: keyboard IsShowing {}", __PRETTY_FUNCTION__, self.isKeyboardVisible);
+ [super deactivate];
+}
+
+@end