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