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