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