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