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