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