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