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