7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import <Cocoa/Cocoa.h>
27 #import <JavaNativeFoundation/JavaNativeFoundation.h>
28
29 #import "sun_lwawt_macosx_CPlatformWindow.h"
30 #import "com_apple_eawt_event_GestureHandler.h"
31 #import "com_apple_eawt_FullScreenHandler.h"
32 #import "ApplicationDelegate.h"
33
34 #import "AWTWindow.h"
35 #import "AWTView.h"
36 #import "GeomUtilities.h"
37 #import "ThreadUtilities.h"
38
39 #define MASK(KEY) \
40 (sun_lwawt_macosx_CPlatformWindow_ ## KEY)
41
42 #define IS(BITS, KEY) \
43 ((BITS & MASK(KEY)) != 0)
44
45 #define SET(BITS, KEY, VALUE) \
46 BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)
47
48 static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
49
50 // Cocoa windowDidBecomeKey/windowDidResignKey notifications
51 // doesn't provide information about "opposite" window, so we
52 // have to do a bit of tracking. This variable points to a window
53 // which had been the key window just before a new key window
54 // was set. It would be nil if the new key window isn't an AWT
55 // window or the app currently has no key window.
56 static AWTWindow* lastKeyWindow = nil;
57
58 // This variable contains coordinates of a window's top left
59 // which was positioned via java.awt.Window.setLocationByPlatform.
60 // It would be NSZeroPoint if 'Location by Platform' is not used.
61 static NSPoint lastTopLeftPoint;
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 \
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
108 // Gesture support
109 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
110 AWT_ASSERT_APPKIT_THREAD;
111
112 JNIEnv *env = [ThreadUtilities getJNIEnv];
113 jobject platformWindow = [((AWTWindow *)self.delegate).javaPlatformWindow jObjectWithEnv:env];
114 if (platformWindow != NULL) {
115 // extract the target AWT Window object out of the CPlatformWindow
116 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
117 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
118 if (awtWindow != NULL) {
119 // translate the point into Java coordinates
120 NSPoint loc = [event locationInWindow];
121 loc.y = [self frame].size.height - loc.y;
122
123 // send up to the GestureHandler to recursively dispatch on the AWT event thread
124 static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
125 static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
126 JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
127 (*env)->DeleteLocalRef(env, awtWindow);
128 }
129 (*env)->DeleteLocalRef(env, platformWindow);
130 }
131 }
132
133 - (void)beginGestureWithEvent:(NSEvent *)event {
134 [self postGesture:event
135 as:com_apple_eawt_event_GestureHandler_PHASE
136 a:-1.0
137 b:0.0];
138 }
139
140 - (void)endGestureWithEvent:(NSEvent *)event {
141 [self postGesture:event
142 as:com_apple_eawt_event_GestureHandler_PHASE
143 a:1.0
144 b:0.0];
145 }
146
253 [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
254 }
255
256 if (IS(mask, DOCUMENT_MODIFIED)) {
257 [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
258 }
259
260 if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
261 if (IS(bits, FULLSCREENABLE)) {
262 [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
263 } else {
264 [self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
265 }
266 }
267
268 if (IS(mask, TRANSPARENT_TITLE_BAR) && [self.nsWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
269 [self.nsWindow setTitlebarAppearsTransparent:IS(bits, TRANSPARENT_TITLE_BAR)];
270 }
271 }
272
273 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
274 ownerWindow:owner
275 styleBits:(jint)bits
276 frameRect:(NSRect)rect
277 contentView:(NSView *)view
278 {
279 AWT_ASSERT_APPKIT_THREAD;
280
281 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
282 NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
283 if (contentRect.size.width <= 0.0) {
284 contentRect.size.width = 1.0;
285 }
286 if (contentRect.size.height <= 0.0) {
287 contentRect.size.height = 1.0;
288 }
289
290 self = [super init];
291
292 if (self == nil) return nil; // no hope
293
443 if (isUnderMouse && !mouseIsOver) {
444 [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];
445 } else if (!isUnderMouse && mouseIsOver) {
446 [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];
447 }
448 }
449 }
450 }
451
452 + (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window {
453 AWT_ASSERT_APPKIT_THREAD;
454 NSScreen *screen = [window screen];
455 NSDictionary *deviceDescription = [screen deviceDescription];
456 return [deviceDescription objectForKey:@"NSScreenNumber"];
457 }
458
459 - (void) dealloc {
460 AWT_ASSERT_APPKIT_THREAD;
461
462 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
463 [self.javaPlatformWindow setJObject:nil withEnv:env];
464 self.javaPlatformWindow = nil;
465 self.nsWindow = nil;
466 self.ownerWindow = nil;
467 [super dealloc];
468 }
469
470 // Tests whether window is blocked by modal dialog/window
471 - (BOOL) isBlocked {
472 BOOL isBlocked = NO;
473
474 JNIEnv *env = [ThreadUtilities getJNIEnv];
475 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
476 if (platformWindow != NULL) {
477 static JNF_MEMBER_CACHE(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z");
478 isBlocked = JNFCallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
479 (*env)->DeleteLocalRef(env, platformWindow);
480 }
481
482 return isBlocked;
483 }
484
485 // Test whether window is simple window and owned by embedded frame
486 - (BOOL) isSimpleWindowOwnedByEmbeddedFrame {
487 BOOL isSimpleWindowOwnedByEmbeddedFrame = NO;
488
489 JNIEnv *env = [ThreadUtilities getJNIEnv];
490 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
491 if (platformWindow != NULL) {
492 static JNF_MEMBER_CACHE(jm_isBlocked, jc_CPlatformWindow, "isSimpleWindowOwnedByEmbeddedFrame", "()Z");
493 isSimpleWindowOwnedByEmbeddedFrame = JNFCallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
494 (*env)->DeleteLocalRef(env, platformWindow);
495 }
496
497 return isSimpleWindowOwnedByEmbeddedFrame;
498 }
499
500 // Tests whether the corresponding Java platform window is visible or not
501 + (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
502 BOOL isVisible = NO;
503
504 if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {
505 AWTWindow *awtWindow = (AWTWindow *)[window delegate];
506 [AWTToolkit eventCountPlusPlus];
507
508 JNIEnv *env = [ThreadUtilities getJNIEnv];
509 jobject platformWindow = [awtWindow.javaPlatformWindow jObjectWithEnv:env];
510 if (platformWindow != NULL) {
511 static JNF_MEMBER_CACHE(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z");
512 isVisible = JNFCallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;
513 (*env)->DeleteLocalRef(env, platformWindow);
514
515 }
516 }
517 return isVisible;
518 }
519
520 // Orders window's childs based on the current focus state
521 - (void) orderChildWindows:(BOOL)focus {
522 AWT_ASSERT_APPKIT_THREAD;
523
524 if (self.isMinimizing || [self isBlocked]) {
525 // Do not perform any ordering, if iconify is in progress
526 // or the window is blocked by a modal window
527 return;
528 }
529
530 NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];
531 NSWindow *window;
532 while ((window = [windowEnumerator nextObject]) != nil) {
558 }
559 }
560 }
561 }
562
563 // NSWindow overrides
564 - (BOOL) canBecomeKeyWindow {
565 AWT_ASSERT_APPKIT_THREAD;
566 return self.isEnabled && (IS(self.styleBits, SHOULD_BECOME_KEY) || [self isSimpleWindowOwnedByEmbeddedFrame]);
567 }
568
569 - (BOOL) canBecomeMainWindow {
570 AWT_ASSERT_APPKIT_THREAD;
571 if (!self.isEnabled) {
572 // Native system can bring up the NSWindow to
573 // the top even if the window is not main.
574 // We should bring up the modal dialog manually
575 [AWTToolkit eventCountPlusPlus];
576
577 JNIEnv *env = [ThreadUtilities getJNIEnv];
578 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
579 if (platformWindow != NULL) {
580 static JNF_MEMBER_CACHE(jm_checkBlockingAndOrder, jc_CPlatformWindow,
581 "checkBlockingAndOrder", "()Z");
582 JNFCallBooleanMethod(env, platformWindow, jm_checkBlockingAndOrder);
583 (*env)->DeleteLocalRef(env, platformWindow);
584 }
585 }
586
587 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
588 }
589
590 - (BOOL) worksWhenModal {
591 AWT_ASSERT_APPKIT_THREAD;
592 return IS(self.styleBits, MODAL_EXCLUDED);
593 }
594
595
596 // NSWindowDelegate methods
597
598 - (void) _deliverMoveResizeEvent {
599 AWT_ASSERT_APPKIT_THREAD;
600
601 // deliver the event if this is a user-initiated live resize or as a side-effect
602 // of a Java initiated resize, because AppKit can override the bounds and force
603 // the bounds of the window to avoid the Dock or remain on screen.
604 [AWTToolkit eventCountPlusPlus];
605 JNIEnv *env = [ThreadUtilities getJNIEnv];
606 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
607 if (platformWindow == NULL) {
608 // TODO: create generic AWT assert
609 }
610
611 NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
612
613 static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
614 JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
615 (jint)frame.origin.x,
616 (jint)frame.origin.y,
617 (jint)frame.size.width,
618 (jint)frame.size.height,
619 (jboolean)[self.nsWindow inLiveResize]);
620 (*env)->DeleteLocalRef(env, platformWindow);
621
622 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
623 }
624
625 - (void)windowDidMove:(NSNotification *)notification {
626 AWT_ASSERT_APPKIT_THREAD;
627
628 [self _deliverMoveResizeEvent];
629 }
630
631 - (void)windowDidResize:(NSNotification *)notification {
632 AWT_ASSERT_APPKIT_THREAD;
633
634 [self _deliverMoveResizeEvent];
635 }
636
637 - (void)windowDidExpose:(NSNotification *)notification {
638 AWT_ASSERT_APPKIT_THREAD;
639
662 while (awtWindow.ownerWindow != nil) {
663 if (awtWindow.ownerWindow == self) {
664 if (iconify) {
665 [window orderOut:window];
666 } else {
667 [window orderFront:window];
668 }
669 break;
670 }
671 awtWindow = awtWindow.ownerWindow;
672 }
673 }
674 }
675 }
676
677 - (void) _deliverIconify:(BOOL)iconify {
678 AWT_ASSERT_APPKIT_THREAD;
679
680 [AWTToolkit eventCountPlusPlus];
681 JNIEnv *env = [ThreadUtilities getJNIEnv];
682 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
683 if (platformWindow != NULL) {
684 static JNF_MEMBER_CACHE(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");
685 JNFCallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);
686 (*env)->DeleteLocalRef(env, platformWindow);
687 }
688 }
689
690 - (void)windowWillMiniaturize:(NSNotification *)notification {
691 AWT_ASSERT_APPKIT_THREAD;
692
693 self.isMinimizing = YES;
694
695 JNIEnv *env = [ThreadUtilities getJNIEnv];
696 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
697 if (platformWindow != NULL) {
698 static JNF_MEMBER_CACHE(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
699 JNFCallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
700 (*env)->DeleteLocalRef(env, platformWindow);
701 }
702 // Explicitly make myself a key window to avoid possible
703 // negative visual effects during iconify operation
704 [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
705 [self iconifyChildWindows:YES];
706 }
707
708 - (void)windowDidMiniaturize:(NSNotification *)notification {
709 AWT_ASSERT_APPKIT_THREAD;
710
711 [self _deliverIconify:JNI_TRUE];
712 self.isMinimizing = NO;
713 }
714
715 - (void)windowDidDeminiaturize:(NSNotification *)notification {
716 AWT_ASSERT_APPKIT_THREAD;
717
718 [self _deliverIconify:JNI_FALSE];
719 [self iconifyChildWindows:NO];
720 }
721
722 - (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
723 //AWT_ASSERT_APPKIT_THREAD;
724 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
725 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
726 if (platformWindow != NULL) {
727 jobject oppositeWindow = [opposite.javaPlatformWindow jObjectWithEnv:env];
728
729 static JNF_MEMBER_CACHE(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");
730 JNFCallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);
731 (*env)->DeleteLocalRef(env, platformWindow);
732 (*env)->DeleteLocalRef(env, oppositeWindow);
733 }
734 }
735
736 - (void) windowDidBecomeMain: (NSNotification *) notification {
737 AWT_ASSERT_APPKIT_THREAD;
738 [AWTToolkit eventCountPlusPlus];
739 #ifdef DEBUG
740 NSLog(@"became main: %d %@ %@", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow]);
741 #endif
742
743 if (![self.nsWindow isKeyWindow]) {
744 [self activateWindowMenuBar];
745 }
746
747 JNIEnv *env = [ThreadUtilities getJNIEnv];
748 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
749 if (platformWindow != NULL) {
750 static JNF_MEMBER_CACHE(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");
751 JNFCallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);
752 (*env)->DeleteLocalRef(env, platformWindow);
753 }
754 }
755
756 - (void) windowDidBecomeKey: (NSNotification *) notification {
757 AWT_ASSERT_APPKIT_THREAD;
758 [AWTToolkit eventCountPlusPlus];
759 #ifdef DEBUG
760 NSLog(@"became key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
761 #endif
762 AWTWindow *opposite = [AWTWindow lastKeyWindow];
763
764 if (![self.nsWindow isMainWindow]) {
765 [self activateWindowMenuBar];
766 }
767
768 [AWTWindow setLastKeyWindow:nil];
769
770 [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
771 [self orderChildWindows:YES];
836 [self.javaMenuBar deactivate];
837
838 // the new key window
839 NSWindow *keyWindow = [NSApp keyWindow];
840 AWTWindow *opposite = nil;
841 if ([AWTWindow isAWTWindow: keyWindow]) {
842 opposite = (AWTWindow *)[keyWindow delegate];
843 [AWTWindow setLastKeyWindow: self];
844 } else {
845 [AWTWindow setLastKeyWindow: nil];
846 }
847
848 [self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
849 [self orderChildWindows:NO];
850 }
851
852 - (BOOL)windowShouldClose:(id)sender {
853 AWT_ASSERT_APPKIT_THREAD;
854 [AWTToolkit eventCountPlusPlus];
855 JNIEnv *env = [ThreadUtilities getJNIEnv];
856 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
857 if (platformWindow != NULL) {
858 static JNF_MEMBER_CACHE(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V");
859 JNFCallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);
860 (*env)->DeleteLocalRef(env, platformWindow);
861 }
862 // The window will be closed (if allowed) as result of sending Java event
863 return NO;
864 }
865
866
867 - (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {
868 static JNF_CLASS_CACHE(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");
869 static JNF_STATIC_MEMBER_CACHE(jm_notifyFullScreenOperation, jc_FullScreenHandler, "handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");
870 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
871 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
872 if (platformWindow != NULL) {
873 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
874 if (awtWindow != NULL) {
875 JNFCallStaticVoidMethod(env, jm_notifyFullScreenOperation, awtWindow, op);
876 (*env)->DeleteLocalRef(env, awtWindow);
877 }
878 (*env)->DeleteLocalRef(env, platformWindow);
879 }
880 }
881
882
883 - (void)windowWillEnterFullScreen:(NSNotification *)notification {
884 static JNF_MEMBER_CACHE(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
885 JNIEnv *env = [ThreadUtilities getJNIEnv];
886 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
887 if (platformWindow != NULL) {
888 JNFCallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);
889 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];
890 (*env)->DeleteLocalRef(env, platformWindow);
891 }
892 }
893
894 - (void)windowDidEnterFullScreen:(NSNotification *)notification {
895 static JNF_MEMBER_CACHE(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
896 JNIEnv *env = [ThreadUtilities getJNIEnv];
897 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
898 if (platformWindow != NULL) {
899 JNFCallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);
900 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];
901 (*env)->DeleteLocalRef(env, platformWindow);
902 }
903 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
904 }
905
906 - (void)windowWillExitFullScreen:(NSNotification *)notification {
907 static JNF_MEMBER_CACHE(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
908 JNIEnv *env = [ThreadUtilities getJNIEnv];
909 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
910 if (platformWindow != NULL) {
911 JNFCallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);
912 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
913 (*env)->DeleteLocalRef(env, platformWindow);
914 }
915 }
916
917 - (void)windowDidExitFullScreen:(NSNotification *)notification {
918 static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
919 JNIEnv *env = [ThreadUtilities getJNIEnv];
920 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
921 if (platformWindow != NULL) {
922 JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
923 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
924 (*env)->DeleteLocalRef(env, platformWindow);
925 }
926 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
927 }
928
929 - (void)sendEvent:(NSEvent *)event {
930 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
931 if ([self isBlocked]) {
932 // Move parent windows to front and make sure that a child window is displayed
933 // in front of its nearest parent.
934 if (self.ownerWindow != nil) {
935 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
936 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
937 if (platformWindow != NULL) {
938 static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
939 JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
940 (*env)->DeleteLocalRef(env, platformWindow);
941 }
942 }
943 [self orderChildWindows:YES];
944 }
945
946 NSPoint p = [NSEvent mouseLocation];
947 NSRect frame = [self.nsWindow frame];
948 NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
949
950 // Check if the click happened in the non-client area (title bar)
951 if (p.y >= (frame.origin.y + contentRect.size.height)) {
952 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
953 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
954 if (platformWindow != NULL) {
955 // Currently, no need to deliver the whole NSEvent.
956 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
957 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
958 (*env)->DeleteLocalRef(env, platformWindow);
959 }
960 }
961 }
962 }
963
964 - (void)constrainSize:(NSSize*)size {
965 float minWidth = 0.f, minHeight = 0.f;
966
967 if (IS(self.styleBits, DECORATED)) {
968 NSRect frame = [self.nsWindow frame];
969 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
970
971 float top = frame.size.height - contentRect.size.height;
972 float left = contentRect.origin.x - frame.origin.x;
973 float bottom = contentRect.origin.y - frame.origin.y;
974 float right = frame.size.width - (contentRect.size.width + left);
975
976 // Speculative estimation: 80 - enough for window decorations controls
977 minWidth += left + right + 80;
1012 lastKeyWindow = window;
1013 }
1014
1015 + (AWTWindow *) lastKeyWindow {
1016 return lastKeyWindow;
1017 }
1018
1019 @end // AWTWindow
1020
1021
1022 /*
1023 * Class: sun_lwawt_macosx_CPlatformWindow
1024 * Method: nativeCreateNSWindow
1025 * Signature: (JJIIII)J
1026 */
1027 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
1028 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong ownerPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
1029 {
1030 __block AWTWindow *window = nil;
1031
1032 JNF_COCOA_ENTER(env);
1033
1034 JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
1035 NSView *contentView = OBJC(contentViewPtr);
1036 NSRect frameRect = NSMakeRect(x, y, w, h);
1037 AWTWindow *owner = [OBJC(ownerPtr) delegate];
1038 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1039
1040 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
1041 ownerWindow:owner
1042 styleBits:styleBits
1043 frameRect:frameRect
1044 contentView:contentView];
1045 // the window is released is CPlatformWindow.nativeDispose()
1046
1047 if (window) [window.nsWindow retain];
1048 }];
1049
1050 JNF_COCOA_EXIT(env);
1051
1052 return ptr_to_jlong(window ? window.nsWindow : nil);
1053 }
1054
1055 /*
1056 * Class: sun_lwawt_macosx_CPlatformWindow
1057 * Method: nativeSetNSWindowStyleBits
1058 * Signature: (JII)V
1059 */
1060 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
1061 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
1062 {
1063 JNF_COCOA_ENTER(env);
1064
1065 NSWindow *nsWindow = OBJC(windowPtr);
1066
1067 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1068
1069 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1070
1071 // scans the bit field, and only updates the values requested by the mask
1072 // (this implicitly handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
1073 jint newBits = window.styleBits & ~mask | bits & mask;
1074
1075 BOOL resized = NO;
1076
1077 // Check for a change to the full window content view option.
1078 // The content view must be resized first, otherwise the window will be resized to fit the existing
1079 // content view.
1080 if (IS(mask, FULL_WINDOW_CONTENT)) {
1081 if (IS(newBits, FULL_WINDOW_CONTENT) != IS(window.styleBits, FULL_WINDOW_CONTENT)) {
1082 NSRect frame = [nsWindow frame];
1083 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:newBits];
1091 }
1092 }
1093
1094 // resets the NSWindow's style mask if the mask intersects any of those bits
1095 if (mask & MASK(_STYLE_PROP_BITMASK)) {
1096 [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
1097 }
1098
1099 // calls methods on NSWindow to change other properties, based on the mask
1100 if (mask & MASK(_METHOD_PROP_BITMASK)) {
1101 [window setPropertiesForStyleBits:newBits mask:mask];
1102 }
1103
1104 window.styleBits = newBits;
1105
1106 if (resized) {
1107 [window _deliverMoveResizeEvent];
1108 }
1109 }];
1110
1111 JNF_COCOA_EXIT(env);
1112 }
1113
1114 /*
1115 * Class: sun_lwawt_macosx_CPlatformWindow
1116 * Method: nativeSetNSWindowMenuBar
1117 * Signature: (JJ)V
1118 */
1119 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
1120 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
1121 {
1122 JNF_COCOA_ENTER(env);
1123
1124 NSWindow *nsWindow = OBJC(windowPtr);
1125 CMenuBar *menuBar = OBJC(menuBarPtr);
1126 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1127
1128 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1129
1130 if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1131 [window.javaMenuBar deactivate];
1132 }
1133
1134 window.javaMenuBar = menuBar;
1135
1136 CMenuBar* actualMenuBar = menuBar;
1137 if (actualMenuBar == nil) {
1138 actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
1139 }
1140
1141 if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1142 [CMenuBar activate:actualMenuBar modallyDisabled:NO];
1143 }
1144 }];
1145
1146 JNF_COCOA_EXIT(env);
1147 }
1148
1149 /*
1150 * Class: sun_lwawt_macosx_CPlatformWindow
1151 * Method: nativeGetNSWindowInsets
1152 * Signature: (J)Ljava/awt/Insets;
1153 */
1154 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
1155 (JNIEnv *env, jclass clazz, jlong windowPtr)
1156 {
1157 jobject ret = NULL;
1158
1159 JNF_COCOA_ENTER(env);
1160
1161 NSWindow *nsWindow = OBJC(windowPtr);
1162 __block NSRect contentRect = NSZeroRect;
1163 __block NSRect frame = NSZeroRect;
1164
1165 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1166
1167 frame = [nsWindow frame];
1168 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
1169 }];
1170
1171 jint top = (jint)(frame.size.height - contentRect.size.height);
1172 jint left = (jint)(contentRect.origin.x - frame.origin.x);
1173 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
1174 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
1175
1176 static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
1177 static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
1178 ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
1179
1180 JNF_COCOA_EXIT(env);
1181 return ret;
1182 }
1183
1184 /*
1185 * Class: sun_lwawt_macosx_CPlatformWindow
1186 * Method: nativeSetNSWindowBounds
1187 * Signature: (JDDDD)V
1188 */
1189 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
1190 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
1191 {
1192 JNF_COCOA_ENTER(env);
1193
1194 NSRect jrect = NSMakeRect(originX, originY, width, height);
1195
1196 // TODO: not sure we need displayIfNeeded message in our view
1197 NSWindow *nsWindow = OBJC(windowPtr);
1198 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1199
1200 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1201
1202 NSRect rect = ConvertNSScreenRect(NULL, jrect);
1203 [window constrainSize:&rect.size];
1204
1205 [nsWindow setFrame:rect display:YES];
1206
1207 // only start tracking events if pointer is above the toplevel
1208 // TODO: should post an Entered event if YES.
1209 NSPoint mLocation = [NSEvent mouseLocation];
1210 [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
1211
1212 // ensure we repaint the whole window after the resize operation
1213 // (this will also re-enable screen updates, which were disabled above)
1214 // TODO: send PaintEvent
1215
1216 // the macOS may ignore our "setFrame" request, in this, case the
1217 // windowDidMove() will not come and we need to manually resync the
1218 // "java.awt.Window" and NSWindow locations, because "java.awt.Window"
1219 // already uses location ignored by the macOS.
1220 // see sun.lwawt.LWWindowPeer#notifyReshape()
1221 if (!NSEqualRects(rect, [nsWindow frame])) {
1222 [window _deliverMoveResizeEvent];
1223 }
1224 }];
1225
1226 JNF_COCOA_EXIT(env);
1227 }
1228
1229 /*
1230 * Class: sun_lwawt_macosx_CPlatformWindow
1231 * Method: nativeSetNSWindowStandardFrame
1232 * Signature: (JDDDD)V
1233 */
1234 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame
1235 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY,
1236 jdouble width, jdouble height)
1237 {
1238 JNF_COCOA_ENTER(env);
1239
1240 NSRect jrect = NSMakeRect(originX, originY, width, height);
1241
1242 NSWindow *nsWindow = OBJC(windowPtr);
1243 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1244
1245 NSRect rect = ConvertNSScreenRect(NULL, jrect);
1246 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1247 window.standardFrame = rect;
1248 }];
1249
1250 JNF_COCOA_EXIT(env);
1251 }
1252
1253 /*
1254 * Class: sun_lwawt_macosx_CPlatformWindow
1255 * Method: nativeSetNSWindowLocationByPlatform
1256 * Signature: (J)V
1257 */
1258 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowLocationByPlatform
1259 (JNIEnv *env, jclass clazz, jlong windowPtr)
1260 {
1261 JNF_COCOA_ENTER(env);
1262
1263 NSWindow *nsWindow = OBJC(windowPtr);
1264 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1265
1266 if (NSEqualPoints(lastTopLeftPoint, NSZeroPoint)) {
1267 // This is the first usage of lastTopLeftPoint. So invoke cascadeTopLeftFromPoint
1268 // twice to avoid positioning the window's top left to zero-point, since it may
1269 // cause negative user experience.
1270 lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1271 }
1272 lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1273 }];
1274
1275 JNF_COCOA_EXIT(env);
1276 }
1277
1278 /*
1279 * Class: sun_lwawt_macosx_CPlatformWindow
1280 * Method: nativeSetNSWindowMinMax
1281 * Signature: (JDDDD)V
1282 */
1283 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
1284 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
1285 {
1286 JNF_COCOA_ENTER(env);
1287
1288 if (minW < 1) minW = 1;
1289 if (minH < 1) minH = 1;
1290 if (maxW < 1) maxW = 1;
1291 if (maxH < 1) maxH = 1;
1292
1293 NSWindow *nsWindow = OBJC(windowPtr);
1294 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1295
1296 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1297
1298 NSSize min = { minW, minH };
1299 NSSize max = { maxW, maxH };
1300
1301 [window constrainSize:&min];
1302 [window constrainSize:&max];
1303
1304 window.javaMinSize = min;
1305 window.javaMaxSize = max;
1306 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
1307 }];
1308
1309 JNF_COCOA_EXIT(env);
1310 }
1311
1312 /*
1313 * Class: sun_lwawt_macosx_CPlatformWindow
1314 * Method: nativePushNSWindowToBack
1315 * Signature: (J)V
1316 */
1317 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
1318 (JNIEnv *env, jclass clazz, jlong windowPtr)
1319 {
1320 JNF_COCOA_ENTER(env);
1321
1322 NSWindow *nsWindow = OBJC(windowPtr);
1323 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1324 [nsWindow orderBack:nil];
1325 // Order parent windows
1326 AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate];
1327 while (awtWindow.ownerWindow != nil) {
1328 awtWindow = awtWindow.ownerWindow;
1329 if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) {
1330 [awtWindow.nsWindow orderBack:nil];
1331 }
1332 }
1333 // Order child windows
1334 [(AWTWindow*)[nsWindow delegate] orderChildWindows:NO];
1335 }];
1336
1337 JNF_COCOA_EXIT(env);
1338 }
1339
1340 /*
1341 * Class: sun_lwawt_macosx_CPlatformWindow
1342 * Method: nativePushNSWindowToFront
1343 * Signature: (J)V
1344 */
1345 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
1346 (JNIEnv *env, jclass clazz, jlong windowPtr)
1347 {
1348 JNF_COCOA_ENTER(env);
1349
1350 NSWindow *nsWindow = OBJC(windowPtr);
1351 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1352
1353 if (![nsWindow isKeyWindow]) {
1354 [nsWindow makeKeyAndOrderFront:nsWindow];
1355 } else {
1356 [nsWindow orderFront:nsWindow];
1357 }
1358 }];
1359
1360 JNF_COCOA_EXIT(env);
1361 }
1362
1363 /*
1364 * Class: sun_lwawt_macosx_CPlatformWindow
1365 * Method: nativeSetNSWindowTitle
1366 * Signature: (JLjava/lang/String;)V
1367 */
1368 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
1369 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
1370 {
1371 JNF_COCOA_ENTER(env);
1372
1373 NSWindow *nsWindow = OBJC(windowPtr);
1374 [nsWindow performSelectorOnMainThread:@selector(setTitle:)
1375 withObject:JNFJavaToNSString(env, jtitle)
1376 waitUntilDone:NO];
1377
1378 JNF_COCOA_EXIT(env);
1379 }
1380
1381 /*
1382 * Class: sun_lwawt_macosx_CPlatformWindow
1383 * Method: nativeRevalidateNSWindowShadow
1384 * Signature: (J)V
1385 */
1386 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
1387 (JNIEnv *env, jclass clazz, jlong windowPtr)
1388 {
1389 JNF_COCOA_ENTER(env);
1390
1391 NSWindow *nsWindow = OBJC(windowPtr);
1392 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1393 [nsWindow invalidateShadow];
1394 }];
1395
1396 JNF_COCOA_EXIT(env);
1397 }
1398
1399 /*
1400 * Class: sun_lwawt_macosx_CPlatformWindow
1401 * Method: nativeScreenOn_AppKitThread
1402 * Signature: (J)I
1403 */
1404 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
1405 (JNIEnv *env, jclass clazz, jlong windowPtr)
1406 {
1407 jint ret = 0;
1408
1409 JNF_COCOA_ENTER(env);
1410 AWT_ASSERT_APPKIT_THREAD;
1411
1412 NSWindow *nsWindow = OBJC(windowPtr);
1413 NSDictionary *props = [[nsWindow screen] deviceDescription];
1414 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
1415
1416 JNF_COCOA_EXIT(env);
1417
1418 return ret;
1419 }
1420
1421 /*
1422 * Class: sun_lwawt_macosx_CPlatformWindow
1423 * Method: nativeSetNSWindowMinimizedIcon
1424 * Signature: (JJ)V
1425 */
1426 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
1427 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
1428 {
1429 JNF_COCOA_ENTER(env);
1430
1431 NSWindow *nsWindow = OBJC(windowPtr);
1432 NSImage *image = OBJC(nsImagePtr);
1433 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1434 [nsWindow setMiniwindowImage:image];
1435 }];
1436
1437 JNF_COCOA_EXIT(env);
1438 }
1439
1440 /*
1441 * Class: sun_lwawt_macosx_CPlatformWindow
1442 * Method: nativeSetNSWindowRepresentedFilename
1443 * Signature: (JLjava/lang/String;)V
1444 */
1445 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
1446 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
1447 {
1448 JNF_COCOA_ENTER(env);
1449
1450 NSWindow *nsWindow = OBJC(windowPtr);
1451 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
1452 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1453 [nsWindow setRepresentedURL:url];
1454 }];
1455
1456 JNF_COCOA_EXIT(env);
1457 }
1458
1459 /*
1460 * Class: sun_lwawt_macosx_CPlatformWindow
1461 * Method: nativeGetTopmostPlatformWindowUnderMouse
1462 * Signature: (J)V
1463 */
1464 JNIEXPORT jobject
1465 JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
1466 (JNIEnv *env, jclass clazz)
1467 {
1468 __block jobject topmostWindowUnderMouse = nil;
1469
1470 JNF_COCOA_ENTER(env);
1471
1472 [ThreadUtilities performOnMainThreadWaiting:YES block:^{
1473 AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
1474 if (awtWindow != nil) {
1475 topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
1476 }
1477 }];
1478
1479 JNF_COCOA_EXIT(env);
1480
1481 return topmostWindowUnderMouse;
1482 }
1483
1484 /*
1485 * Class: sun_lwawt_macosx_CPlatformWindow
1486 * Method: nativeSynthesizeMouseEnteredExitedEvents
1487 * Signature: ()V
1488 */
1489 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__
1490 (JNIEnv *env, jclass clazz)
1491 {
1492 JNF_COCOA_ENTER(env);
1493
1494 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1495 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
1496 }];
1497
1498 JNF_COCOA_EXIT(env);
1499 }
1500
1501 /*
1502 * Class: sun_lwawt_macosx_CPlatformWindow
1503 * Method: nativeSynthesizeMouseEnteredExitedEvents
1504 * Signature: (JI)V
1505 */
1506 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__JI
1507 (JNIEnv *env, jclass clazz, jlong windowPtr, jint eventType)
1508 {
1509 JNF_COCOA_ENTER(env);
1510
1511 if (eventType == NSMouseEntered || eventType == NSMouseExited) {
1512 NSWindow *nsWindow = OBJC(windowPtr);
1513
1514 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1515 [AWTWindow synthesizeMouseEnteredExitedEvents:nsWindow withType:eventType];
1516 }];
1517 } else {
1518 [JNFException raise:env as:kIllegalArgumentException reason:"unknown event type"];
1519 }
1520
1521 JNF_COCOA_EXIT(env);
1522 }
1523
1524 /*
1525 * Class: sun_lwawt_macosx_CPlatformWindow
1526 * Method: _toggleFullScreenMode
1527 * Signature: (J)V
1528 */
1529 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1530 (JNIEnv *env, jobject peer, jlong windowPtr)
1531 {
1532 JNF_COCOA_ENTER(env);
1533
1534 NSWindow *nsWindow = OBJC(windowPtr);
1535 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1536 if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
1537
1538 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1539 [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
1540 }];
1541
1542 JNF_COCOA_EXIT(env);
1543 }
1544
1545 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1546 (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1547 {
1548 JNF_COCOA_ENTER(env);
1549
1550 NSWindow *nsWindow = OBJC(windowPtr);
1551 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1552 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1553
1554 [window setEnabled: isEnabled];
1555 }];
1556
1557 JNF_COCOA_EXIT(env);
1558 }
1559
1560 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDispose
1561 (JNIEnv *env, jclass clazz, jlong windowPtr)
1562 {
1563 JNF_COCOA_ENTER(env);
1564
1565 NSWindow *nsWindow = OBJC(windowPtr);
1566 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1567 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1568
1569 if ([AWTWindow lastKeyWindow] == window) {
1570 [AWTWindow setLastKeyWindow: nil];
1571 }
1572
1573 // AWTWindow holds a reference to the NSWindow in its nsWindow
1574 // property. Unsetting the delegate allows it to be deallocated
1575 // which releases the reference. This, in turn, allows the window
1576 // itself be deallocated.
1577 [nsWindow setDelegate: nil];
1578
1579 [window release];
1580 }];
1581
1582 JNF_COCOA_EXIT(env);
1583 }
1584
1585 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeEnterFullScreenMode
1586 (JNIEnv *env, jclass clazz, jlong windowPtr)
1587 {
1588 JNF_COCOA_ENTER(env);
1589
1590 NSWindow *nsWindow = OBJC(windowPtr);
1591 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1592 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1593 NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1594 CGDirectDisplayID aID = [screenID intValue];
1595
1596 if (CGDisplayCapture(aID) == kCGErrorSuccess) {
1597 // remove window decoration
1598 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1599 [nsWindow setStyleMask:(styleMask & ~NSTitledWindowMask) | NSBorderlessWindowMask];
1600
1601 int shieldLevel = CGShieldingWindowLevel();
1602 window.preFullScreenLevel = [nsWindow level];
1603 [nsWindow setLevel: shieldLevel];
1604
1605 NSRect screenRect = [[nsWindow screen] frame];
1606 [nsWindow setFrame:screenRect display:YES];
1607 } else {
1608 [JNFException raise:[ThreadUtilities getJNIEnv]
1609 as:kRuntimeException
1610 reason:"Failed to enter full screen."];
1611 }
1612 }];
1613
1614 JNF_COCOA_EXIT(env);
1615 }
1616
1617 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeExitFullScreenMode
1618 (JNIEnv *env, jclass clazz, jlong windowPtr)
1619 {
1620 JNF_COCOA_ENTER(env);
1621
1622 NSWindow *nsWindow = OBJC(windowPtr);
1623 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1624 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1625 NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1626 CGDirectDisplayID aID = [screenID intValue];
1627
1628 if (CGDisplayRelease(aID) == kCGErrorSuccess) {
1629 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1630 [nsWindow setStyleMask:styleMask];
1631 [nsWindow setLevel: window.preFullScreenLevel];
1632
1633 // GraphicsDevice takes care of restoring pre full screen bounds
1634 } else {
1635 [JNFException raise:[ThreadUtilities getJNIEnv]
1636 as:kRuntimeException
1637 reason:"Failed to exit full screen."];
1638 }
1639 }];
1640
1641 JNF_COCOA_EXIT(env);
1642 }
1643
|
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
48 static 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.
61 static 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.
66 static 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 \
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
111 AWT_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
262 [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
263 }
264
265 if (IS(mask, DOCUMENT_MODIFIED)) {
266 [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
267 }
268
269 if (IS(mask, FULLSCREENABLE) && [self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
270 if (IS(bits, FULLSCREENABLE)) {
271 [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
272 } else {
273 [self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
274 }
275 }
276
277 if (IS(mask, TRANSPARENT_TITLE_BAR) && [self.nsWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
278 [self.nsWindow setTitlebarAppearsTransparent:IS(bits, TRANSPARENT_TITLE_BAR)];
279 }
280 }
281
282 - (id) initWithPlatformWindow:(jobject)platformWindow
283 ownerWindow:owner
284 styleBits:(jint)bits
285 frameRect:(NSRect)rect
286 contentView:(NSView *)view
287 {
288 AWT_ASSERT_APPKIT_THREAD;
289
290 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
291 NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
292 if (contentRect.size.width <= 0.0) {
293 contentRect.size.width = 1.0;
294 }
295 if (contentRect.size.height <= 0.0) {
296 contentRect.size.height = 1.0;
297 }
298
299 self = [super init];
300
301 if (self == nil) return nil; // no hope
302
452 if (isUnderMouse && !mouseIsOver) {
453 [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];
454 } else if (!isUnderMouse && mouseIsOver) {
455 [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];
456 }
457 }
458 }
459 }
460
461 + (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window {
462 AWT_ASSERT_APPKIT_THREAD;
463 NSScreen *screen = [window screen];
464 NSDictionary *deviceDescription = [screen deviceDescription];
465 return [deviceDescription objectForKey:@"NSScreenNumber"];
466 }
467
468 - (void) dealloc {
469 AWT_ASSERT_APPKIT_THREAD;
470
471 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
472 (*env)->DeleteWeakGlobalRef(env, self.javaPlatformWindow);
473 self.javaPlatformWindow = nil;
474 self.nsWindow = nil;
475 self.ownerWindow = nil;
476 [super dealloc];
477 }
478
479 // Tests whether window is blocked by modal dialog/window
480 - (BOOL) isBlocked {
481 BOOL isBlocked = NO;
482
483 JNIEnv *env = [ThreadUtilities getJNIEnv];
484 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
485 if (platformWindow != NULL) {
486 GET_CPLATFORM_WINDOW_CLASS_RETURN(isBlocked);
487 DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z", isBlocked);
488 isBlocked = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
489 CHECK_EXCEPTION();
490 (*env)->DeleteLocalRef(env, platformWindow);
491 }
492
493 return isBlocked;
494 }
495
496 // Test whether window is simple window and owned by embedded frame
497 - (BOOL) isSimpleWindowOwnedByEmbeddedFrame {
498 BOOL isSimpleWindowOwnedByEmbeddedFrame = NO;
499
500 JNIEnv *env = [ThreadUtilities getJNIEnv];
501 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
502 if (platformWindow != NULL) {
503 GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
504 DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isSimpleWindowOwnedByEmbeddedFrame", "()Z", NO);
505 isSimpleWindowOwnedByEmbeddedFrame = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
506 CHECK_EXCEPTION();
507 (*env)->DeleteLocalRef(env, platformWindow);
508 }
509
510 return isSimpleWindowOwnedByEmbeddedFrame;
511 }
512
513 // Tests whether the corresponding Java platform window is visible or not
514 + (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
515 BOOL isVisible = NO;
516
517 if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {
518 AWTWindow *awtWindow = (AWTWindow *)[window delegate];
519 [AWTToolkit eventCountPlusPlus];
520
521 JNIEnv *env = [ThreadUtilities getJNIEnv];
522 jobject platformWindow = (*env)->NewLocalRef(env, awtWindow.javaPlatformWindow);
523 if (platformWindow != NULL) {
524 GET_CPLATFORM_WINDOW_CLASS_RETURN(isVisible);
525 DECLARE_METHOD_RETURN(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z", isVisible)
526 isVisible = (*env)->CallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;
527 CHECK_EXCEPTION();
528 (*env)->DeleteLocalRef(env, platformWindow);
529
530 }
531 }
532 return isVisible;
533 }
534
535 // Orders window's childs based on the current focus state
536 - (void) orderChildWindows:(BOOL)focus {
537 AWT_ASSERT_APPKIT_THREAD;
538
539 if (self.isMinimizing || [self isBlocked]) {
540 // Do not perform any ordering, if iconify is in progress
541 // or the window is blocked by a modal window
542 return;
543 }
544
545 NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];
546 NSWindow *window;
547 while ((window = [windowEnumerator nextObject]) != nil) {
573 }
574 }
575 }
576 }
577
578 // NSWindow overrides
579 - (BOOL) canBecomeKeyWindow {
580 AWT_ASSERT_APPKIT_THREAD;
581 return self.isEnabled && (IS(self.styleBits, SHOULD_BECOME_KEY) || [self isSimpleWindowOwnedByEmbeddedFrame]);
582 }
583
584 - (BOOL) canBecomeMainWindow {
585 AWT_ASSERT_APPKIT_THREAD;
586 if (!self.isEnabled) {
587 // Native system can bring up the NSWindow to
588 // the top even if the window is not main.
589 // We should bring up the modal dialog manually
590 [AWTToolkit eventCountPlusPlus];
591
592 JNIEnv *env = [ThreadUtilities getJNIEnv];
593 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
594 if (platformWindow != NULL) {
595 GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
596 DECLARE_METHOD_RETURN(jm_checkBlockingAndOrder, jc_CPlatformWindow, "checkBlockingAndOrder", "()Z", NO);
597 (*env)->CallBooleanMethod(env, platformWindow, jm_checkBlockingAndOrder);
598 CHECK_EXCEPTION();
599 (*env)->DeleteLocalRef(env, platformWindow);
600 }
601 }
602
603 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
604 }
605
606 - (BOOL) worksWhenModal {
607 AWT_ASSERT_APPKIT_THREAD;
608 return IS(self.styleBits, MODAL_EXCLUDED);
609 }
610
611
612 // NSWindowDelegate methods
613
614 - (void) _deliverMoveResizeEvent {
615 AWT_ASSERT_APPKIT_THREAD;
616
617 // deliver the event if this is a user-initiated live resize or as a side-effect
618 // of a Java initiated resize, because AppKit can override the bounds and force
619 // the bounds of the window to avoid the Dock or remain on screen.
620 [AWTToolkit eventCountPlusPlus];
621 JNIEnv *env = [ThreadUtilities getJNIEnv];
622 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
623 if (platformWindow == NULL) {
624 // TODO: create generic AWT assert
625 }
626
627 NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
628
629 GET_CPLATFORM_WINDOW_CLASS();
630 DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
631 (*env)->CallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
632 (jint)frame.origin.x,
633 (jint)frame.origin.y,
634 (jint)frame.size.width,
635 (jint)frame.size.height,
636 (jboolean)[self.nsWindow inLiveResize]);
637 CHECK_EXCEPTION();
638 (*env)->DeleteLocalRef(env, platformWindow);
639
640 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
641 }
642
643 - (void)windowDidMove:(NSNotification *)notification {
644 AWT_ASSERT_APPKIT_THREAD;
645
646 [self _deliverMoveResizeEvent];
647 }
648
649 - (void)windowDidResize:(NSNotification *)notification {
650 AWT_ASSERT_APPKIT_THREAD;
651
652 [self _deliverMoveResizeEvent];
653 }
654
655 - (void)windowDidExpose:(NSNotification *)notification {
656 AWT_ASSERT_APPKIT_THREAD;
657
680 while (awtWindow.ownerWindow != nil) {
681 if (awtWindow.ownerWindow == self) {
682 if (iconify) {
683 [window orderOut:window];
684 } else {
685 [window orderFront:window];
686 }
687 break;
688 }
689 awtWindow = awtWindow.ownerWindow;
690 }
691 }
692 }
693 }
694
695 - (void) _deliverIconify:(BOOL)iconify {
696 AWT_ASSERT_APPKIT_THREAD;
697
698 [AWTToolkit eventCountPlusPlus];
699 JNIEnv *env = [ThreadUtilities getJNIEnv];
700 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
701 if (platformWindow != NULL) {
702 GET_CPLATFORM_WINDOW_CLASS();
703 DECLARE_METHOD(jm_deliverIconify, jc_CPlatformWindow, "deliverIconify", "(Z)V");
704 (*env)->CallVoidMethod(env, platformWindow, jm_deliverIconify, iconify);
705 CHECK_EXCEPTION();
706 (*env)->DeleteLocalRef(env, platformWindow);
707 }
708 }
709
710 - (void)windowWillMiniaturize:(NSNotification *)notification {
711 AWT_ASSERT_APPKIT_THREAD;
712
713 self.isMinimizing = YES;
714
715 JNIEnv *env = [ThreadUtilities getJNIEnv];
716 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
717 if (platformWindow != NULL) {
718 GET_CPLATFORM_WINDOW_CLASS();
719 DECLARE_METHOD(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
720 (*env)->CallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
721 CHECK_EXCEPTION();
722 (*env)->DeleteLocalRef(env, platformWindow);
723 }
724 // Explicitly make myself a key window to avoid possible
725 // negative visual effects during iconify operation
726 [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
727 [self iconifyChildWindows:YES];
728 }
729
730 - (void)windowDidMiniaturize:(NSNotification *)notification {
731 AWT_ASSERT_APPKIT_THREAD;
732
733 [self _deliverIconify:JNI_TRUE];
734 self.isMinimizing = NO;
735 }
736
737 - (void)windowDidDeminiaturize:(NSNotification *)notification {
738 AWT_ASSERT_APPKIT_THREAD;
739
740 [self _deliverIconify:JNI_FALSE];
741 [self iconifyChildWindows:NO];
742 }
743
744 - (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite {
745 //AWT_ASSERT_APPKIT_THREAD;
746 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
747 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
748 if (platformWindow != NULL) {
749 jobject oppositeWindow = (*env)->NewLocalRef(env, opposite.javaPlatformWindow);
750 GET_CPLATFORM_WINDOW_CLASS();
751 DECLARE_METHOD(jm_deliverWindowFocusEvent, jc_CPlatformWindow, "deliverWindowFocusEvent", "(ZLsun/lwawt/macosx/CPlatformWindow;)V");
752 (*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowFocusEvent, (jboolean)focused, oppositeWindow);
753 CHECK_EXCEPTION();
754 (*env)->DeleteLocalRef(env, platformWindow);
755 (*env)->DeleteLocalRef(env, oppositeWindow);
756 }
757 }
758
759 - (void) windowDidBecomeMain: (NSNotification *) notification {
760 AWT_ASSERT_APPKIT_THREAD;
761 [AWTToolkit eventCountPlusPlus];
762 #ifdef DEBUG
763 NSLog(@"became main: %d %@ %@", [self.nsWindow isKeyWindow], [self.nsWindow title], [self menuBarForWindow]);
764 #endif
765
766 if (![self.nsWindow isKeyWindow]) {
767 [self activateWindowMenuBar];
768 }
769
770 JNIEnv *env = [ThreadUtilities getJNIEnv];
771 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
772 if (platformWindow != NULL) {
773 GET_CPLATFORM_WINDOW_CLASS();
774 DECLARE_METHOD(jm_windowDidBecomeMain, jc_CPlatformWindow, "windowDidBecomeMain", "()V");
775 (*env)->CallVoidMethod(env, platformWindow, jm_windowDidBecomeMain);
776 CHECK_EXCEPTION();
777 (*env)->DeleteLocalRef(env, platformWindow);
778 }
779 }
780
781 - (void) windowDidBecomeKey: (NSNotification *) notification {
782 AWT_ASSERT_APPKIT_THREAD;
783 [AWTToolkit eventCountPlusPlus];
784 #ifdef DEBUG
785 NSLog(@"became key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
786 #endif
787 AWTWindow *opposite = [AWTWindow lastKeyWindow];
788
789 if (![self.nsWindow isMainWindow]) {
790 [self activateWindowMenuBar];
791 }
792
793 [AWTWindow setLastKeyWindow:nil];
794
795 [self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
796 [self orderChildWindows:YES];
861 [self.javaMenuBar deactivate];
862
863 // the new key window
864 NSWindow *keyWindow = [NSApp keyWindow];
865 AWTWindow *opposite = nil;
866 if ([AWTWindow isAWTWindow: keyWindow]) {
867 opposite = (AWTWindow *)[keyWindow delegate];
868 [AWTWindow setLastKeyWindow: self];
869 } else {
870 [AWTWindow setLastKeyWindow: nil];
871 }
872
873 [self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
874 [self orderChildWindows:NO];
875 }
876
877 - (BOOL)windowShouldClose:(id)sender {
878 AWT_ASSERT_APPKIT_THREAD;
879 [AWTToolkit eventCountPlusPlus];
880 JNIEnv *env = [ThreadUtilities getJNIEnv];
881 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
882 if (platformWindow != NULL) {
883 GET_CPLATFORM_WINDOW_CLASS_RETURN(NO);
884 DECLARE_METHOD_RETURN(jm_deliverWindowClosingEvent, jc_CPlatformWindow, "deliverWindowClosingEvent", "()V", NO);
885 (*env)->CallVoidMethod(env, platformWindow, jm_deliverWindowClosingEvent);
886 CHECK_EXCEPTION();
887 (*env)->DeleteLocalRef(env, platformWindow);
888 }
889 // The window will be closed (if allowed) as result of sending Java event
890 return NO;
891 }
892
893 - (void)_notifyFullScreenOp:(jint)op withEnv:(JNIEnv *)env {
894 DECLARE_CLASS(jc_FullScreenHandler, "com/apple/eawt/FullScreenHandler");
895 DECLARE_STATIC_METHOD(jm_notifyFullScreenOperation, jc_FullScreenHandler,
896 "handleFullScreenEventFromNative", "(Ljava/awt/Window;I)V");
897 GET_CPLATFORM_WINDOW_CLASS();
898 DECLARE_FIELD(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
899 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
900 if (platformWindow != NULL) {
901 jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
902 if (awtWindow != NULL) {
903 (*env)->CallStaticVoidMethod(env, jc_FullScreenHandler, jm_notifyFullScreenOperation, awtWindow, op);
904 CHECK_EXCEPTION();
905 (*env)->DeleteLocalRef(env, awtWindow);
906 }
907 (*env)->DeleteLocalRef(env, platformWindow);
908 }
909 }
910
911
912 - (void)windowWillEnterFullScreen:(NSNotification *)notification {
913 JNIEnv *env = [ThreadUtilities getJNIEnv];
914 GET_CPLATFORM_WINDOW_CLASS();
915 DECLARE_METHOD(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
916 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
917 if (platformWindow != NULL) {
918 (*env)->CallVoidMethod(env, platformWindow, jm_windowWillEnterFullScreen);
919 CHECK_EXCEPTION();
920 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_ENTER withEnv:env];
921 (*env)->DeleteLocalRef(env, platformWindow);
922 }
923 }
924
925 - (void)windowDidEnterFullScreen:(NSNotification *)notification {
926 JNIEnv *env = [ThreadUtilities getJNIEnv];
927 GET_CPLATFORM_WINDOW_CLASS();
928 DECLARE_METHOD(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
929 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
930 if (platformWindow != NULL) {
931 (*env)->CallVoidMethod(env, platformWindow, jm_windowDidEnterFullScreen);
932 CHECK_EXCEPTION();
933 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_ENTER withEnv:env];
934 (*env)->DeleteLocalRef(env, platformWindow);
935 }
936 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
937 }
938
939 - (void)windowWillExitFullScreen:(NSNotification *)notification {
940 JNIEnv *env = [ThreadUtilities getJNIEnv];
941 GET_CPLATFORM_WINDOW_CLASS();
942 DECLARE_METHOD(jm_windowWillExitFullScreen, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
943 if (jm_windowWillExitFullScreen == NULL) {
944 GET_CPLATFORM_WINDOW_CLASS();
945 jm_windowWillExitFullScreen = (*env)->GetMethodID(env, jc_CPlatformWindow, "windowWillExitFullScreen", "()V");
946 }
947 CHECK_NULL(jm_windowWillExitFullScreen);
948 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
949 if (platformWindow != NULL) {
950 (*env)->CallVoidMethod(env, platformWindow, jm_windowWillExitFullScreen);
951 CHECK_EXCEPTION();
952 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
953 (*env)->DeleteLocalRef(env, platformWindow);
954 }
955 }
956
957 - (void)windowDidExitFullScreen:(NSNotification *)notification {
958 JNIEnv *env = [ThreadUtilities getJNIEnv];
959 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
960 if (platformWindow != NULL) {
961 GET_CPLATFORM_WINDOW_CLASS();
962 DECLARE_METHOD(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
963 (*env)->CallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
964 CHECK_EXCEPTION();
965 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
966 (*env)->DeleteLocalRef(env, platformWindow);
967 }
968 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
969 }
970
971 - (void)sendEvent:(NSEvent *)event {
972 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
973 if ([self isBlocked]) {
974 // Move parent windows to front and make sure that a child window is displayed
975 // in front of its nearest parent.
976 if (self.ownerWindow != nil) {
977 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
978 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
979 if (platformWindow != NULL) {
980 GET_CPLATFORM_WINDOW_CLASS();
981 DECLARE_METHOD(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
982 (*env)->CallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
983 CHECK_EXCEPTION();
984 (*env)->DeleteLocalRef(env, platformWindow);
985 }
986 }
987 [self orderChildWindows:YES];
988 }
989
990 NSPoint p = [NSEvent mouseLocation];
991 NSRect frame = [self.nsWindow frame];
992 NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
993
994 // Check if the click happened in the non-client area (title bar)
995 if (p.y >= (frame.origin.y + contentRect.size.height)) {
996 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
997 jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
998 if (platformWindow != NULL) {
999 // Currently, no need to deliver the whole NSEvent.
1000 GET_CPLATFORM_WINDOW_CLASS();
1001 DECLARE_METHOD(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
1002 (*env)->CallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
1003 CHECK_EXCEPTION();
1004 (*env)->DeleteLocalRef(env, platformWindow);
1005 }
1006 }
1007 }
1008 }
1009
1010 - (void)constrainSize:(NSSize*)size {
1011 float minWidth = 0.f, minHeight = 0.f;
1012
1013 if (IS(self.styleBits, DECORATED)) {
1014 NSRect frame = [self.nsWindow frame];
1015 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
1016
1017 float top = frame.size.height - contentRect.size.height;
1018 float left = contentRect.origin.x - frame.origin.x;
1019 float bottom = contentRect.origin.y - frame.origin.y;
1020 float right = frame.size.width - (contentRect.size.width + left);
1021
1022 // Speculative estimation: 80 - enough for window decorations controls
1023 minWidth += left + right + 80;
1058 lastKeyWindow = window;
1059 }
1060
1061 + (AWTWindow *) lastKeyWindow {
1062 return lastKeyWindow;
1063 }
1064
1065 @end // AWTWindow
1066
1067
1068 /*
1069 * Class: sun_lwawt_macosx_CPlatformWindow
1070 * Method: nativeCreateNSWindow
1071 * Signature: (JJIIII)J
1072 */
1073 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
1074 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong ownerPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
1075 {
1076 __block AWTWindow *window = nil;
1077
1078 JNI_COCOA_ENTER(env);
1079
1080 jobject platformWindow = (*env)->NewWeakGlobalRef(env, obj);
1081 NSView *contentView = OBJC(contentViewPtr);
1082 NSRect frameRect = NSMakeRect(x, y, w, h);
1083 AWTWindow *owner = [OBJC(ownerPtr) delegate];
1084 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1085
1086 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
1087 ownerWindow:owner
1088 styleBits:styleBits
1089 frameRect:frameRect
1090 contentView:contentView];
1091 // the window is released is CPlatformWindow.nativeDispose()
1092
1093 if (window) [window.nsWindow retain];
1094 }];
1095
1096 JNI_COCOA_EXIT(env);
1097
1098 return ptr_to_jlong(window ? window.nsWindow : nil);
1099 }
1100
1101 /*
1102 * Class: sun_lwawt_macosx_CPlatformWindow
1103 * Method: nativeSetNSWindowStyleBits
1104 * Signature: (JII)V
1105 */
1106 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
1107 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
1108 {
1109 JNI_COCOA_ENTER(env);
1110
1111 NSWindow *nsWindow = OBJC(windowPtr);
1112
1113 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1114
1115 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1116
1117 // scans the bit field, and only updates the values requested by the mask
1118 // (this implicitly handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
1119 jint newBits = window.styleBits & ~mask | bits & mask;
1120
1121 BOOL resized = NO;
1122
1123 // Check for a change to the full window content view option.
1124 // The content view must be resized first, otherwise the window will be resized to fit the existing
1125 // content view.
1126 if (IS(mask, FULL_WINDOW_CONTENT)) {
1127 if (IS(newBits, FULL_WINDOW_CONTENT) != IS(window.styleBits, FULL_WINDOW_CONTENT)) {
1128 NSRect frame = [nsWindow frame];
1129 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:newBits];
1137 }
1138 }
1139
1140 // resets the NSWindow's style mask if the mask intersects any of those bits
1141 if (mask & MASK(_STYLE_PROP_BITMASK)) {
1142 [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
1143 }
1144
1145 // calls methods on NSWindow to change other properties, based on the mask
1146 if (mask & MASK(_METHOD_PROP_BITMASK)) {
1147 [window setPropertiesForStyleBits:newBits mask:mask];
1148 }
1149
1150 window.styleBits = newBits;
1151
1152 if (resized) {
1153 [window _deliverMoveResizeEvent];
1154 }
1155 }];
1156
1157 JNI_COCOA_EXIT(env);
1158 }
1159
1160 /*
1161 * Class: sun_lwawt_macosx_CPlatformWindow
1162 * Method: nativeSetNSWindowMenuBar
1163 * Signature: (JJ)V
1164 */
1165 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
1166 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
1167 {
1168 JNI_COCOA_ENTER(env);
1169
1170 NSWindow *nsWindow = OBJC(windowPtr);
1171 CMenuBar *menuBar = OBJC(menuBarPtr);
1172 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1173
1174 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1175
1176 if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1177 [window.javaMenuBar deactivate];
1178 }
1179
1180 window.javaMenuBar = menuBar;
1181
1182 CMenuBar* actualMenuBar = menuBar;
1183 if (actualMenuBar == nil) {
1184 actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
1185 }
1186
1187 if ([nsWindow isKeyWindow] || [nsWindow isMainWindow]) {
1188 [CMenuBar activate:actualMenuBar modallyDisabled:NO];
1189 }
1190 }];
1191
1192 JNI_COCOA_EXIT(env);
1193 }
1194
1195 /*
1196 * Class: sun_lwawt_macosx_CPlatformWindow
1197 * Method: nativeGetNSWindowInsets
1198 * Signature: (J)Ljava/awt/Insets;
1199 */
1200 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
1201 (JNIEnv *env, jclass clazz, jlong windowPtr)
1202 {
1203 jobject ret = NULL;
1204
1205 JNI_COCOA_ENTER(env);
1206
1207 NSWindow *nsWindow = OBJC(windowPtr);
1208 __block NSRect contentRect = NSZeroRect;
1209 __block NSRect frame = NSZeroRect;
1210
1211 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
1212
1213 frame = [nsWindow frame];
1214 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
1215 }];
1216
1217 jint top = (jint)(frame.size.height - contentRect.size.height);
1218 jint left = (jint)(contentRect.origin.x - frame.origin.x);
1219 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
1220 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
1221
1222 DECLARE_CLASS_RETURN(jc_Insets, "java/awt/Insets", NULL);
1223 DECLARE_METHOD_RETURN(jc_Insets_ctor, jc_Insets, "<init>", "(IIII)V", NULL);
1224 ret = (*env)->NewObject(env, jc_Insets, jc_Insets_ctor, top, left, bottom, right);
1225
1226 JNI_COCOA_EXIT(env);
1227 return ret;
1228 }
1229
1230 /*
1231 * Class: sun_lwawt_macosx_CPlatformWindow
1232 * Method: nativeSetNSWindowBounds
1233 * Signature: (JDDDD)V
1234 */
1235 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
1236 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
1237 {
1238 JNI_COCOA_ENTER(env);
1239
1240 NSRect jrect = NSMakeRect(originX, originY, width, height);
1241
1242 // TODO: not sure we need displayIfNeeded message in our view
1243 NSWindow *nsWindow = OBJC(windowPtr);
1244 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1245
1246 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1247
1248 NSRect rect = ConvertNSScreenRect(NULL, jrect);
1249 [window constrainSize:&rect.size];
1250
1251 [nsWindow setFrame:rect display:YES];
1252
1253 // only start tracking events if pointer is above the toplevel
1254 // TODO: should post an Entered event if YES.
1255 NSPoint mLocation = [NSEvent mouseLocation];
1256 [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
1257
1258 // ensure we repaint the whole window after the resize operation
1259 // (this will also re-enable screen updates, which were disabled above)
1260 // TODO: send PaintEvent
1261
1262 // the macOS may ignore our "setFrame" request, in this, case the
1263 // windowDidMove() will not come and we need to manually resync the
1264 // "java.awt.Window" and NSWindow locations, because "java.awt.Window"
1265 // already uses location ignored by the macOS.
1266 // see sun.lwawt.LWWindowPeer#notifyReshape()
1267 if (!NSEqualRects(rect, [nsWindow frame])) {
1268 [window _deliverMoveResizeEvent];
1269 }
1270 }];
1271
1272 JNI_COCOA_EXIT(env);
1273 }
1274
1275 /*
1276 * Class: sun_lwawt_macosx_CPlatformWindow
1277 * Method: nativeSetNSWindowStandardFrame
1278 * Signature: (JDDDD)V
1279 */
1280 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame
1281 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY,
1282 jdouble width, jdouble height)
1283 {
1284 JNI_COCOA_ENTER(env);
1285
1286 NSRect jrect = NSMakeRect(originX, originY, width, height);
1287
1288 NSWindow *nsWindow = OBJC(windowPtr);
1289 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1290
1291 NSRect rect = ConvertNSScreenRect(NULL, jrect);
1292 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1293 window.standardFrame = rect;
1294 }];
1295
1296 JNI_COCOA_EXIT(env);
1297 }
1298
1299 /*
1300 * Class: sun_lwawt_macosx_CPlatformWindow
1301 * Method: nativeSetNSWindowLocationByPlatform
1302 * Signature: (J)V
1303 */
1304 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowLocationByPlatform
1305 (JNIEnv *env, jclass clazz, jlong windowPtr)
1306 {
1307 JNI_COCOA_ENTER(env);
1308
1309 NSWindow *nsWindow = OBJC(windowPtr);
1310 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1311
1312 if (NSEqualPoints(lastTopLeftPoint, NSZeroPoint)) {
1313 // This is the first usage of lastTopLeftPoint. So invoke cascadeTopLeftFromPoint
1314 // twice to avoid positioning the window's top left to zero-point, since it may
1315 // cause negative user experience.
1316 lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1317 }
1318 lastTopLeftPoint = [nsWindow cascadeTopLeftFromPoint:lastTopLeftPoint];
1319 }];
1320
1321 JNI_COCOA_EXIT(env);
1322 }
1323
1324 /*
1325 * Class: sun_lwawt_macosx_CPlatformWindow
1326 * Method: nativeSetNSWindowMinMax
1327 * Signature: (JDDDD)V
1328 */
1329 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
1330 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
1331 {
1332 JNI_COCOA_ENTER(env);
1333
1334 if (minW < 1) minW = 1;
1335 if (minH < 1) minH = 1;
1336 if (maxW < 1) maxW = 1;
1337 if (maxH < 1) maxH = 1;
1338
1339 NSWindow *nsWindow = OBJC(windowPtr);
1340 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1341
1342 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1343
1344 NSSize min = { minW, minH };
1345 NSSize max = { maxW, maxH };
1346
1347 [window constrainSize:&min];
1348 [window constrainSize:&max];
1349
1350 window.javaMinSize = min;
1351 window.javaMaxSize = max;
1352 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
1353 }];
1354
1355 JNI_COCOA_EXIT(env);
1356 }
1357
1358 /*
1359 * Class: sun_lwawt_macosx_CPlatformWindow
1360 * Method: nativePushNSWindowToBack
1361 * Signature: (J)V
1362 */
1363 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
1364 (JNIEnv *env, jclass clazz, jlong windowPtr)
1365 {
1366 JNI_COCOA_ENTER(env);
1367
1368 NSWindow *nsWindow = OBJC(windowPtr);
1369 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1370 [nsWindow orderBack:nil];
1371 // Order parent windows
1372 AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate];
1373 while (awtWindow.ownerWindow != nil) {
1374 awtWindow = awtWindow.ownerWindow;
1375 if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) {
1376 [awtWindow.nsWindow orderBack:nil];
1377 }
1378 }
1379 // Order child windows
1380 [(AWTWindow*)[nsWindow delegate] orderChildWindows:NO];
1381 }];
1382
1383 JNI_COCOA_EXIT(env);
1384 }
1385
1386 /*
1387 * Class: sun_lwawt_macosx_CPlatformWindow
1388 * Method: nativePushNSWindowToFront
1389 * Signature: (J)V
1390 */
1391 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
1392 (JNIEnv *env, jclass clazz, jlong windowPtr)
1393 {
1394 JNI_COCOA_ENTER(env);
1395
1396 NSWindow *nsWindow = OBJC(windowPtr);
1397 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1398
1399 if (![nsWindow isKeyWindow]) {
1400 [nsWindow makeKeyAndOrderFront:nsWindow];
1401 } else {
1402 [nsWindow orderFront:nsWindow];
1403 }
1404 }];
1405
1406 JNI_COCOA_EXIT(env);
1407 }
1408
1409 /*
1410 * Class: sun_lwawt_macosx_CPlatformWindow
1411 * Method: nativeSetNSWindowTitle
1412 * Signature: (JLjava/lang/String;)V
1413 */
1414 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
1415 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
1416 {
1417 JNI_COCOA_ENTER(env);
1418
1419 NSWindow *nsWindow = OBJC(windowPtr);
1420 [nsWindow performSelectorOnMainThread:@selector(setTitle:)
1421 withObject:JavaStringToNSString(env, jtitle)
1422 waitUntilDone:NO];
1423
1424 JNI_COCOA_EXIT(env);
1425 }
1426
1427 /*
1428 * Class: sun_lwawt_macosx_CPlatformWindow
1429 * Method: nativeRevalidateNSWindowShadow
1430 * Signature: (J)V
1431 */
1432 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
1433 (JNIEnv *env, jclass clazz, jlong windowPtr)
1434 {
1435 JNI_COCOA_ENTER(env);
1436
1437 NSWindow *nsWindow = OBJC(windowPtr);
1438 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1439 [nsWindow invalidateShadow];
1440 }];
1441
1442 JNI_COCOA_EXIT(env);
1443 }
1444
1445 /*
1446 * Class: sun_lwawt_macosx_CPlatformWindow
1447 * Method: nativeScreenOn_AppKitThread
1448 * Signature: (J)I
1449 */
1450 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
1451 (JNIEnv *env, jclass clazz, jlong windowPtr)
1452 {
1453 jint ret = 0;
1454
1455 JNI_COCOA_ENTER(env);
1456 AWT_ASSERT_APPKIT_THREAD;
1457
1458 NSWindow *nsWindow = OBJC(windowPtr);
1459 NSDictionary *props = [[nsWindow screen] deviceDescription];
1460 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
1461
1462 JNI_COCOA_EXIT(env);
1463
1464 return ret;
1465 }
1466
1467 /*
1468 * Class: sun_lwawt_macosx_CPlatformWindow
1469 * Method: nativeSetNSWindowMinimizedIcon
1470 * Signature: (JJ)V
1471 */
1472 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
1473 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
1474 {
1475 JNI_COCOA_ENTER(env);
1476
1477 NSWindow *nsWindow = OBJC(windowPtr);
1478 NSImage *image = OBJC(nsImagePtr);
1479 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1480 [nsWindow setMiniwindowImage:image];
1481 }];
1482
1483 JNI_COCOA_EXIT(env);
1484 }
1485
1486 /*
1487 * Class: sun_lwawt_macosx_CPlatformWindow
1488 * Method: nativeSetNSWindowRepresentedFilename
1489 * Signature: (JLjava/lang/String;)V
1490 */
1491 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
1492 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
1493 {
1494 JNI_COCOA_ENTER(env);
1495
1496 NSWindow *nsWindow = OBJC(windowPtr);
1497 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:NormalizedPathNSStringFromJavaString(env, filename)];
1498 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1499 [nsWindow setRepresentedURL:url];
1500 }];
1501
1502 JNI_COCOA_EXIT(env);
1503 }
1504
1505 /*
1506 * Class: sun_lwawt_macosx_CPlatformWindow
1507 * Method: nativeGetTopmostPlatformWindowUnderMouse
1508 * Signature: (J)V
1509 */
1510 JNIEXPORT jobject
1511 JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
1512 (JNIEnv *env, jclass clazz)
1513 {
1514 __block jobject topmostWindowUnderMouse = nil;
1515
1516 JNI_COCOA_ENTER(env);
1517
1518 [ThreadUtilities performOnMainThreadWaiting:YES block:^{
1519 AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
1520 if (awtWindow != nil) {
1521 topmostWindowUnderMouse = awtWindow.javaPlatformWindow;
1522 }
1523 }];
1524
1525 JNI_COCOA_EXIT(env);
1526
1527 return topmostWindowUnderMouse;
1528 }
1529
1530 /*
1531 * Class: sun_lwawt_macosx_CPlatformWindow
1532 * Method: nativeSynthesizeMouseEnteredExitedEvents
1533 * Signature: ()V
1534 */
1535 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__
1536 (JNIEnv *env, jclass clazz)
1537 {
1538 JNI_COCOA_ENTER(env);
1539
1540 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1541 [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
1542 }];
1543
1544 JNI_COCOA_EXIT(env);
1545 }
1546
1547 /*
1548 * Class: sun_lwawt_macosx_CPlatformWindow
1549 * Method: nativeSynthesizeMouseEnteredExitedEvents
1550 * Signature: (JI)V
1551 */
1552 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__JI
1553 (JNIEnv *env, jclass clazz, jlong windowPtr, jint eventType)
1554 {
1555 JNI_COCOA_ENTER(env);
1556
1557 if (eventType == NSMouseEntered || eventType == NSMouseExited) {
1558 NSWindow *nsWindow = OBJC(windowPtr);
1559
1560 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1561 [AWTWindow synthesizeMouseEnteredExitedEvents:nsWindow withType:eventType];
1562 }];
1563 } else {
1564 JNU_ThrowIllegalArgumentException(env, "unknown event type");
1565 }
1566
1567 JNI_COCOA_EXIT(env);
1568 }
1569
1570 /*
1571 * Class: sun_lwawt_macosx_CPlatformWindow
1572 * Method: _toggleFullScreenMode
1573 * Signature: (J)V
1574 */
1575 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1576 (JNIEnv *env, jobject peer, jlong windowPtr)
1577 {
1578 JNI_COCOA_ENTER(env);
1579
1580 NSWindow *nsWindow = OBJC(windowPtr);
1581 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1582 if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
1583
1584 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1585 [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
1586 }];
1587
1588 JNI_COCOA_EXIT(env);
1589 }
1590
1591 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1592 (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1593 {
1594 JNI_COCOA_ENTER(env);
1595
1596 NSWindow *nsWindow = OBJC(windowPtr);
1597 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1598 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1599
1600 [window setEnabled: isEnabled];
1601 }];
1602
1603 JNI_COCOA_EXIT(env);
1604 }
1605
1606 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeDispose
1607 (JNIEnv *env, jclass clazz, jlong windowPtr)
1608 {
1609 JNI_COCOA_ENTER(env);
1610
1611 NSWindow *nsWindow = OBJC(windowPtr);
1612 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1613 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1614
1615 if ([AWTWindow lastKeyWindow] == window) {
1616 [AWTWindow setLastKeyWindow: nil];
1617 }
1618
1619 // AWTWindow holds a reference to the NSWindow in its nsWindow
1620 // property. Unsetting the delegate allows it to be deallocated
1621 // which releases the reference. This, in turn, allows the window
1622 // itself be deallocated.
1623 [nsWindow setDelegate: nil];
1624
1625 [window release];
1626 }];
1627
1628 JNI_COCOA_EXIT(env);
1629 }
1630
1631 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeEnterFullScreenMode
1632 (JNIEnv *env, jclass clazz, jlong windowPtr)
1633 {
1634 JNI_COCOA_ENTER(env);
1635
1636 NSWindow *nsWindow = OBJC(windowPtr);
1637 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1638 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1639 NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1640 CGDirectDisplayID aID = [screenID intValue];
1641
1642 if (CGDisplayCapture(aID) == kCGErrorSuccess) {
1643 // remove window decoration
1644 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1645 [nsWindow setStyleMask:(styleMask & ~NSTitledWindowMask) | NSBorderlessWindowMask];
1646
1647 int shieldLevel = CGShieldingWindowLevel();
1648 window.preFullScreenLevel = [nsWindow level];
1649 [nsWindow setLevel: shieldLevel];
1650
1651 NSRect screenRect = [[nsWindow screen] frame];
1652 [nsWindow setFrame:screenRect display:YES];
1653 } else {
1654 [NSException raise:@"Java Exception" reason:@"Failed to enter full screen." userInfo:nil];
1655 }
1656 }];
1657
1658 JNI_COCOA_EXIT(env);
1659 }
1660
1661 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeExitFullScreenMode
1662 (JNIEnv *env, jclass clazz, jlong windowPtr)
1663 {
1664 JNI_COCOA_ENTER(env);
1665
1666 NSWindow *nsWindow = OBJC(windowPtr);
1667 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
1668 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1669 NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
1670 CGDirectDisplayID aID = [screenID intValue];
1671
1672 if (CGDisplayRelease(aID) == kCGErrorSuccess) {
1673 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
1674 [nsWindow setStyleMask:styleMask];
1675 [nsWindow setLevel: window.preFullScreenLevel];
1676
1677 // GraphicsDevice takes care of restoring pre full screen bounds
1678 } else {
1679 [NSException raise:@"Java Exception" reason:@"Failed to exit full screen." userInfo:nil];
1680 }
1681 }];
1682
1683 JNI_COCOA_EXIT(env);
1684 }
1685
|