1 /*
   2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import <Cocoa/Cocoa.h>
  27 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  28 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
  29 
  30 #import "sun_lwawt_macosx_CPlatformWindow.h"
  31 #import "com_apple_eawt_event_GestureHandler.h"
  32 #import "com_apple_eawt_FullScreenHandler.h"
  33 
  34 #import "AWTWindow.h"
  35 #import "AWTView.h"
  36 #import "CMenu.h"
  37 #import "CMenuBar.h"
  38 #import "LWCToolkit.h"
  39 #import "GeomUtilities.h"
  40 #import "ThreadUtilities.h"
  41 #import "OSVersion.h"
  42 
  43 
  44 #define MASK(KEY) \
  45     (sun_lwawt_macosx_CPlatformWindow_ ## KEY)
  46 
  47 #define IS(BITS, KEY) \
  48     ((BITS & MASK(KEY)) != 0)
  49 
  50 #define SET(BITS, KEY, VALUE) \
  51     BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)
  52 
  53 
  54 static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
  55 
  56 @interface JavaResizeGrowBoxOverlayWindow : NSWindow { }
  57 
  58 @end
  59 
  60 @implementation JavaResizeGrowBoxOverlayWindow
  61 
  62 - (BOOL) accessibilityIsIgnored
  63 {
  64     return YES;
  65 }
  66 
  67 - (NSArray *)accessibilityChildrenAttribute
  68 {
  69     return nil;
  70 }
  71 @end
  72 
  73 @implementation AWTWindow
  74 
  75 @synthesize javaPlatformWindow;
  76 @synthesize javaMenuBar;
  77 @synthesize growBoxWindow;
  78 @synthesize javaMinSize;
  79 @synthesize javaMaxSize;
  80 @synthesize styleBits;
  81 
  82 - (void) updateMinMaxSize:(BOOL)resizable {
  83     if (resizable) {
  84         [self setMinSize:self.javaMinSize];
  85         [self setMaxSize:self.javaMaxSize];
  86     } else {
  87         NSRect currentFrame = [self frame];
  88         [self setMinSize:currentFrame.size];
  89         [self setMaxSize:currentFrame.size];
  90     }
  91 }
  92 
  93 // creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
  94 + (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
  95     NSUInteger type = 0;
  96     if (IS(styleBits, DECORATED)) {
  97         type |= NSTitledWindowMask;
  98         if (IS(styleBits, CLOSEABLE))   type |= NSClosableWindowMask;
  99         if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;
 100         if (IS(styleBits, RESIZABLE))   type |= NSResizableWindowMask;
 101     } else {
 102         type |= NSBorderlessWindowMask;
 103     }
 104 
 105     if (IS(styleBits, TEXTURED))      type |= NSTexturedBackgroundWindowMask;
 106     if (IS(styleBits, UNIFIED))       type |= NSUnifiedTitleAndToolbarWindowMask;
 107     if (IS(styleBits, UTILITY))       type |= NSUtilityWindowMask;
 108     if (IS(styleBits, HUD))           type |= NSHUDWindowMask;
 109     if (IS(styleBits, SHEET))         type |= NSDocModalWindowMask;
 110     if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
 111 
 112     return type;
 113 }
 114 
 115 // updates _METHOD_PROP_BITMASK based properties on the window
 116 - (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
 117     if (IS(mask, RESIZABLE)) {
 118         BOOL resizable = IS(bits, RESIZABLE);
 119         [self updateMinMaxSize:resizable];
 120         [self setShowsResizeIndicator:resizable];
 121     }
 122 
 123     if (IS(mask, HAS_SHADOW)) {
 124         [self setHasShadow:IS(bits, HAS_SHADOW)];
 125     }
 126 
 127     if (IS(mask, ZOOMABLE)) {
 128         [[self standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
 129     }
 130 
 131     if (IS(mask, ALWAYS_ON_TOP)) {
 132         [self setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
 133     }
 134 
 135     if (IS(mask, HIDES_ON_DEACTIVATE)) {
 136         [self setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
 137     }
 138 
 139     if (IS(mask, DRAGGABLE_BACKGROUND)) {
 140         [self setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
 141     }
 142 
 143     if (IS(mask, DOCUMENT_MODIFIED)) {
 144         [self setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
 145     }
 146 
 147     if ([self respondsToSelector:@selector(toggleFullScreen:)]) {
 148         if (IS(mask, FULLSCREENABLE)) {
 149             [self setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
 150         } else {
 151             [self setCollectionBehavior:NSWindowCollectionBehaviorDefault];
 152         }
 153     }
 154 
 155 }
 156 
 157 - (BOOL) shouldShowGrowBox {
 158     return isSnowLeopardOrLower() && IS(self.styleBits, RESIZABLE);
 159 }
 160 
 161 - (NSImage *) createGrowBoxImage {
 162     NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(12, 12)];
 163     JRSUIControlRef growBoxWidget = JRSUIControlCreate(FALSE);
 164     JRSUIControlSetWidget(growBoxWidget, kJRSUI_Widget_growBoxTextured);
 165     JRSUIControlSetWindowType(growBoxWidget, kJRSUI_WindowType_utility);
 166     JRSUIRendererRef renderer = JRSUIRendererCreate();
 167     [image lockFocus]; // sets current graphics context to that of the image
 168     JRSUIControlDraw(renderer, growBoxWidget, [[NSGraphicsContext currentContext] graphicsPort], CGRectMake(0, 1, 11, 11));
 169     [image unlockFocus];
 170     JRSUIRendererRelease(renderer);
 171     JRSUIControlRelease(growBoxWidget);
 172     return image;
 173 }
 174 
 175 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
 176                     styleBits:(jint)bits
 177                     frameRect:(NSRect)rect
 178                   contentView:(NSView *)view
 179 {
 180 AWT_ASSERT_APPKIT_THREAD;
 181 
 182     NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
 183     NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
 184     if (contentRect.size.width <= 0.0) {
 185         contentRect.size.width = 1.0;
 186     }
 187     if (contentRect.size.height <= 0.0) {
 188         contentRect.size.height = 1.0;
 189     }
 190 
 191     self = [super initWithContentRect:contentRect
 192                             styleMask:styleMask
 193                               backing:NSBackingStoreBuffered
 194                                 defer:NO];
 195 
 196     if (self == nil) return nil; // no hope
 197 
 198     self.javaPlatformWindow = platformWindow;
 199     self.styleBits = bits;
 200     [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
 201 
 202     [self setDelegate:self];
 203     [self setContentView:view];
 204     [self setInitialFirstResponder:view];
 205     [self setReleasedWhenClosed:NO];
 206     [self setPreservesContentDuringLiveResize:YES];
 207 
 208     if ([self shouldShowGrowBox]) {
 209         NSImage *growBoxImage = [self createGrowBoxImage];
 210         growBoxWindow = [[JavaResizeGrowBoxOverlayWindow alloc] initWithContentRect:NSMakeRect(0, 0, [growBoxImage size].width, [growBoxImage size].height) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
 211         [self.growBoxWindow setIgnoresMouseEvents:YES];
 212         [self.growBoxWindow setOpaque:NO];
 213         [self.growBoxWindow setBackgroundColor:[NSColor clearColor]];
 214         [self.growBoxWindow setHasShadow:NO];
 215         [self.growBoxWindow setReleasedWhenClosed:NO];
 216 
 217         NSImageView *imageView = [[NSImageView alloc] initWithFrame:[self.growBoxWindow frame]];
 218         [imageView setEditable:NO];
 219         [imageView setAnimates:NO];
 220         [imageView setAllowsCutCopyPaste:NO];
 221         [self.growBoxWindow setContentView:imageView];
 222         [imageView setImage:growBoxImage];
 223         [growBoxImage release];
 224         [imageView release];
 225 
 226         [self addChildWindow:self.growBoxWindow ordered:NSWindowAbove];
 227         [self adjustGrowBoxWindow];
 228     } else growBoxWindow = nil;
 229 
 230     return self;
 231 }
 232 
 233 - (BOOL) isTopmostWindowUnderMouse {
 234     
 235     int currentWinID = [self windowNumber]; 
 236     
 237     NSRect screenRect = [[NSScreen mainScreen] frame];    
 238     NSPoint nsMouseLocation = [NSEvent mouseLocation];
 239     CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);    
 240     
 241     NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
 242     
 243     
 244     for (NSDictionary *window in windows) {
 245         int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
 246         if (layer == 0) {
 247             int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];            
 248             CGRect rect;
 249             CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
 250             if (CGRectContainsPoint(rect, cgMouseLocation)) {
 251                 return currentWinID == winID;
 252             } else if (currentWinID == winID) {
 253                 return NO;
 254             }
 255         }
 256     }
 257     return NO;
 258 }
 259 
 260 - (void) synthesizeMouseEnteredExitedEvents {
 261     
 262     int eventType = 0;
 263     BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
 264     BOOL mouseIsOver = [[self contentView] mouseIsOver];
 265     
 266     if (isUnderMouse && !mouseIsOver) {
 267         eventType = NSMouseEntered;
 268     } else if (!isUnderMouse && mouseIsOver) {
 269         eventType = NSMouseExited;        
 270     } else {
 271         return;
 272     }
 273     
 274     NSPoint screenLocation = [NSEvent mouseLocation];        
 275     NSPoint windowLocation = [self convertScreenToBase: screenLocation];        
 276     int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
 277     
 278     NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
 279                                                   location: windowLocation
 280                                              modifierFlags: modifierFlags
 281                                                  timestamp: 0
 282                                               windowNumber: [self windowNumber]
 283                                                    context: nil
 284                                                eventNumber: 0
 285                                             trackingNumber: 0
 286                                                   userData: nil
 287                             ];
 288     
 289     [[self contentView] deliverJavaMouseEvent: mouseEvent];
 290 }
 291 
 292 - (void) dealloc {
 293 AWT_ASSERT_APPKIT_THREAD;
 294 
 295     JNIEnv *env = [ThreadUtilities getJNIEnv];
 296     [self.javaPlatformWindow setJObject:nil withEnv:env];
 297     self.growBoxWindow = nil;
 298 
 299     [super dealloc];
 300 }
 301 
 302 
 303 // NSWindow overrides
 304 - (BOOL) canBecomeKeyWindow {
 305 AWT_ASSERT_APPKIT_THREAD;
 306     return IS(self.styleBits, SHOULD_BECOME_KEY);
 307 }
 308 
 309 - (BOOL) canBecomeMainWindow {
 310 AWT_ASSERT_APPKIT_THREAD;
 311     return IS(self.styleBits, SHOULD_BECOME_MAIN);
 312 }
 313 
 314 - (BOOL) worksWhenModal {
 315 AWT_ASSERT_APPKIT_THREAD;
 316     return IS(self.styleBits, MODAL_EXCLUDED);
 317 }
 318 
 319 
 320 // Gesture support
 321 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
 322 AWT_ASSERT_APPKIT_THREAD;
 323 
 324     JNIEnv *env = [ThreadUtilities getJNIEnv];
 325     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 326     if (platformWindow != NULL) {
 327         // extract the target AWT Window object out of the CPlatformWindow
 328         static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
 329         jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
 330         if (awtWindow != NULL) {
 331             // translate the point into Java coordinates
 332             NSPoint loc = [event locationInWindow];
 333             loc.y = [self frame].size.height - loc.y;
 334 
 335             // send up to the GestureHandler to recursively dispatch on the AWT event thread
 336             static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
 337             static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
 338             JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
 339             (*env)->DeleteLocalRef(env, awtWindow);
 340         }
 341         (*env)->DeleteLocalRef(env, platformWindow);
 342     }
 343 }
 344 
 345 - (void)beginGestureWithEvent:(NSEvent *)event {
 346     [self postGesture:event
 347                    as:com_apple_eawt_event_GestureHandler_PHASE
 348                     a:-1.0
 349                     b:0.0];
 350 }
 351 
 352 - (void)endGestureWithEvent:(NSEvent *)event {
 353     [self postGesture:event
 354                    as:com_apple_eawt_event_GestureHandler_PHASE
 355                     a:1.0
 356                     b:0.0];
 357 }
 358 
 359 - (void)magnifyWithEvent:(NSEvent *)event {
 360     [self postGesture:event
 361                    as:com_apple_eawt_event_GestureHandler_MAGNIFY
 362                     a:[event magnification]
 363                     b:0.0];
 364 }
 365 
 366 - (void)rotateWithEvent:(NSEvent *)event {
 367     [self postGesture:event
 368                    as:com_apple_eawt_event_GestureHandler_ROTATE
 369                     a:[event rotation]
 370                     b:0.0];
 371 }
 372 
 373 - (void)swipeWithEvent:(NSEvent *)event {
 374     [self postGesture:event
 375                    as:com_apple_eawt_event_GestureHandler_SWIPE
 376                     a:[event deltaX]
 377                     b:[event deltaY]];
 378 }
 379 
 380 
 381 // NSWindowDelegate methods
 382 
 383 - (void) adjustGrowBoxWindow {
 384     if (self.growBoxWindow != nil) {
 385         NSRect parentRect = [self frame];
 386         parentRect.origin.x += (parentRect.size.width - [self.growBoxWindow frame].size.width);
 387         [self.growBoxWindow setFrameOrigin:parentRect.origin];
 388     }
 389 }
 390 
 391 - (void) _deliverMoveResizeEvent {
 392 AWT_ASSERT_APPKIT_THREAD;
 393 
 394     // deliver the event if this is a user-initiated live resize or as a side-effect
 395     // of a Java initiated resize, because AppKit can override the bounds and force
 396     // the bounds of the window to avoid the Dock or remain on screen.
 397     [AWTToolkit eventCountPlusPlus];
 398     JNIEnv *env = [ThreadUtilities getJNIEnv];
 399     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 400     if (platformWindow == NULL) {
 401         // TODO: create generic AWT assert
 402     }
 403 
 404     [self adjustGrowBoxWindow];
 405 
 406     NSRect frame = ConvertNSScreenRect(env, [self frame]);
 407 
 408     static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V");
 409     JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
 410                       (jint)frame.origin.x,
 411                       (jint)frame.origin.y,
 412                       (jint)frame.size.width,
 413                       (jint)frame.size.height);
 414     (*env)->DeleteLocalRef(env, platformWindow);
 415 }
 416 
 417 - (void)windowDidMove:(NSNotification *)notification {
 418 AWT_ASSERT_APPKIT_THREAD;
 419 
 420     [self _deliverMoveResizeEvent];
 421 }
 422 
 423 - (void)windowDidResize:(NSNotification *)notification {
 424 AWT_ASSERT_APPKIT_THREAD;
 425 
 426     [self _deliverMoveResizeEvent];
 427 }
 428 
 429 - (void)windowDidExpose:(NSNotification *)notification {
 430 AWT_ASSERT_APPKIT_THREAD;
 431 
 432     [AWTToolkit eventCountPlusPlus];
 433     // TODO: don't see this callback invoked anytime so we track
 434     // window exposing in _setVisible:(BOOL)
 435 }
 436 
 437 - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)proposedFrame {
 438 AWT_ASSERT_APPKIT_THREAD;
 439 
 440     [AWTToolkit eventCountPlusPlus];
 441     JNIEnv *env = [ThreadUtilities getJNIEnv];
 442     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 443     if (platformWindow != NULL) {
 444         static JNF_MEMBER_CACHE(jm_deliverZoom, jc_CPlatformWindow, "deliverZoom", "(Z)V");
 445         JNFCallVoidMethod(env, platformWindow, jm_deliverZoom, ![window isZoomed]);
 446         (*env)->DeleteLocalRef(env, platformWindow);
 447     }
 448     return YES;
 449 }
 450 
 451 - (void) _deliverIconify:(BOOL)iconify {
 452 AWT_ASSERT_APPKIT_THREAD;
 453 
 454     [AWTToolkit eventCountPlusPlus];
 455     JNIEnv *env = [ThreadUtilities getJNIEnv];
 456     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 457     if (platformWindow != NULL) {
 458         static JNF_MEMBER_CACHE(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");
 459         JNFCallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);
 460         (*env)->DeleteLocalRef(env, platformWindow);
 461     }
 462 }
 463 
 464 - (void)windowDidMiniaturize:(NSNotification *)notification {
 465 AWT_ASSERT_APPKIT_THREAD;
 466 
 467     [self _deliverIconify:JNI_TRUE];
 468 }
 469 
 470 - (void)windowDidDeminiaturize:(NSNotification *)notification {
 471 AWT_ASSERT_APPKIT_THREAD;
 472 
 473     [self _deliverIconify:JNI_FALSE];
 474 }
 475 
 476 - (void) _deliverWindowFocusEvent:(BOOL)focused {
 477 //AWT_ASSERT_APPKIT_THREAD;
 478 
 479     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 480     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 481     if (platformWindow != NULL) {
 482         static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(Z)V");
 483         JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused);
 484         (*env)->DeleteLocalRef(env, platformWindow);
 485     }
 486 }
 487 
 488 
 489 - (void) windowDidBecomeKey: (NSNotification *) notification {
 490 AWT_ASSERT_APPKIT_THREAD;
 491     [AWTToolkit eventCountPlusPlus];
 492     [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
 493     [self _deliverWindowFocusEvent:YES];
 494 }
 495 
 496 - (void) windowDidResignKey: (NSNotification *) notification {
 497     // TODO: check why sometimes at start is invoked *not* on AppKit main thread.
 498 AWT_ASSERT_APPKIT_THREAD;
 499     [AWTToolkit eventCountPlusPlus];
 500     [self.javaMenuBar deactivate];
 501     [self _deliverWindowFocusEvent:NO];
 502 }
 503 
 504 - (void) windowDidBecomeMain: (NSNotification *) notification {
 505 AWT_ASSERT_APPKIT_THREAD;
 506     [AWTToolkit eventCountPlusPlus];
 507 
 508     JNIEnv *env = [ThreadUtilities getJNIEnv];
 509     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 510     if (platformWindow != NULL) {
 511         static JNF_MEMBER_CACHE(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");
 512         JNFCallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);
 513         (*env)->DeleteLocalRef(env, platformWindow);
 514     }
 515 }
 516 
 517 - (BOOL)windowShouldClose:(id)sender {
 518 AWT_ASSERT_APPKIT_THREAD;
 519     [AWTToolkit eventCountPlusPlus];
 520     JNIEnv *env = [ThreadUtilities getJNIEnv];
 521     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 522     if (platformWindow != NULL) {
 523         static JNF_MEMBER_CACHE(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V");
 524         JNFCallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);
 525         (*env)->DeleteLocalRef(env, platformWindow);
 526     }
 527     // The window will be closed (if allowed) as result of sending Java event
 528     return NO;
 529 }
 530 
 531 
 532 - (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {
 533     static JNF_CLASS_CACHE(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");
 534     static JNF_STATIC_MEMBER_CACHE(jm_notifyFullScreenOperation, jc_FullScreenHandler, "handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");
 535     static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
 536     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 537     if (platformWindow != NULL) {
 538         jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
 539         if (awtWindow != NULL) {
 540             JNFCallStaticVoidMethod(env, jm_notifyFullScreenOperation, awtWindow, op);
 541             (*env)->DeleteLocalRef(env, awtWindow);
 542         }
 543         (*env)->DeleteLocalRef(env, platformWindow);
 544     }
 545 }
 546 
 547 
 548 - (void)windowWillEnterFullScreen:(NSNotification *)notification {
 549     static JNF_MEMBER_CACHE(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
 550     JNIEnv *env = [ThreadUtilities getJNIEnv];
 551     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 552     if (platformWindow != NULL) {
 553         JNFCallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);
 554         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];
 555         (*env)->DeleteLocalRef(env, platformWindow);
 556     }
 557 }
 558 
 559 - (void)windowDidEnterFullScreen:(NSNotification *)notification {
 560     static JNF_MEMBER_CACHE(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
 561     JNIEnv *env = [ThreadUtilities getJNIEnv];
 562     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 563     if (platformWindow != NULL) {
 564         JNFCallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);
 565         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];
 566         (*env)->DeleteLocalRef(env, platformWindow);
 567     }
 568 }
 569 
 570 - (void)windowWillExitFullScreen:(NSNotification *)notification {
 571     static JNF_MEMBER_CACHE(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
 572     JNIEnv *env = [ThreadUtilities getJNIEnv];
 573     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 574     if (platformWindow != NULL) {
 575         JNFCallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);
 576         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
 577         (*env)->DeleteLocalRef(env, platformWindow);
 578     }
 579 }
 580 
 581 - (void)windowDidExitFullScreen:(NSNotification *)notification {
 582     static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
 583     JNIEnv *env = [ThreadUtilities getJNIEnv];
 584     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 585     if (platformWindow != NULL) {
 586         JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
 587         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
 588         (*env)->DeleteLocalRef(env, platformWindow);
 589     }
 590 }
 591 
 592 - (void)sendEvent:(NSEvent *)event {
 593         if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
 594 
 595             NSPoint p = [NSEvent mouseLocation];
 596             NSRect frame = [self frame];
 597             NSRect contentRect = [self contentRectForFrameRect:frame];
 598 
 599             // Check if the click happened in the non-client area (title bar)
 600             if (p.y >= (frame.origin.y + contentRect.size.height)) {
 601                 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 602                 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 603                 // Currently, no need to deliver the whole NSEvent.
 604                 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
 605                 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
 606             }
 607         }
 608         [super sendEvent:event];
 609 }
 610 @end // AWTWindow
 611 
 612 
 613 /*
 614  * Class:     sun_lwawt_macosx_CPlatformWindow
 615  * Method:    nativeCreateNSWindow
 616  * Signature: (JJIIII)J
 617  */
 618 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
 619 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
 620 {
 621     __block AWTWindow *window = nil;
 622 
 623 JNF_COCOA_ENTER(env);
 624 AWT_ASSERT_NOT_APPKIT_THREAD;
 625 
 626     JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
 627     NSView *contentView = OBJC(contentViewPtr);
 628     NSRect frameRect = NSMakeRect(x, y, w, h);
 629 
 630     [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
 631         AWT_ASSERT_APPKIT_THREAD;
 632 
 633         window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
 634                                                   styleBits:styleBits
 635                                                   frameRect:frameRect
 636                                                 contentView:contentView];
 637 
 638         if (window) CFRetain(window);
 639         [window release]; // GC
 640     }];
 641 
 642 JNF_COCOA_EXIT(env);
 643 
 644     return ptr_to_jlong(window);
 645 }
 646 
 647 /*
 648  * Class:     sun_lwawt_macosx_CPlatformWindow
 649  * Method:    nativeSetNSWindowStyleBits
 650  * Signature: (JII)V
 651  */
 652 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
 653 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
 654 {
 655 JNF_COCOA_ENTER(env);
 656 AWT_ASSERT_NOT_APPKIT_THREAD;
 657 
 658     AWTWindow *window = OBJC(windowPtr);
 659     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 660         AWT_ASSERT_APPKIT_THREAD;
 661 
 662         // scans the bit field, and only updates the values requested by the mask
 663         // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
 664         jint newBits = window.styleBits & ~mask | bits & mask;
 665 
 666         // resets the NSWindow's style mask if the mask intersects any of those bits
 667         if (mask & MASK(_STYLE_PROP_BITMASK)) {
 668             [window setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
 669         }
 670 
 671         // calls methods on NSWindow to change other properties, based on the mask
 672         if (mask & MASK(_METHOD_PROP_BITMASK)) {
 673             [window setPropertiesForStyleBits:bits mask:mask];
 674         }
 675 
 676         window.styleBits = newBits;
 677     }];
 678 
 679 JNF_COCOA_EXIT(env);
 680 }
 681 
 682 /*
 683  * Class:     sun_lwawt_macosx_CPlatformWindow
 684  * Method:    nativeSetNSWindowMenuBar
 685  * Signature: (JJ)V
 686  */
 687 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
 688 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
 689 {
 690 JNF_COCOA_ENTER(env);
 691 AWT_ASSERT_NOT_APPKIT_THREAD;
 692 
 693     AWTWindow *window = OBJC(windowPtr);
 694     CMenuBar *menuBar = OBJC(menuBarPtr);
 695     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 696         AWT_ASSERT_APPKIT_THREAD;
 697 
 698         if ([window isKeyWindow]) [window.javaMenuBar deactivate];
 699         window.javaMenuBar = menuBar;
 700 
 701         // if ([self isKeyWindow]) {
 702         [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
 703         // }
 704     }];
 705 
 706 JNF_COCOA_EXIT(env);
 707 }
 708 
 709 /*
 710  * Class:     sun_lwawt_macosx_CPlatformWindow
 711  * Method:    nativeGetNSWindowInsets
 712  * Signature: (J)Ljava/awt/Insets;
 713  */
 714 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
 715 (JNIEnv *env, jclass clazz, jlong windowPtr)
 716 {
 717     jobject ret = NULL;
 718 
 719 JNF_COCOA_ENTER(env);
 720 AWT_ASSERT_NOT_APPKIT_THREAD;
 721 
 722     AWTWindow *window = OBJC(windowPtr);
 723     __block NSRect contentRect = NSZeroRect;
 724     __block NSRect frame = NSZeroRect;
 725 
 726     [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
 727         AWT_ASSERT_APPKIT_THREAD;
 728 
 729         frame = [window frame];
 730         contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[window styleMask]];
 731     }];
 732 
 733     jint top = (jint)(frame.size.height - contentRect.size.height);
 734     jint left = (jint)(contentRect.origin.x - frame.origin.x);
 735     jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
 736     jint right = (jint)(frame.size.width - (contentRect.size.width + left));
 737 
 738     static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
 739     static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
 740     ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
 741 
 742 JNF_COCOA_EXIT(env);
 743     return ret;
 744 }
 745 
 746 /*
 747  * Class:     sun_lwawt_macosx_CPlatformWindow
 748  * Method:    nativeSetNSWindowBounds
 749  * Signature: (JDDDD)V
 750  */
 751 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
 752 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
 753 {
 754 JNF_COCOA_ENTER(env);
 755 AWT_ASSERT_NOT_APPKIT_THREAD;
 756 
 757     NSRect jrect = NSMakeRect(originX, originY, width, height);
 758 
 759     // TODO: not sure we need displayIfNeeded message in our view
 760     AWTWindow *window = OBJC(windowPtr);
 761     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 762         AWT_ASSERT_APPKIT_THREAD;
 763 
 764         NSRect rect = ConvertNSScreenRect(NULL, jrect);
 765         [window setFrame:rect display:YES];
 766 
 767         // only start tracking events if pointer is above the toplevel
 768         // TODO: should post an Entered event if YES.
 769         NSPoint mLocation = [NSEvent mouseLocation];
 770         [window setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
 771 
 772         // ensure we repaint the whole window after the resize operation
 773         // (this will also re-enable screen updates, which were disabled above)
 774         // TODO: send PaintEvent
 775         
 776         [window synthesizeMouseEnteredExitedEvents];
 777     }];
 778 
 779 JNF_COCOA_EXIT(env);
 780 }
 781 
 782 /*
 783  * Class:     sun_lwawt_macosx_CPlatformWindow
 784  * Method:    nativeSetNSWindowMinMax
 785  * Signature: (JDDDD)V
 786  */
 787 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
 788 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
 789 {
 790 JNF_COCOA_ENTER(env);
 791 AWT_ASSERT_NOT_APPKIT_THREAD;
 792 
 793     if (minW < 1) minW = 1;
 794     if (minH < 1) minH = 1;
 795     if (maxW < 1) maxW = 1;
 796     if (maxH < 1) maxH = 1;
 797 
 798     NSSize min = { minW, minH };
 799     NSSize max = { maxW, maxH };
 800 
 801     AWTWindow *window = OBJC(windowPtr);
 802     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 803         AWT_ASSERT_APPKIT_THREAD;
 804 
 805         window.javaMinSize = min;
 806         window.javaMaxSize = max;
 807         [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
 808     }];
 809 
 810 JNF_COCOA_EXIT(env);
 811 }
 812 
 813 /*
 814  * Class:     sun_lwawt_macosx_CPlatformWindow
 815  * Method:    nativePushNSWindowToBack
 816  * Signature: (J)V
 817  */
 818 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
 819 (JNIEnv *env, jclass clazz, jlong windowPtr)
 820 {
 821 JNF_COCOA_ENTER(env);
 822 AWT_ASSERT_NOT_APPKIT_THREAD;
 823 
 824     AWTWindow *window = OBJC(windowPtr);
 825     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 826         AWT_ASSERT_APPKIT_THREAD;
 827 
 828         [window orderBack:nil];
 829     }];
 830 
 831 JNF_COCOA_EXIT(env);
 832 }
 833 
 834 /*
 835  * Class:     sun_lwawt_macosx_CPlatformWindow
 836  * Method:    nativePushNSWindowToFront
 837  * Signature: (J)V
 838  */
 839 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
 840 (JNIEnv *env, jclass clazz, jlong windowPtr)
 841 {
 842 JNF_COCOA_ENTER(env);
 843 AWT_ASSERT_NOT_APPKIT_THREAD;
 844 
 845     AWTWindow *window = OBJC(windowPtr);
 846     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 847         AWT_ASSERT_APPKIT_THREAD;
 848 
 849         if (![window isKeyWindow]) {
 850             [window makeKeyAndOrderFront:window];
 851         } else {
 852             [window orderFront:window];
 853         }
 854     }];
 855 
 856 JNF_COCOA_EXIT(env);
 857 }
 858 
 859 /*
 860  * Class:     sun_lwawt_macosx_CPlatformWindow
 861  * Method:    nativeSetNSWindowTitle
 862  * Signature: (JLjava/lang/String;)V
 863  */
 864 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
 865 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
 866 {
 867 JNF_COCOA_ENTER(env);
 868 AWT_ASSERT_NOT_APPKIT_THREAD;
 869 
 870     AWTWindow *window = OBJC(windowPtr);
 871     [window performSelectorOnMainThread:@selector(setTitle:)
 872                               withObject:JNFJavaToNSString(env, jtitle)
 873                            waitUntilDone:NO];
 874 
 875 JNF_COCOA_EXIT(env);
 876 }
 877 
 878 /*
 879  * Class:     sun_lwawt_macosx_CPlatformWindow
 880  * Method:    nativeSetNSWindowAlpha
 881  * Signature: (JF)V
 882  */
 883 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowAlpha
 884 (JNIEnv *env, jclass clazz, jlong windowPtr, jfloat alpha)
 885 {
 886 JNF_COCOA_ENTER(env);
 887 AWT_ASSERT_NOT_APPKIT_THREAD;
 888 
 889     AWTWindow *window = OBJC(windowPtr);
 890     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 891         AWT_ASSERT_APPKIT_THREAD;
 892 
 893         [window setAlphaValue:alpha];
 894         [window.growBoxWindow setAlphaValue:alpha];
 895     }];
 896 
 897 JNF_COCOA_EXIT(env);
 898 }
 899 
 900 /*
 901  * Class:     sun_lwawt_macosx_CPlatformWindow
 902  * Method:    nativeRevalidateNSWindowShadow
 903  * Signature: (J)V
 904  */
 905 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
 906 (JNIEnv *env, jclass clazz, jlong windowPtr)
 907 {
 908 JNF_COCOA_ENTER(env);
 909 AWT_ASSERT_NOT_APPKIT_THREAD;
 910 
 911     AWTWindow *window = OBJC(windowPtr);
 912     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 913         AWT_ASSERT_APPKIT_THREAD;
 914 
 915         [window invalidateShadow];
 916     }];
 917 
 918 JNF_COCOA_EXIT(env);
 919 }
 920 
 921 /*
 922  * Class:     sun_lwawt_macosx_CPlatformWindow
 923  * Method:    nativeScreenOn_AppKitThread
 924  * Signature: (J)I
 925  */
 926 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
 927 (JNIEnv *env, jclass clazz, jlong windowPtr)
 928 {
 929     jint ret = 0;
 930 
 931 JNF_COCOA_ENTER(env);
 932 AWT_ASSERT_APPKIT_THREAD;
 933 
 934     AWTWindow *window = OBJC(windowPtr);
 935     NSDictionary *props = [[window screen] deviceDescription];
 936     ret = [[props objectForKey:@"NSScreenNumber"] intValue];
 937 
 938 JNF_COCOA_EXIT(env);
 939 
 940     return ret;
 941 }
 942 
 943 /*
 944  * Class:     sun_lwawt_macosx_CPlatformWindow
 945  * Method:    nativeSetNSWindowMinimizedIcon
 946  * Signature: (JJ)V
 947  */
 948 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
 949 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
 950 {
 951 JNF_COCOA_ENTER(env);
 952 AWT_ASSERT_NOT_APPKIT_THREAD;
 953 
 954     AWTWindow *window = OBJC(windowPtr);
 955     NSImage *image = OBJC(nsImagePtr);
 956     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 957         AWT_ASSERT_APPKIT_THREAD;
 958 
 959         [window setMiniwindowImage:image];
 960     }];
 961 
 962 JNF_COCOA_EXIT(env);
 963 }
 964 
 965 /*
 966  * Class:     sun_lwawt_macosx_CPlatformWindow
 967  * Method:    nativeSetNSWindowRepresentedFilename
 968  * Signature: (JLjava/lang/String;)V
 969  */
 970 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
 971 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
 972 {
 973 JNF_COCOA_ENTER(env);
 974 AWT_ASSERT_NOT_APPKIT_THREAD;
 975 
 976     AWTWindow *window = OBJC(windowPtr);
 977     NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
 978     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
 979         AWT_ASSERT_APPKIT_THREAD;
 980 
 981         [window setRepresentedURL:url];
 982     }];
 983 
 984 JNF_COCOA_EXIT(env);
 985 }
 986 
 987 /*
 988  * Class:     sun_lwawt_macosx_CPlatformWindow
 989  * Method:    nativeSetNSWindowSecurityWarningPositioning
 990  * Signature: (JDDFF)V
 991  */
 992 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowSecurityWarningPositioning
 993 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble x, jdouble y, jfloat biasX, jfloat biasY)
 994 {
 995 JNF_COCOA_ENTER(env);
 996 AWT_ASSERT_NOT_APPKIT_THREAD;
 997 
 998     [JNFException raise:env as:kRuntimeException reason:"unimplemented"];
 999 
1000 JNF_COCOA_EXIT(env);
1001 }
1002 
1003 /*
1004  * Class:     sun_lwawt_macosx_CPlatformWindow
1005  * Method:    nativeSynthesizeMouseEnteredExitedEvents
1006  * Signature: (J)V
1007  */
1008 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
1009 (JNIEnv *env, jclass clazz, jlong windowPtr)
1010 {
1011     JNF_COCOA_ENTER(env);
1012     AWT_ASSERT_NOT_APPKIT_THREAD;
1013     
1014     AWTWindow *window = OBJC(windowPtr);
1015     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1016         AWT_ASSERT_APPKIT_THREAD;
1017         
1018         [window synthesizeMouseEnteredExitedEvents];
1019     }];
1020     
1021     JNF_COCOA_EXIT(env);
1022 }
1023 
1024 /*
1025  * Class:     sun_lwawt_macosx_CPlatformWindow
1026  * Method:    nativeGetScreenNSWindowIsOn_AppKitThread
1027  * Signature: (J)I
1028  */
1029 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
1030 (JNIEnv *env, jclass clazz, jlong windowPtr)
1031 {
1032     jint index = -1;
1033 
1034 JNF_COCOA_ENTER(env);
1035 AWT_ASSERT_APPKIT_THREAD;
1036 
1037     AWTWindow *window = OBJC(windowPtr);
1038     NSScreen* screen = [window screen];
1039 
1040     //+++gdb NOTE: This is using a linear search of the screens. If it should
1041     //  prove to be a bottleneck, this can definitely be improved. However,
1042     //  many screens should prove to be the exception, rather than the rule.
1043     NSArray* screens = [NSScreen screens];
1044     NSUInteger i;
1045     for (i = 0; i < [screens count]; i++)
1046     {
1047         if ([[screens objectAtIndex:i] isEqualTo:screen])
1048         {
1049             index = i;
1050             break;
1051         }
1052     }
1053 
1054 JNF_COCOA_EXIT(env);
1055     return 1;
1056 }
1057 
1058 
1059 /*
1060  * Class:     sun_lwawt_macosx_CPlatformWindow
1061  * Method:    _toggleFullScreenMode
1062  * Signature: (J)V
1063  */
1064 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1065 (JNIEnv *env, jobject peer, jlong windowPtr)
1066 {
1067 JNF_COCOA_ENTER(env);
1068 
1069     AWTWindow *window = OBJC(windowPtr);
1070     SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1071     if (![window respondsToSelector:toggleFullScreenSelector]) return;
1072 
1073     [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1074         [window performSelector:toggleFullScreenSelector withObject:nil];
1075     }];
1076 
1077 JNF_COCOA_EXIT(env);
1078 }
1079 
1080 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
1081 (JNIEnv *env, jclass clazz, jlong windowPtr)
1082 {
1083     __block jboolean underMouse = JNI_FALSE;
1084 
1085 JNF_COCOA_ENTER(env);
1086 AWT_ASSERT_NOT_APPKIT_THREAD;
1087 
1088     AWTWindow *aWindow = OBJC(windowPtr);
1089     [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
1090         AWT_ASSERT_APPKIT_THREAD;
1091 
1092         NSPoint pt = [aWindow mouseLocationOutsideOfEventStream];
1093         underMouse = [[aWindow contentView] hitTest:pt] != nil;
1094     }];
1095 
1096 JNF_COCOA_EXIT(env);
1097 
1098     return underMouse;
1099 }