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