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