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