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