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