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