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