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 == 0x0024) || (codePoint == 0x00A3) || 541 (codePoint == 0x00A5) || 542 ((codePoint >= 0x20A3) && (codePoint <= 0x20BF)) || 543 ((codePoint >= 0x3000) && (codePoint <= 0x303F)) || 544 ((codePoint >= 0xFF00) && (codePoint <= 0xFFEF))) { 545 // Code point is in 'CJK Symbols and Punctuation' or 546 // 'Halfwidth and Fullwidth Forms' Unicode block or 547 // currency symbols unicode 548 return YES; 549 } 550 return NO; 551 } 552 553 -(NSMutableString *) parseString : (id) complexString { 554 if ([complexString isKindOfClass:[NSString class]]) { 555 return [complexString mutableCopy]; 556 } 557 else { 558 return [complexString mutableString]; 559 } 560 } 561 562 // NSAccessibility support 563 - (jobject)awtComponent:(JNIEnv*)env 564 { 565 static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); 566 static JNF_MEMBER_CACHE(jf_Peer, jc_CPlatformView, "peer", "Lsun/lwawt/LWWindowPeer;"); 567 if ((env == NULL) || (m_cPlatformView == NULL)) { 568 NSLog(@"Apple AWT : Error AWTView:awtComponent given bad parameters."); 569 if (env != NULL) 570 { 571 JNFDumpJavaStack(env); 572 } 573 return NULL; 574 } 575 576 jobject peer = NULL; 577 jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); 578 if (!(*env)->IsSameObject(env, jlocal, NULL)) { 579 peer = JNFGetObjectField(env, jlocal, jf_Peer); 580 (*env)->DeleteLocalRef(env, jlocal); 581 } 582 static JNF_CLASS_CACHE(jc_LWWindowPeer, "sun/lwawt/LWWindowPeer"); 583 static JNF_MEMBER_CACHE(jf_Target, jc_LWWindowPeer, "target", "Ljava/awt/Component;"); 584 if (peer == NULL) { 585 NSLog(@"Apple AWT : Error AWTView:awtComponent got null peer from CPlatformView"); 586 JNFDumpJavaStack(env); 587 return NULL; 588 } 589 jobject comp = JNFGetObjectField(env, peer, jf_Target); 590 (*env)->DeleteLocalRef(env, peer); 591 return comp; 592 } 593 594 + (AWTView *) awtView:(JNIEnv*)env ofAccessible:(jobject)jaccessible 595 { 596 static JNF_STATIC_MEMBER_CACHE(jm_getAWTView, sjc_CAccessibility, "getAWTView", "(Ljavax/accessibility/Accessible;)J"); 597 598 jlong jptr = JNFCallStaticLongMethod(env, jm_getAWTView, jaccessible); 599 if (jptr == 0) return nil; 600 601 return (AWTView *)jlong_to_ptr(jptr); 602 } 603 604 - (id)getAxData:(JNIEnv*)env 605 { 606 jobject jcomponent = [self awtComponent:env]; 607 id ax = [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease]; 608 (*env)->DeleteLocalRef(env, jcomponent); 609 return ax; 610 } 611 612 - (NSArray *)accessibilityAttributeNames 613 { 614 return [[super accessibilityAttributeNames] arrayByAddingObject:NSAccessibilityChildrenAttribute]; 615 } 616 617 // NSAccessibility messages 618 // attribute methods 619 - (id)accessibilityAttributeValue:(NSString *)attribute 620 { 621 AWT_ASSERT_APPKIT_THREAD; 622 623 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) 624 { 625 JNIEnv *env = [ThreadUtilities getJNIEnv]; 626 627 (*env)->PushLocalFrame(env, 4); 628 629 id result = NSAccessibilityUnignoredChildrenForOnlyChild([self getAxData:env]); 630 631 (*env)->PopLocalFrame(env, NULL); 632 633 return result; 634 } 635 else 636 { 637 return [super accessibilityAttributeValue:attribute]; 638 } 639 } 640 - (BOOL)accessibilityIsIgnored 641 { 642 return YES; 643 } 644 645 - (id)accessibilityHitTest:(NSPoint)point 646 { 647 AWT_ASSERT_APPKIT_THREAD; 648 JNIEnv *env = [ThreadUtilities getJNIEnv]; 649 650 (*env)->PushLocalFrame(env, 4); 651 652 id result = [[self getAxData:env] accessibilityHitTest:point withEnv:env]; 653 654 (*env)->PopLocalFrame(env, NULL); 655 656 return result; 657 } 658 659 - (id)accessibilityFocusedUIElement 660 { 661 AWT_ASSERT_APPKIT_THREAD; 662 663 JNIEnv *env = [ThreadUtilities getJNIEnv]; 664 665 (*env)->PushLocalFrame(env, 4); 666 667 id result = [[self getAxData:env] accessibilityFocusedUIElement]; 668 669 (*env)->PopLocalFrame(env, NULL); 670 671 return result; 672 } 673 674 // --- Services menu support for lightweights --- 675 676 // finds the focused accessible element, and if it is a text element, obtains the text from it 677 - (NSString *)accessibleSelectedText 678 { 679 id focused = [self accessibilityFocusedUIElement]; 680 if (![focused isKindOfClass:[JavaTextAccessibility class]]) return nil; 681 return [(JavaTextAccessibility *)focused accessibilitySelectedTextAttribute]; 682 } 683 684 // same as above, but converts to RTFD 685 - (NSData *)accessibleSelectedTextAsRTFD 686 { 687 NSString *selectedText = [self accessibleSelectedText]; 688 NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; 689 NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) 690 documentAttributes: 691 @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]; 692 [styledText release]; 693 return rtfdData; 694 } 695 696 // finds the focused accessible element, and if it is a text element, sets the text in it 697 - (BOOL)replaceAccessibleTextSelection:(NSString *)text 698 { 699 id focused = [self accessibilityFocusedUIElement]; 700 if (![focused isKindOfClass:[JavaTextAccessibility class]]) return NO; 701 [(JavaTextAccessibility *)focused accessibilitySetSelectedTextAttribute:text]; 702 return YES; 703 } 704 705 // called for each service in the Services menu - only handle text for now 706 - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType 707 { 708 if ([[self window] firstResponder] != self) return nil; // let AWT components handle themselves 709 710 if ([sendType isEqual:NSStringPboardType] || [returnType isEqual:NSStringPboardType]) { 711 NSString *selectedText = [self accessibleSelectedText]; 712 if (selectedText) return self; 713 } 714 715 return nil; 716 } 717 718 // fetch text from Java and hand off to the service 719 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types 720 { 721 if ([types containsObject:NSStringPboardType]) 722 { 723 [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 724 return [pboard setString:[self accessibleSelectedText] forType:NSStringPboardType]; 725 } 726 727 if ([types containsObject:NSRTFDPboardType]) 728 { 729 [pboard declareTypes:[NSArray arrayWithObject:NSRTFDPboardType] owner:nil]; 730 return [pboard setData:[self accessibleSelectedTextAsRTFD] forType:NSRTFDPboardType]; 731 } 732 733 return NO; 734 } 735 736 // write text back to Java from the service 737 - (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard 738 { 739 if ([[pboard types] containsObject:NSStringPboardType]) 740 { 741 NSString *text = [pboard stringForType:NSStringPboardType]; 742 return [self replaceAccessibleTextSelection:text]; 743 } 744 745 if ([[pboard types] containsObject:NSRTFDPboardType]) 746 { 747 NSData *rtfdData = [pboard dataForType:NSRTFDPboardType]; 748 NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:NULL]; 749 NSString *text = [styledText string]; 750 [styledText release]; 751 752 return [self replaceAccessibleTextSelection:text]; 753 } 754 755 return NO; 756 } 757 758 759 -(void) setDragSource:(CDragSource *)source { 760 self._dragSource = source; 761 } 762 763 764 - (void) setDropTarget:(CDropTarget *)target { 765 self._dropTarget = target; 766 [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES]; 767 } 768 769 /******************************** BEGIN NSDraggingSource Interface ********************************/ 770 771 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag 772 { 773 // If draggingSource is nil route the message to the superclass (if responding to the selector): 774 CDragSource *dragSource = self._dragSource; 775 NSDragOperation dragOp = NSDragOperationNone; 776 777 if (dragSource != nil) { 778 dragOp = [dragSource draggingSourceOperationMaskForLocal:flag]; 779 } 780 return dragOp; 781 } 782 783 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination 784 { 785 // If draggingSource is nil route the message to the superclass (if responding to the selector): 786 CDragSource *dragSource = self._dragSource; 787 NSArray* array = nil; 788 789 if (dragSource != nil) { 790 array = [dragSource namesOfPromisedFilesDroppedAtDestination:dropDestination]; 791 } 792 return array; 793 } 794 795 - (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint 796 { 797 // If draggingSource is nil route the message to the superclass (if responding to the selector): 798 CDragSource *dragSource = self._dragSource; 799 800 if (dragSource != nil) { 801 [dragSource draggedImage:image beganAt:screenPoint]; 802 } 803 } 804 805 - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation 806 { 807 // If draggingSource is nil route the message to the superclass (if responding to the selector): 808 CDragSource *dragSource = self._dragSource; 809 810 if (dragSource != nil) { 811 [dragSource draggedImage:image endedAt:screenPoint operation:operation]; 812 } 813 } 814 815 - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint 816 { 817 // If draggingSource is nil route the message to the superclass (if responding to the selector): 818 CDragSource *dragSource = self._dragSource; 819 820 if (dragSource != nil) { 821 [dragSource draggedImage:image movedTo:screenPoint]; 822 } 823 } 824 825 - (BOOL)ignoreModifierKeysWhileDragging 826 { 827 // If draggingSource is nil route the message to the superclass (if responding to the selector): 828 CDragSource *dragSource = self._dragSource; 829 BOOL result = FALSE; 830 831 if (dragSource != nil) { 832 result = [dragSource ignoreModifierKeysWhileDragging]; 833 } 834 return result; 835 } 836 837 /******************************** END NSDraggingSource Interface ********************************/ 838 839 /******************************** BEGIN NSDraggingDestination Interface ********************************/ 840 841 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender 842 { 843 // If draggingDestination is nil route the message to the superclass: 844 CDropTarget *dropTarget = self._dropTarget; 845 NSDragOperation dragOp = NSDragOperationNone; 846 847 if (dropTarget != nil) { 848 dragOp = [dropTarget draggingEntered:sender]; 849 } 850 return dragOp; 851 } 852 853 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender 854 { 855 // If draggingDestination is nil route the message to the superclass: 856 CDropTarget *dropTarget = self._dropTarget; 857 NSDragOperation dragOp = NSDragOperationNone; 858 859 if (dropTarget != nil) { 860 dragOp = [dropTarget draggingUpdated:sender]; 861 } 862 return dragOp; 863 } 864 865 - (void)draggingExited:(id <NSDraggingInfo>)sender 866 { 867 // If draggingDestination is nil route the message to the superclass: 868 CDropTarget *dropTarget = self._dropTarget; 869 870 if (dropTarget != nil) { 871 [dropTarget draggingExited:sender]; 872 } 873 } 874 875 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender 876 { 877 // If draggingDestination is nil route the message to the superclass: 878 CDropTarget *dropTarget = self._dropTarget; 879 BOOL result = FALSE; 880 881 if (dropTarget != nil) { 882 result = [dropTarget prepareForDragOperation:sender]; 883 } 884 return result; 885 } 886 887 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender 888 { 889 // If draggingDestination is nil route the message to the superclass: 890 CDropTarget *dropTarget = self._dropTarget; 891 BOOL result = FALSE; 892 893 if (dropTarget != nil) { 894 result = [dropTarget performDragOperation:sender]; 895 } 896 return result; 897 } 898 899 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender 900 { 901 // If draggingDestination is nil route the message to the superclass: 902 CDropTarget *dropTarget = self._dropTarget; 903 904 if (dropTarget != nil) { 905 [dropTarget concludeDragOperation:sender]; 906 } 907 } 908 909 - (void)draggingEnded:(id <NSDraggingInfo>)sender 910 { 911 // If draggingDestination is nil route the message to the superclass: 912 CDropTarget *dropTarget = self._dropTarget; 913 914 if (dropTarget != nil) { 915 [dropTarget draggingEnded:sender]; 916 } 917 } 918 919 /******************************** END NSDraggingDestination Interface ********************************/ 920 921 /******************************** BEGIN NSTextInputClient Protocol ********************************/ 922 923 924 JNF_CLASS_CACHE(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod"); 925 926 - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange 927 { 928 #ifdef IM_DEBUG 929 fprintf(stderr, "AWTView InputMethod Selector Called : [insertText]: %s\n", [aString UTF8String]); 930 #endif // IM_DEBUG 931 932 if (fInputMethodLOCKABLE == NULL) { 933 return; 934 } 935 936 // Insert happens at the end of PAH 937 fInPressAndHold = NO; 938 939 // insertText gets called when the user commits text generated from an input method. It also gets 940 // called during ordinary input as well. We only need to send an input method event when we have marked 941 // text, or 'text in progress'. We also need to send the event if we get an insert text out of the blue! 942 // (i.e., when the user uses the Character palette or Inkwell), or when the string to insert is a complex 943 // Unicode value. 944 945 NSMutableString * useString = [self parseString:aString]; 946 NSUInteger utf16Length = [useString lengthOfBytesUsingEncoding:NSUTF16StringEncoding]; 947 NSUInteger utf8Length = [useString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 948 BOOL aStringIsComplex = NO; 949 if ((utf16Length > 2) || 950 ((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:[useString characterAtIndex:0]])) { 951 aStringIsComplex = YES; 952 } 953 954 if ([self hasMarkedText] || !fProcessingKeystroke || aStringIsComplex) { 955 JNIEnv *env = [ThreadUtilities getJNIEnv]; 956 957 static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 958 // We need to select the previous glyph so that it is overwritten. 959 if (fPAHNeedsToSelect) { 960 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 961 fPAHNeedsToSelect = NO; 962 } 963 964 static JNF_MEMBER_CACHE(jm_insertText, jc_CInputMethod, "insertText", "(Ljava/lang/String;)V"); 965 jstring insertedText = JNFNSToJavaString(env, useString); 966 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText); // AWT_THREADING Safe (AWTRunLoopMode) 967 (*env)->DeleteLocalRef(env, insertedText); 968 969 // The input method event will create psuedo-key events for each character in the committed string. 970 // We also don't want to send the character that triggered the insertText, usually a return. [3337563] 971 fKeyEventsNeeded = NO; 972 } 973 else { 974 // Need to set back the fKeyEventsNeeded flag so that the string following the 975 // marked text is not ignored by keyDown 976 if ([useString length] > 0) { 977 fKeyEventsNeeded = YES; 978 } 979 } 980 fPAHNeedsToSelect = NO; 981 } 982 983 - (void) doCommandBySelector:(SEL)aSelector 984 { 985 #ifdef IM_DEBUG 986 fprintf(stderr, "AWTView InputMethod Selector Called : [doCommandBySelector]\n"); 987 NSLog(@"%@", NSStringFromSelector(aSelector)); 988 #endif // IM_DEBUG 989 if (@selector(insertNewline:) == aSelector || @selector(insertTab:) == aSelector || @selector(deleteBackward:) == aSelector) 990 { 991 fKeyEventsNeeded = YES; 992 } 993 } 994 995 // setMarkedText: cannot take a nil first argument. aString can be NSString or NSAttributedString 996 - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replacementRange:(NSRange)replacementRange 997 { 998 if (!fInputMethodLOCKABLE) 999 return; 1000 1001 BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]]; 1002 NSAttributedString *attrString = (isAttributedString ? (NSAttributedString *)aString : nil); 1003 NSString *incomingString = (isAttributedString ? [aString string] : aString); 1004 #ifdef IM_DEBUG 1005 fprintf(stderr, "AWTView InputMethod Selector Called : [setMarkedText] \"%s\", loc=%lu, length=%lu\n", [incomingString UTF8String], (unsigned long)selectionRange.location, (unsigned long)selectionRange.length); 1006 #endif // IM_DEBUG 1007 static JNF_MEMBER_CACHE(jm_startIMUpdate, jc_CInputMethod, "startIMUpdate", "(Ljava/lang/String;)V"); 1008 static JNF_MEMBER_CACHE(jm_addAttribute, jc_CInputMethod, "addAttribute", "(ZZII)V"); 1009 static JNF_MEMBER_CACHE(jm_dispatchText, jc_CInputMethod, "dispatchText", "(IIZ)V"); 1010 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1011 1012 // NSInputContext already did the analysis of the TSM event and created attributes indicating 1013 // the underlining and color that should be done to the string. We need to look at the underline 1014 // style and color to determine what kind of Java hilighting needs to be done. 1015 jstring inProcessText = JNFNSToJavaString(env, incomingString); 1016 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_startIMUpdate, inProcessText); // AWT_THREADING Safe (AWTRunLoopMode) 1017 (*env)->DeleteLocalRef(env, inProcessText); 1018 1019 if (isAttributedString) { 1020 NSUInteger length; 1021 NSRange effectiveRange; 1022 NSDictionary *attributes; 1023 length = [attrString length]; 1024 effectiveRange = NSMakeRange(0, 0); 1025 while (NSMaxRange(effectiveRange) < length) { 1026 attributes = [attrString attributesAtIndex:NSMaxRange(effectiveRange) 1027 effectiveRange:&effectiveRange]; 1028 if (attributes) { 1029 BOOL isThickUnderline, isGray; 1030 NSNumber *underlineSizeObj = 1031 (NSNumber *)[attributes objectForKey:NSUnderlineStyleAttributeName]; 1032 NSInteger underlineSize = [underlineSizeObj integerValue]; 1033 isThickUnderline = (underlineSize > 1); 1034 1035 NSColor *underlineColorObj = 1036 (NSColor *)[attributes objectForKey:NSUnderlineColorAttributeName]; 1037 isGray = !([underlineColorObj isEqual:[NSColor blackColor]]); 1038 1039 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_addAttribute, isThickUnderline, isGray, effectiveRange.location, effectiveRange.length); // AWT_THREADING Safe (AWTRunLoopMode) 1040 } 1041 } 1042 } 1043 1044 static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); 1045 // We need to select the previous glyph so that it is overwritten. 1046 if (fPAHNeedsToSelect) { 1047 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); 1048 fPAHNeedsToSelect = NO; 1049 } 1050 1051 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_dispatchText, selectionRange.location, selectionRange.length, JNI_FALSE); // AWT_THREADING Safe (AWTRunLoopMode) 1052 1053 // If the marked text is being cleared (zero-length string) don't handle the key event. 1054 if ([incomingString length] == 0) { 1055 fKeyEventsNeeded = NO; 1056 } 1057 } 1058 1059 - (void) unmarkText 1060 { 1061 #ifdef IM_DEBUG 1062 fprintf(stderr, "AWTView InputMethod Selector Called : [unmarkText]\n"); 1063 #endif // IM_DEBUG 1064 1065 if (!fInputMethodLOCKABLE) { 1066 return; 1067 } 1068 1069 // unmarkText cancels any input in progress and commits it to the text field. 1070 static JNF_MEMBER_CACHE(jm_unmarkText, jc_CInputMethod, "unmarkText", "()V"); 1071 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1072 JNFCallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); // AWT_THREADING Safe (AWTRunLoopMode) 1073 1074 } 1075 1076 - (BOOL) hasMarkedText 1077 { 1078 #ifdef IM_DEBUG 1079 fprintf(stderr, "AWTView InputMethod Selector Called : [hasMarkedText]\n"); 1080 #endif // IM_DEBUG 1081 1082 if (!fInputMethodLOCKABLE) { 1083 return NO; 1084 } 1085 1086 static JNF_MEMBER_CACHE(jf_fCurrentText, jc_CInputMethod, "fCurrentText", "Ljava/text/AttributedString;"); 1087 static JNF_MEMBER_CACHE(jf_fCurrentTextLength, jc_CInputMethod, "fCurrentTextLength", "I"); 1088 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1089 jobject currentText = JNFGetObjectField(env, fInputMethodLOCKABLE, jf_fCurrentText); 1090 1091 jint currentTextLength = JNFGetIntField(env, fInputMethodLOCKABLE, jf_fCurrentTextLength); 1092 1093 BOOL hasMarkedText = (currentText != NULL && currentTextLength > 0); 1094 1095 if (currentText != NULL) { 1096 (*env)->DeleteLocalRef(env, currentText); 1097 } 1098 1099 return hasMarkedText; 1100 } 1101 1102 - (NSInteger) conversationIdentifier 1103 { 1104 #ifdef IM_DEBUG 1105 fprintf(stderr, "AWTView InputMethod Selector Called : [conversationIdentifier]\n"); 1106 #endif // IM_DEBUG 1107 1108 return (NSInteger) self; 1109 } 1110 1111 /* Returns attributed string at the range. This allows input mangers to 1112 query any range in backing-store (Andy's request) 1113 */ 1114 - (NSAttributedString *) attributedSubstringForProposedRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1115 { 1116 #ifdef IM_DEBUG 1117 fprintf(stderr, "AWTView InputMethod Selector Called : [attributedSubstringFromRange] location=%lu, length=%lu\n", (unsigned long)theRange.location, (unsigned long)theRange.length); 1118 #endif // IM_DEBUG 1119 1120 static JNF_MEMBER_CACHE(jm_substringFromRange, jc_CInputMethod, "attributedSubstringFromRange", "(II)Ljava/lang/String;"); 1121 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1122 jobject theString = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_substringFromRange, theRange.location, theRange.length); // AWT_THREADING Safe (AWTRunLoopMode) 1123 1124 id result = [[[NSAttributedString alloc] initWithString:JNFJavaToNSString(env, theString)] autorelease]; 1125 #ifdef IM_DEBUG 1126 NSLog(@"attributedSubstringFromRange returning \"%@\"", result); 1127 #endif // IM_DEBUG 1128 1129 (*env)->DeleteLocalRef(env, theString); 1130 return result; 1131 } 1132 1133 /* This method returns the range for marked region. If hasMarkedText == false, 1134 it'll return NSNotFound location & 0 length range. 1135 */ 1136 - (NSRange) markedRange 1137 { 1138 1139 #ifdef IM_DEBUG 1140 fprintf(stderr, "AWTView InputMethod Selector Called : [markedRange]\n"); 1141 #endif // IM_DEBUG 1142 1143 if (!fInputMethodLOCKABLE) { 1144 return NSMakeRange(NSNotFound, 0); 1145 } 1146 1147 static JNF_MEMBER_CACHE(jm_markedRange, jc_CInputMethod, "markedRange", "()[I"); 1148 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1149 jarray array; 1150 jboolean isCopy; 1151 jint *_array; 1152 NSRange range = NSMakeRange(NSNotFound, 0); 1153 1154 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_markedRange); // AWT_THREADING Safe (AWTRunLoopMode) 1155 1156 if (array) { 1157 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1158 if (_array != NULL) { 1159 range.location = _array[0]; 1160 range.length = _array[1]; 1161 #ifdef IM_DEBUG 1162 fprintf(stderr, "markedRange returning (%lu, %lu)\n", 1163 (unsigned long)range.location, (unsigned long)range.length); 1164 #endif // IM_DEBUG 1165 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1166 } 1167 (*env)->DeleteLocalRef(env, array); 1168 } 1169 1170 return range; 1171 } 1172 1173 /* This method returns the range for selected region. Just like markedRange method, 1174 its location field contains char index from the text beginning. 1175 */ 1176 - (NSRange) selectedRange 1177 { 1178 if (!fInputMethodLOCKABLE) { 1179 return NSMakeRange(NSNotFound, 0); 1180 } 1181 1182 static JNF_MEMBER_CACHE(jm_selectedRange, jc_CInputMethod, "selectedRange", "()[I"); 1183 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1184 jarray array; 1185 jboolean isCopy; 1186 jint *_array; 1187 NSRange range = NSMakeRange(NSNotFound, 0); 1188 1189 #ifdef IM_DEBUG 1190 fprintf(stderr, "AWTView InputMethod Selector Called : [selectedRange]\n"); 1191 #endif // IM_DEBUG 1192 1193 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_selectedRange); // AWT_THREADING Safe (AWTRunLoopMode) 1194 if (array) { 1195 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1196 if (_array != NULL) { 1197 range.location = _array[0]; 1198 range.length = _array[1]; 1199 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1200 } 1201 (*env)->DeleteLocalRef(env, array); 1202 } 1203 1204 return range; 1205 } 1206 1207 /* This method returns the first frame of rects for theRange in screen coordindate system. 1208 */ 1209 - (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange 1210 { 1211 if (!fInputMethodLOCKABLE) { 1212 return NSZeroRect; 1213 } 1214 1215 static JNF_MEMBER_CACHE(jm_firstRectForCharacterRange, jc_CInputMethod, 1216 "firstRectForCharacterRange", "(I)[I"); 1217 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1218 jarray array; 1219 jboolean isCopy; 1220 jint *_array; 1221 NSRect rect; 1222 1223 #ifdef IM_DEBUG 1224 fprintf(stderr, 1225 "AWTView InputMethod Selector Called : [firstRectForCharacterRange:] location=%lu, length=%lu\n", 1226 (unsigned long)theRange.location, (unsigned long)theRange.length); 1227 #endif // IM_DEBUG 1228 1229 array = JNFCallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange, 1230 theRange.location); // AWT_THREADING Safe (AWTRunLoopMode) 1231 1232 _array = (*env)->GetIntArrayElements(env, array, &isCopy); 1233 if (_array) { 1234 rect = ConvertNSScreenRect(env, NSMakeRect(_array[0], _array[1], _array[2], _array[3])); 1235 (*env)->ReleaseIntArrayElements(env, array, _array, 0); 1236 } else { 1237 rect = NSZeroRect; 1238 } 1239 (*env)->DeleteLocalRef(env, array); 1240 1241 #ifdef IM_DEBUG 1242 fprintf(stderr, 1243 "firstRectForCharacterRange returning x=%f, y=%f, width=%f, height=%f\n", 1244 rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); 1245 #endif // IM_DEBUG 1246 return rect; 1247 } 1248 1249 /* This method returns the index for character that is nearest to thePoint. thPoint is in 1250 screen coordinate system. 1251 */ 1252 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint 1253 { 1254 if (!fInputMethodLOCKABLE) { 1255 return NSNotFound; 1256 } 1257 1258 static JNF_MEMBER_CACHE(jm_characterIndexForPoint, jc_CInputMethod, 1259 "characterIndexForPoint", "(II)I"); 1260 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1261 1262 NSPoint flippedLocation = ConvertNSScreenPoint(env, thePoint); 1263 1264 #ifdef IM_DEBUG 1265 fprintf(stderr, "AWTView InputMethod Selector Called : [characterIndexForPoint:(NSPoint)thePoint] x=%f, y=%f\n", flippedLocation.x, flippedLocation.y); 1266 #endif // IM_DEBUG 1267 1268 jint index = JNFCallIntMethod(env, fInputMethodLOCKABLE, jm_characterIndexForPoint, (jint)flippedLocation.x, (jint)flippedLocation.y); // AWT_THREADING Safe (AWTRunLoopMode) 1269 1270 #ifdef IM_DEBUG 1271 fprintf(stderr, "characterIndexForPoint returning %ld\n", index); 1272 #endif // IM_DEBUG 1273 1274 if (index == -1) { 1275 return NSNotFound; 1276 } else { 1277 return (NSUInteger)index; 1278 } 1279 } 1280 1281 - (NSArray*) validAttributesForMarkedText 1282 { 1283 #ifdef IM_DEBUG 1284 fprintf(stderr, "AWTView InputMethod Selector Called : [validAttributesForMarkedText]\n"); 1285 #endif // IM_DEBUG 1286 1287 return [NSArray array]; 1288 } 1289 1290 - (void)setInputMethod:(jobject)inputMethod 1291 { 1292 #ifdef IM_DEBUG 1293 fprintf(stderr, "AWTView InputMethod Selector Called : [setInputMethod]\n"); 1294 #endif // IM_DEBUG 1295 1296 JNIEnv *env = [ThreadUtilities getJNIEnv]; 1297 1298 // Get rid of the old one 1299 if (fInputMethodLOCKABLE) { 1300 JNFDeleteGlobalRef(env, fInputMethodLOCKABLE); 1301 } 1302 1303 // Save a global ref to the new input method. 1304 if (inputMethod != NULL) 1305 fInputMethodLOCKABLE = JNFNewGlobalRef(env, inputMethod); 1306 else 1307 fInputMethodLOCKABLE = NULL; 1308 } 1309 1310 - (void)abandonInput 1311 { 1312 #ifdef IM_DEBUG 1313 fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); 1314 #endif // IM_DEBUG 1315 1316 [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; 1317 [self unmarkText]; 1318 } 1319 1320 /******************************** END NSTextInputClient Protocol ********************************/ 1321 1322 1323 1324 1325 @end // AWTView 1326 1327 /* 1328 * Class: sun_lwawt_macosx_CPlatformView 1329 * Method: nativeCreateView 1330 * Signature: (IIII)J 1331 */ 1332 JNIEXPORT jlong JNICALL 1333 Java_sun_lwawt_macosx_CPlatformView_nativeCreateView 1334 (JNIEnv *env, jobject obj, jint originX, jint originY, jint width, jint height, jlong windowLayerPtr) 1335 { 1336 __block AWTView *newView = nil; 1337 1338 JNF_COCOA_ENTER(env); 1339 1340 NSRect rect = NSMakeRect(originX, originY, width, height); 1341 jobject cPlatformView = (*env)->NewWeakGlobalRef(env, obj); 1342 1343 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1344 1345 CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); 1346 newView = [[AWTView alloc] initWithRect:rect 1347 platformView:cPlatformView 1348 windowLayer:windowLayer]; 1349 }]; 1350 1351 JNF_COCOA_EXIT(env); 1352 1353 return ptr_to_jlong(newView); 1354 } 1355 1356 /* 1357 * Class: sun_lwawt_macosx_CPlatformView 1358 * Method: nativeSetAutoResizable 1359 * Signature: (JZ)V; 1360 */ 1361 1362 JNIEXPORT void JNICALL 1363 Java_sun_lwawt_macosx_CPlatformView_nativeSetAutoResizable 1364 (JNIEnv *env, jclass cls, jlong viewPtr, jboolean toResize) 1365 { 1366 JNF_COCOA_ENTER(env); 1367 1368 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1369 1370 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 1371 1372 if (toResize) { 1373 [view setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; 1374 } else { 1375 [view setAutoresizingMask: NSViewMinYMargin | NSViewMaxXMargin]; 1376 } 1377 1378 if ([view superview] != nil) { 1379 [[view superview] setAutoresizesSubviews:(BOOL)toResize]; 1380 } 1381 1382 }]; 1383 JNF_COCOA_EXIT(env); 1384 } 1385 1386 /* 1387 * Class: sun_lwawt_macosx_CPlatformView 1388 * Method: nativeGetNSViewDisplayID 1389 * Signature: (J)I; 1390 */ 1391 1392 JNIEXPORT jint JNICALL 1393 Java_sun_lwawt_macosx_CPlatformView_nativeGetNSViewDisplayID 1394 (JNIEnv *env, jclass cls, jlong viewPtr) 1395 { 1396 __block jint ret; //CGDirectDisplayID 1397 1398 JNF_COCOA_ENTER(env); 1399 1400 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1401 NSWindow *window = [view window]; 1402 1403 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1404 1405 ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; 1406 }]; 1407 1408 JNF_COCOA_EXIT(env); 1409 1410 return ret; 1411 } 1412 1413 /* 1414 * Class: sun_lwawt_macosx_CPlatformView 1415 * Method: nativeGetLocationOnScreen 1416 * Signature: (J)Ljava/awt/Rectangle; 1417 */ 1418 1419 JNIEXPORT jobject JNICALL 1420 Java_sun_lwawt_macosx_CPlatformView_nativeGetLocationOnScreen 1421 (JNIEnv *env, jclass cls, jlong viewPtr) 1422 { 1423 jobject jRect = NULL; 1424 1425 JNF_COCOA_ENTER(env); 1426 1427 __block NSRect rect = NSZeroRect; 1428 1429 NSView *view = (NSView *)jlong_to_ptr(viewPtr); 1430 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1431 1432 NSRect viewBounds = [view bounds]; 1433 NSRect frameInWindow = [view convertRect:viewBounds toView:nil]; 1434 rect = [[view window] convertRectToScreen:frameInWindow]; 1435 //Convert coordinates to top-left corner origin 1436 rect = ConvertNSScreenRect(NULL, rect); 1437 1438 }]; 1439 jRect = NSToJavaRect(env, rect); 1440 1441 JNF_COCOA_EXIT(env); 1442 1443 return jRect; 1444 } 1445 1446 /* 1447 * Class: sun_lwawt_macosx_CPlatformView 1448 * Method: nativeIsViewUnderMouse 1449 * Signature: (J)Z; 1450 */ 1451 1452 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformView_nativeIsViewUnderMouse 1453 (JNIEnv *env, jclass clazz, jlong viewPtr) 1454 { 1455 __block jboolean underMouse = JNI_FALSE; 1456 1457 JNF_COCOA_ENTER(env); 1458 1459 NSView *nsView = OBJC(viewPtr); 1460 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 1461 NSPoint ptWindowCoords = [[nsView window] mouseLocationOutsideOfEventStream]; 1462 NSPoint ptViewCoords = [nsView convertPoint:ptWindowCoords fromView:nil]; 1463 underMouse = [nsView hitTest:ptViewCoords] != nil; 1464 }]; 1465 1466 JNF_COCOA_EXIT(env); 1467 1468 return underMouse; 1469 }