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