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