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