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