aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/pugl_osx.m
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/pugl_osx.m')
-rw-r--r--pugl/pugl_osx.m160
1 files changed, 132 insertions, 28 deletions
diff --git a/pugl/pugl_osx.m b/pugl/pugl_osx.m
index 0546eec..6f3d4bc 100644
--- a/pugl/pugl_osx.m
+++ b/pugl/pugl_osx.m
@@ -92,13 +92,14 @@ struct PuglInternalsImpl {
@end
-@interface PuglOpenGLView : NSOpenGLView
+@interface PuglOpenGLView : NSOpenGLView<NSTextInputClient>
{
@public
- PuglView* puglview;
- NSTrackingArea* trackingArea;
- NSTimer* timer;
- NSTimer* urgentTimer;
+ PuglView* puglview;
+ NSTrackingArea* trackingArea;
+ NSMutableAttributedString* markedText;
+ NSTimer* timer;
+ NSTimer* urgentTimer;
}
@end
@@ -421,10 +422,13 @@ handleCrossing(PuglOpenGLView* view, NSEvent* event, const PuglEventType type)
const NSPoint wloc = [self eventLocation:event];
const NSPoint rloc = [NSEvent mouseLocation];
- const NSString* chars = [event characters];
- const char* str = [chars UTF8String];
- const uint32_t code = puglDecodeUTF8((const uint8_t*)str);
- PuglEventKey ev = {
+ const PuglKey spec = keySymToSpecial(puglview, event);
+ const NSString* chars = [event charactersIgnoringModifiers];
+ const char* str = [[chars lowercaseString] UTF8String];
+ const uint32_t code = (
+ spec ? spec : puglDecodeUTF8((const uint8_t*)str));
+
+ const PuglEventKey ev = {
PUGL_KEY_PRESS,
0,
[event timestamp],
@@ -434,22 +438,27 @@ handleCrossing(PuglOpenGLView* view, NSEvent* event, const PuglEventType type)
[[NSScreen mainScreen] frame].size.height - rloc.y,
getModifiers(puglview, event),
[event keyCode],
- (code != 0xFFFD) ? code : 0,
- keySymToSpecial(puglview, event),
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- false
+ (code != 0xFFFD) ? code : 0
};
- strncpy(ev.string, str, 8);
+
puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+
+ if (!spec) {
+ [self interpretKeyEvents:@[event]];
+ }
}
- (void) keyUp:(NSEvent*)event
{
const NSPoint wloc = [self eventLocation:event];
const NSPoint rloc = [NSEvent mouseLocation];
- const NSString* chars = [event characters];
- const char* str = [chars UTF8String];
- PuglEventKey ev = {
+ const PuglKey spec = keySymToSpecial(puglview, event);
+ const NSString* chars = [event charactersIgnoringModifiers];
+ const char* str = [[chars lowercaseString] UTF8String];
+ const uint32_t code =
+ (spec ? spec : puglDecodeUTF8((const uint8_t*)str));
+
+ const PuglEventKey ev = {
PUGL_KEY_RELEASE,
0,
[event timestamp],
@@ -459,15 +468,109 @@ handleCrossing(PuglOpenGLView* view, NSEvent* event, const PuglEventType type)
[[NSScreen mainScreen] frame].size.height - rloc.y,
getModifiers(puglview, event),
[event keyCode],
- puglDecodeUTF8((const uint8_t*)str),
- keySymToSpecial(puglview, event),
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- false,
+ (code != 0xFFFD) ? code : 0
};
- strncpy(ev.string, str, 8);
puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
+- (BOOL) hasMarkedText
+{
+ return [markedText length] > 0;
+}
+
+- (NSRange) markedRange
+{
+ return (([markedText length] > 0)
+ ? NSMakeRange(0, [markedText length] - 1)
+ : NSMakeRange(NSNotFound, 0));
+}
+
+- (NSRange) selectedRange
+{
+ return NSMakeRange(NSNotFound, 0);
+}
+
+- (void)setMarkedText:(id)string
+ selectedRange:(NSRange)selected
+ replacementRange:(NSRange)replacement
+{
+ [markedText release];
+ markedText = (
+ [string isKindOfClass:[NSAttributedString class]]
+ ? [[NSMutableAttributedString alloc] initWithAttributedString:string]
+ : [[NSMutableAttributedString alloc] initWithString:string]);
+}
+
+- (void) unmarkText
+{
+ [[markedText mutableString] setString:@""];
+}
+
+- (NSArray*) validAttributesForMarkedText
+{
+ return @[];
+}
+
+- (NSAttributedString*)
+ attributedSubstringForProposedRange:(NSRange)range
+ actualRange:(NSRangePointer)actual
+{
+ return nil;
+}
+
+- (NSUInteger) characterIndexForPoint:(NSPoint)point
+{
+ return 0;
+}
+
+- (NSRect) firstRectForCharacterRange:(NSRange)range
+ actualRange:(NSRangePointer)actual
+{
+ const NSRect frame = [(id)puglview bounds];
+ return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0);
+}
+
+- (void) insertText:(id)string
+ replacementRange:(NSRange)replacement
+{
+ NSEvent* const event = [NSApp currentEvent];
+ NSString* const characters =
+ ([string isKindOfClass:[NSAttributedString class]]
+ ? [string string]
+ : (NSString*)string);
+
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ for (size_t i = 0; i < [characters length]; ++i) {
+ const uint32_t code = [characters characterAtIndex:i];
+ char utf8[8] = {0};
+ NSUInteger len = 0;
+
+ [characters getBytes:utf8
+ maxLength:sizeof(utf8)
+ usedLength:&len
+ encoding:NSUTF8StringEncoding
+ options:0
+ range:NSMakeRange(i, i + 1)
+ remainingRange:nil];
+
+ PuglEventText ev = { PUGL_TEXT,
+ 0,
+ [event timestamp],
+ wloc.x,
+ puglview->height - wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(puglview, event),
+ [event keyCode],
+ code,
+ { 0, 0, 0, 0, 0, 0, 0, 0 } };
+
+ memcpy(ev.string, utf8, len);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ }
+}
+
- (void) flagsChanged:(NSEvent*)event
{
const uint32_t mods = getModifiers(puglview, event);
@@ -501,10 +604,7 @@ handleCrossing(PuglOpenGLView* view, NSEvent* event, const PuglEventType type)
[[NSScreen mainScreen] frame].size.height - rloc.y,
mods,
[event keyCode],
- 0,
- special,
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- false
+ special
};
puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
@@ -648,8 +748,10 @@ puglCreateWindow(PuglView* view, const char* title)
[NSAutoreleasePool new];
impl->app = [NSApplication sharedApplication];
- impl->glview = [PuglOpenGLView alloc];
- impl->glview->puglview = view;
+ impl->glview = [PuglOpenGLView alloc];
+ impl->glview->trackingArea = nil;
+ impl->glview->markedText = [[NSMutableAttributedString alloc] init];
+ impl->glview->puglview = view;
[impl->glview initWithFrame:NSMakeRect(0, 0, view->width, view->height)];
[impl->glview addConstraint:
@@ -706,6 +808,8 @@ puglCreateWindow(PuglView* view, const char* title)
[window makeKeyAndOrderFront:window];
}
+ [impl->glview updateTrackingAreas];
+
return 0;
}