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