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