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