Implement NSTextInputClient protocol on OS X

This provides support for IME character composition.

Fixes #456.
Closes #643.
This commit is contained in:
Mario Dorn 2015-11-13 17:19:20 +01:00 committed by Camilla Berglund
parent 9f5658c8ac
commit 3107c9548d
2 changed files with 95 additions and 14 deletions

View File

@ -105,6 +105,7 @@ does not find Doxygen, the documentation will not be generated.
- [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned - [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned
- [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault - [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault
- [Cocoa] Bugfix: Modifier flags cache was not updated when window became key - [Cocoa] Bugfix: Modifier flags cache was not updated when window became key
- [Cocoa] Bugfix: Dead key character composition did not work
- [X11] Bugfix: Monitor connection and disconnection events were not reported - [X11] Bugfix: Monitor connection and disconnection events were not reported
- [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end - [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end
- [X11] Bugfix: An XKB structure was leaked during `glfwInit` - [X11] Bugfix: An XKB structure was leaked during `glfwInit`
@ -165,6 +166,7 @@ skills.
- Paul R. Deppe - Paul R. Deppe
- Michael Dickens - Michael Dickens
- Роман Донченко - Роман Донченко
- Mario Dorn
- Jonathan Dummer - Jonathan Dummer
- Ralph Eastwood - Ralph Eastwood
- Siavash Eliasi - Siavash Eliasi

View File

@ -146,6 +146,10 @@ static NSUInteger translateKeyToModifierFlag(int key)
return 0; return 0;
} }
// Defines a constant for empty ranges in NSTextInputClient
//
static const NSRange kEmptyRange = {NSNotFound, 0};
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Delegate for window related notifications // Delegate for window related notifications
@ -296,10 +300,11 @@ static NSUInteger translateKeyToModifierFlag(int key)
// Content view class for the GLFW window // Content view class for the GLFW window
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@interface GLFWContentView : NSView @interface GLFWContentView : NSView <NSTextInputClient>
{ {
_GLFWwindow* window; _GLFWwindow* window;
NSTrackingArea* trackingArea; NSTrackingArea* trackingArea;
NSMutableAttributedString* markedText;
} }
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow; - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
@ -329,6 +334,7 @@ static NSUInteger translateKeyToModifierFlag(int key)
{ {
window = initWindow; window = initWindow;
trackingArea = nil; trackingArea = nil;
markedText = [[NSMutableAttributedString alloc] init];
[self updateTrackingAreas]; [self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObjects: [self registerForDraggedTypes:[NSArray arrayWithObjects:
@ -341,6 +347,7 @@ static NSUInteger translateKeyToModifierFlag(int key)
- (void)dealloc - (void)dealloc
{ {
[trackingArea release]; [trackingArea release];
[markedText release];
[super dealloc]; [super dealloc];
} }
@ -501,18 +508,7 @@ static NSUInteger translateKeyToModifierFlag(int key)
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
NSString* characters = [event characters]; [self interpretKeyEvents:[NSArray arrayWithObject:event]];
NSUInteger i, length = [characters length];
const int plain = !(mods & GLFW_MOD_SUPER);
for (i = 0; i < length; i++)
{
const unichar codepoint = [characters characterAtIndex:i];
if ((codepoint & 0xff00) == 0xf700)
continue;
_glfwInputChar(window, codepoint, mods, plain);
}
} }
- (void)flagsChanged:(NSEvent *)event - (void)flagsChanged:(NSEvent *)event
@ -614,6 +610,89 @@ static NSUInteger translateKeyToModifierFlag(int key)
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
- (BOOL)hasMarkedText
{
return (markedText.length > 0);
}
- (NSRange)markedRange
{
return (markedText.length > 0) ?
NSMakeRange(0, markedText.length-1) :
kEmptyRange;
}
- (NSRange)selectedRange
{
return kEmptyRange;
}
- (void)setMarkedText:(id)aString
selectedRange:(NSRange)selectedRange
replacementRange:(NSRange)replacementRange
{
if( [aString isKindOfClass: [NSAttributedString class]] )
{
[markedText initWithAttributedString: aString];
}
else
{
[markedText initWithString: aString];
}
}
- (void)unmarkText
{
[[markedText mutableString] setString:@""];
}
- (NSArray*)validAttributesForMarkedText
{
return [NSArray array];
}
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange
actualRange:(NSRangePointer)actualRange
{
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
{
return 0;
}
- (NSRect)firstRectForCharacterRange:(NSRange)aRange
actualRange:(NSRangePointer)actualRange
{
return NSMakeRect(0, 0, 0, 0);
}
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
NSEvent* event = [NSApp currentEvent];
const int mods = translateFlags([event modifierFlags]);
NSString* characters;
if ([aString isKindOfClass: [NSAttributedString class]]) {
characters = [aString string];
} else {
characters = (NSString*)aString;
}
NSUInteger i, length = [characters length];
const int plain = !(mods & GLFW_MOD_SUPER);
for (i = 0; i < length; i++)
{
const unichar codepoint = [characters characterAtIndex:i];
if ((codepoint & 0xff00) == 0xf700)
continue;
_glfwInputChar(window, codepoint, mods, plain);
}
}
@end @end