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