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