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