1 /*
   2  * Copyright (c) 2011, 2014, 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 #import "ApplicationDelegate.h"
  34 
  35 #import "AWTWindow.h"
  36 #import "AWTView.h"
  37 #import "CMenu.h"
  38 #import "CMenuBar.h"
  39 #import "LWCToolkit.h"
  40 #import "GeomUtilities.h"
  41 #import "ThreadUtilities.h"
  42 #import "OSVersion.h"
  43 
  44 static const float GROW_BOX_SIZE = 12.f;
  45 
  46 #define MASK(KEY) \
  47     (sun_lwawt_macosx_CPlatformWindow_ ## KEY)
  48 
  49 #define IS(BITS, KEY) \
  50     ((BITS & MASK(KEY)) != 0)
  51 
  52 #define SET(BITS, KEY, VALUE) \
  53     BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)
  54 
  55 static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
  56 
  57 @interface JavaResizeGrowBoxOverlayWindow : NSWindow { }
  58 
  59 @end
  60 
  61 @implementation JavaResizeGrowBoxOverlayWindow
  62 
  63 - (BOOL) accessibilityIsIgnored
  64 {
  65     return YES;
  66 }
  67 
  68 - (NSArray *)accessibilityChildrenAttribute
  69 {
  70     return nil;
  71 }
  72 @end
  73 
  74 // Cocoa windowDidBecomeKey/windowDidResignKey notifications
  75 // doesn't provide information about "opposite" window, so we
  76 // have to do a bit of tracking. This variable points to a window
  77 // which had been the key window just before a new key window
  78 // was set. It would be nil if the new key window isn't an AWT
  79 // window or the app currently has no key window.
  80 static AWTWindow* lastKeyWindow = nil;
  81 
  82 // --------------------------------------------------------------
  83 // NSWindow/NSPanel descendants implementation
  84 #define AWT_NS_WINDOW_IMPLEMENTATION                            \
  85 - (id) initWithDelegate:(AWTWindow *)delegate                   \
  86               frameRect:(NSRect)contectRect                     \
  87               styleMask:(NSUInteger)styleMask                   \
  88             contentView:(NSView *)view                          \
  89 {                                                               \
  90     self = [super initWithContentRect:contectRect               \
  91                             styleMask:styleMask                 \
  92                               backing:NSBackingStoreBuffered    \
  93                                 defer:NO];                      \
  94                                                                 \
  95     if (self == nil) return nil;                                \
  96                                                                 \
  97     [self setDelegate:delegate];                                \
  98     [self setContentView:view];                                 \
  99     [self setInitialFirstResponder:view];                       \
 100     [self setReleasedWhenClosed:NO];                            \
 101     [self setPreservesContentDuringLiveResize:YES];             \
 102                                                                 \
 103     return self;                                                \
 104 }                                                               \
 105                                                                 \
 106 /* NSWindow overrides */                                        \
 107 - (BOOL) canBecomeKeyWindow {                                   \
 108     return [(AWTWindow*)[self delegate] canBecomeKeyWindow];    \
 109 }                                                               \
 110                                                                 \
 111 - (BOOL) canBecomeMainWindow {                                  \
 112     return [(AWTWindow*)[self delegate] canBecomeMainWindow];   \
 113 }                                                               \
 114                                                                 \
 115 - (BOOL) worksWhenModal {                                       \
 116     return [(AWTWindow*)[self delegate] worksWhenModal];        \
 117 }                                                               \
 118                                                                 \
 119 - (void)sendEvent:(NSEvent *)event {                            \
 120     [(AWTWindow*)[self delegate] sendEvent:event];              \
 121     [super sendEvent:event];                                    \
 122 }
 123 
 124 @implementation AWTWindow_Normal
 125 AWT_NS_WINDOW_IMPLEMENTATION
 126 @end
 127 @implementation AWTWindow_Panel
 128 AWT_NS_WINDOW_IMPLEMENTATION
 129 @end
 130 // END of NSWindow/NSPanel descendants implementation
 131 // --------------------------------------------------------------
 132 
 133 
 134 @implementation AWTWindow
 135 
 136 @synthesize nsWindow;
 137 @synthesize javaPlatformWindow;
 138 @synthesize javaMenuBar;
 139 @synthesize growBoxWindow;
 140 @synthesize javaMinSize;
 141 @synthesize javaMaxSize;
 142 @synthesize styleBits;
 143 @synthesize isEnabled;
 144 @synthesize ownerWindow;
 145 
 146 - (void) updateMinMaxSize:(BOOL)resizable {
 147     if (resizable) {
 148         [self.nsWindow setMinSize:self.javaMinSize];
 149         [self.nsWindow setMaxSize:self.javaMaxSize];
 150     } else {
 151         NSRect currentFrame = [self.nsWindow frame];
 152         [self.nsWindow setMinSize:currentFrame.size];
 153         [self.nsWindow setMaxSize:currentFrame.size];
 154     }
 155 }
 156 
 157 // creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
 158 + (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
 159     NSUInteger type = 0;
 160     if (IS(styleBits, DECORATED)) {
 161         type |= NSTitledWindowMask;
 162         if (IS(styleBits, CLOSEABLE))   type |= NSClosableWindowMask;
 163         if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;
 164         if (IS(styleBits, RESIZABLE))   type |= NSResizableWindowMask;
 165     } else {
 166         type |= NSBorderlessWindowMask;
 167     }
 168 
 169     if (IS(styleBits, TEXTURED))      type |= NSTexturedBackgroundWindowMask;
 170     if (IS(styleBits, UNIFIED))       type |= NSUnifiedTitleAndToolbarWindowMask;
 171     if (IS(styleBits, UTILITY))       type |= NSUtilityWindowMask;
 172     if (IS(styleBits, HUD))           type |= NSHUDWindowMask;
 173     if (IS(styleBits, SHEET))         type |= NSDocModalWindowMask;
 174     if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
 175 
 176     return type;
 177 }
 178 
 179 // updates _METHOD_PROP_BITMASK based properties on the window
 180 - (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
 181     if (IS(mask, RESIZABLE)) {
 182         BOOL resizable = IS(bits, RESIZABLE);
 183         [self updateMinMaxSize:resizable];
 184         [self.nsWindow setShowsResizeIndicator:resizable];
 185     }
 186 
 187     if (IS(mask, HAS_SHADOW)) {
 188         [self.nsWindow setHasShadow:IS(bits, HAS_SHADOW)];
 189     }
 190 
 191     if (IS(mask, ZOOMABLE)) {
 192         [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
 193     }
 194 
 195     if (IS(mask, ALWAYS_ON_TOP)) {
 196         [self.nsWindow setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
 197     }
 198 
 199     if (IS(mask, HIDES_ON_DEACTIVATE)) {
 200         [self.nsWindow setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
 201     }
 202 
 203     if (IS(mask, DRAGGABLE_BACKGROUND)) {
 204         [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
 205     }
 206 
 207     if (IS(mask, DOCUMENT_MODIFIED)) {
 208         [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
 209     }
 210 
 211     if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
 212         if (IS(bits, FULLSCREENABLE)) {
 213             [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
 214         } else {
 215             [self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
 216         }
 217     }
 218 
 219 }
 220 
 221 - (BOOL) shouldShowGrowBox {
 222     return isSnowLeopardOrLower() && IS(self.styleBits, RESIZABLE);
 223 }
 224 
 225 - (NSImage *) createGrowBoxImage {
 226     NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(GROW_BOX_SIZE, GROW_BOX_SIZE)];
 227     JRSUIControlRef growBoxWidget = JRSUIControlCreate(FALSE);
 228     JRSUIControlSetWidget(growBoxWidget, kJRSUI_Widget_growBoxTextured);
 229     JRSUIControlSetWindowType(growBoxWidget, kJRSUI_WindowType_utility);
 230     JRSUIRendererRef renderer = JRSUIRendererCreate();
 231     [image lockFocus]; // sets current graphics context to that of the image
 232     JRSUIControlDraw(renderer, growBoxWidget, [[NSGraphicsContext currentContext] graphicsPort], CGRectMake(0, 1, GROW_BOX_SIZE - 1, GROW_BOX_SIZE - 1));
 233     [image unlockFocus];
 234     JRSUIRendererRelease(renderer);
 235     JRSUIControlRelease(growBoxWidget);
 236     return image;
 237 }
 238 
 239 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
 240                   ownerWindow:owner
 241                     styleBits:(jint)bits
 242                     frameRect:(NSRect)rect
 243                   contentView:(NSView *)view
 244 {
 245 AWT_ASSERT_APPKIT_THREAD;
 246 
 247     NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
 248     NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
 249     if (contentRect.size.width <= 0.0) {
 250         contentRect.size.width = 1.0;
 251     }
 252     if (contentRect.size.height <= 0.0) {
 253         contentRect.size.height = 1.0;
 254     }
 255 
 256     self = [super init];
 257 
 258     if (self == nil) return nil; // no hope
 259 
 260     if (IS(bits, UTILITY) ||
 261         IS(bits, NONACTIVATING) ||
 262         IS(bits, HUD) ||
 263         IS(bits, HIDES_ON_DEACTIVATE))
 264     {
 265         self.nsWindow = [[AWTWindow_Panel alloc] initWithDelegate:self
 266                             frameRect:contentRect
 267                             styleMask:styleMask
 268                           contentView:view];
 269     }
 270     else
 271     {
 272         // These windows will appear in the window list in the dock icon menu
 273         self.nsWindow = [[AWTWindow_Normal alloc] initWithDelegate:self
 274                             frameRect:contentRect
 275                             styleMask:styleMask
 276                           contentView:view];
 277     }
 278 
 279     if (self.nsWindow == nil) return nil; // no hope either
 280     [self.nsWindow release]; // the property retains the object already
 281 
 282     self.isEnabled = YES;
 283     self.javaPlatformWindow = platformWindow;
 284     self.styleBits = bits;
 285     self.ownerWindow = owner;
 286     [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
 287 
 288     if ([self shouldShowGrowBox]) {
 289         NSImage *growBoxImage = [self createGrowBoxImage];
 290         growBoxWindow = [[JavaResizeGrowBoxOverlayWindow alloc] initWithContentRect:NSMakeRect(0, 0, [growBoxImage size].width, [growBoxImage size].height) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
 291         [self.growBoxWindow setIgnoresMouseEvents:YES];
 292         [self.growBoxWindow setOpaque:NO];
 293         [self.growBoxWindow setBackgroundColor:[NSColor clearColor]];
 294         [self.growBoxWindow setHasShadow:NO];
 295         [self.growBoxWindow setReleasedWhenClosed:NO];
 296 
 297         NSImageView *imageView = [[NSImageView alloc] initWithFrame:[self.growBoxWindow frame]];
 298         [imageView setEditable:NO];
 299         [imageView setAnimates:NO];
 300         [imageView setAllowsCutCopyPaste:NO];
 301         [self.growBoxWindow setContentView:imageView];
 302         [imageView setImage:growBoxImage];
 303         [growBoxImage release];
 304         [imageView release];
 305 
 306         [self.nsWindow addChildWindow:self.growBoxWindow ordered:NSWindowAbove];
 307         [self adjustGrowBoxWindow];
 308     } else growBoxWindow = nil;
 309 
 310     if (IS(self.styleBits, IS_POPUP)) {
 311         [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/]; 
 312     }
 313 
 314     return self;
 315 }
 316 
 317 + (BOOL) isAWTWindow:(NSWindow *)window {
 318     return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
 319 }
 320 
 321 // return id for the topmost window under mouse
 322 + (NSInteger) getTopmostWindowUnderMouseID {
 323     NSInteger result = -1;
 324     
 325     NSRect screenRect = [[NSScreen mainScreen] frame];
 326     NSPoint nsMouseLocation = [NSEvent mouseLocation];
 327     CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
 328 
 329     NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
 330 
 331 
 332     for (NSDictionary *window in windows) {
 333         NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
 334         if (layer == 0) {
 335             CGRect rect;
 336             CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
 337             if (CGRectContainsPoint(rect, cgMouseLocation)) {
 338                 result = [[window objectForKey:(id)kCGWindowNumber] integerValue];
 339                 break;
 340             }
 341         }
 342     }
 343     [windows release];
 344     return result;
 345 }
 346 
 347 // checks that this window is under the mouse cursor and this point is not overlapped by other windows
 348 - (BOOL) isTopmostWindowUnderMouse {
 349     return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID];
 350 }
 351 
 352 + (AWTWindow *) getTopmostWindowUnderMouse {
 353     NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator];
 354     NSWindow *window;
 355 
 356     NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
 357 
 358     while ((window = [windowEnumerator nextObject]) != nil) {
 359         if ([window windowNumber] == topmostWindowUnderMouseID) {
 360             BOOL isAWTWindow = [AWTWindow isAWTWindow: window];
 361             return isAWTWindow ? (AWTWindow *) [window delegate] : nil;
 362         }
 363     }
 364     return nil;
 365 }
 366 
 367 + (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType {
 368 
 369     NSPoint screenLocation = [NSEvent mouseLocation];
 370     NSPoint windowLocation = [window convertScreenToBase: screenLocation];
 371     int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
 372 
 373     NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
 374                                                  location: windowLocation
 375                                             modifierFlags: modifierFlags
 376                                                 timestamp: 0
 377                                              windowNumber: [window windowNumber]
 378                                                   context: nil
 379                                               eventNumber: 0
 380                                            trackingNumber: 0
 381                                                  userData: nil
 382                            ];
 383 
 384     [[window contentView] deliverJavaMouseEvent: mouseEvent];
 385 }
 386 
 387 +(void) synthesizeMouseEnteredExitedEventsForAllWindows {
 388     NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
 389     NSArray *windows = [NSApp windows];
 390     NSWindow *window;
 391 
 392     NSEnumerator *windowEnumerator = [windows objectEnumerator];
 393     while ((window = [windowEnumerator nextObject]) != nil) {
 394         if ([AWTWindow isAWTWindow: window]) {
 395             BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID);
 396             BOOL mouseIsOver = [[window contentView] mouseIsOver];
 397             if (isUnderMouse && !mouseIsOver) {
 398                 [AWTWindow synthesizeMouseEnteredExitedEvents: window withType:NSMouseEntered];
 399             } else if (!isUnderMouse && mouseIsOver) {
 400                 [AWTWindow synthesizeMouseEnteredExitedEvents: window withType:NSMouseExited];
 401             }
 402         }
 403     }
 404 }
 405 
 406 + (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window {
 407     AWT_ASSERT_APPKIT_THREAD;
 408     NSScreen *screen = [window screen];
 409     NSDictionary *deviceDescription = [screen deviceDescription];
 410     return [deviceDescription objectForKey:@"NSScreenNumber"];
 411 }
 412 
 413 - (void) dealloc {
 414 AWT_ASSERT_APPKIT_THREAD;
 415 
 416     JNIEnv *env = [ThreadUtilities getJNIEnv];
 417     [self.javaPlatformWindow setJObject:nil withEnv:env];
 418     self.growBoxWindow = nil;
 419 
 420     self.nsWindow = nil;
 421     self.ownerWindow = nil;
 422     [super dealloc];
 423 }
 424 
 425 // NSWindow overrides
 426 - (BOOL) canBecomeKeyWindow {
 427 AWT_ASSERT_APPKIT_THREAD;
 428     return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_KEY);
 429 }
 430 
 431 - (BOOL) canBecomeMainWindow {
 432 AWT_ASSERT_APPKIT_THREAD;
 433     return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
 434 }
 435 
 436 - (BOOL) worksWhenModal {
 437 AWT_ASSERT_APPKIT_THREAD;
 438     return IS(self.styleBits, MODAL_EXCLUDED);
 439 }
 440 
 441 
 442 // Gesture support
 443 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
 444 AWT_ASSERT_APPKIT_THREAD;
 445 
 446     JNIEnv *env = [ThreadUtilities getJNIEnv];
 447     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 448     if (platformWindow != NULL) {
 449         // extract the target AWT Window object out of the CPlatformWindow
 450         static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
 451         jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
 452         if (awtWindow != NULL) {
 453             // translate the point into Java coordinates
 454             NSPoint loc = [event locationInWindow];
 455             loc.y = [self.nsWindow frame].size.height - loc.y;
 456 
 457             // send up to the GestureHandler to recursively dispatch on the AWT event thread
 458             static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
 459             static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
 460             JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
 461             (*env)->DeleteLocalRef(env, awtWindow);
 462         }
 463         (*env)->DeleteLocalRef(env, platformWindow);
 464     }
 465 }
 466 
 467 - (void)beginGestureWithEvent:(NSEvent *)event {
 468     [self postGesture:event
 469                    as:com_apple_eawt_event_GestureHandler_PHASE
 470                     a:-1.0
 471                     b:0.0];
 472 }
 473 
 474 - (void)endGestureWithEvent:(NSEvent *)event {
 475     [self postGesture:event
 476                    as:com_apple_eawt_event_GestureHandler_PHASE
 477                     a:1.0
 478                     b:0.0];
 479 }
 480 
 481 - (void)magnifyWithEvent:(NSEvent *)event {
 482     [self postGesture:event
 483                    as:com_apple_eawt_event_GestureHandler_MAGNIFY
 484                     a:[event magnification]
 485                     b:0.0];
 486 }
 487 
 488 - (void)rotateWithEvent:(NSEvent *)event {
 489     [self postGesture:event
 490                    as:com_apple_eawt_event_GestureHandler_ROTATE
 491                     a:[event rotation]
 492                     b:0.0];
 493 }
 494 
 495 - (void)swipeWithEvent:(NSEvent *)event {
 496     [self postGesture:event
 497                    as:com_apple_eawt_event_GestureHandler_SWIPE
 498                     a:[event deltaX]
 499                     b:[event deltaY]];
 500 }
 501 
 502 
 503 // NSWindowDelegate methods
 504 
 505 - (void) adjustGrowBoxWindow {
 506     if (self.growBoxWindow != nil) {
 507         NSRect parentRect = [self.nsWindow frame];
 508         parentRect.origin.x += (parentRect.size.width - [self.growBoxWindow frame].size.width);
 509         [self.growBoxWindow setFrameOrigin:parentRect.origin];
 510     }
 511 }
 512 
 513 - (void) _deliverMoveResizeEvent {
 514 AWT_ASSERT_APPKIT_THREAD;
 515 
 516     // deliver the event if this is a user-initiated live resize or as a side-effect
 517     // of a Java initiated resize, because AppKit can override the bounds and force
 518     // the bounds of the window to avoid the Dock or remain on screen.
 519     [AWTToolkit eventCountPlusPlus];
 520     JNIEnv *env = [ThreadUtilities getJNIEnv];
 521     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 522     if (platformWindow == NULL) {
 523         // TODO: create generic AWT assert
 524     }
 525 
 526     [self adjustGrowBoxWindow];
 527 
 528     NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
 529 
 530     static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
 531     JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
 532                       (jint)frame.origin.x,
 533                       (jint)frame.origin.y,
 534                       (jint)frame.size.width,
 535                       (jint)frame.size.height,
 536                       (jboolean)[self.nsWindow inLiveResize]);
 537     (*env)->DeleteLocalRef(env, platformWindow);
 538 }
 539 
 540 - (void)windowDidMove:(NSNotification *)notification {
 541 AWT_ASSERT_APPKIT_THREAD;
 542 
 543     [self _deliverMoveResizeEvent];
 544 }
 545 
 546 - (void)windowDidResize:(NSNotification *)notification {
 547 AWT_ASSERT_APPKIT_THREAD;
 548 
 549     [self _deliverMoveResizeEvent];
 550 }
 551 
 552 - (void)windowDidExpose:(NSNotification *)notification {
 553 AWT_ASSERT_APPKIT_THREAD;
 554 
 555     [AWTToolkit eventCountPlusPlus];
 556     // TODO: don't see this callback invoked anytime so we track
 557     // window exposing in _setVisible:(BOOL)
 558 }
 559 
 560 - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)proposedFrame {
 561 AWT_ASSERT_APPKIT_THREAD;
 562 
 563     [AWTToolkit eventCountPlusPlus];
 564     JNIEnv *env = [ThreadUtilities getJNIEnv];
 565     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 566     if (platformWindow != NULL) {
 567         static JNF_MEMBER_CACHE(jm_deliverZoom, jc_CPlatformWindow, "deliverZoom", "(Z)V");
 568         JNFCallVoidMethod(env, platformWindow, jm_deliverZoom, ![window isZoomed]);
 569         (*env)->DeleteLocalRef(env, platformWindow);
 570     }
 571     return YES;
 572 }
 573 
 574 - (void) _deliverIconify:(BOOL)iconify {
 575 AWT_ASSERT_APPKIT_THREAD;
 576 
 577     [AWTToolkit eventCountPlusPlus];
 578     JNIEnv *env = [ThreadUtilities getJNIEnv];
 579     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 580     if (platformWindow != NULL) {
 581         static JNF_MEMBER_CACHE(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");
 582         JNFCallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);
 583         (*env)->DeleteLocalRef(env, platformWindow);
 584     }
 585 }
 586 
 587 - (void)windowDidMiniaturize:(NSNotification *)notification {
 588 AWT_ASSERT_APPKIT_THREAD;
 589 
 590     [self _deliverIconify:JNI_TRUE];
 591 }
 592 
 593 - (void)windowDidDeminiaturize:(NSNotification *)notification {
 594 AWT_ASSERT_APPKIT_THREAD;
 595 
 596     [self _deliverIconify:JNI_FALSE];
 597 }
 598 
 599 - (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
 600 //AWT_ASSERT_APPKIT_THREAD;
 601     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 602     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 603     if (platformWindow != NULL) {
 604         jobject oppositeWindow = [opposite.javaPlatformWindow jObjectWithEnv:env];
 605 
 606         static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");
 607         JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);
 608         (*env)->DeleteLocalRef(env, platformWindow);
 609         (*env)->DeleteLocalRef(env, oppositeWindow);
 610     }
 611 }
 612 
 613 
 614 - (void) windowDidBecomeKey: (NSNotification *) notification {
 615 AWT_ASSERT_APPKIT_THREAD;
 616     [AWTToolkit eventCountPlusPlus];
 617     AWTWindow *opposite = [AWTWindow lastKeyWindow];
 618 
 619     // Finds appropriate menubar in our hierarchy,
 620     AWTWindow *awtWindow = self;
 621     while (awtWindow.ownerWindow != nil) {
 622         awtWindow = awtWindow.ownerWindow;
 623     }
 624 
 625     CMenuBar *menuBar = nil;
 626     BOOL isDisabled = NO;
 627     if ([awtWindow.nsWindow isVisible]){
 628         menuBar = awtWindow.javaMenuBar;
 629         isDisabled = !awtWindow.isEnabled;
 630     }
 631 
 632     if (menuBar == nil) {
 633         menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
 634         isDisabled = NO;
 635     }
 636 
 637     [CMenuBar activate:menuBar modallyDisabled:isDisabled];
 638 
 639     [AWTWindow setLastKeyWindow:nil];
 640 
 641     [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
 642 }
 643 
 644 - (void) windowDidResignKey: (NSNotification *) notification {
 645     // TODO: check why sometimes at start is invoked *not* on AppKit main thread.
 646 AWT_ASSERT_APPKIT_THREAD;
 647     [AWTToolkit eventCountPlusPlus];
 648     [self.javaMenuBar deactivate];
 649 
 650     // In theory, this might cause flickering if the window gaining focus
 651     // has its own menu. However, I couldn't reproduce it on practice, so
 652     // perhaps this is a non issue.
 653     CMenuBar* defaultMenu = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
 654     if (defaultMenu != nil) {
 655         [CMenuBar activate:defaultMenu modallyDisabled:NO];
 656     }
 657 
 658     // the new key window
 659     NSWindow *keyWindow = [NSApp keyWindow];
 660     AWTWindow *opposite = nil;
 661     if ([AWTWindow isAWTWindow: keyWindow]) {
 662         opposite = (AWTWindow *)[keyWindow delegate];
 663         [AWTWindow setLastKeyWindow: self];
 664     } else {
 665         [AWTWindow setLastKeyWindow: nil];
 666     }
 667 
 668     [self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
 669 }
 670 
 671 - (void) windowDidBecomeMain: (NSNotification *) notification {
 672 AWT_ASSERT_APPKIT_THREAD;
 673     [AWTToolkit eventCountPlusPlus];
 674 
 675     JNIEnv *env = [ThreadUtilities getJNIEnv];
 676     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 677     if (platformWindow != NULL) {
 678         static JNF_MEMBER_CACHE(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");
 679         JNFCallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);
 680         (*env)->DeleteLocalRef(env, platformWindow);
 681     }
 682 }
 683 
 684 - (BOOL)windowShouldClose:(id)sender {
 685 AWT_ASSERT_APPKIT_THREAD;
 686     [AWTToolkit eventCountPlusPlus];
 687     JNIEnv *env = [ThreadUtilities getJNIEnv];
 688     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 689     if (platformWindow != NULL) {
 690         static JNF_MEMBER_CACHE(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V");
 691         JNFCallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);
 692         (*env)->DeleteLocalRef(env, platformWindow);
 693     }
 694     // The window will be closed (if allowed) as result of sending Java event
 695     return NO;
 696 }
 697 
 698 
 699 - (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {
 700     static JNF_CLASS_CACHE(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");
 701     static JNF_STATIC_MEMBER_CACHE(jm_notifyFullScreenOperation, jc_FullScreenHandler, "handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");
 702     static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
 703     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 704     if (platformWindow != NULL) {
 705         jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
 706         if (awtWindow != NULL) {
 707             JNFCallStaticVoidMethod(env, jm_notifyFullScreenOperation, awtWindow, op);
 708             (*env)->DeleteLocalRef(env, awtWindow);
 709         }
 710         (*env)->DeleteLocalRef(env, platformWindow);
 711     }
 712 }
 713 
 714 
 715 - (void)windowWillEnterFullScreen:(NSNotification *)notification {
 716     static JNF_MEMBER_CACHE(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
 717     JNIEnv *env = [ThreadUtilities getJNIEnv];
 718     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 719     if (platformWindow != NULL) {
 720         JNFCallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);
 721         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];
 722         (*env)->DeleteLocalRef(env, platformWindow);
 723     }
 724 }
 725 
 726 - (void)windowDidEnterFullScreen:(NSNotification *)notification {
 727     static JNF_MEMBER_CACHE(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
 728     JNIEnv *env = [ThreadUtilities getJNIEnv];
 729     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 730     if (platformWindow != NULL) {
 731         JNFCallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);
 732         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];
 733         (*env)->DeleteLocalRef(env, platformWindow);
 734     }
 735 }
 736 
 737 - (void)windowWillExitFullScreen:(NSNotification *)notification {
 738     static JNF_MEMBER_CACHE(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
 739     JNIEnv *env = [ThreadUtilities getJNIEnv];
 740     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 741     if (platformWindow != NULL) {
 742         JNFCallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);
 743         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
 744         (*env)->DeleteLocalRef(env, platformWindow);
 745     }
 746 }
 747 
 748 - (void)windowDidExitFullScreen:(NSNotification *)notification {
 749     static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
 750     JNIEnv *env = [ThreadUtilities getJNIEnv];
 751     jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 752     if (platformWindow != NULL) {
 753         JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
 754         [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
 755         (*env)->DeleteLocalRef(env, platformWindow);
 756     }
 757 }
 758 
 759 - (void)sendEvent:(NSEvent *)event {
 760         if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
 761 
 762             NSPoint p = [NSEvent mouseLocation];
 763             NSRect frame = [self.nsWindow frame];
 764             NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
 765 
 766             // Check if the click happened in the non-client area (title bar)
 767             if (p.y >= (frame.origin.y + contentRect.size.height)) {
 768                 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 769                 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
 770                 // Currently, no need to deliver the whole NSEvent.
 771                 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
 772                 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
 773             }
 774         }
 775 }
 776 
 777 - (void)constrainSize:(NSSize*)size {
 778     float minWidth = 0.f, minHeight = 0.f;
 779 
 780     if (IS(self.styleBits, DECORATED)) {
 781         NSRect frame = [self.nsWindow frame];
 782         NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
 783 
 784         float top = frame.size.height - contentRect.size.height;
 785         float left = contentRect.origin.x - frame.origin.x;
 786         float bottom = contentRect.origin.y - frame.origin.y;
 787         float right = frame.size.width - (contentRect.size.width + left);
 788 
 789         // Speculative estimation: 80 - enough for window decorations controls
 790         minWidth += left + right + 80;
 791         minHeight += top + bottom;
 792     }
 793 
 794     if ([self shouldShowGrowBox]) {
 795         minWidth = MAX(minWidth, GROW_BOX_SIZE);
 796         minHeight += GROW_BOX_SIZE;
 797     }
 798 
 799     minWidth = MAX(1.f, minWidth);
 800     minHeight = MAX(1.f, minHeight);
 801 
 802     size->width = MAX(size->width, minWidth);
 803     size->height = MAX(size->height, minHeight);
 804 }
 805 
 806 - (void) setEnabled: (BOOL)flag {
 807     self.isEnabled = flag;
 808 
 809     if (IS(self.styleBits, CLOSEABLE)) {
 810         [[self.nsWindow standardWindowButton:NSWindowCloseButton] setEnabled: flag];
 811     }
 812 
 813     if (IS(self.styleBits, MINIMIZABLE)) {
 814         [[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];
 815     }
 816 
 817     if (IS(self.styleBits, ZOOMABLE)) {
 818         [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled: flag];
 819     }
 820 
 821     if (IS(self.styleBits, RESIZABLE)) {
 822         [self updateMinMaxSize:flag];
 823         [self.nsWindow setShowsResizeIndicator:flag];
 824     }
 825 }
 826 
 827 + (void) setLastKeyWindow:(AWTWindow *)window {
 828     [window retain];
 829     [lastKeyWindow release];
 830     lastKeyWindow = window;
 831 }
 832 
 833 + (AWTWindow *) lastKeyWindow {
 834     return lastKeyWindow;
 835 }
 836 
 837 
 838 @end // AWTWindow
 839 
 840 
 841 /*
 842  * Class:     sun_lwawt_macosx_CPlatformWindow
 843  * Method:    nativeCreateNSWindow
 844  * Signature: (JJIIII)J
 845  */
 846 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
 847 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong ownerPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
 848 {
 849     __block AWTWindow *window = nil;
 850 
 851 JNF_COCOA_ENTER(env);
 852 
 853     JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
 854     NSView *contentView = OBJC(contentViewPtr);
 855     NSRect frameRect = NSMakeRect(x, y, w, h);
 856     AWTWindow *owner = [OBJC(ownerPtr) delegate];
 857     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 858 
 859         window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
 860                                                ownerWindow:owner
 861                                                  styleBits:styleBits
 862                                                  frameRect:frameRect
 863                                                contentView:contentView];
 864         // the window is released is CPlatformWindow.nativeDispose()
 865 
 866         if (window) CFRetain(window.nsWindow);
 867     }];
 868 
 869 JNF_COCOA_EXIT(env);
 870 
 871     return ptr_to_jlong(window ? window.nsWindow : nil);
 872 }
 873 
 874 /*
 875  * Class:     sun_lwawt_macosx_CPlatformWindow
 876  * Method:    nativeSetNSWindowStyleBits
 877  * Signature: (JII)V
 878  */
 879 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
 880 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
 881 {
 882 JNF_COCOA_ENTER(env);
 883 
 884     NSWindow *nsWindow = OBJC(windowPtr);
 885     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
 886 
 887         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
 888 
 889         // scans the bit field, and only updates the values requested by the mask
 890         // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
 891         jint newBits = window.styleBits & ~mask | bits & mask;
 892 
 893         // resets the NSWindow's style mask if the mask intersects any of those bits
 894         if (mask & MASK(_STYLE_PROP_BITMASK)) {
 895             [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
 896         }
 897 
 898         // calls methods on NSWindow to change other properties, based on the mask
 899         if (mask & MASK(_METHOD_PROP_BITMASK)) {
 900             [window setPropertiesForStyleBits:bits mask:mask];
 901         }
 902 
 903         window.styleBits = newBits;
 904     }];
 905 
 906 JNF_COCOA_EXIT(env);
 907 }
 908 
 909 /*
 910  * Class:     sun_lwawt_macosx_CPlatformWindow
 911  * Method:    nativeSetNSWindowMenuBar
 912  * Signature: (JJ)V
 913  */
 914 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
 915 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
 916 {
 917 JNF_COCOA_ENTER(env);
 918 
 919     NSWindow *nsWindow = OBJC(windowPtr);
 920     CMenuBar *menuBar = OBJC(menuBarPtr);
 921     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
 922 
 923         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
 924 
 925         if ([nsWindow isKeyWindow]) {
 926             [window.javaMenuBar deactivate];
 927         }
 928 
 929         window.javaMenuBar = menuBar;
 930 
 931         CMenuBar* actualMenuBar = menuBar;
 932         if (actualMenuBar == nil) {
 933             actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
 934         }
 935 
 936         if ([nsWindow isKeyWindow]) {
 937             [CMenuBar activate:actualMenuBar modallyDisabled:NO];
 938         }
 939     }];
 940 
 941 JNF_COCOA_EXIT(env);
 942 }
 943 
 944 /*
 945  * Class:     sun_lwawt_macosx_CPlatformWindow
 946  * Method:    nativeGetNSWindowInsets
 947  * Signature: (J)Ljava/awt/Insets;
 948  */
 949 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
 950 (JNIEnv *env, jclass clazz, jlong windowPtr)
 951 {
 952     jobject ret = NULL;
 953 
 954 JNF_COCOA_ENTER(env);
 955 
 956     NSWindow *nsWindow = OBJC(windowPtr);
 957     __block NSRect contentRect = NSZeroRect;
 958     __block NSRect frame = NSZeroRect;
 959 
 960     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 961 
 962         frame = [nsWindow frame];
 963         contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
 964     }];
 965 
 966     jint top = (jint)(frame.size.height - contentRect.size.height);
 967     jint left = (jint)(contentRect.origin.x - frame.origin.x);
 968     jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
 969     jint right = (jint)(frame.size.width - (contentRect.size.width + left));
 970 
 971     static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
 972     static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
 973     ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
 974 
 975 JNF_COCOA_EXIT(env);
 976     return ret;
 977 }
 978 
 979 /*
 980  * Class:     sun_lwawt_macosx_CPlatformWindow
 981  * Method:    nativeSetNSWindowBounds
 982  * Signature: (JDDDD)V
 983  */
 984 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
 985 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
 986 {
 987 JNF_COCOA_ENTER(env);
 988 
 989     NSRect jrect = NSMakeRect(originX, originY, width, height);
 990 
 991     // TODO: not sure we need displayIfNeeded message in our view
 992     NSWindow *nsWindow = OBJC(windowPtr);
 993     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
 994 
 995         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
 996 
 997         NSRect rect = ConvertNSScreenRect(NULL, jrect);
 998         [window constrainSize:&rect.size];
 999 
1000         [nsWindow setFrame:rect display:YES];
1001 
1002         // only start tracking events if pointer is above the toplevel
1003         // TODO: should post an Entered event if YES.
1004         NSPoint mLocation = [NSEvent mouseLocation];
1005         [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
1006 
1007         // ensure we repaint the whole window after the resize operation
1008         // (this will also re-enable screen updates, which were disabled above)
1009         // TODO: send PaintEvent
1010 
1011         [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
1012     }];
1013 
1014 JNF_COCOA_EXIT(env);
1015 }
1016 
1017 /*
1018  * Class:     sun_lwawt_macosx_CPlatformWindow
1019  * Method:    nativeSetNSWindowMinMax
1020  * Signature: (JDDDD)V
1021  */
1022 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
1023 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
1024 {
1025 JNF_COCOA_ENTER(env);
1026 
1027     if (minW < 1) minW = 1;
1028     if (minH < 1) minH = 1;
1029     if (maxW < 1) maxW = 1;
1030     if (maxH < 1) maxH = 1;
1031 
1032     NSWindow *nsWindow = OBJC(windowPtr);
1033     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1034 
1035         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1036 
1037         NSSize min = { minW, minH };
1038         NSSize max = { maxW, maxH };
1039 
1040         [window constrainSize:&min];
1041         [window constrainSize:&max];
1042 
1043         window.javaMinSize = min;
1044         window.javaMaxSize = max;
1045         [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
1046     }];
1047 
1048 JNF_COCOA_EXIT(env);
1049 }
1050 
1051 /*
1052  * Class:     sun_lwawt_macosx_CPlatformWindow
1053  * Method:    nativePushNSWindowToBack
1054  * Signature: (J)V
1055  */
1056 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
1057 (JNIEnv *env, jclass clazz, jlong windowPtr)
1058 {
1059 JNF_COCOA_ENTER(env);
1060 
1061     NSWindow *nsWindow = OBJC(windowPtr);
1062     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1063         [nsWindow orderBack:nil];
1064     }];
1065 
1066 JNF_COCOA_EXIT(env);
1067 }
1068 
1069 /*
1070  * Class:     sun_lwawt_macosx_CPlatformWindow
1071  * Method:    nativePushNSWindowToFront
1072  * Signature: (J)V
1073  */
1074 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
1075 (JNIEnv *env, jclass clazz, jlong windowPtr)
1076 {
1077 JNF_COCOA_ENTER(env);
1078 
1079     NSWindow *nsWindow = OBJC(windowPtr);
1080     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1081 
1082         if (![nsWindow isKeyWindow]) {
1083             [nsWindow makeKeyAndOrderFront:nsWindow];
1084         } else {
1085             [nsWindow orderFront:nsWindow];
1086         }
1087     }];
1088 
1089 JNF_COCOA_EXIT(env);
1090 }
1091 
1092 /*
1093  * Class:     sun_lwawt_macosx_CPlatformWindow
1094  * Method:    nativeSetNSWindowTitle
1095  * Signature: (JLjava/lang/String;)V
1096  */
1097 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
1098 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
1099 {
1100 JNF_COCOA_ENTER(env);
1101 
1102     NSWindow *nsWindow = OBJC(windowPtr);
1103     [nsWindow performSelectorOnMainThread:@selector(setTitle:)
1104                               withObject:JNFJavaToNSString(env, jtitle)
1105                            waitUntilDone:NO];
1106 
1107 JNF_COCOA_EXIT(env);
1108 }
1109 
1110 /*
1111  * Class:     sun_lwawt_macosx_CPlatformWindow
1112  * Method:    nativeRevalidateNSWindowShadow
1113  * Signature: (J)V
1114  */
1115 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
1116 (JNIEnv *env, jclass clazz, jlong windowPtr)
1117 {
1118 JNF_COCOA_ENTER(env);
1119 
1120     NSWindow *nsWindow = OBJC(windowPtr);
1121     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1122         [nsWindow invalidateShadow];
1123     }];
1124 
1125 JNF_COCOA_EXIT(env);
1126 }
1127 
1128 /*
1129  * Class:     sun_lwawt_macosx_CPlatformWindow
1130  * Method:    nativeScreenOn_AppKitThread
1131  * Signature: (J)I
1132  */
1133 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
1134 (JNIEnv *env, jclass clazz, jlong windowPtr)
1135 {
1136     jint ret = 0;
1137 
1138 JNF_COCOA_ENTER(env);
1139 AWT_ASSERT_APPKIT_THREAD;
1140 
1141     NSWindow *nsWindow = OBJC(windowPtr);
1142     NSDictionary *props = [[nsWindow screen] deviceDescription];
1143     ret = [[props objectForKey:@"NSScreenNumber"] intValue];
1144 
1145 JNF_COCOA_EXIT(env);
1146 
1147     return ret;
1148 }
1149 
1150 /*
1151  * Class:     sun_lwawt_macosx_CPlatformWindow
1152  * Method:    nativeSetNSWindowMinimizedIcon
1153  * Signature: (JJ)V
1154  */
1155 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
1156 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
1157 {
1158 JNF_COCOA_ENTER(env);
1159 
1160     NSWindow *nsWindow = OBJC(windowPtr);
1161     NSImage *image = OBJC(nsImagePtr);
1162     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1163         [nsWindow setMiniwindowImage:image];
1164     }];
1165 
1166 JNF_COCOA_EXIT(env);
1167 }
1168 
1169 /*
1170  * Class:     sun_lwawt_macosx_CPlatformWindow
1171  * Method:    nativeSetNSWindowRepresentedFilename
1172  * Signature: (JLjava/lang/String;)V
1173  */
1174 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
1175 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
1176 {
1177 JNF_COCOA_ENTER(env);
1178 
1179     NSWindow *nsWindow = OBJC(windowPtr);
1180     NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
1181     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1182         [nsWindow setRepresentedURL:url];
1183     }];
1184 
1185 JNF_COCOA_EXIT(env);
1186 }
1187 
1188 /*
1189  * Class:     sun_lwawt_macosx_CPlatformWindow
1190  * Method:    nativeGetTopMostWindowUnderMouse
1191  * Signature: (J)V
1192  */
1193 JNIEXPORT jobject
1194 JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
1195 (JNIEnv *env, jclass clazz)
1196 {
1197     jobject topmostWindowUnderMouse = nil;
1198 
1199     JNF_COCOA_ENTER(env);
1200     AWT_ASSERT_APPKIT_THREAD;
1201 
1202     AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
1203     if (awtWindow != nil) {
1204         topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
1205     }
1206 
1207     JNF_COCOA_EXIT(env);
1208 
1209     return topmostWindowUnderMouse;
1210 }
1211 
1212 /*
1213  * Class:     sun_lwawt_macosx_CPlatformWindow
1214  * Method:    nativeSynthesizeMouseEnteredExitedEvents
1215  * Signature: (J)V
1216  */
1217 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
1218 (JNIEnv *env, jclass clazz)
1219 {
1220     JNF_COCOA_ENTER(env);
1221 
1222     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1223         [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
1224     }];
1225 
1226     JNF_COCOA_EXIT(env);
1227 }
1228 
1229 /*
1230  * Class:     sun_lwawt_macosx_CPlatformWindow
1231  * Method:    _toggleFullScreenMode
1232  * Signature: (J)V
1233  */
1234 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1235 (JNIEnv *env, jobject peer, jlong windowPtr)
1236 {
1237 JNF_COCOA_ENTER(env);
1238 
1239     NSWindow *nsWindow = OBJC(windowPtr);
1240     SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1241     if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
1242 
1243     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1244         [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
1245     }];
1246 
1247 JNF_COCOA_EXIT(env);
1248 }
1249 
1250 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1251 (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1252 {
1253 JNF_COCOA_ENTER(env);
1254 
1255     NSWindow *nsWindow = OBJC(windowPtr);
1256     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1257         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1258 
1259         [window setEnabled: isEnabled];
1260     }];
1261 
1262 JNF_COCOA_EXIT(env);
1263 }
1264 
1265 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDispose
1266 (JNIEnv *env, jclass clazz, jlong windowPtr)
1267 {
1268 JNF_COCOA_ENTER(env);
1269 
1270     NSWindow *nsWindow = OBJC(windowPtr);
1271     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1272         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1273 
1274         if ([AWTWindow lastKeyWindow] == window) {
1275             [AWTWindow setLastKeyWindow: nil];
1276         }
1277 
1278         // AWTWindow holds a reference to the NSWindow in its nsWindow
1279         // property. Unsetting the delegate allows it to be deallocated
1280         // which releases the reference. This, in turn, allows the window
1281         // itself be deallocated.
1282         [nsWindow setDelegate: nil];
1283 
1284         [window release];
1285     }];
1286 
1287 JNF_COCOA_EXIT(env);
1288 }
1289