1/* 2 * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#import "jni_util.h" 27#import "CGLGraphicsConfig.h" 28#import "AWTView.h" 29#import "AWTWindow.h" 30#import "JavaComponentAccessibility.h" 31#import "JavaTextAccessibility.h" 32#import "JavaAccessibilityUtilities.h" 33#import "GeomUtilities.h" 34#import "ThreadUtilities.h" 35#import "JNIUtilities.h" 36 37#import <Carbon/Carbon.h> 38 39// keyboard layout 40static NSString *kbdLayout; 41 42@interface AWTView() 43@property (retain) CDropTarget *_dropTarget; 44@property (retain) CDragSource *_dragSource; 45 46-(void) deliverResize: (NSRect) rect; 47-(void) resetTrackingArea; 48-(void) deliverJavaKeyEventHelper: (NSEvent*) event; 49-(BOOL) isCodePointInUnicodeBlockNeedingIMEvent: (unichar) codePoint; 50-(NSMutableString *) parseString : (id) complexString; 51@end 52 53// Uncomment this line to see fprintfs of each InputMethod API being called on this View 54//#define IM_DEBUG TRUE 55//#define EXTRA_DEBUG 56 57static BOOL shouldUsePressAndHold() { 58 return YES; 59} 60 61@implementation AWTView 62 63@synthesize _dropTarget; 64@synthesize _dragSource; 65@synthesize cglLayer; 66@synthesize mouseIsOver; 67 68// Note: Must be called on main (AppKit) thread only 69- (id) initWithRect: (NSRect) rect 70 platformView: (jobject) cPlatformView 71 windowLayer: (CALayer*) windowLayer 72{ 73 AWT_ASSERT_APPKIT_THREAD; 74 // Initialize ourselves 75 self = [super initWithFrame: rect]; 76 if (self == nil) return self; 77 78 m_cPlatformView = cPlatformView; 79 fInputMethodLOCKABLE = NULL; 80 fKeyEventsNeeded = NO; 81 fProcessingKeystroke = NO; 82 83 fEnablePressAndHold = shouldUsePressAndHold(); 84 fInPressAndHold = NO; 85 fPAHNeedsToSelect = NO; 86 87 mouseIsOver = NO; 88 [self resetTrackingArea]; 89 [self setAutoresizesSubviews:NO]; 90 91 if (windowLayer != nil) { 92 self.cglLayer = windowLayer; 93 //Layer hosting view 94 [self setLayer: cglLayer]; 95 [self setWantsLayer: YES]; 96 //Layer backed view 97 //[self.layer addSublayer: (CALayer *)cglLayer]; 98 //[self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize]; 99 //[self setLayerContentsPlacement: NSViewLayerContentsPlacementTopLeft]; 100 //[self setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; 101 } 102 103 return self; 104} 105 106- (void) dealloc { 107 AWT_ASSERT_APPKIT_THREAD; 108 109 self.cglLayer = nil; 110 111 JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; 112 (*env)->DeleteWeakGlobalRef(env, m_cPlatformView); 113 m_cPlatformView = NULL; 114 115 if (fInputMethodLOCKABLE != NULL) 116 { 117 JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; 118 119 (*env)->DeleteGlobalRef(env, fInputMethodLOCKABLE); 120 fInputMethodLOCKABLE = NULL; 121 } 122 123 if (rolloverTrackingArea != nil) { 124 [self removeTrackingArea:rolloverTrackingArea]; 125 [rolloverTrackingArea release]; 126 rolloverTrackingArea = nil; 127 } 128 129 [super dealloc]; 130} 131 132- (void) viewDidMoveToWindow { 133 AWT_ASSERT_APPKIT_THREAD; 134 135 [AWTToolkit eventCountPlusPlus]; 136 137 [ThreadUtilities performOnMainThreadWaiting:NO block:^() { 138 [[self window] makeFirstResponder: self]; 139 }]; 140 if ([self window] != NULL) { 141 [self resetTrackingArea]; 142 } 143} 144 145- (BOOL) acceptsFirstMouse: (NSEvent *)event { 146 return YES; 147} 148 149- (BOOL) acceptsFirstResponder { 150 return YES; 151} 152 153- (BOOL) becomeFirstResponder { 154 return YES; 155} 156 157- (BOOL) preservesContentDuringLiveResize { 158 return YES; 159} 160 161/* 162 * Automatically triggered functions. 163 */ 164 165- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize { 166 [super resizeWithOldSuperviewSize: oldBoundsSize]; 167 [self deliverResize: [self frame]]; 168} 169 170/* 171 * MouseEvents support 172 */ 173 174- (void) mouseDown: (NSEvent *)event { 175 NSInputManager *inputManager = [NSInputManager currentInputManager]; 176 if ([inputManager wantsToHandleMouseEvents]) { 177#if IM_DEBUG 178 NSLog(@"-> IM wants to handle event"); 179#endif 180 if (![inputManager handleMouseEvent:event]) { 181 [self deliverJavaMouseEvent: event]; 182 } else { 183#if IM_DEBUG 184 NSLog(@"-> Event was handled."); 185#endif 186 } 187 } else { 188#if IM_DEBUG 189 NSLog(@"-> IM does not want to handle event"); 190#endif 191 [self deliverJavaMouseEvent: event]; 192 } 193} 194 195- (void) mouseUp: (NSEvent *)event { 196 [self deliverJavaMouseEvent: event]; 197} 198 199- (void) rightMouseDown: (NSEvent *)event { 200 [self deliverJavaMouseEvent: event]; 201} 202 203- (void) rightMouseUp: (NSEvent *)event { 204 [self deliverJavaMouseEvent: event]; 205} 206 207- (void) otherMouseDown: (NSEvent *)event { 208 [self deliverJavaMouseEvent: event]; 209} 210 211- (void) otherMouseUp: (NSEvent *)event { 212 [self deliverJavaMouseEvent: event]; 213} 214 215- (void) mouseMoved: (NSEvent *)event { 216 // TODO: better way to redirect move events to the "under" view 217 218 NSPoint eventLocation = [event locationInWindow]; 219 NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; 220 221 if ([self mouse: localPoint inRect: [self bounds]]) { 222 [self deliverJavaMouseEvent: event]; 223 } else { 224 [[self nextResponder] mouseDown:event]; 225 } 226} 227 228- (void) mouseDragged: (NSEvent *)event { 229 [self deliverJavaMouseEvent: event]; 230} 231 232- (void) rightMouseDragged: (NSEvent *)event { 233 [self deliverJavaMouseEvent: event]; 234} 235 236- (void) otherMouseDragged: (NSEvent *)event { 237 [self deliverJavaMouseEvent: event]; 238} 239 240- (void) mouseEntered: (NSEvent *)event { 241 [[self window] setAcceptsMouseMovedEvents:YES]; 242 //[[self window] makeFirstResponder:self]; 243 [self deliverJavaMouseEvent: event]; 244} 245 246- (void) mouseExited: (NSEvent *)event { 247 [[self window] setAcceptsMouseMovedEvents:NO]; 248 [self deliverJavaMouseEvent: event]; 249 //Restore the cursor back. 250 //[CCursorManager _setCursor: [NSCursor arrowCursor]]; 251} 252 253- (void) scrollWheel: (NSEvent*) event { 254 [self deliverJavaMouseEvent: event]; 255} 256 257/* 258 * KeyEvents support 259 */ 260 261- (void) keyDown: (NSEvent *)event { 262 fProcessingKeystroke = YES; 263 fKeyEventsNeeded = YES; 264 265 // Allow TSM to look at the event and potentially send back NSTextInputClient messages. 266 [self interpretKeyEvents:[NSArray arrayWithObject:event]]; 267 268 if (fEnablePressAndHold && [event willBeHandledByComplexInputMethod] && 269 fInputMethodLOCKABLE) 270 { 271 fProcessingKeystroke = NO; 272 if (!fInPressAndHold) { 273 fInPressAndHold = YES; 274 fPAHNeedsToSelect = YES; 275 } else { 276 // Abandon input to reset IM and unblock input after canceling 277 // input accented symbols 278 279 switch([event keyCode]) { 280 case kVK_Escape: 281 case kVK_Delete: 282 case kVK_Return: 283 case kVK_ForwardDelete: 284 case kVK_PageUp: 285 case kVK_PageDown: 286 case kVK_DownArrow: 287 case kVK_UpArrow: 288 case kVK_Home: 289 case kVK_End: 290 [self abandonInput]; 291 break; 292 } 293 } 294 return; 295 } 296 297 NSString *eventCharacters = [event characters]; 298 BOOL isDeadKey = (eventCharacters != nil && [eventCharacters length] == 0); 299 300 if ((![self hasMarkedText] && fKeyEventsNeeded) || isDeadKey) { 301 [self deliverJavaKeyEventHelper: event]; 302 } 303 304 fProcessingKeystroke = NO; 305} 306 307- (void) keyUp: (NSEvent *)event { 308 [self deliverJavaKeyEventHelper: event]; 309} 310 311- (void) flagsChanged: (NSEvent *)event { 312 [self deliverJavaKeyEventHelper: event]; 313} 314 315- (BOOL) performKeyEquivalent: (NSEvent *) event { 316 // if IM is active key events should be ignored 317 if (![self hasMarkedText] && !fInPressAndHold) { 318 [self deliverJavaKeyEventHelper: event]; 319 } 320 321 // Workaround for 8020209: special case for "Cmd =" and "Cmd ." 322 // because Cocoa calls performKeyEquivalent twice for these keystrokes 323 NSUInteger modFlags = [event modifierFlags] & 324 (NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask | NSControlKeyMask); 325 if (modFlags == NSCommandKeyMask) { 326 NSString *eventChars = [event charactersIgnoringModifiers]; 327 if ([eventChars length] == 1) { 328 unichar ch = [eventChars characterAtIndex:0]; 329 if (ch == '=' || ch == '.') { 330 [[NSApp mainMenu] performKeyEquivalent: event]; 331 return YES; 332 } 333 } 334 335 } 336 337 return NO; 338} 339 340/** 341 * Utility methods and accessors 342 */ 343 344-(void) deliverJavaMouseEvent: (NSEvent *) event { 345 BOOL isEnabled = YES; 346 NSWindow* window = [self window]; 347 if ([window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]]) { 348 isEnabled = [(AWTWindow*)[window delegate] isEnabled]; 349 } 350 351 if (!isEnabled) { 352 return; 353 } 354 355 NSEventType type = [event type]; 356 357 // check synthesized mouse entered/exited events 358 if ((type == NSMouseEntered && mouseIsOver) || (type == NSMouseExited && !mouseIsOver)) { 359 return; 360 }else if ((type == NSMouseEntered && !mouseIsOver) || (type == NSMouseExited && mouseIsOver)) { 361 mouseIsOver = !mouseIsOver; 362 } 363 364 [AWTToolkit eventCountPlusPlus]; 365 366 JNIEnv *env = [ThreadUtilities getJNIEnv]; 367 368 NSPoint eventLocation = [event locationInWindow]; 369 NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; 370 NSPoint absP = [NSEvent mouseLocation]; 371 372 // Convert global numbers between Cocoa's coordinate system and Java. 373 // TODO: need consitent way for doing that both with global as well as with local coordinates. 374 // The reason to do it here is one more native method for getting screen dimension otherwise. 375 376 NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; 377 absP.y = screenRect.size.height - absP.y; 378 jint clickCount; 379 380 if (type == NSMouseEntered || 381 type == NSMouseExited || 382 type == NSScrollWheel || 383 type == NSMouseMoved) { 384 clickCount = 0; 385 } else { 386 clickCount = [event clickCount]; 387 } 388 389 jdouble deltaX = [event deltaX]; 390 jdouble deltaY = [event deltaY]; 391 if ([AWTToolkit hasPreciseScrollingDeltas: event]) { 392 deltaX = [event scrollingDeltaX] * 0.1; 393 deltaY = [event scrollingDeltaY] * 0.1; 394 } 395 396 DECLARE_CLASS(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); 397 DECLARE_METHOD(jctor_NSEvent, jc_NSEvent, "<init>", "(IIIIIIIIDDI)V"); 398 jobject jEvent = (*env)->NewObject(env, jc_NSEvent, jctor_NSEvent, 399 [event type], 400 [event modifierFlags], 401 clickCount, 402 [event buttonNumber], 403 (jint)localPoint.x, (jint)localPoint.y, 404 (jint)absP.x, (jint)absP.y, 405 deltaY, 406 deltaX, 407 [AWTToolkit scrollStateWithEvent: event]); 408 CHECK_NULL(jEvent); 409 410 DECLARE_CLASS(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); 411 DECLARE_METHOD(jm_deliverMouseEvent, jc_PlatformView, "deliverMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V"); 412 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 413 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 414 (*env)->CallVoidMethod(env, jlocal, jm_deliverMouseEvent, jEvent); 415 CHECK_EXCEPTION(); 416 (*env)->DeleteLocalRef(env, jlocal); 417 } 418 (*env)->DeleteLocalRef(env, jEvent); 419} 420 421- (void) resetTrackingArea { 422 if (rolloverTrackingArea != nil) { 423 [self removeTrackingArea:rolloverTrackingArea]; 424 [rolloverTrackingArea release]; 425 } 426 427 int options = (NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited | 428 NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag); 429 430 rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] 431 options: options 432 owner:self 433 userInfo:nil 434 ]; 435 [self addTrackingArea:rolloverTrackingArea]; 436} 437 438- (void)updateTrackingAreas { 439 [super updateTrackingAreas]; 440 [self resetTrackingArea]; 441} 442 443- (void) resetCursorRects { 444 [super resetCursorRects]; 445 [self resetTrackingArea]; 446} 447 448-(void) deliverJavaKeyEventHelper: (NSEvent *) event { 449 static NSEvent* sLastKeyEvent = nil; 450 if (event == sLastKeyEvent) { 451 // The event is repeatedly delivered by keyDown: after performKeyEquivalent: 452 return; 453 } 454 [sLastKeyEvent release]; 455 sLastKeyEvent = [event retain]; 456 457 [AWTToolkit eventCountPlusPlus]; 458 JNIEnv *env = [ThreadUtilities getJNIEnv]; 459 460 jstring characters = NULL; 461 jstring charactersIgnoringModifiers = NULL; 462 if ([event type] != NSFlagsChanged) { 463 characters = NSStringToJavaString(env, [event characters]); 464 charactersIgnoringModifiers = NSStringToJavaString(env, [event charactersIgnoringModifiers]); 465 } 466 467 DECLARE_CLASS(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); 468 DECLARE_METHOD(jctor_NSEvent, jc_NSEvent, "<init>", "(IISLjava/lang/String;Ljava/lang/String;)V"); 469 jobject jEvent = (*env)->NewObject(env, jc_NSEvent, jctor_NSEvent, 470 [event type], 471 [event modifierFlags], 472 [event keyCode], 473 characters, 474 charactersIgnoringModifiers); 475 CHECK_NULL(jEvent); 476 477 DECLARE_CLASS(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); 478 DECLARE_METHOD(jm_deliverKeyEvent, jc_PlatformView, 479 "deliverKeyEvent", "(Lsun/lwawt/macosx/NSEvent;)V"); 480 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 481 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 482 (*env)->CallVoidMethod(env, jlocal, jm_deliverKeyEvent, jEvent); 483 CHECK_EXCEPTION(); 484 (*env)->DeleteLocalRef(env, jlocal); 485 } 486 if (characters != NULL) { 487 (*env)->DeleteLocalRef(env, characters); 488 } 489 (*env)->DeleteLocalRef(env, jEvent); 490} 491 492-(void) deliverResize: (NSRect) rect { 493 jint x = (jint) rect.origin.x; 494 jint y = (jint) rect.origin.y; 495 jint w = (jint) rect.size.width; 496 jint h = (jint) rect.size.height; 497 JNIEnv *env = [ThreadUtilities getJNIEnv]; 498 DECLARE_CLASS(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); 499 DECLARE_METHOD(jm_deliverResize, jc_PlatformView, "deliverResize", "(IIII)V"); 500 501 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 502 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 503 (*env)->CallVoidMethod(env, jlocal, jm_deliverResize, x,y,w,h); 504 CHECK_EXCEPTION(); 505 (*env)->DeleteLocalRef(env, jlocal); 506 } 507} 508 509 510- (void) drawRect:(NSRect)dirtyRect { 511 AWT_ASSERT_APPKIT_THREAD; 512 513 [super drawRect:dirtyRect]; 514 JNIEnv *env = [ThreadUtilities getJNIEnv]; 515 if (env != NULL) { 516 /* 517 if ([self inLiveResize]) { 518 NSRect rs[4]; 519 NSInteger count; 520 [self getRectsExposedDuringLiveResize:rs count:&count]; 521 for (int i = 0; i < count; i++) { 522 JNU_CallMethodByName(env, NULL, [m_awtWindow cPlatformView], 523 "deliverWindowDidExposeEvent", "(FFFF)V", 524 (jfloat)rs[i].origin.x, (jfloat)rs[i].origin.y, 525 (jfloat)rs[i].size.width, (jfloat)rs[i].size.height); 526 if ((*env)->ExceptionOccurred(env)) { 527 (*env)->ExceptionDescribe(env); 528 (*env)->ExceptionClear(env); 529 } 530 } 531 } else { 532 */ 533 DECLARE_CLASS(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); 534 DECLARE_METHOD(jm_deliverWindowDidExposeEvent, jc_CPlatformView, "deliverWindowDidExposeEvent", "()V"); 535 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 536 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 537 (*env)->CallVoidMethod(env, jlocal, jm_deliverWindowDidExposeEvent); 538 CHECK_EXCEPTION(); 539 (*env)->DeleteLocalRef(env, jlocal); 540 } 541 /* 542 } 543 */ 544 } 545} 546 547-(BOOL) isCodePointInUnicodeBlockNeedingIMEvent: (unichar) codePoint { 548 if ((codePoint == 0x0024) || (codePoint == 0x00A3) || 549 (codePoint == 0x00A5) || 550 ((codePoint >= 0x20A3) && (codePoint <= 0x20BF)) || 551 ((codePoint >= 0x3000) && (codePoint <= 0x303F)) || 552 ((codePoint >= 0xFF00) && (codePoint <= 0xFFEF))) { 553 // Code point is in 'CJK Symbols and Punctuation' or 554 // 'Halfwidth and Fullwidth Forms' Unicode block or 555 // currency symbols unicode 556 return YES; 557 } 558 return NO; 559} 560 561-(NSMutableString *) parseString : (id) complexString { 562 if ([complexString isKindOfClass:[NSString class]]) { 563 return [complexString mutableCopy]; 564 } 565 else { 566 return [complexString mutableString]; 567 } 568} 569 570// NSAccessibility support 571- (jobject)awtComponent:(JNIEnv*)env 572{ 573 DECLARE_CLASS_RETURN(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView", NULL); 574 DECLARE_FIELD_RETURN(jf_Peer, jc_CPlatformView, "peer", "Lsun/lwawt/LWWindowPeer;", NULL); 575 if ((env == NULL) || (m_cPlatformView == NULL)) { 576 NSLog(@"Apple AWT : Error AWTView:awtComponent given bad parameters."); 577 NSLog(@"%@",[NSThread callStackSymbols]); 578 return NULL; 579 } 580 581 jobject peer = NULL; 582 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 583 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 584 peer = (*env)->GetObjectField(env, jlocal, jf_Peer); 585 (*env)->DeleteLocalRef(env, jlocal); 586 } 587 DECLARE_CLASS_RETURN(jc_LWWindowPeer, "sun/lwawt/LWWindowPeer", NULL); 588 DECLARE_FIELD_RETURN(jf_Target, jc_LWWindowPeer, "target", "Ljava/awt/Component;", NULL); 589 if (peer == NULL) { 590 NSLog(@"Apple AWT : Error AWTView:awtComponent got null peer from CPlatformView"); 591 NSLog(@"%@",[NSThread callStackSymbols]); 592 return NULL; 593 } 594 jobject comp = (*env)->GetObjectField(env, peer, jf_Target); 595 (*env)->DeleteLocalRef(env, peer); 596 return comp; 597} 598 599+ (AWTView *) awtView:(JNIEnv*)env ofAccessible:(jobject)jaccessible 600{ 601 DECLARE_CLASS_RETURN(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility", NULL); 602 DECLARE_STATIC_METHOD_RETURN(jm_getAWTView, sjc_CAccessibility, "getAWTView", "(Ljavax/accessibility/Accessible;)J", NULL); 603 604 jlong jptr = (*env)->CallStaticLongMethod(env, sjc_CAccessibility, jm_getAWTView, jaccessible); 605 CHECK_EXCEPTION(); 606 if (jptr == 0) return nil; 607 608 return (AWTView *)jlong_to_ptr(jptr); 609} 610 611- (id)getAxData:(JNIEnv*)env 612{ 613 jobject jcomponent = [self awtComponent:env]; 614 id ax = [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease]; 615 (*env)->DeleteLocalRef(env, jcomponent); 616 return ax; 617} 618 619- (NSArray *)accessibilityAttributeNames 620{ 621 return [[super accessibilityAttributeNames] arrayByAddingObject:NSAccessibilityChildrenAttribute]; 622} 623 624// NSAccessibility messages 625// attribute methods 626- (id)accessibilityAttributeValue:(NSString *)attribute 627{ 628 AWT_ASSERT_APPKIT_THREAD; 629 630 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) 631 { 632 JNIEnv *env = [ThreadUtilities getJNIEnv]; 633 634 (*env)->PushLocalFrame(env, 4); 635 636 id result = NSAccessibilityUnignoredChildrenForOnlyChild([self getAxData:env]); 637 638 (*env)->PopLocalFrame(env, NULL); 639 640 return result; 641 } 642 else 643 { 644 return [super accessibilityAttributeValue:attribute]; 645 } 646} 647- (BOOL)accessibilityIsIgnored 648{ 649 return YES; 650} 651 652- (id)accessibilityHitTest:(NSPoint)point 653{ 654 AWT_ASSERT_APPKIT_THREAD; 655 JNIEnv *env = [ThreadUtilities getJNIEnv]; 656 657 (*env)->PushLocalFrame(env, 4); 658 659 id result = [[self getAxData:env] accessibilityHitTest:point withEnv:env]; 660 661 (*env)->PopLocalFrame(env, NULL); 662 663 return result; 664} 665 666- (id)accessibilityFocusedUIElement 667{ 668 AWT_ASSERT_APPKIT_THREAD; 669 670 JNIEnv *env = [ThreadUtilities getJNIEnv]; 671 672 (*env)->PushLocalFrame(env, 4); 673 674 id result = [[self getAxData:env] accessibilityFocusedUIElement]; 675 676 (*env)->PopLocalFrame(env, NULL); 677 678 return result; 679} 680 681// --- Services menu support for lightweights --- 682 683// finds the focused accessible element, and if it is a text element, obtains the text from it 684- (NSString *)accessibleSelectedText 685{ 686 id focused = [self accessibilityFocusedUIElement]; 687 if (![focused isKindOfClass:[JavaTextAccessibility class]]) return nil; 688 return [(JavaTextAccessibility *)focused accessibilitySelectedTextAttribute]; 689} 690 691// same as above, but converts to RTFD 692- (NSData *)accessibleSelectedTextAsRTFD 693{ 694 NSString *selectedText = [self accessibleSelectedText]; 695 NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; 696 NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) 697 documentAttributes: 698 @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]; 699 [styledText release]; 700 return rtfdData; 701} 702 703// finds the focused accessible element, and if it is a text element, sets the text in it 704- (BOOL)replaceAccessibleTextSelection:(NSString *)text 705{ 706 id focused = [self accessibilityFocusedUIElement]; 707 if (![focused isKindOfClass:[JavaTextAccessibility class]]) return NO; 708 [(JavaTextAccessibility *)focused accessibilitySetSelectedTextAttribute:text]; 709 return YES; 710} 711 712// called for each service in the Services menu - only handle text for now 713- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType 714{ 715 if ([[self window] firstResponder] != self) return nil; // let AWT components handle themselves 716 717 if ([sendType isEqual:NSStringPboardType] || [returnType isEqual:NSStringPboardType]) { 718 NSString *selectedText = [self accessibleSelectedText]; 719 if (selectedText) return self; 720 } 721 722 return nil; 723} 724 725// fetch text from Java and hand off to the service 726- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types 727{ 728 if ([types containsObject:NSStringPboardType]) 729 { 730 [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 731 return [pboard setString:[self accessibleSelectedText] forType:NSStringPboardType]; 732 } 733 734 if ([types containsObject:NSRTFDPboardType]) 735 { 736 [pboard declareTypes:[NSArray arrayWithObject:NSRTFDPboardType] owner:nil]; 737 return [pboard setData:[self accessibleSelectedTextAsRTFD] forType:NSRTFDPboardType]; 738 } 739 740 return NO; 741} 742 743// write text back to Java from the service 744- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard 745{ 746 if ([[pboard types] containsObject:NSStringPboardType]) 747 { 748 NSString *text = [pboard stringForType:NSStringPboardType]; 749 return [self replaceAccessibleTextSelection:text]; 750 } 751 752 if ([[pboard types] containsObject:NSRTFDPboardType]) 753 { 754 NSData *rtfdData = [pboard dataForType:NSRTFDPboardType]; 755 NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:NULL]; 756 NSString *text = [styledText string]; 757 [styledText release]; 758 759 return [self replaceAccessibleTextSelection:text]; 760 } 761 762 return NO; 763} 764 765 766-(void) setDragSource:(CDragSource *)source { 767 self._dragSource = source; 768} 769 770 771- (void) setDropTarget:(CDropTarget *)target { 772 self._dropTarget = target; 773 [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES]; 774} 775 776/******************************** BEGIN NSDraggingSource Interface ********************************/ 777 778- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag 779{ 780 // If draggingSource is nil route the message to the superclass (if responding to the selector): 781 CDragSource *dragSource = self._dragSource; 782 NSDragOperation dragOp = NSDragOperationNone; 783 784 if (dragSource != nil) { 785 dragOp = [dragSource draggingSourceOperationMaskForLocal:flag]; 786 } 787 return dragOp; 788} 789 790- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination 791{ 792 // If draggingSource is nil route the message to the superclass (if responding to the selector): 793 CDragSource *dragSource = self._dragSource; 794 NSArray* array = nil; 795 796 if (dragSource != nil) { 797 array = [dragSource namesOfPromisedFilesDroppedAtDestination:dropDestination]; 798 } 799 return array; 800} 801 802- (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint 803{ 804 // If draggingSource is nil route the message to the superclass (if responding to the selector): 805 CDragSource *dragSource = self._dragSource; 806 807 if (dragSource != nil) { 808 [dragSource draggedImage:image beganAt:screenPoint]; 809 } 810} 811 812- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation 813{ 814 // If draggingSource is nil route the message to the superclass (if responding to the selector): 815 CDragSource *dragSource = self._dragSource; 816 817 if (dragSource != nil) { 818 [dragSource draggedImage:image endedAt:screenPoint operation:operation]; 819 } 820} 821 822- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint 823{ 824 // If draggingSource is nil route the message to the superclass (if responding to the selector): 825 CDragSource *dragSource = self._dragSource; 826 827 if (dragSource != nil) { 828 [dragSource draggedImage:image movedTo:screenPoint]; 829 } 830} 831 832- (BOOL)ignoreModifierKeysWhileDragging 833{ 834 // If draggingSource is nil route the message to the superclass (if responding to the selector): 835 CDragSource *dragSource = self._dragSource; 836 BOOL result = FALSE; 837 838 if (dragSource != nil) { 839 result = [dragSource ignoreModifierKeysWhileDragging]; 840 } 841 return result; 842} 843 844/******************************** END NSDraggingSource Interface ********************************/ 845 846/******************************** BEGIN NSDraggingDestination Interface ********************************/ 847 848- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender 849{ 850 // If draggingDestination is nil route the message to the superclass: 851 CDropTarget *dropTarget = self._dropTarget; 852 NSDragOperation dragOp = NSDragOperationNone; 853 854 if (dropTarget != nil) { 855 dragOp = [dropTarget draggingEntered:sender]; 856 } 857 return dragOp; 858} 859 860- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender 861{ 862 // If draggingDestination is nil route the message to the superclass: 863 CDropTarget *dropTarget = self._dropTarget; 864 NSDragOperation dragOp = NSDragOperationNone; 865 866 if (dropTarget != nil) { 867 dragOp = [dropTarget draggingUpdated:sender]; 868 } 869 return dragOp; 870} 871 872- (void)draggingExited:(id <NSDraggingInfo>)sender 873{ 874 // If draggingDestination is nil route the message to the superclass: 875 CDropTarget *dropTarget = self._dropTarget; 876 877 if (dropTarget != nil) { 878 [dropTarget draggingExited:sender]; 879 } 880} 881 882- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender 883{ 884 // If draggingDestination is nil route the message to the superclass: 885 CDropTarget *dropTarget = self._dropTarget; 886 BOOL result = FALSE; 887 888 if (dropTarget != nil) { 889 result = [dropTarget prepareForDragOperation:sender]; 890 } 891 return result; 892} 893 894- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender 895{ 896 // If draggingDestination is nil route the message to the superclass: 897 CDropTarget *dropTarget = self._dropTarget; 898 BOOL result = FALSE; 899 900 if (dropTarget != nil) { 901 result = [dropTarget performDragOperation:sender]; 902 } 903 return result; 904} 905 906- (void)concludeDragOperation:(id <NSDraggingInfo>)sender 907{ 908 // If draggingDestination is nil route the message to the superclass: 909 CDropTarget *dropTarget = self._dropTarget; 910 911 if (dropTarget != nil) { 912 [dropTarget concludeDragOperation:sender]; 913 } 914} 915 916- (void)draggingEnded:(id <NSDraggingInfo>)sender 917{ 918 // If draggingDestination is nil route the message to the superclass: 919 CDropTarget *dropTarget = self._dropTarget; 920 921 if (dropTarget != nil) { 922 [dropTarget draggingEnded:sender]; 923 } 924} 925 926/******************************** END NSDraggingDestination Interface ********************************/ 927 928/******************************** BEGIN NSTextInputClient Protocol ********************************/ 929 930 931static jclass jc_CInputMethod = NULL; 932 933#define GET_CIM_CLASS() \ 934 GET_CLASS(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod"); 935 936#define GET_CIM_CLASS_RETURN(ret) \ 937 GET_CLASS_RETURN(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod", ret); 938 939- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange 940{ 941#ifdef IM_DEBUG 942 fprintf(stderr, "AWTView InputMethod Selector Called : [insertText]: %s\n", [aString UTF8String]); 943#endif // IM_DEBUG 944 945 if (fInputMethodLOCKABLE == NULL) { 946 return; 947 } 948 949 // Insert happens at the end of PAH 950 fInPressAndHold = NO; 951 952 // insertText gets called when the user commits text generated from an input method. It also gets 953 // called during ordinary input as well. We only need to send an input method event when we have marked 954 // text, or 'text in progress'. We also need to send the event if we get an insert text out of the blue! 955 // (i.e., when the user uses the Character palette or Inkwell), or when the string to insert is a complex 956 // Unicode value. 957 958 NSMutableString * useString = [self parseString:aString]; 959 NSUInteger utf16Length = [useString lengthOfBytesUsingEncoding:NSUTF16StringEncoding]; 960 NSUInteger utf8Length = [useString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 961 BOOL aStringIsComplex = NO; 962 963 unichar codePoint = [useString characterAtIndex:0]; 964 965#ifdef IM_DEBUG 966 NSLog(@"insertText kbdlayout %@ ",(NSString *)kbdLayout); 967#endif // IM_DEBUG 968 969 if ((utf16Length > 2) || 970 ((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:codePoint]) || 971 ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"]))) { 972 aStringIsComplex = YES; 973 } 974 975 if ([self hasMarkedText] || !fProcessingKeystroke || aStringIsComplex) { 976 JNIEnv *env = [ThreadUtilities getJNIEnv]; 977 978 GET_CIM_CLASS(); 979 DECLARE_METHOD(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 980 // We need to select the previous glyph so that it is overwritten. 981 if (fPAHNeedsToSelect) { 982 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 983 CHECK_EXCEPTION(); 984 fPAHNeedsToSelect = NO; 985 } 986 987 DECLARE_METHOD(jm_insertText, jc_CInputMethod, "insertText", "(Ljava/lang/String;)V"); 988 jstring insertedText = NSStringToJavaString(env, useString); 989 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText); 990 CHECK_EXCEPTION(); 991 (*env)->DeleteLocalRef(env, insertedText); 992 993 // The input method event will create psuedo-key events for each character in the committed string. 994 // We also don't want to send the character that triggered the insertText, usually a return. [3337563] 995 fKeyEventsNeeded = NO; 996 } 997 else { 998 // Need to set back the fKeyEventsNeeded flag so that the string following the 999 // marked text is not ignored by keyDown 1000 if ([useString length] > 0) { 1001 fKeyEventsNeeded = YES; 1002 } 1003 } 1004 fPAHNeedsToSelect = NO; 1005 1006 // Abandon input to reset IM and unblock input after entering accented 1007 // symbols 1008 1009 [self abandonInput]; 1010} 1011 1012+ (void)keyboardInputSourceChanged:(NSNotification *)notification 1013{ 1014#ifdef IM_DEBUG 1015 NSLog(@"keyboardInputSourceChangeNotification received"); 1016#endif 1017 NSTextInputContext *curContxt = [NSTextInputContext currentInputContext]; 1018 kbdLayout = curContxt.selectedKeyboardInputSource; 1019} 1020 1021- (void) doCommandBySelector:(SEL)aSelector 1022{ 1023#ifdef IM_DEBUG 1024 fprintf(stderr, "AWTView InputMethod Selector Called : [doCommandBySelector]\n"); 1025 NSLog(@"%@", NSStringFromSelector(aSelector)); 1026#endif // IM_DEBUG 1027 if (@selector(insertNewline:) == aSelector || @selector(insertTab:) == aSelector || @selector(deleteBackward:) == aSelector) 1028 { 1029 fKeyEventsNeeded = YES; 1030 } 1031} 1032 1033// setMarkedText: cannot take a nil first argument. aString can be NSString or NSAttributedString 1034- (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replacementRange:(NSRange)replacementRange 1035{ 1036 if (!fInputMethodLOCKABLE) 1037 return; 1038 1039 BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]]; 1040 NSAttributedString *attrString = (isAttributedString ? (NSAttributedString *)aString : nil); 1041 NSString *incomingString = (isAttributedString ? [aString string] : aString); 1042#ifdef IM_DEBUG 1043 fprintf(stderr, "AWTView InputMethod Selector Called : [setMarkedText] \"%s\", loc=%lu, length=%lu\n", [incomingString UTF8String], (unsigned long)selectionRange.location, (unsigned long)selectionRange.length); 1044#endif // IM_DEBUG 1045 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1046 GET_CIM_CLASS(); 1047 DECLARE_METHOD(jm_startIMUpdate, jc_CInputMethod, "startIMUpdate", "(Ljava/lang/String;)V"); 1048 DECLARE_METHOD(jm_addAttribute, jc_CInputMethod, "addAttribute", "(ZZII)V"); 1049 DECLARE_METHOD(jm_dispatchText, jc_CInputMethod, "dispatchText", "(IIZ)V"); 1050 1051 // NSInputContext already did the analysis of the TSM event and created attributes indicating 1052 // the underlining and color that should be done to the string. We need to look at the underline 1053 // style and color to determine what kind of Java hilighting needs to be done. 1054 jstring inProcessText = NSStringToJavaString(env, incomingString); 1055 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_startIMUpdate, inProcessText); 1056 CHECK_EXCEPTION(); 1057 (*env)->DeleteLocalRef(env, inProcessText); 1058 1059 if (isAttributedString) { 1060 NSUInteger length; 1061 NSRange effectiveRange; 1062 NSDictionary *attributes; 1063 length = [attrString length]; 1064 effectiveRange = NSMakeRange(0, 0); 1065 while (NSMaxRange(effectiveRange) < length) { 1066 attributes = [attrString attributesAtIndex:NSMaxRange(effectiveRange) 1067 effectiveRange:&effectiveRange]; 1068 if (attributes) { 1069 BOOL isThickUnderline, isGray; 1070 NSNumber *underlineSizeObj = 1071 (NSNumber *)[attributes objectForKey:NSUnderlineStyleAttributeName]; 1072 NSInteger underlineSize = [underlineSizeObj integerValue]; 1073 isThickUnderline = (underlineSize > 1); 1074 1075 NSColor *underlineColorObj = 1076 (NSColor *)[attributes objectForKey:NSUnderlineColorAttributeName]; 1077 isGray = !([underlineColorObj isEqual:[NSColor blackColor]]); 1078 1079 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_addAttribute, isThickUnderline, 1080 isGray, effectiveRange.location, effectiveRange.length); 1081 CHECK_EXCEPTION(); 1082 } 1083 } 1084 } 1085 1086 DECLARE_METHOD(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 1087 // We need to select the previous glyph so that it is overwritten. 1088 if (fPAHNeedsToSelect) { 1089 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 1090 CHECK_EXCEPTION(); 1091 fPAHNeedsToSelect = NO; 1092 } 1093 1094 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_dispatchText, 1095 selectionRange.location, selectionRange.length, JNI_FALSE); 1096 CHECK_EXCEPTION(); 1097 // If the marked text is being cleared (zero-length string) don't handle the key event. 1098 if ([incomingString length] == 0) { 1099 fKeyEventsNeeded = NO; 1100 } 1101} 1102 1103- (void) unmarkText 1104{ 1105#ifdef IM_DEBUG 1106 fprintf(stderr, "AWTView InputMethod Selector Called : [unmarkText]\n"); 1107#endif // IM_DEBUG 1108 1109 if (!fInputMethodLOCKABLE) { 1110 return; 1111 } 1112 1113 // unmarkText cancels any input in progress and commits it to the text field. 1114 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1115 GET_CIM_CLASS(); 1116 DECLARE_METHOD(jm_unmarkText, jc_CInputMethod, "unmarkText", "()V"); 1117 (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); 1118 CHECK_EXCEPTION(); 1119} 1120 1121- (BOOL) hasMarkedText 1122{ 1123#ifdef IM_DEBUG 1124 fprintf(stderr, "AWTView InputMethod Selector Called : [hasMarkedText]\n"); 1125#endif // IM_DEBUG 1126 1127 if (!fInputMethodLOCKABLE) { 1128 return NO; 1129 } 1130 1131 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1132 GET_CIM_CLASS_RETURN(NO); 1133 DECLARE_FIELD_RETURN(jf_fCurrentText, jc_CInputMethod, "fCurrentText", "Ljava/text/AttributedString;", NO); 1134 DECLARE_FIELD_RETURN(jf_fCurrentTextLength, jc_CInputMethod, "fCurrentTextLength", "I", NO); 1135 jobject currentText = (*env)->GetObjectField(env, fInputMethodLOCKABLE, jf_fCurrentText); 1136 CHECK_EXCEPTION(); 1137 1138 jint currentTextLength = (*env)->GetIntField(env, fInputMethodLOCKABLE, jf_fCurrentTextLength); 1139 CHECK_EXCEPTION(); 1140 1141 BOOL hasMarkedText = (currentText != NULL && currentTextLength > 0); 1142 1143 if (currentText != NULL) { 1144 (*env)->DeleteLocalRef(env, currentText); 1145 } 1146 1147 return hasMarkedText; 1148} 1149 1150- (NSInteger) conversationIdentifier 1151{ 1152#ifdef IM_DEBUG 1153 fprintf(stderr, "AWTView InputMethod Selector Called : [conversationIdentifier]\n"); 1154#endif // IM_DEBUG 1155 1156 return (NSInteger) self; 1157} 1158 1159/* Returns attributed string at the range. This allows input mangers to 1160 query any range in backing-store (Andy's request) 1161 */ 1162- (NSAttributedString *) attributedSubstringForProposedRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1163{ 1164#ifdef IM_DEBUG 1165 fprintf(stderr, "AWTView InputMethod Selector Called : [attributedSubstringFromRange] location=%lu, length=%lu\n", (unsigned long)theRange.location, (unsigned long)theRange.length); 1166#endif // IM_DEBUG 1167 if (!fInputMethodLOCKABLE) { 1168 return nil; 1169 } 1170 1171 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1172 GET_CIM_CLASS_RETURN(nil); 1173 DECLARE_METHOD_RETURN(jm_substringFromRange, jc_CInputMethod, "attributedSubstringFromRange", "(II)Ljava/lang/String;", nil); 1174 jobject theString = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_substringFromRange, theRange.location, theRange.length); 1175 CHECK_EXCEPTION_NULL_RETURN(theString, nil); 1176 1177 id result = [[[NSAttributedString alloc] initWithString:JavaStringToNSString(env, theString)] autorelease]; 1178#ifdef IM_DEBUG 1179 NSLog(@"attributedSubstringFromRange returning \"%@\"", result); 1180#endif // IM_DEBUG 1181 1182 (*env)->DeleteLocalRef(env, theString); 1183 return result; 1184} 1185 1186/* This method returns the range for marked region. If hasMarkedText == false, 1187 it'll return NSNotFound location & 0 length range. 1188 */ 1189- (NSRange) markedRange 1190{ 1191 1192#ifdef IM_DEBUG 1193 fprintf(stderr, "AWTView InputMethod Selector Called : [markedRange]\n"); 1194#endif // IM_DEBUG 1195 1196 if (!fInputMethodLOCKABLE) { 1197 return NSMakeRange(NSNotFound, 0); 1198 } 1199 1200 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1201 jarray array; 1202 jboolean isCopy; 1203 jint *_array; 1204 NSRange range = NSMakeRange(NSNotFound, 0); 1205 GET_CIM_CLASS_RETURN(range); 1206 DECLARE_METHOD_RETURN(jm_markedRange, jc_CInputMethod, "markedRange", "()[I", range); 1207 1208 array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_markedRange); 1209 CHECK_EXCEPTION(); 1210 1211 if (array) { 1212 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1213 if (_array != NULL) { 1214 range.location = _array[0]; 1215 range.length = _array[1]; 1216#ifdef IM_DEBUG 1217 fprintf(stderr, "markedRange returning (%lu, %lu)\n", 1218 (unsigned long)range.location, (unsigned long)range.length); 1219#endif // IM_DEBUG 1220 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1221 } 1222 (*env)->DeleteLocalRef(env, array); 1223 } 1224 1225 return range; 1226} 1227 1228/* This method returns the range for selected region. Just like markedRange method, 1229 its location field contains char index from the text beginning. 1230 */ 1231- (NSRange) selectedRange 1232{ 1233 if (!fInputMethodLOCKABLE) { 1234 return NSMakeRange(NSNotFound, 0); 1235 } 1236 1237 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1238 jarray array; 1239 jboolean isCopy; 1240 jint *_array; 1241 NSRange range = NSMakeRange(NSNotFound, 0); 1242 GET_CIM_CLASS_RETURN(range); 1243 DECLARE_METHOD_RETURN(jm_selectedRange, jc_CInputMethod, "selectedRange", "()[I", range); 1244 1245#ifdef IM_DEBUG 1246 fprintf(stderr, "AWTView InputMethod Selector Called : [selectedRange]\n"); 1247#endif // IM_DEBUG 1248 1249 array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_selectedRange); 1250 CHECK_EXCEPTION(); 1251 if (array) { 1252 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1253 if (_array != NULL) { 1254 range.location = _array[0]; 1255 range.length = _array[1]; 1256 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1257 } 1258 (*env)->DeleteLocalRef(env, array); 1259 } 1260 1261 return range; 1262} 1263 1264/* This method returns the first frame of rects for theRange in screen coordindate system. 1265 */ 1266- (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1267{ 1268 if (!fInputMethodLOCKABLE) { 1269 return NSZeroRect; 1270 } 1271 1272 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1273 GET_CIM_CLASS_RETURN(NSZeroRect); 1274 DECLARE_METHOD_RETURN(jm_firstRectForCharacterRange, jc_CInputMethod, 1275 "firstRectForCharacterRange", "(I)[I", NSZeroRect); 1276 jarray array; 1277 jboolean isCopy; 1278 jint *_array; 1279 NSRect rect; 1280 1281#ifdef IM_DEBUG 1282 fprintf(stderr, 1283 "AWTView InputMethod Selector Called : [firstRectForCharacterRange:] location=%lu, length=%lu\n", 1284 (unsigned long)theRange.location, (unsigned long)theRange.length); 1285#endif // IM_DEBUG 1286 1287 array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange, 1288 theRange.location); 1289 CHECK_EXCEPTION(); 1290 1291 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1292 if (_array) { 1293 rect = ConvertNSScreenRect(env, NSMakeRect(_array[0], _array[1], _array[2], _array[3])); 1294 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1295 } else { 1296 rect = NSZeroRect; 1297 } 1298 (*env)->DeleteLocalRef(env, array); 1299 1300#ifdef IM_DEBUG 1301 fprintf(stderr, 1302 "firstRectForCharacterRange returning x=%f, y=%f, width=%f, height=%f\n", 1303 rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); 1304#endif // IM_DEBUG 1305 return rect; 1306} 1307 1308/* This method returns the index for character that is nearest to thePoint. thPoint is in 1309 screen coordinate system. 1310 */ 1311- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint 1312{ 1313 if (!fInputMethodLOCKABLE) { 1314 return NSNotFound; 1315 } 1316 1317 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1318 GET_CIM_CLASS_RETURN(NSNotFound); 1319 DECLARE_METHOD_RETURN(jm_characterIndexForPoint, jc_CInputMethod, 1320 "characterIndexForPoint", "(II)I", NSNotFound); 1321 1322 NSPoint flippedLocation = ConvertNSScreenPoint(env, thePoint); 1323 1324#ifdef IM_DEBUG 1325 fprintf(stderr, "AWTView InputMethod Selector Called : [characterIndexForPoint:(NSPoint)thePoint] x=%f, y=%f\n", flippedLocation.x, flippedLocation.y); 1326#endif // IM_DEBUG 1327 1328 jint index = (*env)->CallIntMethod(env, fInputMethodLOCKABLE, jm_characterIndexForPoint, 1329 (jint)flippedLocation.x, (jint)flippedLocation.y); 1330 CHECK_EXCEPTION(); 1331 1332#ifdef IM_DEBUG 1333 fprintf(stderr, "characterIndexForPoint returning %d\n", index); 1334#endif // IM_DEBUG 1335 1336 if (index == -1) { 1337 return NSNotFound; 1338 } else { 1339 return (NSUInteger)index; 1340 } 1341} 1342 1343- (NSArray*) validAttributesForMarkedText 1344{ 1345#ifdef IM_DEBUG 1346 fprintf(stderr, "AWTView InputMethod Selector Called : [validAttributesForMarkedText]\n"); 1347#endif // IM_DEBUG 1348 1349 return [NSArray array]; 1350} 1351 1352- (void)setInputMethod:(jobject)inputMethod 1353{ 1354#ifdef IM_DEBUG 1355 fprintf(stderr, "AWTView InputMethod Selector Called : [setInputMethod]\n"); 1356#endif // IM_DEBUG 1357 1358 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1359 1360 // Get rid of the old one 1361 if (fInputMethodLOCKABLE) { 1362 (*env)->DeleteGlobalRef(env, fInputMethodLOCKABLE); 1363 } 1364 1365 fInputMethodLOCKABLE = inputMethod; // input method arg must be a GlobalRef 1366 1367 NSTextInputContext *curContxt = [NSTextInputContext currentInputContext]; 1368 kbdLayout = curContxt.selectedKeyboardInputSource; 1369 [[NSNotificationCenter defaultCenter] addObserver:[AWTView class] 1370 selector:@selector(keyboardInputSourceChanged:) 1371 name:NSTextInputContextKeyboardSelectionDidChangeNotification 1372 object:nil]; 1373} 1374 1375- (void)abandonInput 1376{ 1377#ifdef IM_DEBUG 1378 fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); 1379#endif // IM_DEBUG 1380 1381 [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; 1382 [self unmarkText]; 1383} 1384 1385/******************************** END NSTextInputClient Protocol ********************************/ 1386 1387 1388 1389 1390@end // AWTView 1391 1392/* 1393 * Class: sun_lwawt_macosx_CPlatformView 1394 * Method: nativeCreateView 1395 * Signature: (IIII)J 1396 */ 1397JNIEXPORT jlong JNICALL 1398Java_sun_lwawt_macosx_CPlatformView_nativeCreateView 1399(JNIEnv *env, jobject obj, jint originX, jint originY, jint width, jint height, jlong windowLayerPtr) 1400{ 1401 __block AWTView *newView = nil; 1402 1403 JNI_COCOA_ENTER(env); 1404 1405 NSRect rect = NSMakeRect(originX, originY, width, height); 1406 jobject cPlatformView = (*env)->NewWeakGlobalRef(env, obj); 1407 CHECK_EXCEPTION(); 1408 1409 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1410 1411 CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); 1412 newView = [[AWTView alloc] initWithRect:rect 1413 platformView:cPlatformView 1414 windowLayer:windowLayer]; 1415 }]; 1416 1417 JNI_COCOA_EXIT(env); 1418 1419 return ptr_to_jlong(newView); 1420} 1421 1422/* 1423 * Class: sun_lwawt_macosx_CPlatformView 1424 * Method: nativeSetAutoResizable 1425 * Signature: (JZ)V; 1426 */ 1427 1428JNIEXPORT void JNICALL 1429Java_sun_lwawt_macosx_CPlatformView_nativeSetAutoResizable 1430(JNIEnv *env, jclass cls, jlong viewPtr, jboolean toResize) 1431{ 1432 JNI_COCOA_ENTER(env); 1433 1434 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1435 1436 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 1437 1438 if (toResize) { 1439 [view setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; 1440 } else { 1441 [view setAutoresizingMask: NSViewMinYMargin | NSViewMaxXMargin]; 1442 } 1443 1444 if ([view superview] != nil) { 1445 [[view superview] setAutoresizesSubviews:(BOOL)toResize]; 1446 } 1447 1448 }]; 1449 JNI_COCOA_EXIT(env); 1450} 1451 1452/* 1453 * Class: sun_lwawt_macosx_CPlatformView 1454 * Method: nativeGetNSViewDisplayID 1455 * Signature: (J)I; 1456 */ 1457 1458JNIEXPORT jint JNICALL 1459Java_sun_lwawt_macosx_CPlatformView_nativeGetNSViewDisplayID 1460(JNIEnv *env, jclass cls, jlong viewPtr) 1461{ 1462 __block jint ret; //CGDirectDisplayID 1463 1464 JNI_COCOA_ENTER(env); 1465 1466 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1467 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1468 NSWindow *window = [view window]; 1469 ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; 1470 }]; 1471 1472 JNI_COCOA_EXIT(env); 1473 1474 return ret; 1475} 1476 1477/* 1478 * Class: sun_lwawt_macosx_CPlatformView 1479 * Method: nativeGetLocationOnScreen 1480 * Signature: (J)Ljava/awt/Rectangle; 1481 */ 1482 1483JNIEXPORT jobject JNICALL 1484Java_sun_lwawt_macosx_CPlatformView_nativeGetLocationOnScreen 1485(JNIEnv *env, jclass cls, jlong viewPtr) 1486{ 1487 jobject jRect = NULL; 1488 1489 JNI_COCOA_ENTER(env); 1490 1491 __block NSRect rect = NSZeroRect; 1492 1493 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1494 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1495 1496 NSRect viewBounds = [view bounds]; 1497 NSRect frameInWindow = [view convertRect:viewBounds toView:nil]; 1498 rect = [[view window] convertRectToScreen:frameInWindow]; 1499 //Convert coordinates to top-left corner origin 1500 rect = ConvertNSScreenRect(NULL, rect); 1501 1502 }]; 1503 jRect = NSToJavaRect(env, rect); 1504 1505 JNI_COCOA_EXIT(env); 1506 1507 return jRect; 1508} 1509 1510/* 1511 * Class: sun_lwawt_macosx_CPlatformView 1512 * Method: nativeIsViewUnderMouse 1513 * Signature: (J)Z; 1514 */ 1515 1516JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformView_nativeIsViewUnderMouse 1517(JNIEnv *env, jclass clazz, jlong viewPtr) 1518{ 1519 __block jboolean underMouse = JNI_FALSE; 1520 1521 JNI_COCOA_ENTER(env); 1522 1523 NSView *nsView = OBJC(viewPtr); 1524 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1525 NSPoint ptWindowCoords = [[nsView window] mouseLocationOutsideOfEventStream]; 1526 NSPoint ptViewCoords = [nsView convertPoint:ptWindowCoords fromView:nil]; 1527 underMouse = [nsView hitTest:ptViewCoords] != nil; 1528 }]; 1529 1530 JNI_COCOA_EXIT(env); 1531 1532 return underMouse; 1533} 1534