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 955 unichar codePoint = [useString characterAtIndex:0]; 956 957 #ifdef IM_DEBUG 958 NSLog(@"insertText kbdlayout %@ ",(NSString *)kbdLayout); 959 #endif // IM_DEBUG 960 961 if ((utf16Length > 2) || 962 ((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:codePoint]) || 963 ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"]))) { 964 aStringIsComplex = YES; 965 } 966 967 if ([self hasMarkedText] || !fProcessingKeystroke || aStringIsComplex) { 968 JNIEnv *env = [ThreadUtilities getJNIEnv]; 969 970 static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 971 // We need to select the previous glyph so that it is overwritten. 972 if (fPAHNeedsToSelect) { 973 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 974 fPAHNeedsToSelect = NO; 975 } 976 977 static JNF_MEMBER_CACHE(jm_insertText, jc_CInputMethod, "insertText", "(Ljava/lang/String;)V"); 978 jstring insertedText = JNFNSToJavaString(env, useString); 979 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText); // AWT_THREADING Safe (AWTRunLoopMode) 980 (*env)->DeleteLocalRef(env, insertedText); 981 982 // The input method event will create psuedo-key events for each character in the committed string. 983 // We also don't want to send the character that triggered the insertText, usually a return. [3337563] 984 fKeyEventsNeeded = NO; 985 } 986 else { 987 // Need to set back the fKeyEventsNeeded flag so that the string following the 988 // marked text is not ignored by keyDown 989 if ([useString length] > 0) { 990 fKeyEventsNeeded = YES; 991 } 992 } 993 fPAHNeedsToSelect = NO; 994 995 // Abandon input to reset IM and unblock input after entering accented 996 // symbols 997 998 [self abandonInput]; 999 } 1000 1001 - (void) doCommandBySelector:(SEL)aSelector 1002 { 1003 #ifdef IM_DEBUG 1004 fprintf(stderr, "AWTView InputMethod Selector Called : [doCommandBySelector]\n"); 1005 NSLog(@"%@", NSStringFromSelector(aSelector)); 1006 #endif // IM_DEBUG 1007 if (@selector(insertNewline:) == aSelector || @selector(insertTab:) == aSelector || @selector(deleteBackward:) == aSelector) 1008 { 1009 fKeyEventsNeeded = YES; 1010 } 1011 } 1012 1013 // setMarkedText: cannot take a nil first argument. aString can be NSString or NSAttributedString 1014 - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replacementRange:(NSRange)replacementRange 1015 { 1016 if (!fInputMethodLOCKABLE) 1017 return; 1018 1019 BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]]; 1020 NSAttributedString *attrString = (isAttributedString ? (NSAttributedString *)aString : nil); 1021 NSString *incomingString = (isAttributedString ? [aString string] : aString); 1022 #ifdef IM_DEBUG 1023 fprintf(stderr, "AWTView InputMethod Selector Called : [setMarkedText] \"%s\", loc=%lu, length=%lu\n", [incomingString UTF8String], (unsigned long)selectionRange.location, (unsigned long)selectionRange.length); 1024 #endif // IM_DEBUG 1025 static JNF_MEMBER_CACHE(jm_startIMUpdate, jc_CInputMethod, "startIMUpdate", "(Ljava/lang/String;)V"); 1026 static JNF_MEMBER_CACHE(jm_addAttribute, jc_CInputMethod, "addAttribute", "(ZZII)V"); 1027 static JNF_MEMBER_CACHE(jm_dispatchText, jc_CInputMethod, "dispatchText", "(IIZ)V"); 1028 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1029 1030 // NSInputContext already did the analysis of the TSM event and created attributes indicating 1031 // the underlining and color that should be done to the string. We need to look at the underline 1032 // style and color to determine what kind of Java hilighting needs to be done. 1033 jstring inProcessText = JNFNSToJavaString(env, incomingString); 1034 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_startIMUpdate, inProcessText); // AWT_THREADING Safe (AWTRunLoopMode) 1035 (*env)->DeleteLocalRef(env, inProcessText); 1036 1037 if (isAttributedString) { 1038 NSUInteger length; 1039 NSRange effectiveRange; 1040 NSDictionary *attributes; 1041 length = [attrString length]; 1042 effectiveRange = NSMakeRange(0, 0); 1043 while (NSMaxRange(effectiveRange) < length) { 1044 attributes = [attrString attributesAtIndex:NSMaxRange(effectiveRange) 1045 effectiveRange:&effectiveRange]; 1046 if (attributes) { 1047 BOOL isThickUnderline, isGray; 1048 NSNumber *underlineSizeObj = 1049 (NSNumber *)[attributes objectForKey:NSUnderlineStyleAttributeName]; 1050 NSInteger underlineSize = [underlineSizeObj integerValue]; 1051 isThickUnderline = (underlineSize > 1); 1052 1053 NSColor *underlineColorObj = 1054 (NSColor *)[attributes objectForKey:NSUnderlineColorAttributeName]; 1055 isGray = !([underlineColorObj isEqual:[NSColor blackColor]]); 1056 1057 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_addAttribute, isThickUnderline, isGray, effectiveRange.location, effectiveRange.length); // AWT_THREADING Safe (AWTRunLoopMode) 1058 } 1059 } 1060 } 1061 1062 static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 1063 // We need to select the previous glyph so that it is overwritten. 1064 if (fPAHNeedsToSelect) { 1065 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 1066 fPAHNeedsToSelect = NO; 1067 } 1068 1069 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_dispatchText, selectionRange.location, selectionRange.length, JNI_FALSE); // AWT_THREADING Safe (AWTRunLoopMode) 1070 1071 // If the marked text is being cleared (zero-length string) don't handle the key event. 1072 if ([incomingString length] == 0) { 1073 fKeyEventsNeeded = NO; 1074 } 1075 } 1076 1077 - (void) unmarkText 1078 { 1079 #ifdef IM_DEBUG 1080 fprintf(stderr, "AWTView InputMethod Selector Called : [unmarkText]\n"); 1081 #endif // IM_DEBUG 1082 1083 if (!fInputMethodLOCKABLE) { 1084 return; 1085 } 1086 1087 // unmarkText cancels any input in progress and commits it to the text field. 1088 static JNF_MEMBER_CACHE(jm_unmarkText, jc_CInputMethod, "unmarkText", "()V"); 1089 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1090 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); // AWT_THREADING Safe (AWTRunLoopMode) 1091 1092 } 1093 1094 - (BOOL) hasMarkedText 1095 { 1096 #ifdef IM_DEBUG 1097 fprintf(stderr, "AWTView InputMethod Selector Called : [hasMarkedText]\n"); 1098 #endif // IM_DEBUG 1099 1100 if (!fInputMethodLOCKABLE) { 1101 return NO; 1102 } 1103 1104 static JNF_MEMBER_CACHE(jf_fCurrentText, jc_CInputMethod, "fCurrentText", "Ljava/text/AttributedString;"); 1105 static JNF_MEMBER_CACHE(jf_fCurrentTextLength, jc_CInputMethod, "fCurrentTextLength", "I"); 1106 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1107 jobject currentText = JNFGetObjectField(env, fInputMethodLOCKABLE, jf_fCurrentText); 1108 1109 jint currentTextLength = JNFGetIntField(env, fInputMethodLOCKABLE, jf_fCurrentTextLength); 1110 1111 BOOL hasMarkedText = (currentText != NULL && currentTextLength > 0); 1112 1113 if (currentText != NULL) { 1114 (*env)->DeleteLocalRef(env, currentText); 1115 } 1116 1117 return hasMarkedText; 1118 } 1119 1120 - (NSInteger) conversationIdentifier 1121 { 1122 #ifdef IM_DEBUG 1123 fprintf(stderr, "AWTView InputMethod Selector Called : [conversationIdentifier]\n"); 1124 #endif // IM_DEBUG 1125 1126 return (NSInteger) self; 1127 } 1128 1129 /* Returns attributed string at the range. This allows input mangers to 1130 query any range in backing-store (Andy's request) 1131 */ 1132 - (NSAttributedString *) attributedSubstringForProposedRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1133 { 1134 #ifdef IM_DEBUG 1135 fprintf(stderr, "AWTView InputMethod Selector Called : [attributedSubstringFromRange] location=%lu, length=%lu\n", (unsigned long)theRange.location, (unsigned long)theRange.length); 1136 #endif // IM_DEBUG 1137 1138 static JNF_MEMBER_CACHE(jm_substringFromRange, jc_CInputMethod, "attributedSubstringFromRange", "(II)Ljava/lang/String;"); 1139 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1140 jobject theString = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_substringFromRange, theRange.location, theRange.length); // AWT_THREADING Safe (AWTRunLoopMode) 1141 1142 id result = [[[NSAttributedString alloc] initWithString:JNFJavaToNSString(env, theString)] autorelease]; 1143 #ifdef IM_DEBUG 1144 NSLog(@"attributedSubstringFromRange returning \"%@\"", result); 1145 #endif // IM_DEBUG 1146 1147 (*env)->DeleteLocalRef(env, theString); 1148 return result; 1149 } 1150 1151 /* This method returns the range for marked region. If hasMarkedText == false, 1152 it'll return NSNotFound location & 0 length range. 1153 */ 1154 - (NSRange) markedRange 1155 { 1156 1157 #ifdef IM_DEBUG 1158 fprintf(stderr, "AWTView InputMethod Selector Called : [markedRange]\n"); 1159 #endif // IM_DEBUG 1160 1161 if (!fInputMethodLOCKABLE) { 1162 return NSMakeRange(NSNotFound, 0); 1163 } 1164 1165 static JNF_MEMBER_CACHE(jm_markedRange, jc_CInputMethod, "markedRange", "()[I"); 1166 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1167 jarray array; 1168 jboolean isCopy; 1169 jint *_array; 1170 NSRange range = NSMakeRange(NSNotFound, 0); 1171 1172 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_markedRange); // AWT_THREADING Safe (AWTRunLoopMode) 1173 1174 if (array) { 1175 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1176 if (_array != NULL) { 1177 range.location = _array[0]; 1178 range.length = _array[1]; 1179 #ifdef IM_DEBUG 1180 fprintf(stderr, "markedRange returning (%lu, %lu)\n", 1181 (unsigned long)range.location, (unsigned long)range.length); 1182 #endif // IM_DEBUG 1183 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1184 } 1185 (*env)->DeleteLocalRef(env, array); 1186 } 1187 1188 return range; 1189 } 1190 1191 /* This method returns the range for selected region. Just like markedRange method, 1192 its location field contains char index from the text beginning. 1193 */ 1194 - (NSRange) selectedRange 1195 { 1196 if (!fInputMethodLOCKABLE) { 1197 return NSMakeRange(NSNotFound, 0); 1198 } 1199 1200 static JNF_MEMBER_CACHE(jm_selectedRange, jc_CInputMethod, "selectedRange", "()[I"); 1201 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1202 jarray array; 1203 jboolean isCopy; 1204 jint *_array; 1205 NSRange range = NSMakeRange(NSNotFound, 0); 1206 1207 #ifdef IM_DEBUG 1208 fprintf(stderr, "AWTView InputMethod Selector Called : [selectedRange]\n"); 1209 #endif // IM_DEBUG 1210 1211 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_selectedRange); // AWT_THREADING Safe (AWTRunLoopMode) 1212 if (array) { 1213 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1214 if (_array != NULL) { 1215 range.location = _array[0]; 1216 range.length = _array[1]; 1217 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1218 } 1219 (*env)->DeleteLocalRef(env, array); 1220 } 1221 1222 return range; 1223 } 1224 1225 /* This method returns the first frame of rects for theRange in screen coordindate system. 1226 */ 1227 - (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1228 { 1229 if (!fInputMethodLOCKABLE) { 1230 return NSZeroRect; 1231 } 1232 1233 static JNF_MEMBER_CACHE(jm_firstRectForCharacterRange, jc_CInputMethod, 1234 "firstRectForCharacterRange", "(I)[I"); 1235 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1236 jarray array; 1237 jboolean isCopy; 1238 jint *_array; 1239 NSRect rect; 1240 1241 #ifdef IM_DEBUG 1242 fprintf(stderr, 1243 "AWTView InputMethod Selector Called : [firstRectForCharacterRange:] location=%lu, length=%lu\n", 1244 (unsigned long)theRange.location, (unsigned long)theRange.length); 1245 #endif // IM_DEBUG 1246 1247 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange, 1248 theRange.location); // AWT_THREADING Safe (AWTRunLoopMode) 1249 1250 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1251 if (_array) { 1252 rect = ConvertNSScreenRect(env, NSMakeRect(_array[0], _array[1], _array[2], _array[3])); 1253 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1254 } else { 1255 rect = NSZeroRect; 1256 } 1257 (*env)->DeleteLocalRef(env, array); 1258 1259 #ifdef IM_DEBUG 1260 fprintf(stderr, 1261 "firstRectForCharacterRange returning x=%f, y=%f, width=%f, height=%f\n", 1262 rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); 1263 #endif // IM_DEBUG 1264 return rect; 1265 } 1266 1267 /* This method returns the index for character that is nearest to thePoint. thPoint is in 1268 screen coordinate system. 1269 */ 1270 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint 1271 { 1272 if (!fInputMethodLOCKABLE) { 1273 return NSNotFound; 1274 } 1275 1276 static JNF_MEMBER_CACHE(jm_characterIndexForPoint, jc_CInputMethod, 1277 "characterIndexForPoint", "(II)I"); 1278 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1279 1280 NSPoint flippedLocation = ConvertNSScreenPoint(env, thePoint); 1281 1282 #ifdef IM_DEBUG 1283 fprintf(stderr, "AWTView InputMethod Selector Called : [characterIndexForPoint:(NSPoint)thePoint] x=%f, y=%f\n", flippedLocation.x, flippedLocation.y); 1284 #endif // IM_DEBUG 1285 1286 jint index = JNFCallIntMethod(env, fInputMethodLOCKABLE, jm_characterIndexForPoint, (jint)flippedLocation.x, (jint)flippedLocation.y); // AWT_THREADING Safe (AWTRunLoopMode) 1287 1288 #ifdef IM_DEBUG 1289 fprintf(stderr, "characterIndexForPoint returning %ld\n", index); 1290 #endif // IM_DEBUG 1291 1292 if (index == -1) { 1293 return NSNotFound; 1294 } else { 1295 return (NSUInteger)index; 1296 } 1297 } 1298 1299 - (NSArray*) validAttributesForMarkedText 1300 { 1301 #ifdef IM_DEBUG 1302 fprintf(stderr, "AWTView InputMethod Selector Called : [validAttributesForMarkedText]\n"); 1303 #endif // IM_DEBUG 1304 1305 return [NSArray array]; 1306 } 1307 1308 - (void)setInputMethod:(jobject)inputMethod 1309 { 1310 #ifdef IM_DEBUG 1311 fprintf(stderr, "AWTView InputMethod Selector Called : [setInputMethod]\n"); 1312 #endif // IM_DEBUG 1313 1314 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1315 1316 // Get rid of the old one 1317 if (fInputMethodLOCKABLE) { 1318 JNFDeleteGlobalRef(env, fInputMethodLOCKABLE); 1319 } 1320 1321 // Save a global ref to the new input method. 1322 if (inputMethod != NULL) 1323 fInputMethodLOCKABLE = JNFNewGlobalRef(env, inputMethod); 1324 else 1325 fInputMethodLOCKABLE = NULL; 1326 1327 kbdLayout = TISGetInputSourceProperty(TISCopyCurrentKeyboardInputSource(), kTISPropertyInputSourceID); 1328 } 1329 1330 - (void)abandonInput 1331 { 1332 #ifdef IM_DEBUG 1333 fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); 1334 #endif // IM_DEBUG 1335 1336 [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; 1337 [self unmarkText]; 1338 } 1339 1340 /******************************** END NSTextInputClient Protocol ********************************/ 1341 1342 1343 1344 1345 @end // AWTView 1346 1347 /* 1348 * Class: sun_lwawt_macosx_CPlatformView 1349 * Method: nativeCreateView 1350 * Signature: (IIII)J 1351 */ 1352 JNIEXPORT jlong JNICALL 1353 Java_sun_lwawt_macosx_CPlatformView_nativeCreateView 1354 (JNIEnv *env, jobject obj, jint originX, jint originY, jint width, jint height, jlong windowLayerPtr) 1355 { 1356 __block AWTView *newView = nil; 1357 1358 JNF_COCOA_ENTER(env); 1359 1360 NSRect rect = NSMakeRect(originX, originY, width, height); 1361 jobject cPlatformView = (*env)->NewWeakGlobalRef(env, obj); 1362 1363 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1364 1365 CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); 1366 newView = [[AWTView alloc] initWithRect:rect 1367 platformView:cPlatformView 1368 windowLayer:windowLayer]; 1369 }]; 1370 1371 JNF_COCOA_EXIT(env); 1372 1373 return ptr_to_jlong(newView); 1374 } 1375 1376 /* 1377 * Class: sun_lwawt_macosx_CPlatformView 1378 * Method: nativeSetAutoResizable 1379 * Signature: (JZ)V; 1380 */ 1381 1382 JNIEXPORT void JNICALL 1383 Java_sun_lwawt_macosx_CPlatformView_nativeSetAutoResizable 1384 (JNIEnv *env, jclass cls, jlong viewPtr, jboolean toResize) 1385 { 1386 JNF_COCOA_ENTER(env); 1387 1388 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1389 1390 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 1391 1392 if (toResize) { 1393 [view setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; 1394 } else { 1395 [view setAutoresizingMask: NSViewMinYMargin | NSViewMaxXMargin]; 1396 } 1397 1398 if ([view superview] != nil) { 1399 [[view superview] setAutoresizesSubviews:(BOOL)toResize]; 1400 } 1401 1402 }]; 1403 JNF_COCOA_EXIT(env); 1404 } 1405 1406 /* 1407 * Class: sun_lwawt_macosx_CPlatformView 1408 * Method: nativeGetNSViewDisplayID 1409 * Signature: (J)I; 1410 */ 1411 1412 JNIEXPORT jint JNICALL 1413 Java_sun_lwawt_macosx_CPlatformView_nativeGetNSViewDisplayID 1414 (JNIEnv *env, jclass cls, jlong viewPtr) 1415 { 1416 __block jint ret; //CGDirectDisplayID 1417 1418 JNF_COCOA_ENTER(env); 1419 1420 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1421 NSWindow *window = [view window]; 1422 1423 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1424 1425 ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; 1426 }]; 1427 1428 JNF_COCOA_EXIT(env); 1429 1430 return ret; 1431 } 1432 1433 /* 1434 * Class: sun_lwawt_macosx_CPlatformView 1435 * Method: nativeGetLocationOnScreen 1436 * Signature: (J)Ljava/awt/Rectangle; 1437 */ 1438 1439 JNIEXPORT jobject JNICALL 1440 Java_sun_lwawt_macosx_CPlatformView_nativeGetLocationOnScreen 1441 (JNIEnv *env, jclass cls, jlong viewPtr) 1442 { 1443 jobject jRect = NULL; 1444 1445 JNF_COCOA_ENTER(env); 1446 1447 __block NSRect rect = NSZeroRect; 1448 1449 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1450 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1451 1452 NSRect viewBounds = [view bounds]; 1453 NSRect frameInWindow = [view convertRect:viewBounds toView:nil]; 1454 rect = [[view window] convertRectToScreen:frameInWindow]; 1455 //Convert coordinates to top-left corner origin 1456 rect = ConvertNSScreenRect(NULL, rect); 1457 1458 }]; 1459 jRect = NSToJavaRect(env, rect); 1460 1461 JNF_COCOA_EXIT(env); 1462 1463 return jRect; 1464 } 1465 1466 /* 1467 * Class: sun_lwawt_macosx_CPlatformView 1468 * Method: nativeIsViewUnderMouse 1469 * Signature: (J)Z; 1470 */ 1471 1472 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformView_nativeIsViewUnderMouse 1473 (JNIEnv *env, jclass clazz, jlong viewPtr) 1474 { 1475 __block jboolean underMouse = JNI_FALSE; 1476 1477 JNF_COCOA_ENTER(env); 1478 1479 NSView *nsView = OBJC(viewPtr); 1480 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1481 NSPoint ptWindowCoords = [[nsView window] mouseLocationOutsideOfEventStream]; 1482 NSPoint ptViewCoords = [nsView convertPoint:ptWindowCoords fromView:nil]; 1483 underMouse = [nsView hitTest:ptViewCoords] != nil; 1484 }]; 1485 1486 JNF_COCOA_EXIT(env); 1487 1488 return underMouse; 1489 }