diff --git a/cocos/platform/CMakeLists.txt b/cocos/platform/CMakeLists.txt index c5c8ce171c..a330236782 100644 --- a/cocos/platform/CMakeLists.txt +++ b/cocos/platform/CMakeLists.txt @@ -94,6 +94,7 @@ elseif(APPLE) platform/ios/CCPlatformDefine-ios.h platform/ios/CCStdC-ios.h platform/ios/OpenGL_Internal-ios.h + platform/ios/CCInputView-ios.h ) set(COCOS_PLATFORM_SPECIFIC_SRC ${COCOS_PLATFORM_SPECIFIC_SRC} @@ -104,6 +105,7 @@ elseif(APPLE) platform/ios/CCEAGLView-ios.mm platform/ios/CCGLViewImpl-ios.mm platform/ios/CCImage-ios.mm + platform/ios/CCInputView-ios.mm ) endif() diff --git a/cocos/platform/ios/CCEAGLView-ios.h b/cocos/platform/ios/CCEAGLView-ios.h index c1908e7dd3..ac9b40b242 100644 --- a/cocos/platform/ios/CCEAGLView-ios.h +++ b/cocos/platform/ios/CCEAGLView-ios.h @@ -60,10 +60,6 @@ APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright (C) 2008 Apple Inc. All Rights Reserved. */ - -#include "platform/CCPlatformConfig.h" -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS - #import #import #import @@ -78,42 +74,16 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. * The view content is basically an EAGL surface you render your OpenGL scene into. * Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel. */ -@interface CCEAGLView : UIView +@interface CCEAGLView : UIView { -// id renderer_; -// EAGLContext *context_; // weak ref - - NSString *pixelformat_; - GLuint depthFormat_; BOOL preserveBackbuffer_; - - CGSize size_; CGRect safeArea_; BOOL discardFramebufferSupported_; //fsaa addition - BOOL multisampling_; unsigned int requestedSamples_; - BOOL isUseUITextField; -@private - NSString * markedText_; - CGRect caretRect_; - CGRect originalRect_; - NSNotification* keyboardShowNotification_; - BOOL isKeyboardShown_; } -@property(nonatomic, readonly) UITextPosition *beginningOfDocument; -@property(nonatomic, readonly) UITextPosition *endOfDocument; -@property(nonatomic, assign) id inputDelegate; -@property(nonatomic, readonly) UITextRange *markedTextRange; -@property (nonatomic, copy) NSDictionary *markedTextStyle; -@property(readwrite, copy) UITextRange *selectedTextRange; -@property(nonatomic, readonly) id tokenizer; -@property(nonatomic, readonly, getter = isKeyboardShown) BOOL isKeyboardShown; -@property(nonatomic, copy) NSNotification* keyboardShowNotification; -@property(nonatomic) UITextAutocorrectionType autocorrectionType; // default is UITextAutocorrectionTypeDefault - /** creates an initializes an CCEAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer */ + (id) viewWithFrame:(CGRect)frame; /** creates an initializes an CCEAGLView with a frame, a color buffer format, and 0-bit depth buffer */ @@ -130,7 +100,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. /** Initializes an CCEAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup and multisampling support */ - (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples; -/** pixel format: it could be RGBA8 (32-bit) or RGB565 (16-bit) */ +//// * pixel format: it could be RGBA8 (32-bit) or RGB565 (16-bit) @property(nonatomic,readonly) NSString* pixelFormat; /** depth format of the render buffer: 0, 16 or 24 bits*/ @property(nonatomic,readonly) GLuint depthFormat; @@ -155,6 +125,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. -(void) doAnimationWhenKeyboardMoveWithDuration:(float) duration distance:(float) dis; -(void) doAnimationWhenAnotherEditBeClicked; -@end -#endif // CC_PLATFORM_IOS +- (void) showKeyboard; +- (void) hideKeyboard; +@end diff --git a/cocos/platform/ios/CCEAGLView-ios.mm b/cocos/platform/ios/CCEAGLView-ios.mm index c07666872d..9bc1d6814c 100644 --- a/cocos/platform/ios/CCEAGLView-ios.mm +++ b/cocos/platform/ios/CCEAGLView-ios.mm @@ -69,12 +69,14 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #import "base/CCTouch.h" #import "base/CCIMEDispatcher.h" #import "renderer/backend/metal/DeviceMTL.h" +#import "platform/ios/CCInputView-ios.h" //CLASS IMPLEMENTATIONS: #define IOS_MAX_TOUCHES_COUNT 10 -@interface CCEAGLView (Private) +@interface CCEAGLView () +@property (nonatomic) UIView* textInputView; - (BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup; - (unsigned int) convertPixelFormat:(NSString*) pixelFormat; @end @@ -85,8 +87,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. @synthesize pixelFormat=pixelformat_, depthFormat=depthFormat_; @synthesize context=context_; @synthesize multiSampling=multiSampling_; -@synthesize isKeyboardShown=isKeyboardShown_; -@synthesize keyboardShowNotification = keyboardShowNotification_; + + (Class) layerClass { return [CAMetalLayer class]; @@ -126,13 +127,8 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. { if((self = [super initWithFrame:frame])) { - isUseUITextField = YES; - markedText_ = nil; + self.textInputView = [[CCInputView alloc] initWithFrame:frame]; - originalRect_ = self.frame; - self.keyboardShowNotification = nil; - self.autocorrectionType = UITextAutocorrectionTypeNo; - if ([self respondsToSelector:@selector(setContentScaleFactor:)]) { self.contentScaleFactor = [[UIScreen mainScreen] scale]; @@ -159,31 +155,12 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. if ( (self = [super initWithCoder:aDecoder]) ) { size_ = [self bounds].size; - markedText_ = nil; + self.textInputView = [[CCInputView alloc] initWithCoder:aDecoder]; } return self; } -- (void)didMoveToWindow -{ -#if !defined(CC_TARGET_OS_TVOS) - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(onUIKeyboardNotification:) - name:UIKeyboardWillShowNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(onUIKeyboardNotification:) - name:UIKeyboardDidShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(onUIKeyboardNotification:) - name:UIKeyboardWillHideNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(onUIKeyboardNotification:) - name:UIKeyboardDidHideNotification object:nil]; -#endif -} -(int) getWidth { @@ -200,7 +177,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; // remove keyboard notification - self.keyboardShowNotification = nullptr; // implicit release + [self.textInputView release]; [super dealloc]; } @@ -250,34 +227,10 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. return ret; } - --(void) handleTouchesAfterKeyboardShow -{ - NSArray *subviews = self.subviews; - - for(UIView* view in subviews) - { - if([view isKindOfClass:NSClassFromString(@"UITextView")] || - [view isKindOfClass:NSClassFromString(@"UITextField")]) - { - if ([view isFirstResponder]) - { - [view resignFirstResponder]; - return; - } - } - } -} - // Pass the touches to the superview #pragma mark CCEAGLView - Touch Delegate - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - if (isKeyboardShown_) - { - [self handleTouchesAfterKeyboardShow]; - } - +{ UITouch* ids[IOS_MAX_TOUCHES_COUNT] = {0}; float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f}; float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f}; @@ -377,438 +330,25 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. glview->handleTouchesCancel(i, (intptr_t*)ids, xs, ys); } -#pragma mark - UIView - Responder - -- (BOOL)canBecomeFirstResponder +- (void) showKeyboard { - if (nil != markedText_) { - [markedText_ release]; - } - markedText_ = nil; - if (isUseUITextField) - { - return NO; - } - return YES; + [self addSubview:self.textInputView]; + [self.textInputView becomeFirstResponder]; } -- (BOOL)becomeFirstResponder +- (void) hideKeyboard { - isUseUITextField = NO; - return [super becomeFirstResponder]; + [self.textInputView resignFirstResponder]; + [self.textInputView removeFromSuperview]; } -- (BOOL)resignFirstResponder +-(void) doAnimationWhenKeyboardMoveWithDuration:(float) duration distance:(float) dis { - isUseUITextField = YES; - return [super resignFirstResponder]; -} - -#pragma mark - UIKeyInput protocol - - -- (BOOL)hasText -{ - return NO; -} - -- (void)insertText:(NSString *)text -{ - if (nil != markedText_) { - [markedText_ release]; - markedText_ = nil; - } - const char * pszText = [text cStringUsingEncoding:NSUTF8StringEncoding]; - cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); -} - -- (void)deleteBackward -{ - if (nil != markedText_) { - [markedText_ release]; - markedText_ = nil; - } - cocos2d::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); -} - -#pragma mark - UITextInputTrait protocol - --(UITextAutocapitalizationType) autocapitalizationType -{ - return UITextAutocapitalizationTypeNone; -} - -#pragma mark - UITextInput protocol - -#pragma mark UITextInput - properties - -@synthesize beginningOfDocument; -@synthesize endOfDocument; -@synthesize inputDelegate; -@synthesize markedTextRange; -@synthesize markedTextStyle; -// @synthesize selectedTextRange; // must implement -@synthesize tokenizer; -@synthesize autocorrectionType; - -/* Text may have a selection, either zero-length (a caret) or ranged. Editing operations are - * always performed on the text from this selection. nil corresponds to no selection. */ -- (void)setSelectedTextRange:(UITextRange *)aSelectedTextRange -{ - CCLOG("UITextRange:setSelectedTextRange"); -} -- (UITextRange *)selectedTextRange -{ - return [[[UITextRange alloc] init] autorelease]; -} - -#pragma mark UITextInput - Replacing and Returning Text - -- (NSString *)textInRange:(UITextRange *)range -{ - CCLOG("textInRange"); - return @""; -} -- (void)replaceRange:(UITextRange *)range withText:(NSString *)theText -{ - CCLOG("replaceRange"); -} - -#pragma mark UITextInput - Working with Marked and Selected Text - - - -/* If text can be selected, it can be marked. Marked text represents provisionally - * inserted text that has yet to be confirmed by the user. It requires unique visual - * treatment in its display. If there is any marked text, the selection, whether a - * caret or an extended range, always resides within. - * - * Setting marked text either replaces the existing marked text or, if none is present, - * inserts it from the current selection. */ - -- (void)setMarkedTextRange:(UITextRange *)markedTextRange -{ - CCLOG("setMarkedTextRange"); -} - -- (UITextRange *)markedTextRange -{ - CCLOG("markedTextRange"); - return nil; // Nil if no marked text. -} -- (void)setMarkedTextStyle:(NSDictionary *)markedTextStyle -{ - CCLOG("setMarkedTextStyle"); } -- (NSDictionary *)markedTextStyle -{ - CCLOG("markedTextStyle"); - return nil; -} -- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange -{ - CCLOG("setMarkedText"); - if (markedText == markedText_) { - return; - } - if (nil != markedText_) { - [markedText_ release]; - } - markedText_ = markedText; - [markedText_ retain]; -} -- (void)unmarkText -{ - CCLOG("unmarkText"); - if (nil == markedText_) - { - return; - } - const char * pszText = [markedText_ cStringUsingEncoding:NSUTF8StringEncoding]; - cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); - [markedText_ release]; - markedText_ = nil; -} - -#pragma mark Methods for creating ranges and positions. - -- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition -{ - CCLOG("textRangeFromPosition"); - return nil; -} -- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset -{ - CCLOG("positionFromPosition"); - return nil; -} -- (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset -{ - CCLOG("positionFromPosition"); - return nil; -} - -/* Simple evaluation of positions */ -- (NSComparisonResult)comparePosition:(UITextPosition *)position toPosition:(UITextPosition *)other -{ - CCLOG("comparePosition"); - return (NSComparisonResult)0; -} -- (NSInteger)offsetFromPosition:(UITextPosition *)from toPosition:(UITextPosition *)toPosition -{ - CCLOG("offsetFromPosition"); - return 0; -} - -- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction -{ - CCLOG("positionWithinRange"); - return nil; -} -- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction -{ - CCLOG("characterRangeByExtendingPosition"); - return nil; -} - -#pragma mark Writing direction - -- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction -{ - CCLOG("baseWritingDirectionForPosition"); - return UITextWritingDirectionNatural; -} -- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range -{ - CCLOG("setBaseWritingDirection"); -} - -#pragma mark Geometry - -/* Geometry used to provide, for example, a correction rect. */ -- (CGRect)firstRectForRange:(UITextRange *)range -{ - CCLOG("firstRectForRange"); - return CGRectNull; -} -- (CGRect)caretRectForPosition:(UITextPosition *)position -{ - CCLOG("caretRectForPosition"); - return caretRect_; -} - -#pragma mark Hit testing - -/* JS - Find the closest position to a given point */ -- (UITextPosition *)closestPositionToPoint:(CGPoint)point -{ - CCLOG("closestPositionToPoint"); - return nil; -} -- (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range -{ - CCLOG("closestPositionToPoint"); - return nil; -} -- (UITextRange *)characterRangeAtPoint:(CGPoint)point -{ - CCLOG("characterRangeAtPoint"); - return nil; -} - -- (NSArray *)selectionRectsForRange:(UITextRange *)range -{ - CCLOG("selectionRectsForRange"); - return nil; -} - -#pragma mark - UIKeyboard notification - -#if !defined(CC_TARGET_OS_TVOS) -- (void)onUIKeyboardNotification:(NSNotification *)notif -{ - NSString * type = notif.name; - - NSDictionary* info = [notif userInfo]; - CGRect begin = [self convertRect: - [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] - fromView:self]; - CGRect end = [self convertRect: - [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] - fromView:self]; - double aniDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - - CGSize viewSize = self.frame.size; - - CGFloat tmp; - switch (getFixedOrientation([[UIApplication sharedApplication] statusBarOrientation])) - { - case UIInterfaceOrientationPortrait: - begin.origin.y = viewSize.height - begin.origin.y - begin.size.height; - end.origin.y = viewSize.height - end.origin.y - end.size.height; - break; - - case UIInterfaceOrientationPortraitUpsideDown: - begin.origin.x = viewSize.width - (begin.origin.x + begin.size.width); - end.origin.x = viewSize.width - (end.origin.x + end.size.width); - break; - - case UIInterfaceOrientationLandscapeLeft: - std::swap(begin.size.width, begin.size.height); - std::swap(end.size.width, end.size.height); - std::swap(viewSize.width, viewSize.height); - - tmp = begin.origin.x; - begin.origin.x = begin.origin.y; - begin.origin.y = viewSize.height - tmp - begin.size.height; - tmp = end.origin.x; - end.origin.x = end.origin.y; - end.origin.y = viewSize.height - tmp - end.size.height; - break; - - case UIInterfaceOrientationLandscapeRight: - std::swap(begin.size.width, begin.size.height); - std::swap(end.size.width, end.size.height); - std::swap(viewSize.width, viewSize.height); - - tmp = begin.origin.x; - begin.origin.x = begin.origin.y; - begin.origin.y = tmp; - tmp = end.origin.x; - end.origin.x = end.origin.y; - end.origin.y = tmp; - break; - - default: - break; - } - - auto glview = cocos2d::Director::getInstance()->getOpenGLView(); - float scaleX = glview->getScaleX(); - float scaleY = glview->getScaleY(); - - // Convert to pixel coordinate - begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor)); - end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor)); - - float offestY = glview->getViewPortRect().origin.y; - if (offestY < 0.0f) - { - begin.origin.y += offestY; - begin.size.height -= offestY; - end.size.height -= offestY; - } - - // Convert to design coordinate - begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY)); - end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY)); - - - cocos2d::IMEKeyboardNotificationInfo notiInfo; - notiInfo.begin = cocos2d::Rect(begin.origin.x, - begin.origin.y, - begin.size.width, - begin.size.height); - notiInfo.end = cocos2d::Rect(end.origin.x, - end.origin.y, - end.size.width, - end.size.height); - notiInfo.duration = (float)aniDuration; - - cocos2d::IMEDispatcher* dispatcher = cocos2d::IMEDispatcher::sharedDispatcher(); - if (UIKeyboardWillShowNotification == type) - { - self.keyboardShowNotification = notif; // implicit copy - dispatcher->dispatchKeyboardWillShow(notiInfo); - } - else if (UIKeyboardDidShowNotification == type) - { - //CGSize screenSize = self.window.screen.bounds.size; - dispatcher->dispatchKeyboardDidShow(notiInfo); - caretRect_ = end; - - int fontSize = [UIFont smallSystemFontSize]; - caretRect_.origin.y = viewSize.height - (caretRect_.origin.y + caretRect_.size.height + fontSize); - caretRect_.size.height = 0; - isKeyboardShown_ = YES; - } - else if (UIKeyboardWillHideNotification == type) - { - dispatcher->dispatchKeyboardWillHide(notiInfo); - } - else if (UIKeyboardDidHideNotification == type) - { - caretRect_ = CGRectZero; - dispatcher->dispatchKeyboardDidHide(notiInfo); - isKeyboardShown_ = NO; - } -} -#endif - -#if !defined(CC_TARGET_OS_TVOS) -UIInterfaceOrientation getFixedOrientation(UIInterfaceOrientation statusBarOrientation) -{ - if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) - { - statusBarOrientation = UIInterfaceOrientationPortrait; - } - return statusBarOrientation; -} -#endif - --(void) doAnimationWhenKeyboardMoveWithDuration:(float)duration distance:(float)dis -{ - [UIView beginAnimations:nil context:nullptr]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDuration:duration]; - [UIView setAnimationBeginsFromCurrentState:YES]; - - //NSLog(@"[animation] dis = %f, scale = %f \n", dis, cocos2d::GLView::getInstance()->getScaleY()); - - if (dis < 0.0f) dis = 0.0f; - - auto glview = cocos2d::Director::getInstance()->getOpenGLView(); - dis *= glview->getScaleY(); - - dis /= self.contentScaleFactor; - -#if defined(CC_TARGET_OS_TVOS) - self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y - dis, originalRect_.size.width, originalRect_.size.height); -#else - switch (getFixedOrientation([[UIApplication sharedApplication] statusBarOrientation])) - { - case UIInterfaceOrientationPortrait: - self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y - dis, originalRect_.size.width, originalRect_.size.height); - break; - - case UIInterfaceOrientationPortraitUpsideDown: - self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y + dis, originalRect_.size.width, originalRect_.size.height); - break; - - case UIInterfaceOrientationLandscapeLeft: - self.frame = CGRectMake(originalRect_.origin.x - dis, originalRect_.origin.y , originalRect_.size.width, originalRect_.size.height); - break; - - case UIInterfaceOrientationLandscapeRight: - self.frame = CGRectMake(originalRect_.origin.x + dis, originalRect_.origin.y , originalRect_.size.width, originalRect_.size.height); - break; - - default: - break; - } -#endif - - [UIView commitAnimations]; -} - -(void) doAnimationWhenAnotherEditBeClicked { - if (self.keyboardShowNotification != nil) - { - [[NSNotificationCenter defaultCenter]postNotification:self.keyboardShowNotification]; - } } @end diff --git a/cocos/platform/ios/CCGLViewImpl-ios.mm b/cocos/platform/ios/CCGLViewImpl-ios.mm index 476d66377a..5d5b366914 100644 --- a/cocos/platform/ios/CCGLViewImpl-ios.mm +++ b/cocos/platform/ios/CCGLViewImpl-ios.mm @@ -224,11 +224,11 @@ void GLViewImpl::setIMEKeyboardState(bool open) if (open) { - [eaglview becomeFirstResponder]; + [eaglview showKeyboard]; } else { - [eaglview resignFirstResponder]; + [eaglview hideKeyboard]; } } diff --git a/cocos/platform/ios/CCInputView-ios.h b/cocos/platform/ios/CCInputView-ios.h new file mode 100644 index 0000000000..94b69ff605 --- /dev/null +++ b/cocos/platform/ios/CCInputView-ios.h @@ -0,0 +1,4 @@ +#import + +@interface CCInputView : UIView +@end diff --git a/cocos/platform/ios/CCInputView-ios.mm b/cocos/platform/ios/CCInputView-ios.mm new file mode 100644 index 0000000000..65390b2de4 --- /dev/null +++ b/cocos/platform/ios/CCInputView-ios.mm @@ -0,0 +1,347 @@ +#import "platform/ios/CCInputView-ios.h" +#import "base/CCIMEDispatcher.h" +#import "base/CCDirector.h" + +@interface CCInputView () + +@property(nonatomic) NSString* myMarkedText; +@property(nonatomic) BOOL isKeyboardShown; + +@end + +@implementation CCInputView + +@synthesize myMarkedText; +@synthesize isKeyboardShown; + +@synthesize hasText; +@synthesize selectedTextRange; +@synthesize beginningOfDocument; +@synthesize endOfDocument; +@synthesize markedTextStyle; +@synthesize tokenizer; +@synthesize autocorrectionType; + +- (instancetype) initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame] ) { + self.myMarkedText = nil; + self.autocorrectionType = UITextAutocorrectionTypeNo; + } + + return self; +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; // remove keyboard notification + [self.myMarkedText release]; + [self removeFromSuperview]; + [super dealloc]; +} + +- (void)didMoveToWindow +{ +#if !defined(CC_TARGET_OS_TVOS) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardWillShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardDidShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardWillHideNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardDidHideNotification object:nil]; +#endif +} + +- (BOOL) canBecomeFirstResponder { + return YES; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self resignFirstResponder]; + [self removeFromSuperview]; +} + + +#pragma TextInput protocol + +- (id)inputDelegate { + return nil; +} + +- (void)setInputDelegate:(id)inputDelegate { + +} + +- (void)deleteBackward { + if (nil != self.myMarkedText) { + [self.myMarkedText release]; + self.myMarkedText = nil; + } + cocos2d::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); +} + +- (void)insertText:(nonnull NSString *)text { + if (nil != self.myMarkedText) { + [self.myMarkedText release]; + self.myMarkedText = nil; + } + const char * pszText = [text cStringUsingEncoding:NSUTF8StringEncoding]; + cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); +} + +- (NSWritingDirection)baseWritingDirectionForPosition:(nonnull UITextPosition *)position inDirection:(UITextStorageDirection)direction { + CCLOG("baseWritingDirectionForPosition"); + return NSWritingDirectionLeftToRight; +} + +- (CGRect)caretRectForPosition:(nonnull UITextPosition *)position { + CCLOG("caretRectForPosition"); + return CGRectZero; +} + +- (nullable UITextRange *)characterRangeAtPoint:(CGPoint)point { + CCLOG("characterRangeAtPoint"); + return nil; +} + +- (nullable UITextRange *)characterRangeByExtendingPosition:(nonnull UITextPosition *)position inDirection:(UITextLayoutDirection)direction { + CCLOG("characterRangeByExtendingPosition"); + return nil; +} + +- (nullable UITextPosition *)closestPositionToPoint:(CGPoint)point { + CCLOG("closestPositionToPoint"); + return nil; +} + +- (nullable UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(nonnull UITextRange *)range { + CCLOG("closestPositionToPoint"); + return nil; +} + +- (NSComparisonResult)comparePosition:(nonnull UITextPosition *)position toPosition:(nonnull UITextPosition *)other { + CCLOG("comparePosition"); + return (NSComparisonResult)0; +} + +- (CGRect)firstRectForRange:(nonnull UITextRange *)range { + CCLOG("firstRectForRange"); + return CGRectNull; +} + +- (NSInteger)offsetFromPosition:(nonnull UITextPosition *)from toPosition:(nonnull UITextPosition *)toPosition { + CCLOG("offsetFromPosition"); + return 0; +} + +- (nullable UITextPosition *)positionFromPosition:(nonnull UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset { + CCLOG("positionFromPosition"); + return nil; +} + +- (nullable UITextPosition *)positionFromPosition:(nonnull UITextPosition *)position offset:(NSInteger)offset { + CCLOG("positionFromPosition"); + return nil; +} + +- (nullable UITextPosition *)positionWithinRange:(nonnull UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction { + CCLOG("positionWithinRange"); + return nil; +} + +- (void)replaceRange:(nonnull UITextRange *)range withText:(nonnull NSString *)text { + +} + +- (nonnull NSArray *)selectionRectsForRange:(nonnull UITextRange *)range { + CCLOG("selectionRectsForRange"); + return nil; +} + +- (void)setBaseWritingDirection:(NSWritingDirection)writingDirection forRange:(nonnull UITextRange *)range { + +} + +- (void)setMarkedText:(nullable NSString *)markedText selectedRange:(NSRange)selectedRange { + CCLOG("setMarkedText"); + if (markedText == self.myMarkedText) { + return; + } + if (nil != self.myMarkedText) { + [self.myMarkedText release]; + } + self.myMarkedText = markedText; + [self.myMarkedText retain]; +} + +- (UITextRange *)markedTextRange +{ + CCLOG("markedTextRange"); + if (nil != self.myMarkedText) { + return [[[UITextRange alloc] init] autorelease]; + } + return nil; // Nil if no marked text. +} + +- (nullable NSString *)textInRange:(nonnull UITextRange *)range { + CCLOG("textInRange"); + if (nil != self.myMarkedText) { + return self.myMarkedText; + } + return nil; +} + +- (nullable UITextRange *)textRangeFromPosition:(nonnull UITextPosition *)fromPosition toPosition:(nonnull UITextPosition *)toPosition { + CCLOG("textRangeFromPosition"); + return nil; +} + +- (void)unmarkText { + CCLOG("unmarkText"); + if (nil == self.myMarkedText) + { + return; + } + const char * pszText = [self.myMarkedText cStringUsingEncoding:NSUTF8StringEncoding]; + cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); + [self.myMarkedText release]; + self.myMarkedText = nil; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)coder { + +} + +#pragma UIKeyboard notification + +#if !defined(CC_TARGET_OS_TVOS) +namespace { + UIInterfaceOrientation getFixedOrientation(UIInterfaceOrientation statusBarOrientation) + { + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) + { + statusBarOrientation = UIInterfaceOrientationPortrait; + } + return statusBarOrientation; + } +} +#endif + +- (void)onUIKeyboardNotification:(NSNotification *)notif +{ + NSString * type = notif.name; + + NSDictionary* info = [notif userInfo]; + CGRect begin = [self convertRect: + [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] + fromView:self]; + CGRect end = [self convertRect: + [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] + fromView:self]; + double aniDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + CGSize viewSize = self.frame.size; + + CGFloat tmp; + switch (getFixedOrientation([[UIApplication sharedApplication] statusBarOrientation])) + { + case UIInterfaceOrientationPortrait: + begin.origin.y = viewSize.height - begin.origin.y - begin.size.height; + end.origin.y = viewSize.height - end.origin.y - end.size.height; + break; + + case UIInterfaceOrientationPortraitUpsideDown: + begin.origin.x = viewSize.width - (begin.origin.x + begin.size.width); + end.origin.x = viewSize.width - (end.origin.x + end.size.width); + break; + + case UIInterfaceOrientationLandscapeLeft: + std::swap(begin.size.width, begin.size.height); + std::swap(end.size.width, end.size.height); + std::swap(viewSize.width, viewSize.height); + + tmp = begin.origin.x; + begin.origin.x = begin.origin.y; + begin.origin.y = viewSize.height - tmp - begin.size.height; + tmp = end.origin.x; + end.origin.x = end.origin.y; + end.origin.y = viewSize.height - tmp - end.size.height; + break; + + case UIInterfaceOrientationLandscapeRight: + std::swap(begin.size.width, begin.size.height); + std::swap(end.size.width, end.size.height); + std::swap(viewSize.width, viewSize.height); + + tmp = begin.origin.x; + begin.origin.x = begin.origin.y; + begin.origin.y = tmp; + tmp = end.origin.x; + end.origin.x = end.origin.y; + end.origin.y = tmp; + break; + + default: + break; + } + + auto glview = cocos2d::Director::getInstance()->getOpenGLView(); + float scaleX = glview->getScaleX(); + float scaleY = glview->getScaleY(); + + // Convert to pixel coordinate + begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor)); + end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor)); + + float offestY = glview->getViewPortRect().origin.y; + if (offestY < 0.0f) + { + begin.origin.y += offestY; + begin.size.height -= offestY; + end.size.height -= offestY; + } + + // Convert to design coordinate + begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY)); + end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY)); + + + cocos2d::IMEKeyboardNotificationInfo notiInfo; + notiInfo.begin = cocos2d::Rect(begin.origin.x, + begin.origin.y, + begin.size.width, + begin.size.height); + notiInfo.end = cocos2d::Rect(end.origin.x, + end.origin.y, + end.size.width, + end.size.height); + notiInfo.duration = (float)aniDuration; + + cocos2d::IMEDispatcher* dispatcher = cocos2d::IMEDispatcher::sharedDispatcher(); + if (UIKeyboardWillShowNotification == type) + { + dispatcher->dispatchKeyboardWillShow(notiInfo); + } + else if (UIKeyboardDidShowNotification == type) + { + //CGSize screenSize = self.window.screen.bounds.size; + dispatcher->dispatchKeyboardDidShow(notiInfo); + } + else if (UIKeyboardWillHideNotification == type) + { + dispatcher->dispatchKeyboardWillHide(notiInfo); + } + else if (UIKeyboardDidHideNotification == type) + { + dispatcher->dispatchKeyboardDidHide(notiInfo); + } +} + +@end