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