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