diff options
author | culler <culler> | 2019-10-24 23:56:43 (GMT) |
---|---|---|
committer | culler <culler> | 2019-10-24 23:56:43 (GMT) |
commit | c9c3c73d09cd696f710a5c6bfd731d9cdb243276 (patch) | |
tree | 97fe5c8f77496aea79aedaaf8585bfc7946269e6 | |
parent | 2b66c3ae4d05b4f4c64b795fb6e276c24c44f37e (diff) | |
download | tk-c9c3c73d09cd696f710a5c6bfd731d9cdb243276.zip tk-c9c3c73d09cd696f710a5c6bfd731d9cdb243276.tar.gz tk-c9c3c73d09cd696f710a5c6bfd731d9cdb243276.tar.bz2 |
Make Apple's press-and-hold accent menu work with Tk entry and text widgets.
-rw-r--r-- | library/entry.tcl | 5 | ||||
-rw-r--r-- | library/text.tcl | 3 | ||||
-rw-r--r-- | library/ttk/entry.tcl | 3 | ||||
-rw-r--r-- | macosx/tkMacOSXKeyEvent.c | 86 |
4 files changed, 62 insertions, 35 deletions
diff --git a/library/entry.tcl b/library/entry.tcl index 36c331d..2c72fee 100644 --- a/library/entry.tcl +++ b/library/entry.tcl @@ -272,7 +272,7 @@ bind Entry <Meta-Delete> { } } -# Bindings for IME text input. +# Bindings for IME text input and accents. bind Entry <<TkStartIMEMarkedText>> { dict set ::tk::Priv(IMETextMark) "%W" [%W index insert] @@ -283,6 +283,9 @@ bind Entry <<TkEndIMEMarkedText>> { bind Entry <<TkClearIMEMarkedText>> { %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert] } +bind Entry <<TkAccentBackspace>> { + tk::EntryBackspace %W +} # A few additional bindings of my own. diff --git a/library/text.tcl b/library/text.tcl index 24f8428..e1130a4 100644 --- a/library/text.tcl +++ b/library/text.tcl @@ -403,6 +403,9 @@ bind Text <<TkEndIMEMarkedText>> { bind Text <<TkClearIMEMarkedText>> { %W delete IMEmarkedtext.first IMEmarkedtext.last } +bind Text <<TkAccentBackspace>> { + %W delete insert-1c +} # Macintosh only bindings: diff --git a/library/ttk/entry.tcl b/library/ttk/entry.tcl index 6a34488..7bca47f 100644 --- a/library/ttk/entry.tcl +++ b/library/ttk/entry.tcl @@ -156,6 +156,9 @@ bind TEntry <<TkEndIMEMarkedText>> { bind TEntry <<TkClearIMEMarkedText>> { %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert] } +bind Entry <<TkAccentBackspace>> { + tk::EntryBackspace %W +} ### Clipboard procedures. # diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 19be7cf..09abb01 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -285,7 +285,7 @@ static unsigned isFunctionKey(unsigned int code); return self; } -/* +/* * Implementation of the NSTextInputClient protocol. */ @@ -297,9 +297,14 @@ static unsigned isFunctionKey(unsigned int code); - (void)insertText: (id)aString replacementRange: (NSRange)repRange { - int i, len = [(NSString *) aString length]; + int i, len; XEvent xEvent; - + NSString *str; + + str = ([aString isKindOfClass: [NSAttributedString class]]) ? + str = [aString string] : aString; + len = [str length]; + if (NS_KEYLOG) { TKLog(@"insertText '%@'\tlen = %d", aString, len); } @@ -322,6 +327,19 @@ static unsigned isFunctionKey(unsigned int code); xEvent.xany.type = KeyPress; /* + * Apple evidently sets location to 0 to signal that an accented letter has + * been selected from the accent menu. An unaccented letter has already + * been displayed and we need to erase it before displaying the accented + * letter. + */ + + if (repRange.location == 0) { + TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); + Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr; + TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL); + } + + /* * NSString represents a non-BMP character as a string of length 2 where * the first character is the high surrogate and the second character is * the low surrogate. We could record this in the XEvent by setting the @@ -332,10 +350,10 @@ static unsigned isFunctionKey(unsigned int code); */ for (i = 0; i < len; i++) { - UniChar nextChar = [aString characterAtIndex: i]; + UniChar nextChar = [str characterAtIndex: i]; if (CFStringIsSurrogateHighCharacter(nextChar)) { #if 0 - UniChar lowChar = [aString characterAtIndex: ++i]; + UniChar lowChar = [str characterAtIndex: ++i]; xEvent.xkey.keycode = CFStringGetLongCharacterForSurrogatePair( nextChar, lowChar); xEvent.xkey.nbytes = TkUniCharToUtf(xEvent.xkey.keycode, @@ -348,7 +366,7 @@ static unsigned isFunctionKey(unsigned int code); #endif } else { xEvent.xkey.keycode = (int) nextChar; - [[aString substringWithRange: NSMakeRange(i,1)] + [[str substringWithRange: NSMakeRange(i,1)] getCString: xEvent.xkey.trans_chars maxLength: XMaxTransChars encoding: NSUTF8StringEncoding]; xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars); @@ -358,20 +376,20 @@ static unsigned isFunctionKey(unsigned int code); Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } - releaseCode = (UInt16) [aString characterAtIndex: 0]; + releaseCode = (UInt16) [str characterAtIndex: 0]; } /* * This required method is allowed to return nil. */ -- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange actualRange:(NSRangePointer)thePointer { return nil; } -/* +/* * This method is supposed to insert (or replace selected text with) the string * argument. If the argument is an NSString, it should be displayed with a * distinguishing appearance, e.g underlined. @@ -384,11 +402,13 @@ static unsigned isFunctionKey(unsigned int code); TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr; NSString *temp; - NSString *str = [aString respondsToSelector:@selector (string)] ? - [aString string] : aString; + NSString *str; + + str = ([aString isKindOfClass: [NSAttributedString class]]) ? + str = [aString string] : aString; if (focusWin) { - + /* * Remember the widget where the composition is happening, in case it * gets defocussed during the composition. @@ -415,7 +435,7 @@ static unsigned isFunctionKey(unsigned int code); /* * Use our insertText method to display the marked text. */ - + TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL); temp = [str copy]; [self insertText: temp replacementRange:repRange]; @@ -424,7 +444,6 @@ static unsigned isFunctionKey(unsigned int code); TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL); } - - (BOOL)hasMarkedText { return privateWorkingText != nil; @@ -443,11 +462,19 @@ static unsigned isFunctionKey(unsigned int code); return rng; } +- (void)cancelComposingText +{ + if (NS_KEYLOG) { + TKLog(@"cancelComposingText"); + } + [self deleteWorkingText]; + processingCompose = NO; +} - (void)unmarkText { if (NS_KEYLOG) { - TKLog(@"unmark (accept) text"); + TKLog(@"unmarkText"); } [self deleteWorkingText]; processingCompose = NO; @@ -489,31 +516,22 @@ static unsigned isFunctionKey(unsigned int code); } processingCompose = NO; if (aSelector == @selector (deleteBackward:)) { - /* - * Happens when user backspaces over an ongoing composition: - * throw a 'delete' into the event queue. - */ - - XEvent xEvent; - - setupXEvent(&xEvent, [self window], 0); - xEvent.xany.type = KeyPress; - xEvent.xkey.nbytes = 1; - xEvent.xkey.keycode = (0x33 << 16) | 0x7F; - xEvent.xkey.trans_chars[0] = 0x7F; - xEvent.xkey.trans_chars[1] = 0x0; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); + Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr; + TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL); } } - (NSArray *)validAttributesForMarkedText { static NSArray *arr = nil; - if (arr == nil) { - arr = [NSArray new]; + arr = [[NSArray alloc] initWithObjects: + NSUnderlineStyleAttributeName, + NSUnderlineColorAttributeName, + nil]; + [arr retain]; } - /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ return arr; } @@ -522,7 +540,7 @@ static unsigned isFunctionKey(unsigned int code); if (NS_KEYLOG) { TKLog(@"selectedRange request"); } - return NSMakeRange(NSNotFound, 0); + return NSMakeRange(0, 0); } - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint @@ -530,7 +548,7 @@ static unsigned isFunctionKey(unsigned int code); if (NS_KEYLOG) { TKLog(@"characterIndexForPoint request"); } - return 0; + return NSNotFound; } - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange |