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