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