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