Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
41152 views
/*1* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import <Cocoa/Cocoa.h>2627#import "sun_lwawt_macosx_CPlatformWindow.h"28#import "com_apple_eawt_event_GestureHandler.h"29#import "com_apple_eawt_FullScreenHandler.h"30#import "ApplicationDelegate.h"3132#import "AWTWindow.h"33#import "AWTView.h"34#import "GeomUtilities.h"35#import "ThreadUtilities.h"36#import "JNIUtilities.h"3738#define MASK(KEY) \39(sun_lwawt_macosx_CPlatformWindow_ ## KEY)4041#define IS(BITS, KEY) \42((BITS & MASK(KEY)) != 0)4344#define SET(BITS, KEY, VALUE) \45BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)4647static jclass jc_CPlatformWindow = NULL;48#define GET_CPLATFORM_WINDOW_CLASS() \49GET_CLASS(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");5051#define GET_CPLATFORM_WINDOW_CLASS_RETURN(ret) \52GET_CLASS_RETURN(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow", ret);5354// Cocoa windowDidBecomeKey/windowDidResignKey notifications55// doesn't provide information about "opposite" window, so we56// have to do a bit of tracking. This variable points to a window57// which had been the key window just before a new key window58// was set. It would be nil if the new key window isn't an AWT59// window or the app currently has no key window.60static AWTWindow* lastKeyWindow = nil;6162// This variable contains coordinates of a window's top left63// which was positioned via java.awt.Window.setLocationByPlatform.64// It would be NSZeroPoint if 'Location by Platform' is not used.65static NSPoint lastTopLeftPoint;6667// --------------------------------------------------------------68// NSWindow/NSPanel descendants implementation69#define AWT_NS_WINDOW_IMPLEMENTATION \70- (id) initWithDelegate:(AWTWindow *)delegate \71frameRect:(NSRect)contectRect \72styleMask:(NSUInteger)styleMask \73contentView:(NSView *)view \74{ \75self = [super initWithContentRect:contectRect \76styleMask:styleMask \77backing:NSBackingStoreBuffered \78defer:NO]; \79\80if (self == nil) return nil; \81\82[self setDelegate:delegate]; \83[self setContentView:view]; \84[self setInitialFirstResponder:view]; \85[self setReleasedWhenClosed:NO]; \86[self setPreservesContentDuringLiveResize:YES]; \87\88return self; \89} \90\91/* NSWindow overrides */ \92- (BOOL) canBecomeKeyWindow { \93return [(AWTWindow*)[self delegate] canBecomeKeyWindow]; \94} \95\96- (BOOL) canBecomeMainWindow { \97return [(AWTWindow*)[self delegate] canBecomeMainWindow]; \98} \99\100- (BOOL) worksWhenModal { \101return [(AWTWindow*)[self delegate] worksWhenModal]; \102} \103\104- (void)sendEvent:(NSEvent *)event { \105[(AWTWindow*)[self delegate] sendEvent:event]; \106[super sendEvent:event]; \107}108109@implementation AWTWindow_Normal110AWT_NS_WINDOW_IMPLEMENTATION111112// Gesture support113- (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {114AWT_ASSERT_APPKIT_THREAD;115116JNIEnv *env = [ThreadUtilities getJNIEnv];117jobject platformWindow = (*env)->NewLocalRef(env, ((AWTWindow *)self.delegate).javaPlatformWindow);118if (platformWindow != NULL) {119// extract the target AWT Window object out of the CPlatformWindow120GET_CPLATFORM_WINDOW_CLASS();121DECLARE_FIELD(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");122jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);123if (awtWindow != NULL) {124// translate the point into Java coordinates125NSPoint loc = [event locationInWindow];126loc.y = [self frame].size.height - loc.y;127128// send up to the GestureHandler to recursively dispatch on the AWT event thread129DECLARE_CLASS(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");130DECLARE_METHOD(sjm_handleGestureFromNative, jc_GestureHandler,131"handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");132(*env)->CallStaticVoidMethod(env, jc_GestureHandler, sjm_handleGestureFromNative,133awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);134CHECK_EXCEPTION();135(*env)->DeleteLocalRef(env, awtWindow);136}137(*env)->DeleteLocalRef(env, platformWindow);138}139}140141- (void)beginGestureWithEvent:(NSEvent *)event {142[self postGesture:event143as:com_apple_eawt_event_GestureHandler_PHASE144a:-1.0145b:0.0];146}147148- (void)endGestureWithEvent:(NSEvent *)event {149[self postGesture:event150as:com_apple_eawt_event_GestureHandler_PHASE151a:1.0152b:0.0];153}154155- (void)magnifyWithEvent:(NSEvent *)event {156[self postGesture:event157as:com_apple_eawt_event_GestureHandler_MAGNIFY158a:[event magnification]159b:0.0];160}161162- (void)rotateWithEvent:(NSEvent *)event {163[self postGesture:event164as:com_apple_eawt_event_GestureHandler_ROTATE165a:[event rotation]166b:0.0];167}168169- (void)swipeWithEvent:(NSEvent *)event {170[self postGesture:event171as:com_apple_eawt_event_GestureHandler_SWIPE172a:[event deltaX]173b:[event deltaY]];174}175176@end177@implementation AWTWindow_Panel178AWT_NS_WINDOW_IMPLEMENTATION179@end180// END of NSWindow/NSPanel descendants implementation181// --------------------------------------------------------------182183184@implementation AWTWindow185186@synthesize nsWindow;187@synthesize javaPlatformWindow;188@synthesize javaMenuBar;189@synthesize javaMinSize;190@synthesize javaMaxSize;191@synthesize styleBits;192@synthesize isEnabled;193@synthesize ownerWindow;194@synthesize preFullScreenLevel;195@synthesize standardFrame;196@synthesize isMinimizing;197@synthesize keyNotificationRecd;198199- (void) updateMinMaxSize:(BOOL)resizable {200if (resizable) {201[self.nsWindow setMinSize:self.javaMinSize];202[self.nsWindow setMaxSize:self.javaMaxSize];203} else {204NSRect currentFrame = [self.nsWindow frame];205[self.nsWindow setMinSize:currentFrame.size];206[self.nsWindow setMaxSize:currentFrame.size];207}208}209210// creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits211+ (NSUInteger) styleMaskForStyleBits:(jint)styleBits {212NSUInteger type = 0;213if (IS(styleBits, DECORATED)) {214type |= NSTitledWindowMask;215if (IS(styleBits, CLOSEABLE)) type |= NSClosableWindowMask;216if (IS(styleBits, RESIZABLE)) type |= NSResizableWindowMask;217if (IS(styleBits, FULL_WINDOW_CONTENT)) type |= NSFullSizeContentViewWindowMask;218} else {219type |= NSBorderlessWindowMask;220}221222if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;223if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;224if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;225if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;226if (IS(styleBits, HUD)) type |= NSHUDWindowMask;227if (IS(styleBits, SHEET)) type |= NSWindowStyleMaskDocModalWindow;228if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;229230return type;231}232233// updates _METHOD_PROP_BITMASK based properties on the window234- (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {235if (IS(mask, RESIZABLE)) {236BOOL 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.241BOOL zoom = resizable && IS(bits, ZOOMABLE);242[[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:zoom];243}244245if (IS(mask, HAS_SHADOW)) {246[self.nsWindow setHasShadow:IS(bits, HAS_SHADOW)];247}248249if (IS(mask, ZOOMABLE)) {250[[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];251}252253if (IS(mask, ALWAYS_ON_TOP)) {254[self.nsWindow setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];255}256257if (IS(mask, HIDES_ON_DEACTIVATE)) {258[self.nsWindow setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];259}260261if (IS(mask, DRAGGABLE_BACKGROUND)) {262[self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];263}264265if (IS(mask, DOCUMENT_MODIFIED)) {266[self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];267}268269if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {270if (IS(bits, FULLSCREENABLE)) {271[self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];272} else {273[self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];274}275}276277if (IS(mask, TRANSPARENT_TITLE_BAR) && [self.nsWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {278[self.nsWindow setTitlebarAppearsTransparent:IS(bits, TRANSPARENT_TITLE_BAR)];279}280281if (IS(mask, TITLE_VISIBLE) && [self.nsWindow respondsToSelector:@selector(setTitleVisibility:)]) {282[self.nsWindow setTitleVisibility:(IS(bits, TITLE_VISIBLE)) ? NSWindowTitleVisible :NSWindowTitleHidden];283}284285}286287- (id) initWithPlatformWindow:(jobject)platformWindow288ownerWindow:owner289styleBits:(jint)bits290frameRect:(NSRect)rect291contentView:(NSView *)view292{293AWT_ASSERT_APPKIT_THREAD;294295NSUInteger newBits = bits;296if (IS(bits, SHEET) && owner == nil) {297newBits = bits & ~NSWindowStyleMaskDocModalWindow;298}299NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:newBits];300301NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];302if (contentRect.size.width <= 0.0) {303contentRect.size.width = 1.0;304}305if (contentRect.size.height <= 0.0) {306contentRect.size.height = 1.0;307}308309self = [super init];310311if (self == nil) return nil; // no hope312313if (IS(bits, UTILITY) ||314IS(bits, NONACTIVATING) ||315IS(bits, HUD) ||316IS(bits, HIDES_ON_DEACTIVATE) ||317IS(bits, SHEET))318{319self.nsWindow = [[AWTWindow_Panel alloc] initWithDelegate:self320frameRect:contentRect321styleMask:styleMask322contentView:view];323}324else325{326// These windows will appear in the window list in the dock icon menu327self.nsWindow = [[AWTWindow_Normal alloc] initWithDelegate:self328frameRect:contentRect329styleMask:styleMask330contentView:view];331}332333if (self.nsWindow == nil) return nil; // no hope either334[self.nsWindow release]; // the property retains the object already335336self.keyNotificationRecd = NO;337self.isEnabled = YES;338self.isMinimizing = NO;339self.javaPlatformWindow = platformWindow;340self.styleBits = bits;341self.ownerWindow = owner;342[self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];343344if (IS(self.styleBits, IS_POPUP)) {345[self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];346}347348if (IS(bits, SHEET) && owner != nil) {349[self.nsWindow setStyleMask: NSWindowStyleMaskDocModalWindow];350}351352return self;353}354355+ (BOOL) isAWTWindow:(NSWindow *)window {356return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];357}358359// Retrieves the list of possible window layers (levels)360+ (NSArray*) getWindowLayers {361static NSArray *windowLayers;362static dispatch_once_t token;363364// Initialize the list of possible window layers365dispatch_once(&token, ^{366// The layers are ordered from front to back, (i.e. the toppest one is the first)367windowLayers = [NSArray arrayWithObjects:368[NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)],369[NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)],370[NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)],371nil372];373[windowLayers retain];374});375return windowLayers;376}377378// returns id for the topmost window under mouse379+ (NSInteger) getTopmostWindowUnderMouseID {380NSInteger result = -1;381382NSArray *windowLayers = [AWTWindow getWindowLayers];383// Looking for the window under mouse starting from the toppest layer384for (NSNumber *layer in windowLayers) {385result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]];386if (result != -1) {387break;388}389}390return result;391}392393+ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer {394NSInteger result = -1;395396NSRect screenRect = [[NSScreen mainScreen] frame];397NSPoint nsMouseLocation = [NSEvent mouseLocation];398CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);399400NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);401402for (NSDictionary *window in windows) {403NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];404if (layer == windowLayer) {405CGRect rect;406CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);407if (CGRectContainsPoint(rect, cgMouseLocation)) {408result = [[window objectForKey:(id)kCGWindowNumber] integerValue];409break;410}411}412}413[windows release];414return result;415}416417// checks that this window is under the mouse cursor and this point is not overlapped by others windows418- (BOOL) isTopmostWindowUnderMouse {419return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID];420}421422+ (AWTWindow *) getTopmostWindowUnderMouse {423NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator];424NSWindow *window;425426NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];427428while ((window = [windowEnumerator nextObject]) != nil) {429if ([window windowNumber] == topmostWindowUnderMouseID) {430BOOL isAWTWindow = [AWTWindow isAWTWindow: window];431return isAWTWindow ? (AWTWindow *) [window delegate] : nil;432}433}434return nil;435}436437+ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType {438439NSPoint screenLocation = [NSEvent mouseLocation];440NSPoint windowLocation = [window convertScreenToBase: screenLocation];441int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;442443NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType444location: windowLocation445modifierFlags: modifierFlags446timestamp: 0447windowNumber: [window windowNumber]448context: nil449eventNumber: 0450trackingNumber: 0451userData: nil452];453454[[window contentView] deliverJavaMouseEvent: mouseEvent];455}456457+ (void) synthesizeMouseEnteredExitedEventsForAllWindows {458459NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];460NSArray *windows = [NSApp windows];461NSWindow *window;462463NSEnumerator *windowEnumerator = [windows objectEnumerator];464while ((window = [windowEnumerator nextObject]) != nil) {465if ([AWTWindow isAWTWindow: window]) {466BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID);467BOOL mouseIsOver = [[window contentView] mouseIsOver];468if (isUnderMouse && !mouseIsOver) {469[AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];470} else if (!isUnderMouse && mouseIsOver) {471[AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];472}473}474}475}476477+ (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window {478AWT_ASSERT_APPKIT_THREAD;479NSScreen *screen = [window screen];480NSDictionary *deviceDescription = [screen deviceDescription];481return [deviceDescription objectForKey:@"NSScreenNumber"];482}483484- (void) dealloc {485AWT_ASSERT_APPKIT_THREAD;486487JNIEnv *env = [ThreadUtilities getJNIEnvUncached];488(*env)->DeleteWeakGlobalRef(env, self.javaPlatformWindow);489self.javaPlatformWindow = nil;490self.nsWindow = nil;491self.ownerWindow = nil;492[super dealloc];493}494495// Tests whether window is blocked by modal dialog/window496- (BOOL) isBlocked {497BOOL isBlocked = NO;498499JNIEnv *env = [ThreadUtilities getJNIEnv];500jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);501if (platformWindow != NULL) {502GET_CPLATFORM_WINDOW_CLASS_RETURN(isBlocked);503DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z", isBlocked);504isBlocked = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;505CHECK_EXCEPTION();506(*env)->DeleteLocalRef(env, platformWindow);507}508509return isBlocked;510}511512// Test whether window is simple window and owned by embedded frame513- (BOOL) isSimpleWindowOwnedByEmbeddedFrame {514BOOL isSimpleWindowOwnedByEmbeddedFrame = NO;515516JNIEnv *env = [ThreadUtilities getJNIEnv];517jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);518if (platformWindow != NULL) {519GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);520DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isSimpleWindowOwnedByEmbeddedFrame", "()Z", NO);521isSimpleWindowOwnedByEmbeddedFrame = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;522CHECK_EXCEPTION();523(*env)->DeleteLocalRef(env, platformWindow);524}525526return isSimpleWindowOwnedByEmbeddedFrame;527}528529// Tests whether the corresponding Java platform window is visible or not530+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {531BOOL isVisible = NO;532533if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {534AWTWindow *awtWindow = (AWTWindow *)[window delegate];535[AWTToolkit eventCountPlusPlus];536537JNIEnv *env = [ThreadUtilities getJNIEnv];538jobject platformWindow = (*env)->NewLocalRef(env, awtWindow.javaPlatformWindow);539if (platformWindow != NULL) {540GET_CPLATFORM_WINDOW_CLASS_RETURN(isVisible);541DECLARE_METHOD_RETURN(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z", isVisible)542isVisible = (*env)->CallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;543CHECK_EXCEPTION();544(*env)->DeleteLocalRef(env, platformWindow);545546}547}548return isVisible;549}550551// Orders window's childs based on the current focus state552- (void) orderChildWindows:(BOOL)focus {553AWT_ASSERT_APPKIT_THREAD;554555if (self.isMinimizing || [self isBlocked]) {556// Do not perform any ordering, if iconify is in progress557// or the window is blocked by a modal window558return;559}560561NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];562NSWindow *window;563while ((window = [windowEnumerator nextObject]) != nil) {564if ([AWTWindow isJavaPlatformWindowVisible:window]) {565AWTWindow *awtWindow = (AWTWindow *)[window delegate];566AWTWindow *owner = awtWindow.ownerWindow;567if (IS(awtWindow.styleBits, ALWAYS_ON_TOP)) {568// Do not order 'always on top' windows569continue;570}571while (awtWindow.ownerWindow != nil) {572if (awtWindow.ownerWindow == self) {573if (focus) {574// Move the childWindow to floating level575// so it will appear in front of its576// parent which owns the focus577[window setLevel:NSFloatingWindowLevel];578} else {579// Focus owner has changed, move the childWindow580// back to normal window level581[window setLevel:NSNormalWindowLevel];582}583// The childWindow should be displayed in front of584// its nearest parentWindow585[window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]];586break;587}588awtWindow = awtWindow.ownerWindow;589}590}591}592}593594// NSWindow overrides595- (BOOL) canBecomeKeyWindow {596AWT_ASSERT_APPKIT_THREAD;597return self.isEnabled && (IS(self.styleBits, SHOULD_BECOME_KEY) || [self isSimpleWindowOwnedByEmbeddedFrame]);598}599600- (BOOL) canBecomeMainWindow {601AWT_ASSERT_APPKIT_THREAD;602if (!self.isEnabled) {603// Native system can bring up the NSWindow to604// the top even if the window is not main.605// We should bring up the modal dialog manually606[AWTToolkit eventCountPlusPlus];607608JNIEnv *env = [ThreadUtilities getJNIEnv];609jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);610if (platformWindow != NULL) {611GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);612DECLARE_METHOD_RETURN(jm_checkBlockingAndOrder, jc_CPlatformWindow, "checkBlockingAndOrder", "()Z", NO);613(*env)->CallBooleanMethod(env, platformWindow, jm_checkBlockingAndOrder);614CHECK_EXCEPTION();615(*env)->DeleteLocalRef(env, platformWindow);616}617}618619return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);620}621622- (BOOL) worksWhenModal {623AWT_ASSERT_APPKIT_THREAD;624return IS(self.styleBits, MODAL_EXCLUDED);625}626627628// NSWindowDelegate methods629630- (void) _deliverMoveResizeEvent {631AWT_ASSERT_APPKIT_THREAD;632633// deliver the event if this is a user-initiated live resize or as a side-effect634// of a Java initiated resize, because AppKit can override the bounds and force635// the bounds of the window to avoid the Dock or remain on screen.636[AWTToolkit eventCountPlusPlus];637JNIEnv *env = [ThreadUtilities getJNIEnv];638jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);639if (platformWindow == NULL) {640// TODO: create generic AWT assert641}642643NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);644645GET_CPLATFORM_WINDOW_CLASS();646DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");647(*env)->CallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,648(jint)frame.origin.x,649(jint)frame.origin.y,650(jint)frame.size.width,651(jint)frame.size.height,652(jboolean)[self.nsWindow inLiveResize]);653CHECK_EXCEPTION();654(*env)->DeleteLocalRef(env, platformWindow);655656[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];657}658659- (void)windowDidMove:(NSNotification *)notification {660AWT_ASSERT_APPKIT_THREAD;661662[self _deliverMoveResizeEvent];663}664665- (void)windowDidResize:(NSNotification *)notification {666AWT_ASSERT_APPKIT_THREAD;667668[self _deliverMoveResizeEvent];669}670671- (void)windowDidExpose:(NSNotification *)notification {672AWT_ASSERT_APPKIT_THREAD;673674[AWTToolkit eventCountPlusPlus];675// TODO: don't see this callback invoked anytime so we track676// window exposing in _setVisible:(BOOL)677}678679- (NSRect)windowWillUseStandardFrame:(NSWindow *)window680defaultFrame:(NSRect)newFrame {681682return NSEqualSizes(NSZeroSize, [self standardFrame].size)683? newFrame684: [self standardFrame];685}686687// Hides/shows window's childs during iconify/de-iconify operation688- (void) iconifyChildWindows:(BOOL)iconify {689AWT_ASSERT_APPKIT_THREAD;690691NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];692NSWindow *window;693while ((window = [windowEnumerator nextObject]) != nil) {694if ([AWTWindow isJavaPlatformWindowVisible:window]) {695AWTWindow *awtWindow = (AWTWindow *)[window delegate];696while (awtWindow.ownerWindow != nil) {697if (awtWindow.ownerWindow == self) {698if (iconify) {699[window orderOut:window];700} else {701[window orderFront:window];702}703break;704}705awtWindow = awtWindow.ownerWindow;706}707}708}709}710711- (void) _deliverIconify:(BOOL)iconify {712AWT_ASSERT_APPKIT_THREAD;713714[AWTToolkit eventCountPlusPlus];715JNIEnv *env = [ThreadUtilities getJNIEnv];716jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);717if (platformWindow != NULL) {718GET_CPLATFORM_WINDOW_CLASS();719DECLARE_METHOD(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");720(*env)->CallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);721CHECK_EXCEPTION();722(*env)->DeleteLocalRef(env, platformWindow);723}724}725726- (void)windowWillMiniaturize:(NSNotification *)notification {727AWT_ASSERT_APPKIT_THREAD;728729self.isMinimizing = YES;730731JNIEnv *env = [ThreadUtilities getJNIEnv];732jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);733if (platformWindow != NULL) {734GET_CPLATFORM_WINDOW_CLASS();735DECLARE_METHOD(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");736(*env)->CallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);737CHECK_EXCEPTION();738(*env)->DeleteLocalRef(env, platformWindow);739}740// Explicitly make myself a key window to avoid possible741// negative visual effects during iconify operation742[self.nsWindow makeKeyAndOrderFront:self.nsWindow];743[self iconifyChildWindows:YES];744}745746- (void)windowDidMiniaturize:(NSNotification *)notification {747AWT_ASSERT_APPKIT_THREAD;748749[self _deliverIconify:JNI_TRUE];750self.isMinimizing = NO;751}752753- (void)windowDidDeminiaturize:(NSNotification *)notification {754AWT_ASSERT_APPKIT_THREAD;755756[self _deliverIconify:JNI_FALSE];757[self iconifyChildWindows:NO];758}759760- (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {761//AWT_ASSERT_APPKIT_THREAD;762JNIEnv *env = [ThreadUtilities getJNIEnvUncached];763jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);764if (platformWindow != NULL) {765jobject oppositeWindow = (*env)->NewLocalRef(env, opposite.javaPlatformWindow);766GET_CPLATFORM_WINDOW_CLASS();767DECLARE_METHOD(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");768(*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);769CHECK_EXCEPTION();770(*env)->DeleteLocalRef(env, platformWindow);771(*env)->DeleteLocalRef(env, oppositeWindow);772}773}774775- (void) windowDidBecomeMain: (NSNotification *) notification {776AWT_ASSERT_APPKIT_THREAD;777[AWTToolkit eventCountPlusPlus];778#ifdef DEBUG779NSLog(@"became main: %d %@ %@ %d", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow], self.keyNotificationRecd);780#endif781782// if for some reason, no KEY notification is received but this main window is also a key window783// then we need to execute the KEY notification functionality.784if(self.keyNotificationRecd != YES && [self.nsWindow isKeyWindow]) {785[self doWindowDidBecomeKey];786}787self.keyNotificationRecd = NO;788789if (![self.nsWindow isKeyWindow]) {790[self activateWindowMenuBar];791}792793JNIEnv *env = [ThreadUtilities getJNIEnv];794jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);795if (platformWindow != NULL) {796GET_CPLATFORM_WINDOW_CLASS();797DECLARE_METHOD(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");798(*env)->CallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);799CHECK_EXCEPTION();800(*env)->DeleteLocalRef(env, platformWindow);801}802}803804- (void) windowDidBecomeKey: (NSNotification *) notification {805AWT_ASSERT_APPKIT_THREAD;806[AWTToolkit eventCountPlusPlus];807#ifdef DEBUG808NSLog(@"became key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);809#endif810[self doWindowDidBecomeKey];811self.keyNotificationRecd = YES;812}813814- (void) doWindowDidBecomeKey {815AWT_ASSERT_APPKIT_THREAD;816AWTWindow *opposite = [AWTWindow lastKeyWindow];817818if (![self.nsWindow isMainWindow]) {819[self activateWindowMenuBar];820}821822[AWTWindow setLastKeyWindow:nil];823824[self _deliverWindowFocusEvent:YES oppositeWindow: opposite];825[self orderChildWindows:YES];826}827828- (void) activateWindowMenuBar {829AWT_ASSERT_APPKIT_THREAD;830// Finds appropriate menubar in our hierarchy831AWTWindow *awtWindow = self;832while (awtWindow.ownerWindow != nil) {833awtWindow = awtWindow.ownerWindow;834}835836CMenuBar *menuBar = nil;837BOOL isDisabled = NO;838if ([awtWindow.nsWindow isVisible]){839menuBar = awtWindow.javaMenuBar;840isDisabled = !awtWindow.isEnabled;841}842843if (menuBar == nil) {844menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];845isDisabled = NO;846}847848[CMenuBar activate:menuBar modallyDisabled:isDisabled];849}850851#ifdef DEBUG852- (CMenuBar *) menuBarForWindow {853AWT_ASSERT_APPKIT_THREAD;854AWTWindow *awtWindow = self;855while (awtWindow.ownerWindow != nil) {856awtWindow = awtWindow.ownerWindow;857}858return awtWindow.javaMenuBar;859}860#endif861862- (void) windowDidResignKey: (NSNotification *) notification {863// TODO: check why sometimes at start is invoked *not* on AppKit main thread.864AWT_ASSERT_APPKIT_THREAD;865[AWTToolkit eventCountPlusPlus];866#ifdef DEBUG867NSLog(@"resigned key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);868#endif869if (![self.nsWindow isMainWindow]) {870[self deactivateWindow];871}872}873874- (void) windowDidResignMain: (NSNotification *) notification {875AWT_ASSERT_APPKIT_THREAD;876[AWTToolkit eventCountPlusPlus];877#ifdef DEBUG878NSLog(@"resigned main: %d %@ %@", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow]);879#endif880if (![self.nsWindow isKeyWindow]) {881[self deactivateWindow];882}883}884885- (void) deactivateWindow {886AWT_ASSERT_APPKIT_THREAD;887#ifdef DEBUG888NSLog(@"deactivating window: %@", [self.nsWindow title]);889#endif890[self.javaMenuBar deactivate];891892// the new key window893NSWindow *keyWindow = [NSApp keyWindow];894AWTWindow *opposite = nil;895if ([AWTWindow isAWTWindow: keyWindow]) {896opposite = (AWTWindow *)[keyWindow delegate];897[AWTWindow setLastKeyWindow: self];898} else {899[AWTWindow setLastKeyWindow: nil];900}901902[self _deliverWindowFocusEvent:NO oppositeWindow: opposite];903[self orderChildWindows:NO];904}905906- (BOOL)windowShouldClose:(id)sender {907AWT_ASSERT_APPKIT_THREAD;908[AWTToolkit eventCountPlusPlus];909JNIEnv *env = [ThreadUtilities getJNIEnv];910jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);911if (platformWindow != NULL) {912GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);913DECLARE_METHOD_RETURN(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V", NO);914(*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);915CHECK_EXCEPTION();916(*env)->DeleteLocalRef(env, platformWindow);917}918// The window will be closed (if allowed) as result of sending Java event919return NO;920}921922- (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {923DECLARE_CLASS(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");924DECLARE_STATIC_METHOD(jm_notifyFullScreenOperation, jc_FullScreenHandler,925"handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");926GET_CPLATFORM_WINDOW_CLASS();927DECLARE_FIELD(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");928jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);929if (platformWindow != NULL) {930jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);931if (awtWindow != NULL) {932(*env)->CallStaticVoidMethod(env, jc_FullScreenHandler, jm_notifyFullScreenOperation, awtWindow, op);933CHECK_EXCEPTION();934(*env)->DeleteLocalRef(env, awtWindow);935}936(*env)->DeleteLocalRef(env, platformWindow);937}938}939940941- (void)windowWillEnterFullScreen:(NSNotification *)notification {942JNIEnv *env = [ThreadUtilities getJNIEnv];943GET_CPLATFORM_WINDOW_CLASS();944DECLARE_METHOD(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");945jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);946if (platformWindow != NULL) {947(*env)->CallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);948CHECK_EXCEPTION();949[self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];950(*env)->DeleteLocalRef(env, platformWindow);951}952}953954- (void)windowDidEnterFullScreen:(NSNotification *)notification {955JNIEnv *env = [ThreadUtilities getJNIEnv];956GET_CPLATFORM_WINDOW_CLASS();957DECLARE_METHOD(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");958jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);959if (platformWindow != NULL) {960(*env)->CallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);961CHECK_EXCEPTION();962[self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];963(*env)->DeleteLocalRef(env, platformWindow);964}965[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];966}967968- (void)windowWillExitFullScreen:(NSNotification *)notification {969JNIEnv *env = [ThreadUtilities getJNIEnv];970GET_CPLATFORM_WINDOW_CLASS();971DECLARE_METHOD(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");972if (jm_windowWillExitFullScreen == NULL) {973GET_CPLATFORM_WINDOW_CLASS();974jm_windowWillExitFullScreen = (*env)->GetMethodID(env, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");975}976CHECK_NULL(jm_windowWillExitFullScreen);977jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);978if (platformWindow != NULL) {979(*env)->CallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);980CHECK_EXCEPTION();981[self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];982(*env)->DeleteLocalRef(env, platformWindow);983}984}985986- (void)windowDidExitFullScreen:(NSNotification *)notification {987JNIEnv *env = [ThreadUtilities getJNIEnv];988jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);989if (platformWindow != NULL) {990GET_CPLATFORM_WINDOW_CLASS();991DECLARE_METHOD(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");992(*env)->CallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);993CHECK_EXCEPTION();994[self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];995(*env)->DeleteLocalRef(env, platformWindow);996}997[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];998}9991000- (void)sendEvent:(NSEvent *)event {1001if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {1002if ([self isBlocked]) {1003// Move parent windows to front and make sure that a child window is displayed1004// in front of its nearest parent.1005if (self.ownerWindow != nil) {1006JNIEnv *env = [ThreadUtilities getJNIEnvUncached];1007jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);1008if (platformWindow != NULL) {1009GET_CPLATFORM_WINDOW_CLASS();1010DECLARE_METHOD(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");1011(*env)->CallVoidMethod(env,platformWindow, jm_orderAboveSiblings);1012CHECK_EXCEPTION();1013(*env)->DeleteLocalRef(env, platformWindow);1014}1015}1016[self orderChildWindows:YES];1017}10181019NSPoint p = [NSEvent mouseLocation];1020NSRect frame = [self.nsWindow frame];1021NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];10221023// Check if the click happened in the non-client area (title bar)1024if (p.y >= (frame.origin.y + contentRect.size.height)) {1025JNIEnv *env = [ThreadUtilities getJNIEnvUncached];1026jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);1027if (platformWindow != NULL) {1028// Currently, no need to deliver the whole NSEvent.1029GET_CPLATFORM_WINDOW_CLASS();1030DECLARE_METHOD(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");1031(*env)->CallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);1032CHECK_EXCEPTION();1033(*env)->DeleteLocalRef(env, platformWindow);1034}1035}1036}1037}10381039- (void)constrainSize:(NSSize*)size {1040float minWidth = 0.f, minHeight = 0.f;10411042if (IS(self.styleBits, DECORATED)) {1043NSRect frame = [self.nsWindow frame];1044NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];10451046float top = frame.size.height - contentRect.size.height;1047float left = contentRect.origin.x - frame.origin.x;1048float bottom = contentRect.origin.y - frame.origin.y;1049float right = frame.size.width - (contentRect.size.width + left);10501051// Speculative estimation: 80 - enough for window decorations controls1052minWidth += left + right + 80;1053minHeight += top + bottom;1054}10551056minWidth = MAX(1.f, minWidth);1057minHeight = MAX(1.f, minHeight);10581059size->width = MAX(size->width, minWidth);1060size->height = MAX(size->height, minHeight);1061}10621063- (void) setEnabled: (BOOL)flag {1064self.isEnabled = flag;10651066if (IS(self.styleBits, CLOSEABLE)) {1067[[self.nsWindow standardWindowButton:NSWindowCloseButton] setEnabled: flag];1068}10691070if (IS(self.styleBits, MINIMIZABLE)) {1071[[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];1072}10731074if (IS(self.styleBits, ZOOMABLE)) {1075[[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled: flag];1076}10771078if (IS(self.styleBits, RESIZABLE)) {1079[self updateMinMaxSize:flag];1080[self.nsWindow setShowsResizeIndicator:flag];1081}1082}10831084+ (void) setLastKeyWindow:(AWTWindow *)window {1085[window retain];1086[lastKeyWindow release];1087lastKeyWindow = window;1088}10891090+ (AWTWindow *) lastKeyWindow {1091return lastKeyWindow;1092}10931094@end // AWTWindow109510961097/*1098* Class: sun_lwawt_macosx_CPlatformWindow1099* Method: nativeCreateNSWindow1100* Signature: (JJIIII)J1101*/1102JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow1103(JNIEnv *env, jobject obj, jlong contentViewPtr, jlong ownerPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)1104{1105__block AWTWindow *window = nil;11061107JNI_COCOA_ENTER(env);11081109jobject platformWindow = (*env)->NewWeakGlobalRef(env, obj);1110NSView *contentView = OBJC(contentViewPtr);1111NSRect frameRect = NSMakeRect(x, y, w, h);1112AWTWindow *owner = [OBJC(ownerPtr) delegate];1113[ThreadUtilities performOnMainThreadWaiting:YES block:^(){11141115window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow1116ownerWindow:owner1117styleBits:styleBits1118frameRect:frameRect1119contentView:contentView];1120// the window is released is CPlatformWindow.nativeDispose()11211122if (window) [window.nsWindow retain];1123}];11241125JNI_COCOA_EXIT(env);11261127return ptr_to_jlong(window ? window.nsWindow : nil);1128}11291130/*1131* Class: sun_lwawt_macosx_CPlatformWindow1132* Method: nativeSetNSWindowStyleBits1133* Signature: (JII)V1134*/1135JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits1136(JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)1137{1138JNI_COCOA_ENTER(env);11391140NSWindow *nsWindow = OBJC(windowPtr);11411142[ThreadUtilities performOnMainThreadWaiting:NO block:^(){11431144AWTWindow *window = (AWTWindow*)[nsWindow delegate];11451146// scans the bit field, and only updates the values requested by the mask1147// (this implicitly handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)1148jint newBits = window.styleBits & ~mask | bits & mask;11491150BOOL resized = NO;11511152// Check for a change to the full window content view option.1153// The content view must be resized first, otherwise the window will be resized to fit the existing1154// content view.1155if (IS(mask, FULL_WINDOW_CONTENT)) {1156if (IS(newBits, FULL_WINDOW_CONTENT) != IS(window.styleBits, FULL_WINDOW_CONTENT)) {1157NSRect frame = [nsWindow frame];1158NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:newBits];1159NSRect screenContentRect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];1160NSRect contentFrame = NSMakeRect(screenContentRect.origin.x - frame.origin.x,1161screenContentRect.origin.y - frame.origin.y,1162screenContentRect.size.width,1163screenContentRect.size.height);1164nsWindow.contentView.frame = contentFrame;1165resized = YES;1166}1167}11681169// resets the NSWindow's style mask if the mask intersects any of those bits1170if (mask & MASK(_STYLE_PROP_BITMASK)) {1171[nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];1172}11731174// calls methods on NSWindow to change other properties, based on the mask1175if (mask & MASK(_METHOD_PROP_BITMASK)) {1176[window setPropertiesForStyleBits:newBits mask:mask];1177}11781179window.styleBits = newBits;11801181if (resized) {1182[window _deliverMoveResizeEvent];1183}1184}];11851186JNI_COCOA_EXIT(env);1187}11881189/*1190* Class: sun_lwawt_macosx_CPlatformWindow1191* Method: nativeSetNSWindowMenuBar1192* Signature: (JJ)V1193*/1194JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar1195(JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)1196{1197JNI_COCOA_ENTER(env);11981199NSWindow *nsWindow = OBJC(windowPtr);1200CMenuBar *menuBar = OBJC(menuBarPtr);1201[ThreadUtilities performOnMainThreadWaiting:NO block:^(){12021203AWTWindow *window = (AWTWindow*)[nsWindow delegate];12041205if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {1206[window.javaMenuBar deactivate];1207}12081209window.javaMenuBar = menuBar;12101211CMenuBar* actualMenuBar = menuBar;1212if (actualMenuBar == nil) {1213actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];1214}12151216if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {1217[CMenuBar activate:actualMenuBar modallyDisabled:NO];1218}1219}];12201221JNI_COCOA_EXIT(env);1222}12231224/*1225* Class: sun_lwawt_macosx_CPlatformWindow1226* Method: nativeGetNSWindowInsets1227* Signature: (J)Ljava/awt/Insets;1228*/1229JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets1230(JNIEnv *env, jclass clazz, jlong windowPtr)1231{1232jobject ret = NULL;12331234JNI_COCOA_ENTER(env);12351236NSWindow *nsWindow = OBJC(windowPtr);1237__block NSRect contentRect = NSZeroRect;1238__block NSRect frame = NSZeroRect;12391240[ThreadUtilities performOnMainThreadWaiting:YES block:^(){12411242frame = [nsWindow frame];1243contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];1244}];12451246jint top = (jint)(frame.size.height - contentRect.size.height);1247jint left = (jint)(contentRect.origin.x - frame.origin.x);1248jint bottom = (jint)(contentRect.origin.y - frame.origin.y);1249jint right = (jint)(frame.size.width - (contentRect.size.width + left));12501251DECLARE_CLASS_RETURN(jc_Insets, "java/awt/Insets", NULL);1252DECLARE_METHOD_RETURN(jc_Insets_ctor, jc_Insets, "<init>", "(IIII)V", NULL);1253ret = (*env)->NewObject(env, jc_Insets, jc_Insets_ctor, top, left, bottom, right);12541255JNI_COCOA_EXIT(env);1256return ret;1257}12581259/*1260* Class: sun_lwawt_macosx_CPlatformWindow1261* Method: nativeSetNSWindowBounds1262* Signature: (JDDDD)V1263*/1264JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds1265(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)1266{1267JNI_COCOA_ENTER(env);12681269NSRect jrect = NSMakeRect(originX, originY, width, height);12701271// TODO: not sure we need displayIfNeeded message in our view1272NSWindow *nsWindow = OBJC(windowPtr);1273[ThreadUtilities performOnMainThreadWaiting:NO block:^(){12741275AWTWindow *window = (AWTWindow*)[nsWindow delegate];12761277NSRect rect = ConvertNSScreenRect(NULL, jrect);1278[window constrainSize:&rect.size];12791280[nsWindow setFrame:rect display:YES];12811282// only start tracking events if pointer is above the toplevel1283// TODO: should post an Entered event if YES.1284NSPoint mLocation = [NSEvent mouseLocation];1285[nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];12861287// ensure we repaint the whole window after the resize operation1288// (this will also re-enable screen updates, which were disabled above)1289// TODO: send PaintEvent12901291// the macOS may ignore our "setFrame" request, in this, case the1292// windowDidMove() will not come and we need to manually resync the1293// "java.awt.Window" and NSWindow locations, because "java.awt.Window"1294// already uses location ignored by the macOS.1295// see sun.lwawt.LWWindowPeer#notifyReshape()1296if (!NSEqualRects(rect, [nsWindow frame])) {1297[window _deliverMoveResizeEvent];1298}1299}];13001301JNI_COCOA_EXIT(env);1302}13031304/*1305* Class: sun_lwawt_macosx_CPlatformWindow1306* Method: nativeSetNSWindowStandardFrame1307* Signature: (JDDDD)V1308*/1309JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame1310(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY,1311jdouble width, jdouble height)1312{1313JNI_COCOA_ENTER(env);13141315NSRect jrect = NSMakeRect(originX, originY, width, height);13161317NSWindow *nsWindow = OBJC(windowPtr);1318[ThreadUtilities performOnMainThreadWaiting:NO block:^(){13191320NSRect rect = ConvertNSScreenRect(NULL, jrect);1321AWTWindow *window = (AWTWindow*)[nsWindow delegate];1322window.standardFrame = rect;1323}];13241325JNI_COCOA_EXIT(env);1326}13271328/*1329* Class: sun_lwawt_macosx_CPlatformWindow1330* Method: nativeSetNSWindowLocationByPlatform1331* Signature: (J)V1332*/1333JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowLocationByPlatform1334(JNIEnv *env, jclass clazz, jlong windowPtr)1335{1336JNI_COCOA_ENTER(env);13371338NSWindow *nsWindow = OBJC(windowPtr);1339[ThreadUtilities performOnMainThreadWaiting:NO block:^(){13401341if (NSEqualPoints(lastTopLeftPoint, NSZeroPoint)) {1342// This is the first usage of lastTopLeftPoint. So invoke cascadeTopLeftFromPoint1343// twice to avoid positioning the window's top left to zero-point, since it may1344// cause negative user experience.1345lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];1346}1347lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];1348}];13491350JNI_COCOA_EXIT(env);1351}13521353/*1354* Class: sun_lwawt_macosx_CPlatformWindow1355* Method: nativeSetNSWindowMinMax1356* Signature: (JDDDD)V1357*/1358JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax1359(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)1360{1361JNI_COCOA_ENTER(env);13621363if (minW < 1) minW = 1;1364if (minH < 1) minH = 1;1365if (maxW < 1) maxW = 1;1366if (maxH < 1) maxH = 1;13671368NSWindow *nsWindow = OBJC(windowPtr);1369[ThreadUtilities performOnMainThreadWaiting:NO block:^(){13701371AWTWindow *window = (AWTWindow*)[nsWindow delegate];13721373NSSize min = { minW, minH };1374NSSize max = { maxW, maxH };13751376[window constrainSize:&min];1377[window constrainSize:&max];13781379window.javaMinSize = min;1380window.javaMaxSize = max;1381[window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];1382}];13831384JNI_COCOA_EXIT(env);1385}13861387/*1388* Class: sun_lwawt_macosx_CPlatformWindow1389* Method: nativePushNSWindowToBack1390* Signature: (J)V1391*/1392JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack1393(JNIEnv *env, jclass clazz, jlong windowPtr)1394{1395JNI_COCOA_ENTER(env);13961397NSWindow *nsWindow = OBJC(windowPtr);1398[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1399[nsWindow orderBack:nil];1400// Order parent windows1401AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate];1402while (awtWindow.ownerWindow != nil) {1403awtWindow = awtWindow.ownerWindow;1404if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) {1405[awtWindow.nsWindow orderBack:nil];1406}1407}1408// Order child windows1409[(AWTWindow*)[nsWindow delegate] orderChildWindows:NO];1410}];14111412JNI_COCOA_EXIT(env);1413}14141415/*1416* Class: sun_lwawt_macosx_CPlatformWindow1417* Method: nativePushNSWindowToFront1418* Signature: (J)V1419*/1420JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront1421(JNIEnv *env, jclass clazz, jlong windowPtr)1422{1423JNI_COCOA_ENTER(env);14241425NSWindow *nsWindow = OBJC(windowPtr);1426[ThreadUtilities performOnMainThreadWaiting:NO block:^(){14271428if (![nsWindow isKeyWindow]) {1429[nsWindow makeKeyAndOrderFront:nsWindow];1430} else {1431[nsWindow orderFront:nsWindow];1432}1433}];14341435JNI_COCOA_EXIT(env);1436}14371438/*1439* Class: sun_lwawt_macosx_CPlatformWindow1440* Method: nativeSetNSWindowTitle1441* Signature: (JLjava/lang/String;)V1442*/1443JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle1444(JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)1445{1446JNI_COCOA_ENTER(env);14471448NSWindow *nsWindow = OBJC(windowPtr);1449[nsWindow performSelectorOnMainThread:@selector(setTitle:)1450withObject:JavaStringToNSString(env, jtitle)1451waitUntilDone:NO];14521453JNI_COCOA_EXIT(env);1454}14551456/*1457* Class: sun_lwawt_macosx_CPlatformWindow1458* Method: nativeRevalidateNSWindowShadow1459* Signature: (J)V1460*/1461JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow1462(JNIEnv *env, jclass clazz, jlong windowPtr)1463{1464JNI_COCOA_ENTER(env);14651466NSWindow *nsWindow = OBJC(windowPtr);1467[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1468[nsWindow invalidateShadow];1469}];14701471JNI_COCOA_EXIT(env);1472}14731474/*1475* Class: sun_lwawt_macosx_CPlatformWindow1476* Method: nativeScreenOn_AppKitThread1477* Signature: (J)I1478*/1479JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread1480(JNIEnv *env, jclass clazz, jlong windowPtr)1481{1482jint ret = 0;14831484JNI_COCOA_ENTER(env);1485AWT_ASSERT_APPKIT_THREAD;14861487NSWindow *nsWindow = OBJC(windowPtr);1488NSDictionary *props = [[nsWindow screen] deviceDescription];1489ret = [[props objectForKey:@"NSScreenNumber"] intValue];14901491JNI_COCOA_EXIT(env);14921493return ret;1494}14951496/*1497* Class: sun_lwawt_macosx_CPlatformWindow1498* Method: nativeSetNSWindowMinimizedIcon1499* Signature: (JJ)V1500*/1501JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon1502(JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)1503{1504JNI_COCOA_ENTER(env);15051506NSWindow *nsWindow = OBJC(windowPtr);1507NSImage *image = OBJC(nsImagePtr);1508[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1509[nsWindow setMiniwindowImage:image];1510}];15111512JNI_COCOA_EXIT(env);1513}15141515/*1516* Class: sun_lwawt_macosx_CPlatformWindow1517* Method: nativeSetNSWindowRepresentedFilename1518* Signature: (JLjava/lang/String;)V1519*/1520JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename1521(JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)1522{1523JNI_COCOA_ENTER(env);15241525NSWindow *nsWindow = OBJC(windowPtr);1526NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:NormalizedPathNSStringFromJavaString(env, filename)];1527[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1528[nsWindow setRepresentedURL:url];1529}];15301531JNI_COCOA_EXIT(env);1532}15331534/*1535* Class: sun_lwawt_macosx_CPlatformWindow1536* Method: nativeGetTopmostPlatformWindowUnderMouse1537* Signature: (J)V1538*/1539JNIEXPORT jobject1540JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse1541(JNIEnv *env, jclass clazz)1542{1543__block jobject topmostWindowUnderMouse = nil;15441545JNI_COCOA_ENTER(env);15461547[ThreadUtilities performOnMainThreadWaiting:YES block:^{1548AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];1549if (awtWindow != nil) {1550topmostWindowUnderMouse = awtWindow.javaPlatformWindow;1551}1552}];15531554JNI_COCOA_EXIT(env);15551556return topmostWindowUnderMouse;1557}15581559/*1560* Class: sun_lwawt_macosx_CPlatformWindow1561* Method: nativeSynthesizeMouseEnteredExitedEvents1562* Signature: ()V1563*/1564JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__1565(JNIEnv *env, jclass clazz)1566{1567JNI_COCOA_ENTER(env);15681569[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1570[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];1571}];15721573JNI_COCOA_EXIT(env);1574}15751576/*1577* Class: sun_lwawt_macosx_CPlatformWindow1578* Method: nativeSynthesizeMouseEnteredExitedEvents1579* Signature: (JI)V1580*/1581JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__JI1582(JNIEnv *env, jclass clazz, jlong windowPtr, jint eventType)1583{1584JNI_COCOA_ENTER(env);15851586if (eventType == NSMouseEntered || eventType == NSMouseExited) {1587NSWindow *nsWindow = OBJC(windowPtr);15881589[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1590[AWTWindow synthesizeMouseEnteredExitedEvents:nsWindow withType:eventType];1591}];1592} else {1593JNU_ThrowIllegalArgumentException(env, "unknown event type");1594}15951596JNI_COCOA_EXIT(env);1597}15981599/*1600* Class: sun_lwawt_macosx_CPlatformWindow1601* Method: _toggleFullScreenMode1602* Signature: (J)V1603*/1604JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode1605(JNIEnv *env, jobject peer, jlong windowPtr)1606{1607JNI_COCOA_ENTER(env);16081609NSWindow *nsWindow = OBJC(windowPtr);1610SEL toggleFullScreenSelector = @selector(toggleFullScreen:);1611if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;16121613[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1614[nsWindow performSelector:toggleFullScreenSelector withObject:nil];1615}];16161617JNI_COCOA_EXIT(env);1618}16191620JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled1621(JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)1622{1623JNI_COCOA_ENTER(env);16241625NSWindow *nsWindow = OBJC(windowPtr);1626[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1627AWTWindow *window = (AWTWindow*)[nsWindow delegate];16281629[window setEnabled: isEnabled];1630}];16311632JNI_COCOA_EXIT(env);1633}16341635JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDispose1636(JNIEnv *env, jclass clazz, jlong windowPtr)1637{1638JNI_COCOA_ENTER(env);16391640NSWindow *nsWindow = OBJC(windowPtr);1641[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1642AWTWindow *window = (AWTWindow*)[nsWindow delegate];16431644if ([AWTWindow lastKeyWindow] == window) {1645[AWTWindow setLastKeyWindow: nil];1646}16471648// AWTWindow holds a reference to the NSWindow in its nsWindow1649// property. Unsetting the delegate allows it to be deallocated1650// which releases the reference. This, in turn, allows the window1651// itself be deallocated.1652[nsWindow setDelegate: nil];16531654[window release];1655}];16561657JNI_COCOA_EXIT(env);1658}16591660JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeEnterFullScreenMode1661(JNIEnv *env, jclass clazz, jlong windowPtr)1662{1663JNI_COCOA_ENTER(env);16641665NSWindow *nsWindow = OBJC(windowPtr);1666[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1667AWTWindow *window = (AWTWindow*)[nsWindow delegate];1668NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];1669CGDirectDisplayID aID = [screenID intValue];16701671if (CGDisplayCapture(aID) == kCGErrorSuccess) {1672// remove window decoration1673NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];1674[nsWindow setStyleMask:(styleMask & ~NSTitledWindowMask) | NSBorderlessWindowMask];16751676int shieldLevel = CGShieldingWindowLevel();1677window.preFullScreenLevel = [nsWindow level];1678[nsWindow setLevel: shieldLevel];16791680NSRect screenRect = [[nsWindow screen] frame];1681[nsWindow setFrame:screenRect display:YES];1682} else {1683[NSException raise:@"Java Exception" reason:@"Failed to enter full screen." userInfo:nil];1684}1685}];16861687JNI_COCOA_EXIT(env);1688}16891690JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeExitFullScreenMode1691(JNIEnv *env, jclass clazz, jlong windowPtr)1692{1693JNI_COCOA_ENTER(env);16941695NSWindow *nsWindow = OBJC(windowPtr);1696[ThreadUtilities performOnMainThreadWaiting:NO block:^(){1697AWTWindow *window = (AWTWindow*)[nsWindow delegate];1698NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];1699CGDirectDisplayID aID = [screenID intValue];17001701if (CGDisplayRelease(aID) == kCGErrorSuccess) {1702NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];1703[nsWindow setStyleMask:styleMask];1704[nsWindow setLevel: window.preFullScreenLevel];17051706// GraphicsDevice takes care of restoring pre full screen bounds1707} else {1708[NSException raise:@"Java Exception" reason:@"Failed to exit full screen." userInfo:nil];1709}1710}];17111712JNI_COCOA_EXIT(env);1713}1714171517161717