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