annotate src/macosx/native/sun/awt/AWTView.m @ 5236:9189ec1bb33a

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