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