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