1/*
2 * Copyright (c) 2011, 2018, 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
28#import "sun_lwawt_macosx_CPlatformWindow.h"
29#import "com_apple_eawt_event_GestureHandler.h"
30#import "com_apple_eawt_FullScreenHandler.h"
31#import "ApplicationDelegate.h"
32
33#import "AWTWindow.h"
34#import "AWTView.h"
35#import "GeomUtilities.h"
36#import "ThreadUtilities.h"
37#import "JNIUtilities.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
48static jclass jc_CPlatformWindow = NULL;
49#define GET_CPLATFORM_WINDOW_CLASS() \
50    GET_CLASS(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
51
52#define GET_CPLATFORM_WINDOW_CLASS_RETURN(ret) \
53    GET_CLASS_RETURN(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow", ret);
54
55// Cocoa windowDidBecomeKey/windowDidResignKey notifications
56// doesn't provide information about "opposite" window, so we
57// have to do a bit of tracking. This variable points to a window
58// which had been the key window just before a new key window
59// was set. It would be nil if the new key window isn't an AWT
60// window or the app currently has no key window.
61static AWTWindow* lastKeyWindow = nil;
62
63// This variable contains coordinates of a window's top left
64// which was positioned via java.awt.Window.setLocationByPlatform.
65// It would be NSZeroPoint if 'Location by Platform' is not used.
66static NSPoint lastTopLeftPoint;
67
68// --------------------------------------------------------------
69// NSWindow/NSPanel descendants implementation
70#define AWT_NS_WINDOW_IMPLEMENTATION                            \
71- (id) initWithDelegate:(AWTWindow *)delegate                   \
72              frameRect:(NSRect)contectRect                     \
73              styleMask:(NSUInteger)styleMask                   \
74            contentView:(NSView *)view                          \
75{                                                               \
76    self = [super initWithContentRect:contectRect               \
77                            styleMask:styleMask                 \
78                              backing:NSBackingStoreBuffered    \
79                                defer:NO];                      \
80                                                                \
81    if (self == nil) return nil;                                \
82                                                                \
83    [self setDelegate:delegate];                                \
84    [self setContentView:view];                                 \
85    [self setInitialFirstResponder:view];                       \
86    [self setReleasedWhenClosed:NO];                            \
87    [self setPreservesContentDuringLiveResize:YES];             \
88                                                                \
89    return self;                                                \
90}                                                               \
91                                                                \
92/* NSWindow overrides */                                        \
93- (BOOL) canBecomeKeyWindow {                                   \
94    return [(AWTWindow*)[self delegate] canBecomeKeyWindow];    \
95}                                                               \
96                                                                \
97- (BOOL) canBecomeMainWindow {                                  \
98    return [(AWTWindow*)[self delegate] canBecomeMainWindow];   \
99}                                                               \
100                                                                \
101- (BOOL) worksWhenModal {                                       \
102    return [(AWTWindow*)[self delegate] worksWhenModal];        \
103}                                                               \
104                                                                \
105- (void)sendEvent:(NSEvent *)event {                            \
106    [(AWTWindow*)[self delegate] sendEvent:event];              \
107    [super sendEvent:event];                                    \
108}
109
110@implementation AWTWindow_Normal
111AWT_NS_WINDOW_IMPLEMENTATION
112
113// Gesture support
114- (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
115    AWT_ASSERT_APPKIT_THREAD;
116
117    JNIEnv *env = [ThreadUtilities getJNIEnv];
118    jobject platformWindow = (*env)->NewLocalRef(env, ((AWTWindow *)self.delegate).javaPlatformWindow);
119    if (platformWindow != NULL) {
120        // extract the target AWT Window object out of the CPlatformWindow
121        GET_CPLATFORM_WINDOW_CLASS();
122        DECLARE_FIELD(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
123        jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
124        if (awtWindow != NULL) {
125            // translate the point into Java coordinates
126            NSPoint loc = [event locationInWindow];
127            loc.y = [self frame].size.height - loc.y;
128
129            // send up to the GestureHandler to recursively dispatch on the AWT event thread
130            DECLARE_CLASS(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
131            DECLARE_METHOD(sjm_handleGestureFromNative, jc_GestureHandler,
132                            "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
133            (*env)->CallStaticVoidMethod(env, jc_GestureHandler, sjm_handleGestureFromNative,
134                               awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
135            CHECK_EXCEPTION();
136            (*env)->DeleteLocalRef(env, awtWindow);
137        }
138        (*env)->DeleteLocalRef(env, platformWindow);
139    }
140}
141
142- (void)beginGestureWithEvent:(NSEvent *)event {
143    [self postGesture:event
144                   as:com_apple_eawt_event_GestureHandler_PHASE
145                    a:-1.0
146                    b:0.0];
147}
148
149- (void)endGestureWithEvent:(NSEvent *)event {
150    [self postGesture:event
151                   as:com_apple_eawt_event_GestureHandler_PHASE
152                    a:1.0
153                    b:0.0];
154}
155
156- (void)magnifyWithEvent:(NSEvent *)event {
157    [self postGesture:event
158                   as:com_apple_eawt_event_GestureHandler_MAGNIFY
159                    a:[event magnification]
160                    b:0.0];
161}
162
163- (void)rotateWithEvent:(NSEvent *)event {
164    [self postGesture:event
165                   as:com_apple_eawt_event_GestureHandler_ROTATE
166                    a:[event rotation]
167                    b:0.0];
168}
169
170- (void)swipeWithEvent:(NSEvent *)event {
171    [self postGesture:event
172                   as:com_apple_eawt_event_GestureHandler_SWIPE
173                    a:[event deltaX]
174                    b:[event deltaY]];
175}
176
177@end
178@implementation AWTWindow_Panel
179AWT_NS_WINDOW_IMPLEMENTATION
180@end
181// END of NSWindow/NSPanel descendants implementation
182// --------------------------------------------------------------
183
184
185@implementation AWTWindow
186
187@synthesize nsWindow;
188@synthesize javaPlatformWindow;
189@synthesize javaMenuBar;
190@synthesize javaMinSize;
191@synthesize javaMaxSize;
192@synthesize styleBits;
193@synthesize isEnabled;
194@synthesize ownerWindow;
195@synthesize preFullScreenLevel;
196@synthesize standardFrame;
197@synthesize isMinimizing;
198
199- (void) updateMinMaxSize:(BOOL)resizable {
200    if (resizable) {
201        [self.nsWindow setMinSize:self.javaMinSize];
202        [self.nsWindow setMaxSize:self.javaMaxSize];
203    } else {
204        NSRect currentFrame = [self.nsWindow frame];
205        [self.nsWindow setMinSize:currentFrame.size];
206        [self.nsWindow setMaxSize:currentFrame.size];
207    }
208}
209
210// creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
211+ (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
212    NSUInteger type = 0;
213    if (IS(styleBits, DECORATED)) {
214        type |= NSTitledWindowMask;
215        if (IS(styleBits, CLOSEABLE))            type |= NSClosableWindowMask;
216        if (IS(styleBits, RESIZABLE))            type |= NSResizableWindowMask;
217        if (IS(styleBits, FULL_WINDOW_CONTENT))  type |= NSFullSizeContentViewWindowMask;
218    } else {
219        type |= NSBorderlessWindowMask;
220    }
221
222    if (IS(styleBits, MINIMIZABLE))   type |= NSMiniaturizableWindowMask;
223    if (IS(styleBits, TEXTURED))      type |= NSTexturedBackgroundWindowMask;
224    if (IS(styleBits, UNIFIED))       type |= NSUnifiedTitleAndToolbarWindowMask;
225    if (IS(styleBits, UTILITY))       type |= NSUtilityWindowMask;
226    if (IS(styleBits, HUD))           type |= NSHUDWindowMask;
227    if (IS(styleBits, SHEET))         type |= NSDocModalWindowMask;
228    if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
229
230    return type;
231}
232
233// updates _METHOD_PROP_BITMASK based properties on the window
234- (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
235    if (IS(mask, RESIZABLE)) {
236        BOOL resizable = IS(bits, RESIZABLE);
237        [self updateMinMaxSize:resizable];
238        [self.nsWindow setShowsResizeIndicator:resizable];
239        // Zoom button should be disabled, if the window is not resizable,
240        // otherwise button should be restored to initial state.
241        BOOL zoom = resizable && IS(bits, ZOOMABLE);
242        [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:zoom];
243    }
244
245    if (IS(mask, HAS_SHADOW)) {
246        [self.nsWindow setHasShadow:IS(bits, HAS_SHADOW)];
247    }
248
249    if (IS(mask, ZOOMABLE)) {
250        [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
251    }
252
253    if (IS(mask, ALWAYS_ON_TOP)) {
254        [self.nsWindow setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
255    }
256
257    if (IS(mask, HIDES_ON_DEACTIVATE)) {
258        [self.nsWindow setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
259    }
260
261    if (IS(mask, DRAGGABLE_BACKGROUND)) {
262        [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
263    }
264
265    if (IS(mask, DOCUMENT_MODIFIED)) {
266        [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
267    }
268
269    if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
270        if (IS(bits, FULLSCREENABLE)) {
271            [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
272        } else {
273            [self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
274        }
275    }
276
277    if (IS(mask, TRANSPARENT_TITLE_BAR) && [self.nsWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
278        [self.nsWindow setTitlebarAppearsTransparent:IS(bits, TRANSPARENT_TITLE_BAR)];
279    }
280}
281
282- (id) initWithPlatformWindow:(jobject)platformWindow
283                  ownerWindow:owner
284                    styleBits:(jint)bits
285                    frameRect:(NSRect)rect
286                  contentView:(NSView *)view
287{
288AWT_ASSERT_APPKIT_THREAD;
289
290    NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
291    NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
292    if (contentRect.size.width <= 0.0) {
293        contentRect.size.width = 1.0;
294    }
295    if (contentRect.size.height <= 0.0) {
296        contentRect.size.height = 1.0;
297    }
298
299    self = [super init];
300
301    if (self == nil) return nil; // no hope
302
303    if (IS(bits, UTILITY) ||
304        IS(bits, NONACTIVATING) ||
305        IS(bits, HUD) ||
306        IS(bits, HIDES_ON_DEACTIVATE))
307    {
308        self.nsWindow = [[AWTWindow_Panel alloc] initWithDelegate:self
309                            frameRect:contentRect
310                            styleMask:styleMask
311                          contentView:view];
312    }
313    else
314    {
315        // These windows will appear in the window list in the dock icon menu
316        self.nsWindow = [[AWTWindow_Normal alloc] initWithDelegate:self
317                            frameRect:contentRect
318                            styleMask:styleMask
319                          contentView:view];
320    }
321
322    if (self.nsWindow == nil) return nil; // no hope either
323    [self.nsWindow release]; // the property retains the object already
324
325    self.isEnabled = YES;
326    self.isMinimizing = NO;
327    self.javaPlatformWindow = platformWindow;
328    self.styleBits = bits;
329    self.ownerWindow = owner;
330    [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
331
332    if (IS(self.styleBits, IS_POPUP)) {
333        [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];
334    }
335
336    return self;
337}
338
339+ (BOOL) isAWTWindow:(NSWindow *)window {
340    return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
341}
342
343// Retrieves the list of possible window layers (levels)
344+ (NSArray*) getWindowLayers {
345    static NSArray *windowLayers;
346    static dispatch_once_t token;
347
348    // Initialize the list of possible window layers
349    dispatch_once(&token, ^{
350        // The layers are ordered from front to back, (i.e. the toppest one is the first)
351        windowLayers = [NSArray arrayWithObjects:
352                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)],
353                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)],
354                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)],
355                            nil
356                        ];
357        [windowLayers retain];
358    });
359    return windowLayers;
360}
361
362// returns id for the topmost window under mouse
363+ (NSInteger) getTopmostWindowUnderMouseID {
364    NSInteger result = -1;
365
366    NSArray *windowLayers = [AWTWindow getWindowLayers];
367    // Looking for the window under mouse starting from the toppest layer
368    for (NSNumber *layer in windowLayers) {
369        result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]];
370        if (result != -1) {
371            break;
372        }
373    }
374    return result;
375}
376
377+ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer {
378    NSInteger result = -1;
379
380    NSRect screenRect = [[NSScreen mainScreen] frame];
381    NSPoint nsMouseLocation = [NSEvent mouseLocation];
382    CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
383
384    NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
385
386    for (NSDictionary *window in windows) {
387        NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
388        if (layer == windowLayer) {
389            CGRect rect;
390            CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
391            if (CGRectContainsPoint(rect, cgMouseLocation)) {
392                result = [[window objectForKey:(id)kCGWindowNumber] integerValue];
393                break;
394            }
395        }
396    }
397    [windows release];
398    return result;
399}
400
401// checks that this window is under the mouse cursor and this point is not overlapped by others windows
402- (BOOL) isTopmostWindowUnderMouse {
403    return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID];
404}
405
406+ (AWTWindow *) getTopmostWindowUnderMouse {
407    NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator];
408    NSWindow *window;
409
410    NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
411
412    while ((window = [windowEnumerator nextObject]) != nil) {
413        if ([window windowNumber] == topmostWindowUnderMouseID) {
414            BOOL isAWTWindow = [AWTWindow isAWTWindow: window];
415            return isAWTWindow ? (AWTWindow *) [window delegate] : nil;
416        }
417    }
418    return nil;
419}
420
421+ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType {
422
423    NSPoint screenLocation = [NSEvent mouseLocation];
424    NSPoint windowLocation = [window convertScreenToBase: screenLocation];
425    int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
426
427    NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
428                                                 location: windowLocation
429                                            modifierFlags: modifierFlags
430                                                timestamp: 0
431                                             windowNumber: [window windowNumber]
432                                                  context: nil
433                                              eventNumber: 0
434                                           trackingNumber: 0
435                                                 userData: nil
436                           ];
437
438    [[window contentView] deliverJavaMouseEvent: mouseEvent];
439}
440
441+ (void) synthesizeMouseEnteredExitedEventsForAllWindows {
442
443    NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
444    NSArray *windows = [NSApp windows];
445    NSWindow *window;
446
447    NSEnumerator *windowEnumerator = [windows objectEnumerator];
448    while ((window = [windowEnumerator nextObject]) != nil) {
449        if ([AWTWindow isAWTWindow: window]) {
450            BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID);
451            BOOL mouseIsOver = [[window contentView] mouseIsOver];
452            if (isUnderMouse && !mouseIsOver) {
453                [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];
454            } else if (!isUnderMouse && mouseIsOver) {
455                [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];
456            }
457        }
458    }
459}
460
461+ (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window {
462    AWT_ASSERT_APPKIT_THREAD;
463    NSScreen *screen = [window screen];
464    NSDictionary *deviceDescription = [screen deviceDescription];
465    return [deviceDescription objectForKey:@"NSScreenNumber"];
466}
467
468- (void) dealloc {
469AWT_ASSERT_APPKIT_THREAD;
470
471    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
472    (*env)->DeleteWeakGlobalRef(env, self.javaPlatformWindow);
473    self.javaPlatformWindow = nil;
474    self.nsWindow = nil;
475    self.ownerWindow = nil;
476    [super dealloc];
477}
478
479// Tests whether window is blocked by modal dialog/window
480- (BOOL) isBlocked {
481    BOOL isBlocked = NO;
482
483    JNIEnv *env = [ThreadUtilities getJNIEnv];
484    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
485    if (platformWindow != NULL) {
486        GET_CPLATFORM_WINDOW_CLASS_RETURN(isBlocked);
487        DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z", isBlocked);
488        isBlocked = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
489        CHECK_EXCEPTION();
490        (*env)->DeleteLocalRef(env, platformWindow);
491    }
492
493    return isBlocked;
494}
495
496// Test whether window is simple window and owned by embedded frame
497- (BOOL) isSimpleWindowOwnedByEmbeddedFrame {
498    BOOL isSimpleWindowOwnedByEmbeddedFrame = NO;
499
500    JNIEnv *env = [ThreadUtilities getJNIEnv];
501    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
502    if (platformWindow != NULL) {
503        GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
504        DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isSimpleWindowOwnedByEmbeddedFrame", "()Z", NO);
505        isSimpleWindowOwnedByEmbeddedFrame = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
506        CHECK_EXCEPTION();
507        (*env)->DeleteLocalRef(env, platformWindow);
508    }
509
510    return isSimpleWindowOwnedByEmbeddedFrame;
511}
512
513// Tests whether the corresponding Java platform window is visible or not
514+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
515    BOOL isVisible = NO;
516
517    if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {
518        AWTWindow *awtWindow = (AWTWindow *)[window delegate];
519        [AWTToolkit eventCountPlusPlus];
520
521        JNIEnv *env = [ThreadUtilities getJNIEnv];
522        jobject platformWindow = (*env)->NewLocalRef(env, awtWindow.javaPlatformWindow);
523        if (platformWindow != NULL) {
524            GET_CPLATFORM_WINDOW_CLASS_RETURN(isVisible);
525            DECLARE_METHOD_RETURN(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z", isVisible)
526            isVisible = (*env)->CallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;
527            CHECK_EXCEPTION();
528            (*env)->DeleteLocalRef(env, platformWindow);
529
530        }
531    }
532    return isVisible;
533}
534
535// Orders window's childs based on the current focus state
536- (void) orderChildWindows:(BOOL)focus {
537AWT_ASSERT_APPKIT_THREAD;
538
539    if (self.isMinimizing || [self isBlocked]) {
540        // Do not perform any ordering, if iconify is in progress
541        // or the window is blocked by a modal window
542        return;
543    }
544
545    NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];
546    NSWindow *window;
547    while ((window = [windowEnumerator nextObject]) != nil) {
548        if ([AWTWindow isJavaPlatformWindowVisible:window]) {
549            AWTWindow *awtWindow = (AWTWindow *)[window delegate];
550            AWTWindow *owner = awtWindow.ownerWindow;
551            if (IS(awtWindow.styleBits, ALWAYS_ON_TOP)) {
552                // Do not order 'always on top' windows
553                continue;
554            }
555            while (awtWindow.ownerWindow != nil) {
556                if (awtWindow.ownerWindow == self) {
557                    if (focus) {
558                        // Move the childWindow to floating level
559                        // so it will appear in front of its
560                        // parent which owns the focus
561                        [window setLevel:NSFloatingWindowLevel];
562                    } else {
563                        // Focus owner has changed, move the childWindow
564                        // back to normal window level
565                        [window setLevel:NSNormalWindowLevel];
566                    }
567                    // The childWindow should be displayed in front of
568                    // its nearest parentWindow
569                    [window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]];
570                    break;
571                }
572                awtWindow = awtWindow.ownerWindow;
573            }
574        }
575    }
576}
577
578// NSWindow overrides
579- (BOOL) canBecomeKeyWindow {
580AWT_ASSERT_APPKIT_THREAD;
581    return self.isEnabled && (IS(self.styleBits, SHOULD_BECOME_KEY) || [self isSimpleWindowOwnedByEmbeddedFrame]);
582}
583
584- (BOOL) canBecomeMainWindow {
585AWT_ASSERT_APPKIT_THREAD;
586    if (!self.isEnabled) {
587        // Native system can bring up the NSWindow to
588        // the top even if the window is not main.
589        // We should bring up the modal dialog manually
590        [AWTToolkit eventCountPlusPlus];
591
592        JNIEnv *env = [ThreadUtilities getJNIEnv];
593        jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
594        if (platformWindow != NULL) {
595            GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
596            DECLARE_METHOD_RETURN(jm_checkBlockingAndOrder, jc_CPlatformWindow, "checkBlockingAndOrder", "()Z", NO);
597            (*env)->CallBooleanMethod(env, platformWindow, jm_checkBlockingAndOrder);
598            CHECK_EXCEPTION();
599            (*env)->DeleteLocalRef(env, platformWindow);
600        }
601    }
602
603    return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
604}
605
606- (BOOL) worksWhenModal {
607AWT_ASSERT_APPKIT_THREAD;
608    return IS(self.styleBits, MODAL_EXCLUDED);
609}
610
611
612// NSWindowDelegate methods
613
614- (void) _deliverMoveResizeEvent {
615AWT_ASSERT_APPKIT_THREAD;
616
617    // deliver the event if this is a user-initiated live resize or as a side-effect
618    // of a Java initiated resize, because AppKit can override the bounds and force
619    // the bounds of the window to avoid the Dock or remain on screen.
620    [AWTToolkit eventCountPlusPlus];
621    JNIEnv *env = [ThreadUtilities getJNIEnv];
622    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
623    if (platformWindow == NULL) {
624        // TODO: create generic AWT assert
625    }
626
627    NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
628
629    GET_CPLATFORM_WINDOW_CLASS();
630    DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
631    (*env)->CallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
632                      (jint)frame.origin.x,
633                      (jint)frame.origin.y,
634                      (jint)frame.size.width,
635                      (jint)frame.size.height,
636                      (jboolean)[self.nsWindow inLiveResize]);
637    CHECK_EXCEPTION();
638    (*env)->DeleteLocalRef(env, platformWindow);
639
640    [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
641}
642
643- (void)windowDidMove:(NSNotification *)notification {
644AWT_ASSERT_APPKIT_THREAD;
645
646    [self _deliverMoveResizeEvent];
647}
648
649- (void)windowDidResize:(NSNotification *)notification {
650AWT_ASSERT_APPKIT_THREAD;
651
652    [self _deliverMoveResizeEvent];
653}
654
655- (void)windowDidExpose:(NSNotification *)notification {
656AWT_ASSERT_APPKIT_THREAD;
657
658    [AWTToolkit eventCountPlusPlus];
659    // TODO: don't see this callback invoked anytime so we track
660    // window exposing in _setVisible:(BOOL)
661}
662
663- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
664                        defaultFrame:(NSRect)newFrame {
665
666    return NSEqualSizes(NSZeroSize, [self standardFrame].size)
667                ? newFrame
668                : [self standardFrame];
669}
670
671// Hides/shows window's childs during iconify/de-iconify operation
672- (void) iconifyChildWindows:(BOOL)iconify {
673AWT_ASSERT_APPKIT_THREAD;
674
675    NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];
676    NSWindow *window;
677    while ((window = [windowEnumerator nextObject]) != nil) {
678        if ([AWTWindow isJavaPlatformWindowVisible:window]) {
679            AWTWindow *awtWindow = (AWTWindow *)[window delegate];
680            while (awtWindow.ownerWindow != nil) {
681                if (awtWindow.ownerWindow == self) {
682                    if (iconify) {
683                        [window orderOut:window];
684                    } else {
685                        [window orderFront:window];
686                    }
687                    break;
688                }
689                awtWindow = awtWindow.ownerWindow;
690            }
691        }
692    }
693}
694
695- (void) _deliverIconify:(BOOL)iconify {
696AWT_ASSERT_APPKIT_THREAD;
697
698    [AWTToolkit eventCountPlusPlus];
699    JNIEnv *env = [ThreadUtilities getJNIEnv];
700    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
701    if (platformWindow != NULL) {
702        GET_CPLATFORM_WINDOW_CLASS();
703        DECLARE_METHOD(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");
704        (*env)->CallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);
705        CHECK_EXCEPTION();
706        (*env)->DeleteLocalRef(env, platformWindow);
707    }
708}
709
710- (void)windowWillMiniaturize:(NSNotification *)notification {
711AWT_ASSERT_APPKIT_THREAD;
712
713    self.isMinimizing = YES;
714
715    JNIEnv *env = [ThreadUtilities getJNIEnv];
716    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
717    if (platformWindow != NULL) {
718        GET_CPLATFORM_WINDOW_CLASS();
719        DECLARE_METHOD(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
720        (*env)->CallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
721        CHECK_EXCEPTION();
722        (*env)->DeleteLocalRef(env, platformWindow);
723    }
724    // Explicitly make myself a key window to avoid possible
725    // negative visual effects during iconify operation
726    [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
727    [self iconifyChildWindows:YES];
728}
729
730- (void)windowDidMiniaturize:(NSNotification *)notification {
731AWT_ASSERT_APPKIT_THREAD;
732
733    [self _deliverIconify:JNI_TRUE];
734    self.isMinimizing = NO;
735}
736
737- (void)windowDidDeminiaturize:(NSNotification *)notification {
738AWT_ASSERT_APPKIT_THREAD;
739
740    [self _deliverIconify:JNI_FALSE];
741    [self iconifyChildWindows:NO];
742}
743
744- (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
745//AWT_ASSERT_APPKIT_THREAD;
746    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
747    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
748    if (platformWindow != NULL) {
749        jobject oppositeWindow = (*env)->NewLocalRef(env, opposite.javaPlatformWindow);
750        GET_CPLATFORM_WINDOW_CLASS();
751        DECLARE_METHOD(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");
752        (*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);
753        CHECK_EXCEPTION();
754        (*env)->DeleteLocalRef(env, platformWindow);
755        (*env)->DeleteLocalRef(env, oppositeWindow);
756    }
757}
758
759- (void) windowDidBecomeMain: (NSNotification *) notification {
760AWT_ASSERT_APPKIT_THREAD;
761    [AWTToolkit eventCountPlusPlus];
762#ifdef DEBUG
763    NSLog(@"became main: %d %@ %@", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow]);
764#endif
765
766    if (![self.nsWindow isKeyWindow]) {
767        [self activateWindowMenuBar];
768    }
769
770    JNIEnv *env = [ThreadUtilities getJNIEnv];
771    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
772    if (platformWindow != NULL) {
773        GET_CPLATFORM_WINDOW_CLASS();
774        DECLARE_METHOD(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");
775        (*env)->CallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);
776        CHECK_EXCEPTION();
777        (*env)->DeleteLocalRef(env, platformWindow);
778    }
779}
780
781- (void) windowDidBecomeKey: (NSNotification *) notification {
782AWT_ASSERT_APPKIT_THREAD;
783    [AWTToolkit eventCountPlusPlus];
784#ifdef DEBUG
785    NSLog(@"became key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
786#endif
787    AWTWindow *opposite = [AWTWindow lastKeyWindow];
788
789    if (![self.nsWindow isMainWindow]) {
790        [self activateWindowMenuBar];
791    }
792
793    [AWTWindow setLastKeyWindow:nil];
794
795    [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
796    [self orderChildWindows:YES];
797}
798
799- (void) activateWindowMenuBar {
800AWT_ASSERT_APPKIT_THREAD;
801    // Finds appropriate menubar in our hierarchy
802    AWTWindow *awtWindow = self;
803    while (awtWindow.ownerWindow != nil) {
804        awtWindow = awtWindow.ownerWindow;
805    }
806
807    CMenuBar *menuBar = nil;
808    BOOL isDisabled = NO;
809    if ([awtWindow.nsWindow isVisible]){
810        menuBar = awtWindow.javaMenuBar;
811        isDisabled = !awtWindow.isEnabled;
812    }
813
814    if (menuBar == nil) {
815        menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
816        isDisabled = NO;
817    }
818
819    [CMenuBar activate:menuBar modallyDisabled:isDisabled];
820}
821
822#ifdef DEBUG
823- (CMenuBar *) menuBarForWindow {
824AWT_ASSERT_APPKIT_THREAD;
825    AWTWindow *awtWindow = self;
826    while (awtWindow.ownerWindow != nil) {
827        awtWindow = awtWindow.ownerWindow;
828    }
829    return awtWindow.javaMenuBar;
830}
831#endif
832
833- (void) windowDidResignKey: (NSNotification *) notification {
834    // TODO: check why sometimes at start is invoked *not* on AppKit main thread.
835AWT_ASSERT_APPKIT_THREAD;
836    [AWTToolkit eventCountPlusPlus];
837#ifdef DEBUG
838    NSLog(@"resigned key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
839#endif
840    if (![self.nsWindow isMainWindow]) {
841        [self deactivateWindow];
842    }
843}
844
845- (void) windowDidResignMain: (NSNotification *) notification {
846AWT_ASSERT_APPKIT_THREAD;
847    [AWTToolkit eventCountPlusPlus];
848#ifdef DEBUG
849    NSLog(@"resigned main: %d %@ %@", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow]);
850#endif
851    if (![self.nsWindow isKeyWindow]) {
852        [self deactivateWindow];
853    }
854}
855
856- (void) deactivateWindow {
857AWT_ASSERT_APPKIT_THREAD;
858#ifdef DEBUG
859    NSLog(@"deactivating window: %@", [self.nsWindow title]);
860#endif
861    [self.javaMenuBar deactivate];
862
863    // the new key window
864    NSWindow *keyWindow = [NSApp keyWindow];
865    AWTWindow *opposite = nil;
866    if ([AWTWindow isAWTWindow: keyWindow]) {
867        opposite = (AWTWindow *)[keyWindow delegate];
868        [AWTWindow setLastKeyWindow: self];
869    } else {
870        [AWTWindow setLastKeyWindow: nil];
871    }
872
873    [self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
874    [self orderChildWindows:NO];
875}
876
877- (BOOL)windowShouldClose:(id)sender {
878AWT_ASSERT_APPKIT_THREAD;
879    [AWTToolkit eventCountPlusPlus];
880    JNIEnv *env = [ThreadUtilities getJNIEnv];
881    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
882    if (platformWindow != NULL) {
883        GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
884        DECLARE_METHOD_RETURN(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V", NO);
885        (*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);
886        CHECK_EXCEPTION();
887        (*env)->DeleteLocalRef(env, platformWindow);
888    }
889    // The window will be closed (if allowed) as result of sending Java event
890    return NO;
891}
892
893- (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {
894    DECLARE_CLASS(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");
895    DECLARE_STATIC_METHOD(jm_notifyFullScreenOperation, jc_FullScreenHandler,
896                           "handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");
897    GET_CPLATFORM_WINDOW_CLASS();
898    DECLARE_FIELD(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
899    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
900    if (platformWindow != NULL) {
901        jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
902        if (awtWindow != NULL) {
903            (*env)->CallStaticVoidMethod(env, jc_FullScreenHandler, jm_notifyFullScreenOperation, awtWindow, op);
904            CHECK_EXCEPTION();
905            (*env)->DeleteLocalRef(env, awtWindow);
906        }
907        (*env)->DeleteLocalRef(env, platformWindow);
908    }
909}
910
911
912- (void)windowWillEnterFullScreen:(NSNotification *)notification {
913    JNIEnv *env = [ThreadUtilities getJNIEnv];
914    GET_CPLATFORM_WINDOW_CLASS();
915    DECLARE_METHOD(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
916    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
917    if (platformWindow != NULL) {
918        (*env)->CallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);
919        CHECK_EXCEPTION();
920        [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];
921        (*env)->DeleteLocalRef(env, platformWindow);
922    }
923}
924
925- (void)windowDidEnterFullScreen:(NSNotification *)notification {
926    JNIEnv *env = [ThreadUtilities getJNIEnv];
927    GET_CPLATFORM_WINDOW_CLASS();
928    DECLARE_METHOD(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
929    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
930    if (platformWindow != NULL) {
931        (*env)->CallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);
932        CHECK_EXCEPTION();
933        [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];
934        (*env)->DeleteLocalRef(env, platformWindow);
935    }
936    [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
937}
938
939- (void)windowWillExitFullScreen:(NSNotification *)notification {
940    JNIEnv *env = [ThreadUtilities getJNIEnv];
941    GET_CPLATFORM_WINDOW_CLASS();
942    DECLARE_METHOD(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
943    if (jm_windowWillExitFullScreen == NULL) {
944        GET_CPLATFORM_WINDOW_CLASS();
945        jm_windowWillExitFullScreen = (*env)->GetMethodID(env, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
946    }
947    CHECK_NULL(jm_windowWillExitFullScreen);
948    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
949    if (platformWindow != NULL) {
950        (*env)->CallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);
951        CHECK_EXCEPTION();
952        [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
953        (*env)->DeleteLocalRef(env, platformWindow);
954    }
955}
956
957- (void)windowDidExitFullScreen:(NSNotification *)notification {
958    JNIEnv *env = [ThreadUtilities getJNIEnv];
959    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
960    if (platformWindow != NULL) {
961        GET_CPLATFORM_WINDOW_CLASS();
962        DECLARE_METHOD(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
963        (*env)->CallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
964        CHECK_EXCEPTION();
965        [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
966        (*env)->DeleteLocalRef(env, platformWindow);
967    }
968    [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
969}
970
971- (void)sendEvent:(NSEvent *)event {
972        if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
973            if ([self isBlocked]) {
974                // Move parent windows to front and make sure that a child window is displayed
975                // in front of its nearest parent.
976                if (self.ownerWindow != nil) {
977                    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
978                    jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
979                    if (platformWindow != NULL) {
980                        GET_CPLATFORM_WINDOW_CLASS();
981                        DECLARE_METHOD(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
982                        (*env)->CallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
983                        CHECK_EXCEPTION();
984                        (*env)->DeleteLocalRef(env, platformWindow);
985                    }
986                }
987                [self orderChildWindows:YES];
988            }
989
990            NSPoint p = [NSEvent mouseLocation];
991            NSRect frame = [self.nsWindow frame];
992            NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
993
994            // Check if the click happened in the non-client area (title bar)
995            if (p.y >= (frame.origin.y + contentRect.size.height)) {
996                JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
997                jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
998                if (platformWindow != NULL) {
999                    // Currently, no need to deliver the whole NSEvent.
1000                    GET_CPLATFORM_WINDOW_CLASS();
1001                    DECLARE_METHOD(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
1002                    (*env)->CallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
1003                    CHECK_EXCEPTION();
1004                    (*env)->DeleteLocalRef(env, platformWindow);
1005                }
1006            }
1007        }
1008}
1009
1010- (void)constrainSize:(NSSize*)size {
1011    float minWidth = 0.f, minHeight = 0.f;
1012
1013    if (IS(self.styleBits, DECORATED)) {
1014        NSRect frame = [self.nsWindow frame];
1015        NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
1016
1017        float top = frame.size.height - contentRect.size.height;
1018        float left = contentRect.origin.x - frame.origin.x;
1019        float bottom = contentRect.origin.y - frame.origin.y;
1020        float right = frame.size.width - (contentRect.size.width + left);
1021
1022        // Speculative estimation: 80 - enough for window decorations controls
1023        minWidth += left + right + 80;
1024        minHeight += top + bottom;
1025    }
1026
1027    minWidth = MAX(1.f, minWidth);
1028    minHeight = MAX(1.f, minHeight);
1029
1030    size->width = MAX(size->width, minWidth);
1031    size->height = MAX(size->height, minHeight);
1032}
1033
1034- (void) setEnabled: (BOOL)flag {
1035    self.isEnabled = flag;
1036
1037    if (IS(self.styleBits, CLOSEABLE)) {
1038        [[self.nsWindow standardWindowButton:NSWindowCloseButton] setEnabled: flag];
1039    }
1040
1041    if (IS(self.styleBits, MINIMIZABLE)) {
1042        [[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];
1043    }
1044
1045    if (IS(self.styleBits, ZOOMABLE)) {
1046        [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled: flag];
1047    }
1048
1049    if (IS(self.styleBits, RESIZABLE)) {
1050        [self updateMinMaxSize:flag];
1051        [self.nsWindow setShowsResizeIndicator:flag];
1052    }
1053}
1054
1055+ (void) setLastKeyWindow:(AWTWindow *)window {
1056    [window retain];
1057    [lastKeyWindow release];
1058    lastKeyWindow = window;
1059}
1060
1061+ (AWTWindow *) lastKeyWindow {
1062    return lastKeyWindow;
1063}
1064
1065@end // AWTWindow
1066
1067
1068/*
1069 * Class:     sun_lwawt_macosx_CPlatformWindow
1070 * Method:    nativeCreateNSWindow
1071 * Signature: (JJIIII)J
1072 */
1073JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
1074(JNIEnv *env, jobject obj, jlong contentViewPtr, jlong ownerPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
1075{
1076    __block AWTWindow *window = nil;
1077
1078JNI_COCOA_ENTER(env);
1079
1080    jobject platformWindow = (*env)->NewWeakGlobalRef(env, obj);
1081    NSView *contentView = OBJC(contentViewPtr);
1082    NSRect frameRect = NSMakeRect(x, y, w, h);
1083    AWTWindow *owner = [OBJC(ownerPtr) delegate];
1084    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1085
1086        window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
1087                                               ownerWindow:owner
1088                                                 styleBits:styleBits
1089                                                 frameRect:frameRect
1090                                               contentView:contentView];
1091        // the window is released is CPlatformWindow.nativeDispose()
1092
1093        if (window) [window.nsWindow retain];
1094    }];
1095
1096JNI_COCOA_EXIT(env);
1097
1098    return ptr_to_jlong(window ? window.nsWindow : nil);
1099}
1100
1101/*
1102 * Class:     sun_lwawt_macosx_CPlatformWindow
1103 * Method:    nativeSetNSWindowStyleBits
1104 * Signature: (JII)V
1105 */
1106JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
1107(JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
1108{
1109JNI_COCOA_ENTER(env);
1110
1111    NSWindow *nsWindow = OBJC(windowPtr);
1112
1113    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1114
1115        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1116
1117        // scans the bit field, and only updates the values requested by the mask
1118        // (this implicitly handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
1119        jint newBits = window.styleBits & ~mask | bits & mask;
1120
1121        BOOL resized = NO;
1122
1123        // Check for a change to the full window content view option.
1124        // The content view must be resized first, otherwise the window will be resized to fit the existing
1125        // content view.
1126        if (IS(mask, FULL_WINDOW_CONTENT)) {
1127            if (IS(newBits, FULL_WINDOW_CONTENT) != IS(window.styleBits, FULL_WINDOW_CONTENT)) {
1128                NSRect frame = [nsWindow frame];
1129                NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:newBits];
1130                NSRect screenContentRect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];
1131                NSRect contentFrame = NSMakeRect(screenContentRect.origin.x - frame.origin.x,
1132                    screenContentRect.origin.y - frame.origin.y,
1133                    screenContentRect.size.width,
1134                    screenContentRect.size.height);
1135                nsWindow.contentView.frame = contentFrame;
1136                resized = YES;
1137            }
1138        }
1139
1140        // resets the NSWindow's style mask if the mask intersects any of those bits
1141        if (mask & MASK(_STYLE_PROP_BITMASK)) {
1142            [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
1143        }
1144
1145        // calls methods on NSWindow to change other properties, based on the mask
1146        if (mask & MASK(_METHOD_PROP_BITMASK)) {
1147            [window setPropertiesForStyleBits:newBits mask:mask];
1148        }
1149
1150        window.styleBits = newBits;
1151
1152        if (resized) {
1153            [window _deliverMoveResizeEvent];
1154        }
1155    }];
1156
1157JNI_COCOA_EXIT(env);
1158}
1159
1160/*
1161 * Class:     sun_lwawt_macosx_CPlatformWindow
1162 * Method:    nativeSetNSWindowMenuBar
1163 * Signature: (JJ)V
1164 */
1165JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
1166(JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
1167{
1168JNI_COCOA_ENTER(env);
1169
1170    NSWindow *nsWindow = OBJC(windowPtr);
1171    CMenuBar *menuBar = OBJC(menuBarPtr);
1172    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1173
1174        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1175
1176        if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1177            [window.javaMenuBar deactivate];
1178        }
1179
1180        window.javaMenuBar = menuBar;
1181
1182        CMenuBar* actualMenuBar = menuBar;
1183        if (actualMenuBar == nil) {
1184            actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
1185        }
1186
1187        if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1188            [CMenuBar activate:actualMenuBar modallyDisabled:NO];
1189        }
1190    }];
1191
1192JNI_COCOA_EXIT(env);
1193}
1194
1195/*
1196 * Class:     sun_lwawt_macosx_CPlatformWindow
1197 * Method:    nativeGetNSWindowInsets
1198 * Signature: (J)Ljava/awt/Insets;
1199 */
1200JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
1201(JNIEnv *env, jclass clazz, jlong windowPtr)
1202{
1203    jobject ret = NULL;
1204
1205JNI_COCOA_ENTER(env);
1206
1207    NSWindow *nsWindow = OBJC(windowPtr);
1208    __block NSRect contentRect = NSZeroRect;
1209    __block NSRect frame = NSZeroRect;
1210
1211    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1212
1213        frame = [nsWindow frame];
1214        contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
1215    }];
1216
1217    jint top = (jint)(frame.size.height - contentRect.size.height);
1218    jint left = (jint)(contentRect.origin.x - frame.origin.x);
1219    jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
1220    jint right = (jint)(frame.size.width - (contentRect.size.width + left));
1221
1222    DECLARE_CLASS_RETURN(jc_Insets, "java/awt/Insets", NULL);
1223    DECLARE_METHOD_RETURN(jc_Insets_ctor, jc_Insets, "<init>", "(IIII)V", NULL);
1224    ret = (*env)->NewObject(env, jc_Insets, jc_Insets_ctor, top, left, bottom, right);
1225
1226JNI_COCOA_EXIT(env);
1227    return ret;
1228}
1229
1230/*
1231 * Class:     sun_lwawt_macosx_CPlatformWindow
1232 * Method:    nativeSetNSWindowBounds
1233 * Signature: (JDDDD)V
1234 */
1235JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
1236(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
1237{
1238JNI_COCOA_ENTER(env);
1239
1240    NSRect jrect = NSMakeRect(originX, originY, width, height);
1241
1242    // TODO: not sure we need displayIfNeeded message in our view
1243    NSWindow *nsWindow = OBJC(windowPtr);
1244    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1245
1246        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1247
1248        NSRect rect = ConvertNSScreenRect(NULL, jrect);
1249        [window constrainSize:&rect.size];
1250
1251        [nsWindow setFrame:rect display:YES];
1252
1253        // only start tracking events if pointer is above the toplevel
1254        // TODO: should post an Entered event if YES.
1255        NSPoint mLocation = [NSEvent mouseLocation];
1256        [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
1257
1258        // ensure we repaint the whole window after the resize operation
1259        // (this will also re-enable screen updates, which were disabled above)
1260        // TODO: send PaintEvent
1261
1262        // the macOS may ignore our "setFrame" request, in this, case the
1263        // windowDidMove() will not come and we need to manually resync the
1264        // "java.awt.Window" and NSWindow locations, because "java.awt.Window"
1265        // already uses location ignored by the macOS.
1266        // see sun.lwawt.LWWindowPeer#notifyReshape()
1267        if (!NSEqualRects(rect, [nsWindow frame])) {
1268            [window _deliverMoveResizeEvent];
1269        }
1270    }];
1271
1272JNI_COCOA_EXIT(env);
1273}
1274
1275/*
1276 * Class:     sun_lwawt_macosx_CPlatformWindow
1277 * Method:    nativeSetNSWindowStandardFrame
1278 * Signature: (JDDDD)V
1279 */
1280JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame
1281(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY,
1282     jdouble width, jdouble height)
1283{
1284    JNI_COCOA_ENTER(env);
1285
1286    NSRect jrect = NSMakeRect(originX, originY, width, height);
1287
1288    NSWindow *nsWindow = OBJC(windowPtr);
1289    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1290
1291        NSRect rect = ConvertNSScreenRect(NULL, jrect);
1292        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1293        window.standardFrame = rect;
1294    }];
1295
1296    JNI_COCOA_EXIT(env);
1297}
1298
1299/*
1300 * Class:     sun_lwawt_macosx_CPlatformWindow
1301 * Method:    nativeSetNSWindowLocationByPlatform
1302 * Signature: (J)V
1303 */
1304JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowLocationByPlatform
1305(JNIEnv *env, jclass clazz, jlong windowPtr)
1306{
1307    JNI_COCOA_ENTER(env);
1308
1309    NSWindow *nsWindow = OBJC(windowPtr);
1310    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1311
1312        if (NSEqualPoints(lastTopLeftPoint, NSZeroPoint)) {
1313            // This is the first usage of lastTopLeftPoint. So invoke cascadeTopLeftFromPoint
1314            // twice to avoid positioning the window's top left to zero-point, since it may
1315            // cause negative user experience.
1316            lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1317        }
1318        lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1319    }];
1320
1321    JNI_COCOA_EXIT(env);
1322}
1323
1324/*
1325 * Class:     sun_lwawt_macosx_CPlatformWindow
1326 * Method:    nativeSetNSWindowMinMax
1327 * Signature: (JDDDD)V
1328 */
1329JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
1330(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
1331{
1332JNI_COCOA_ENTER(env);
1333
1334    if (minW < 1) minW = 1;
1335    if (minH < 1) minH = 1;
1336    if (maxW < 1) maxW = 1;
1337    if (maxH < 1) maxH = 1;
1338
1339    NSWindow *nsWindow = OBJC(windowPtr);
1340    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1341
1342        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1343
1344        NSSize min = { minW, minH };
1345        NSSize max = { maxW, maxH };
1346
1347        [window constrainSize:&min];
1348        [window constrainSize:&max];
1349
1350        window.javaMinSize = min;
1351        window.javaMaxSize = max;
1352        [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
1353    }];
1354
1355JNI_COCOA_EXIT(env);
1356}
1357
1358/*
1359 * Class:     sun_lwawt_macosx_CPlatformWindow
1360 * Method:    nativePushNSWindowToBack
1361 * Signature: (J)V
1362 */
1363JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
1364(JNIEnv *env, jclass clazz, jlong windowPtr)
1365{
1366JNI_COCOA_ENTER(env);
1367
1368    NSWindow *nsWindow = OBJC(windowPtr);
1369    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1370        [nsWindow orderBack:nil];
1371        // Order parent windows
1372        AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate];
1373        while (awtWindow.ownerWindow != nil) {
1374            awtWindow = awtWindow.ownerWindow;
1375            if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) {
1376                [awtWindow.nsWindow orderBack:nil];
1377            }
1378        }
1379        // Order child windows
1380        [(AWTWindow*)[nsWindow delegate] orderChildWindows:NO];
1381    }];
1382
1383JNI_COCOA_EXIT(env);
1384}
1385
1386/*
1387 * Class:     sun_lwawt_macosx_CPlatformWindow
1388 * Method:    nativePushNSWindowToFront
1389 * Signature: (J)V
1390 */
1391JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
1392(JNIEnv *env, jclass clazz, jlong windowPtr)
1393{
1394JNI_COCOA_ENTER(env);
1395
1396    NSWindow *nsWindow = OBJC(windowPtr);
1397    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1398
1399        if (![nsWindow isKeyWindow]) {
1400            [nsWindow makeKeyAndOrderFront:nsWindow];
1401        } else {
1402            [nsWindow orderFront:nsWindow];
1403        }
1404    }];
1405
1406JNI_COCOA_EXIT(env);
1407}
1408
1409/*
1410 * Class:     sun_lwawt_macosx_CPlatformWindow
1411 * Method:    nativeSetNSWindowTitle
1412 * Signature: (JLjava/lang/String;)V
1413 */
1414JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
1415(JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
1416{
1417JNI_COCOA_ENTER(env);
1418
1419    NSWindow *nsWindow = OBJC(windowPtr);
1420    [nsWindow performSelectorOnMainThread:@selector(setTitle:)
1421                              withObject:JavaStringToNSString(env, jtitle)
1422                           waitUntilDone:NO];
1423
1424JNI_COCOA_EXIT(env);
1425}
1426
1427/*
1428 * Class:     sun_lwawt_macosx_CPlatformWindow
1429 * Method:    nativeRevalidateNSWindowShadow
1430 * Signature: (J)V
1431 */
1432JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
1433(JNIEnv *env, jclass clazz, jlong windowPtr)
1434{
1435JNI_COCOA_ENTER(env);
1436
1437    NSWindow *nsWindow = OBJC(windowPtr);
1438    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1439        [nsWindow invalidateShadow];
1440    }];
1441
1442JNI_COCOA_EXIT(env);
1443}
1444
1445/*
1446 * Class:     sun_lwawt_macosx_CPlatformWindow
1447 * Method:    nativeScreenOn_AppKitThread
1448 * Signature: (J)I
1449 */
1450JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
1451(JNIEnv *env, jclass clazz, jlong windowPtr)
1452{
1453    jint ret = 0;
1454
1455JNI_COCOA_ENTER(env);
1456AWT_ASSERT_APPKIT_THREAD;
1457
1458    NSWindow *nsWindow = OBJC(windowPtr);
1459    NSDictionary *props = [[nsWindow screen] deviceDescription];
1460    ret = [[props objectForKey:@"NSScreenNumber"] intValue];
1461
1462JNI_COCOA_EXIT(env);
1463
1464    return ret;
1465}
1466
1467/*
1468 * Class:     sun_lwawt_macosx_CPlatformWindow
1469 * Method:    nativeSetNSWindowMinimizedIcon
1470 * Signature: (JJ)V
1471 */
1472JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
1473(JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
1474{
1475JNI_COCOA_ENTER(env);
1476
1477    NSWindow *nsWindow = OBJC(windowPtr);
1478    NSImage *image = OBJC(nsImagePtr);
1479    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1480        [nsWindow setMiniwindowImage:image];
1481    }];
1482
1483JNI_COCOA_EXIT(env);
1484}
1485
1486/*
1487 * Class:     sun_lwawt_macosx_CPlatformWindow
1488 * Method:    nativeSetNSWindowRepresentedFilename
1489 * Signature: (JLjava/lang/String;)V
1490 */
1491JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
1492(JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
1493{
1494JNI_COCOA_ENTER(env);
1495
1496    NSWindow *nsWindow = OBJC(windowPtr);
1497    NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:NormalizedPathNSStringFromJavaString(env, filename)];
1498    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1499        [nsWindow setRepresentedURL:url];
1500    }];
1501
1502JNI_COCOA_EXIT(env);
1503}
1504
1505/*
1506 * Class:     sun_lwawt_macosx_CPlatformWindow
1507 * Method:    nativeGetTopmostPlatformWindowUnderMouse
1508 * Signature: (J)V
1509 */
1510JNIEXPORT jobject
1511JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
1512(JNIEnv *env, jclass clazz)
1513{
1514    __block jobject topmostWindowUnderMouse = nil;
1515
1516    JNI_COCOA_ENTER(env);
1517
1518    [ThreadUtilities performOnMainThreadWaiting:YES block:^{
1519        AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
1520        if (awtWindow != nil) {
1521            topmostWindowUnderMouse = awtWindow.javaPlatformWindow;
1522        }
1523    }];
1524
1525    JNI_COCOA_EXIT(env);
1526
1527    return topmostWindowUnderMouse;
1528}
1529
1530/*
1531 * Class:     sun_lwawt_macosx_CPlatformWindow
1532 * Method:    nativeSynthesizeMouseEnteredExitedEvents
1533 * Signature: ()V
1534 */
1535JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__
1536(JNIEnv *env, jclass clazz)
1537{
1538    JNI_COCOA_ENTER(env);
1539
1540    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1541        [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
1542    }];
1543
1544    JNI_COCOA_EXIT(env);
1545}
1546
1547/*
1548 * Class:     sun_lwawt_macosx_CPlatformWindow
1549 * Method:    nativeSynthesizeMouseEnteredExitedEvents
1550 * Signature: (JI)V
1551 */
1552JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__JI
1553(JNIEnv *env, jclass clazz, jlong windowPtr, jint eventType)
1554{
1555JNI_COCOA_ENTER(env);
1556
1557    if (eventType == NSMouseEntered || eventType == NSMouseExited) {
1558        NSWindow *nsWindow = OBJC(windowPtr);
1559
1560        [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1561            [AWTWindow synthesizeMouseEnteredExitedEvents:nsWindow withType:eventType];
1562        }];
1563    } else {
1564        JNU_ThrowIllegalArgumentException(env, "unknown event type");
1565    }
1566
1567JNI_COCOA_EXIT(env);
1568}
1569
1570/*
1571 * Class:     sun_lwawt_macosx_CPlatformWindow
1572 * Method:    _toggleFullScreenMode
1573 * Signature: (J)V
1574 */
1575JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1576(JNIEnv *env, jobject peer, jlong windowPtr)
1577{
1578JNI_COCOA_ENTER(env);
1579
1580    NSWindow *nsWindow = OBJC(windowPtr);
1581    SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1582    if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
1583
1584    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1585        [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
1586    }];
1587
1588JNI_COCOA_EXIT(env);
1589}
1590
1591JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1592(JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1593{
1594JNI_COCOA_ENTER(env);
1595
1596    NSWindow *nsWindow = OBJC(windowPtr);
1597    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1598        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1599
1600        [window setEnabled: isEnabled];
1601    }];
1602
1603JNI_COCOA_EXIT(env);
1604}
1605
1606JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDispose
1607(JNIEnv *env, jclass clazz, jlong windowPtr)
1608{
1609JNI_COCOA_ENTER(env);
1610
1611    NSWindow *nsWindow = OBJC(windowPtr);
1612    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1613        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1614
1615        if ([AWTWindow lastKeyWindow] == window) {
1616            [AWTWindow setLastKeyWindow: nil];
1617        }
1618
1619        // AWTWindow holds a reference to the NSWindow in its nsWindow
1620        // property. Unsetting the delegate allows it to be deallocated
1621        // which releases the reference. This, in turn, allows the window
1622        // itself be deallocated.
1623        [nsWindow setDelegate: nil];
1624
1625        [window release];
1626    }];
1627
1628JNI_COCOA_EXIT(env);
1629}
1630
1631JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeEnterFullScreenMode
1632(JNIEnv *env, jclass clazz, jlong windowPtr)
1633{
1634JNI_COCOA_ENTER(env);
1635
1636    NSWindow *nsWindow = OBJC(windowPtr);
1637    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1638        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1639        NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1640        CGDirectDisplayID aID = [screenID intValue];
1641
1642        if (CGDisplayCapture(aID) == kCGErrorSuccess) {
1643            // remove window decoration
1644            NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1645            [nsWindow setStyleMask:(styleMask & ~NSTitledWindowMask) | NSBorderlessWindowMask];
1646
1647            int shieldLevel = CGShieldingWindowLevel();
1648            window.preFullScreenLevel = [nsWindow level];
1649            [nsWindow setLevel: shieldLevel];
1650
1651            NSRect screenRect = [[nsWindow screen] frame];
1652            [nsWindow setFrame:screenRect display:YES];
1653        } else {
1654            [NSException raise:@"Java Exception" reason:@"Failed to enter full screen." userInfo:nil];
1655        }
1656    }];
1657
1658JNI_COCOA_EXIT(env);
1659}
1660
1661JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeExitFullScreenMode
1662(JNIEnv *env, jclass clazz, jlong windowPtr)
1663{
1664JNI_COCOA_ENTER(env);
1665
1666    NSWindow *nsWindow = OBJC(windowPtr);
1667    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1668        AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1669        NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1670        CGDirectDisplayID aID = [screenID intValue];
1671
1672        if (CGDisplayRelease(aID) == kCGErrorSuccess) {
1673            NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1674            [nsWindow setStyleMask:styleMask];
1675            [nsWindow setLevel: window.preFullScreenLevel];
1676
1677            // GraphicsDevice takes care of restoring pre full screen bounds
1678        } else {
1679            [NSException raise:@"Java Exception" reason:@"Failed to exit full screen." userInfo:nil];
1680        }
1681    }];
1682
1683JNI_COCOA_EXIT(env);
1684}
1685
1686