34 #import "AWTWindow.h"
35 #import "AWTView.h"
36 #import "CMenu.h"
37 #import "CMenuBar.h"
38 #import "LWCToolkit.h"
39 #import "GeomUtilities.h"
40 #import "ThreadUtilities.h"
41 #import "OSVersion.h"
42
43 #define MASK(KEY) \
44 (sun_lwawt_macosx_CPlatformWindow_ ## KEY)
45
46 #define IS(BITS, KEY) \
47 ((BITS & MASK(KEY)) != 0)
48
49 #define SET(BITS, KEY, VALUE) \
50 BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)
51
52 static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
53
54 @implementation AWTWindow
55
56 @synthesize javaPlatformWindow;
57 @synthesize javaMenuBar;
58 @synthesize javaMinSize;
59 @synthesize javaMaxSize;
60 @synthesize styleBits;
61 @synthesize isEnabled;
62
63 - (void) updateMinMaxSize:(BOOL)resizable {
64 if (resizable) {
65 [self setMinSize:self.javaMinSize];
66 [self setMaxSize:self.javaMaxSize];
67 } else {
68 NSRect currentFrame = [self frame];
69 [self setMinSize:currentFrame.size];
70 [self setMaxSize:currentFrame.size];
71 }
72 }
73
74 // creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
75 + (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
76 NSUInteger type = 0;
77 if (IS(styleBits, DECORATED)) {
78 type |= NSTitledWindowMask;
79 if (IS(styleBits, CLOSEABLE)) type |= NSClosableWindowMask;
80 if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;
81 if (IS(styleBits, RESIZABLE)) type |= NSResizableWindowMask;
82 } else {
83 type |= NSBorderlessWindowMask;
84 }
85
86 if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;
87 if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;
88 if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;
89 if (IS(styleBits, HUD)) type |= NSHUDWindowMask;
90 if (IS(styleBits, SHEET)) type |= NSDocModalWindowMask;
91 if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
92
93 return type;
94 }
95
96 // updates _METHOD_PROP_BITMASK based properties on the window
97 - (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
98 if (IS(mask, RESIZABLE)) {
99 BOOL resizable = IS(bits, RESIZABLE);
100 [self updateMinMaxSize:resizable];
101 [self setShowsResizeIndicator:resizable];
102 }
103
104 if (IS(mask, HAS_SHADOW)) {
105 [self setHasShadow:IS(bits, HAS_SHADOW)];
106 }
107
108 if (IS(mask, ZOOMABLE)) {
109 [[self standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
110 }
111
112 if (IS(mask, ALWAYS_ON_TOP)) {
113 [self setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
114 }
115
116 if (IS(mask, HIDES_ON_DEACTIVATE)) {
117 [self setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
118 }
119
120 if (IS(mask, DRAGGABLE_BACKGROUND)) {
121 [self setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
122 }
123
124 if (IS(mask, DOCUMENT_MODIFIED)) {
125 [self setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
126 }
127
128 if ([self respondsToSelector:@selector(toggleFullScreen:)]) {
129 if (IS(mask, FULLSCREENABLE)) {
130 [self setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
131 } else {
132 [self setCollectionBehavior:NSWindowCollectionBehaviorDefault];
133 }
134 }
135
136 }
137
138 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
139 styleBits:(jint)bits
140 frameRect:(NSRect)rect
141 contentView:(NSView *)view
142 {
143 AWT_ASSERT_APPKIT_THREAD;
144
145 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
146 NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
147 if (contentRect.size.width <= 0.0) {
148 contentRect.size.width = 1.0;
149 }
150 if (contentRect.size.height <= 0.0) {
151 contentRect.size.height = 1.0;
152 }
153
154 self = [super initWithContentRect:contentRect
155 styleMask:styleMask
156 backing:NSBackingStoreBuffered
157 defer:NO];
158
159 if (self == nil) return nil; // no hope
160
161 self.isEnabled = YES;
162 self.javaPlatformWindow = platformWindow;
163 self.styleBits = bits;
164 [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
165
166 [self setDelegate:self];
167 [self setContentView:view];
168 [self setInitialFirstResponder:view];
169 [self setReleasedWhenClosed:NO];
170 [self setPreservesContentDuringLiveResize:YES];
171
172 return self;
173 }
174
175 // checks that this window is under the mouse cursor and this point is not overlapped by others windows
176 - (BOOL) isTopmostWindowUnderMouse {
177
178 int currentWinID = [self windowNumber];
179
180 NSRect screenRect = [[NSScreen mainScreen] frame];
181 NSPoint nsMouseLocation = [NSEvent mouseLocation];
182 CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
183
184 NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
185
186
187 for (NSDictionary *window in windows) {
188 int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
189 if (layer == 0) {
190 int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];
191 CGRect rect;
192 CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
193 if (CGRectContainsPoint(rect, cgMouseLocation)) {
194 return currentWinID == winID;
195 } else if (currentWinID == winID) {
196 return NO;
197 }
198 }
199 }
200 return NO;
201 }
202
203 - (void) synthesizeMouseEnteredExitedEvents {
204
205 int eventType = 0;
206 BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
207 BOOL mouseIsOver = [[self contentView] mouseIsOver];
208
209 if (isUnderMouse && !mouseIsOver) {
210 eventType = NSMouseEntered;
211 } else if (!isUnderMouse && mouseIsOver) {
212 eventType = NSMouseExited;
213 } else {
214 return;
215 }
216
217 NSPoint screenLocation = [NSEvent mouseLocation];
218 NSPoint windowLocation = [self convertScreenToBase: screenLocation];
219 int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
220
221 NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
222 location: windowLocation
223 modifierFlags: modifierFlags
224 timestamp: 0
225 windowNumber: [self windowNumber]
226 context: nil
227 eventNumber: 0
228 trackingNumber: 0
229 userData: nil
230 ];
231
232 [[self contentView] deliverJavaMouseEvent: mouseEvent];
233 }
234
235 - (void) dealloc {
236 AWT_ASSERT_APPKIT_THREAD;
237
238 JNIEnv *env = [ThreadUtilities getJNIEnv];
239 [self.javaPlatformWindow setJObject:nil withEnv:env];
240
241 [super dealloc];
242 }
243
244 // NSWindow overrides
245 - (BOOL) canBecomeKeyWindow {
246 AWT_ASSERT_APPKIT_THREAD;
247 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_KEY);
248 }
249
250 - (BOOL) canBecomeMainWindow {
251 AWT_ASSERT_APPKIT_THREAD;
252 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
253 }
254
255 - (BOOL) worksWhenModal {
256 AWT_ASSERT_APPKIT_THREAD;
257 return IS(self.styleBits, MODAL_EXCLUDED);
258 }
259
260
261 // Gesture support
262 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
263 AWT_ASSERT_APPKIT_THREAD;
264
265 JNIEnv *env = [ThreadUtilities getJNIEnv];
266 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
267 if (platformWindow != NULL) {
268 // extract the target AWT Window object out of the CPlatformWindow
269 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
270 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
271 if (awtWindow != NULL) {
272 // translate the point into Java coordinates
273 NSPoint loc = [event locationInWindow];
274 loc.y = [self frame].size.height - loc.y;
275
276 // send up to the GestureHandler to recursively dispatch on the AWT event thread
277 static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
278 static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
279 JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
280 (*env)->DeleteLocalRef(env, awtWindow);
281 }
282 (*env)->DeleteLocalRef(env, platformWindow);
283 }
284 }
285
286 - (void)beginGestureWithEvent:(NSEvent *)event {
287 [self postGesture:event
288 as:com_apple_eawt_event_GestureHandler_PHASE
289 a:-1.0
290 b:0.0];
291 }
292
293 - (void)endGestureWithEvent:(NSEvent *)event {
294 [self postGesture:event
317 a:[event deltaX]
318 b:[event deltaY]];
319 }
320
321
322 // NSWindowDelegate methods
323
324 - (void) _deliverMoveResizeEvent {
325 AWT_ASSERT_APPKIT_THREAD;
326
327 // deliver the event if this is a user-initiated live resize or as a side-effect
328 // of a Java initiated resize, because AppKit can override the bounds and force
329 // the bounds of the window to avoid the Dock or remain on screen.
330 [AWTToolkit eventCountPlusPlus];
331 JNIEnv *env = [ThreadUtilities getJNIEnv];
332 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
333 if (platformWindow == NULL) {
334 // TODO: create generic AWT assert
335 }
336
337 NSRect frame = ConvertNSScreenRect(env, [self frame]);
338
339 static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V");
340 JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
341 (jint)frame.origin.x,
342 (jint)frame.origin.y,
343 (jint)frame.size.width,
344 (jint)frame.size.height);
345 (*env)->DeleteLocalRef(env, platformWindow);
346 }
347
348 - (void)windowDidMove:(NSNotification *)notification {
349 AWT_ASSERT_APPKIT_THREAD;
350
351 [self _deliverMoveResizeEvent];
352 }
353
354 - (void)windowDidResize:(NSNotification *)notification {
355 AWT_ASSERT_APPKIT_THREAD;
356
357 [self _deliverMoveResizeEvent];
507 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
508 (*env)->DeleteLocalRef(env, platformWindow);
509 }
510 }
511
512 - (void)windowDidExitFullScreen:(NSNotification *)notification {
513 static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
514 JNIEnv *env = [ThreadUtilities getJNIEnv];
515 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
516 if (platformWindow != NULL) {
517 JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
518 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
519 (*env)->DeleteLocalRef(env, platformWindow);
520 }
521 }
522
523 - (void)sendEvent:(NSEvent *)event {
524 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
525
526 NSPoint p = [NSEvent mouseLocation];
527 NSRect frame = [self frame];
528 NSRect contentRect = [self contentRectForFrameRect:frame];
529
530 // Check if the click happened in the non-client area (title bar)
531 if (p.y >= (frame.origin.y + contentRect.size.height)) {
532 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
533 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
534 // Currently, no need to deliver the whole NSEvent.
535 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
536 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
537 }
538 }
539 [super sendEvent:event];
540 }
541
542 - (void)constrainSize:(NSSize*)size {
543 float minWidth = 0.f, minHeight = 0.f;
544
545 if (IS(self.styleBits, DECORATED)) {
546 NSRect frame = [self frame];
547 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self styleMask]];
548
549 float top = frame.size.height - contentRect.size.height;
550 float left = contentRect.origin.x - frame.origin.x;
551 float bottom = contentRect.origin.y - frame.origin.y;
552 float right = frame.size.width - (contentRect.size.width + left);
553
554 // Speculative estimation: 80 - enough for window decorations controls
555 minWidth += left + right + 80;
556 minHeight += top + bottom;
557 }
558
559 minWidth = MAX(1.f, minWidth);
560 minHeight = MAX(1.f, minHeight);
561
562 size->width = MAX(size->width, minWidth);
563 size->height = MAX(size->height, minHeight);
564 }
565
566 - (void) setEnabled: (BOOL)flag {
567 self.isEnabled = flag;
568
569 if (IS(self.styleBits, CLOSEABLE)) {
570 [[self standardWindowButton:NSWindowCloseButton] setEnabled: flag];
571 }
572
573 if (IS(self.styleBits, MINIMIZABLE)) {
574 [[self standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];
575 }
576
577 if (IS(self.styleBits, ZOOMABLE)) {
578 [[self standardWindowButton:NSWindowZoomButton] setEnabled: flag];
579 }
580
581 if (IS(self.styleBits, RESIZABLE)) {
582 [self updateMinMaxSize:flag];
583 [self setShowsResizeIndicator:flag];
584 }
585 }
586
587 @end // AWTWindow
588
589
590 /*
591 * Class: sun_lwawt_macosx_CPlatformWindow
592 * Method: nativeCreateNSWindow
593 * Signature: (JJIIII)J
594 */
595 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
596 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
597 {
598 __block AWTWindow *window = nil;
599
600 JNF_COCOA_ENTER(env);
601 AWT_ASSERT_NOT_APPKIT_THREAD;
602
603 JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
604 NSView *contentView = OBJC(contentViewPtr);
605 NSRect frameRect = NSMakeRect(x, y, w, h);
606
607 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
608 AWT_ASSERT_APPKIT_THREAD;
609
610 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
611 styleBits:styleBits
612 frameRect:frameRect
613 contentView:contentView];
614
615 if (window) CFRetain(window);
616 [window release]; // GC
617 }];
618
619 JNF_COCOA_EXIT(env);
620
621 return ptr_to_jlong(window);
622 }
623
624 /*
625 * Class: sun_lwawt_macosx_CPlatformWindow
626 * Method: nativeSetNSWindowStyleBits
627 * Signature: (JII)V
628 */
629 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
630 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
631 {
632 JNF_COCOA_ENTER(env);
633 AWT_ASSERT_NOT_APPKIT_THREAD;
634
635 AWTWindow *window = OBJC(windowPtr);
636 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
637 AWT_ASSERT_APPKIT_THREAD;
638
639 // scans the bit field, and only updates the values requested by the mask
640 // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
641 jint newBits = window.styleBits & ~mask | bits & mask;
642
643 // resets the NSWindow's style mask if the mask intersects any of those bits
644 if (mask & MASK(_STYLE_PROP_BITMASK)) {
645 [window setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
646 }
647
648 // calls methods on NSWindow to change other properties, based on the mask
649 if (mask & MASK(_METHOD_PROP_BITMASK)) {
650 [window setPropertiesForStyleBits:bits mask:mask];
651 }
652
653 window.styleBits = newBits;
654 }];
655
656 JNF_COCOA_EXIT(env);
657 }
658
659 /*
660 * Class: sun_lwawt_macosx_CPlatformWindow
661 * Method: nativeSetNSWindowMenuBar
662 * Signature: (JJ)V
663 */
664 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
665 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
666 {
667 JNF_COCOA_ENTER(env);
668 AWT_ASSERT_NOT_APPKIT_THREAD;
669
670 AWTWindow *window = OBJC(windowPtr);
671 CMenuBar *menuBar = OBJC(menuBarPtr);
672 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
673 AWT_ASSERT_APPKIT_THREAD;
674
675 if ([window isKeyWindow]) [window.javaMenuBar deactivate];
676 window.javaMenuBar = menuBar;
677
678 // if ([self isKeyWindow]) {
679 [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
680 // }
681 }];
682
683 JNF_COCOA_EXIT(env);
684 }
685
686 /*
687 * Class: sun_lwawt_macosx_CPlatformWindow
688 * Method: nativeGetNSWindowInsets
689 * Signature: (J)Ljava/awt/Insets;
690 */
691 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
692 (JNIEnv *env, jclass clazz, jlong windowPtr)
693 {
694 jobject ret = NULL;
695
696 JNF_COCOA_ENTER(env);
697 AWT_ASSERT_NOT_APPKIT_THREAD;
698
699 AWTWindow *window = OBJC(windowPtr);
700 __block NSRect contentRect = NSZeroRect;
701 __block NSRect frame = NSZeroRect;
702
703 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
704 AWT_ASSERT_APPKIT_THREAD;
705
706 frame = [window frame];
707 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[window styleMask]];
708 }];
709
710 jint top = (jint)(frame.size.height - contentRect.size.height);
711 jint left = (jint)(contentRect.origin.x - frame.origin.x);
712 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
713 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
714
715 static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
716 static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
717 ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
718
719 JNF_COCOA_EXIT(env);
720 return ret;
721 }
722
723 /*
724 * Class: sun_lwawt_macosx_CPlatformWindow
725 * Method: nativeSetNSWindowBounds
726 * Signature: (JDDDD)V
727 */
728 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
729 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
730 {
731 JNF_COCOA_ENTER(env);
732 AWT_ASSERT_NOT_APPKIT_THREAD;
733
734 NSRect jrect = NSMakeRect(originX, originY, width, height);
735
736 // TODO: not sure we need displayIfNeeded message in our view
737 AWTWindow *window = OBJC(windowPtr);
738 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
739 AWT_ASSERT_APPKIT_THREAD;
740
741 NSRect rect = ConvertNSScreenRect(NULL, jrect);
742 [window constrainSize:&rect.size];
743
744 [window setFrame:rect display:YES];
745
746 // only start tracking events if pointer is above the toplevel
747 // TODO: should post an Entered event if YES.
748 NSPoint mLocation = [NSEvent mouseLocation];
749 [window setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
750
751 // ensure we repaint the whole window after the resize operation
752 // (this will also re-enable screen updates, which were disabled above)
753 // TODO: send PaintEvent
754
755 [window synthesizeMouseEnteredExitedEvents];
756 }];
757
758 JNF_COCOA_EXIT(env);
759 }
760
761 /*
762 * Class: sun_lwawt_macosx_CPlatformWindow
763 * Method: nativeSetNSWindowMinMax
764 * Signature: (JDDDD)V
765 */
766 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
767 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
768 {
769 JNF_COCOA_ENTER(env);
770 AWT_ASSERT_NOT_APPKIT_THREAD;
771
772 if (minW < 1) minW = 1;
773 if (minH < 1) minH = 1;
774 if (maxW < 1) maxW = 1;
775 if (maxH < 1) maxH = 1;
776
777 AWTWindow *window = OBJC(windowPtr);
778 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
779 AWT_ASSERT_APPKIT_THREAD;
780
781 NSSize min = { minW, minH };
782 NSSize max = { maxW, maxH };
783
784 [window constrainSize:&min];
785 [window constrainSize:&max];
786
787 window.javaMinSize = min;
788 window.javaMaxSize = max;
789 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
790 }];
791
792 JNF_COCOA_EXIT(env);
793 }
794
795 /*
796 * Class: sun_lwawt_macosx_CPlatformWindow
797 * Method: nativePushNSWindowToBack
798 * Signature: (J)V
799 */
800 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
801 (JNIEnv *env, jclass clazz, jlong windowPtr)
802 {
803 JNF_COCOA_ENTER(env);
804 AWT_ASSERT_NOT_APPKIT_THREAD;
805
806 AWTWindow *window = OBJC(windowPtr);
807 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
808 AWT_ASSERT_APPKIT_THREAD;
809
810 [window orderBack:nil];
811 }];
812
813 JNF_COCOA_EXIT(env);
814 }
815
816 /*
817 * Class: sun_lwawt_macosx_CPlatformWindow
818 * Method: nativePushNSWindowToFront
819 * Signature: (J)V
820 */
821 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
822 (JNIEnv *env, jclass clazz, jlong windowPtr)
823 {
824 JNF_COCOA_ENTER(env);
825 AWT_ASSERT_NOT_APPKIT_THREAD;
826
827 AWTWindow *window = OBJC(windowPtr);
828 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
829 AWT_ASSERT_APPKIT_THREAD;
830
831 if (![window isKeyWindow]) {
832 [window makeKeyAndOrderFront:window];
833 } else {
834 [window orderFront:window];
835 }
836 }];
837
838 JNF_COCOA_EXIT(env);
839 }
840
841 /*
842 * Class: sun_lwawt_macosx_CPlatformWindow
843 * Method: nativeSetNSWindowTitle
844 * Signature: (JLjava/lang/String;)V
845 */
846 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
847 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
848 {
849 JNF_COCOA_ENTER(env);
850 AWT_ASSERT_NOT_APPKIT_THREAD;
851
852 AWTWindow *window = OBJC(windowPtr);
853 [window performSelectorOnMainThread:@selector(setTitle:)
854 withObject:JNFJavaToNSString(env, jtitle)
855 waitUntilDone:NO];
856
857 JNF_COCOA_EXIT(env);
858 }
859
860 /*
861 * Class: sun_lwawt_macosx_CPlatformWindow
862 * Method: nativeSetNSWindowAlpha
863 * Signature: (JF)V
864 */
865 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowAlpha
866 (JNIEnv *env, jclass clazz, jlong windowPtr, jfloat alpha)
867 {
868 JNF_COCOA_ENTER(env);
869 AWT_ASSERT_NOT_APPKIT_THREAD;
870
871 AWTWindow *window = OBJC(windowPtr);
872 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
873 AWT_ASSERT_APPKIT_THREAD;
874
875 [window setAlphaValue:alpha];
876 }];
877
878 JNF_COCOA_EXIT(env);
879 }
880
881 /*
882 * Class: sun_lwawt_macosx_CPlatformWindow
883 * Method: nativeRevalidateNSWindowShadow
884 * Signature: (J)V
885 */
886 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
887 (JNIEnv *env, jclass clazz, jlong windowPtr)
888 {
889 JNF_COCOA_ENTER(env);
890 AWT_ASSERT_NOT_APPKIT_THREAD;
891
892 AWTWindow *window = OBJC(windowPtr);
893 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
894 AWT_ASSERT_APPKIT_THREAD;
895
896 [window invalidateShadow];
897 }];
898
899 JNF_COCOA_EXIT(env);
900 }
901
902 /*
903 * Class: sun_lwawt_macosx_CPlatformWindow
904 * Method: nativeScreenOn_AppKitThread
905 * Signature: (J)I
906 */
907 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
908 (JNIEnv *env, jclass clazz, jlong windowPtr)
909 {
910 jint ret = 0;
911
912 JNF_COCOA_ENTER(env);
913 AWT_ASSERT_APPKIT_THREAD;
914
915 AWTWindow *window = OBJC(windowPtr);
916 NSDictionary *props = [[window screen] deviceDescription];
917 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
918
919 JNF_COCOA_EXIT(env);
920
921 return ret;
922 }
923
924 /*
925 * Class: sun_lwawt_macosx_CPlatformWindow
926 * Method: nativeSetNSWindowMinimizedIcon
927 * Signature: (JJ)V
928 */
929 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
930 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
931 {
932 JNF_COCOA_ENTER(env);
933 AWT_ASSERT_NOT_APPKIT_THREAD;
934
935 AWTWindow *window = OBJC(windowPtr);
936 NSImage *image = OBJC(nsImagePtr);
937 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
938 AWT_ASSERT_APPKIT_THREAD;
939
940 [window setMiniwindowImage:image];
941 }];
942
943 JNF_COCOA_EXIT(env);
944 }
945
946 /*
947 * Class: sun_lwawt_macosx_CPlatformWindow
948 * Method: nativeSetNSWindowRepresentedFilename
949 * Signature: (JLjava/lang/String;)V
950 */
951 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
952 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
953 {
954 JNF_COCOA_ENTER(env);
955 AWT_ASSERT_NOT_APPKIT_THREAD;
956
957 AWTWindow *window = OBJC(windowPtr);
958 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
959 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
960 AWT_ASSERT_APPKIT_THREAD;
961
962 [window setRepresentedURL:url];
963 }];
964
965 JNF_COCOA_EXIT(env);
966 }
967
968 /*
969 * Class: sun_lwawt_macosx_CPlatformWindow
970 * Method: nativeSetNSWindowSecurityWarningPositioning
971 * Signature: (JDDFF)V
972 */
973 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowSecurityWarningPositioning
974 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble x, jdouble y, jfloat biasX, jfloat biasY)
975 {
976 JNF_COCOA_ENTER(env);
977 AWT_ASSERT_NOT_APPKIT_THREAD;
978
979 [JNFException raise:env as:kRuntimeException reason:"unimplemented"];
980
981 JNF_COCOA_EXIT(env);
982 }
983
984 /*
985 * Class: sun_lwawt_macosx_CPlatformWindow
986 * Method: nativeSynthesizeMouseEnteredExitedEvents
987 * Signature: (J)V
988 */
989 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
990 (JNIEnv *env, jclass clazz, jlong windowPtr)
991 {
992 JNF_COCOA_ENTER(env);
993 AWT_ASSERT_NOT_APPKIT_THREAD;
994
995 AWTWindow *window = OBJC(windowPtr);
996 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
997 AWT_ASSERT_APPKIT_THREAD;
998
999 [window synthesizeMouseEnteredExitedEvents];
1000 }];
1001
1002 JNF_COCOA_EXIT(env);
1003 }
1004
1005 /*
1006 * Class: sun_lwawt_macosx_CPlatformWindow
1007 * Method: nativeGetScreenNSWindowIsOn_AppKitThread
1008 * Signature: (J)I
1009 */
1010 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
1011 (JNIEnv *env, jclass clazz, jlong windowPtr)
1012 {
1013 jint index = -1;
1014
1015 JNF_COCOA_ENTER(env);
1016 AWT_ASSERT_APPKIT_THREAD;
1017
1018 AWTWindow *window = OBJC(windowPtr);
1019 NSScreen* screen = [window screen];
1020
1021 //+++gdb NOTE: This is using a linear search of the screens. If it should
1022 // prove to be a bottleneck, this can definitely be improved. However,
1023 // many screens should prove to be the exception, rather than the rule.
1024 NSArray* screens = [NSScreen screens];
1025 NSUInteger i;
1026 for (i = 0; i < [screens count]; i++)
1027 {
1028 if ([[screens objectAtIndex:i] isEqualTo:screen])
1029 {
1030 index = i;
1031 break;
1032 }
1033 }
1034
1035 JNF_COCOA_EXIT(env);
1036 return 1;
1037 }
1038
1039
1040 /*
1041 * Class: sun_lwawt_macosx_CPlatformWindow
1042 * Method: _toggleFullScreenMode
1043 * Signature: (J)V
1044 */
1045 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1046 (JNIEnv *env, jobject peer, jlong windowPtr)
1047 {
1048 JNF_COCOA_ENTER(env);
1049
1050 AWTWindow *window = OBJC(windowPtr);
1051 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1052 if (![window respondsToSelector:toggleFullScreenSelector]) return;
1053
1054 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1055 [window performSelector:toggleFullScreenSelector withObject:nil];
1056 }];
1057
1058 JNF_COCOA_EXIT(env);
1059 }
1060
1061 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
1062 (JNIEnv *env, jclass clazz, jlong windowPtr)
1063 {
1064 __block jboolean underMouse = JNI_FALSE;
1065
1066 JNF_COCOA_ENTER(env);
1067 AWT_ASSERT_NOT_APPKIT_THREAD;
1068
1069 AWTWindow *aWindow = OBJC(windowPtr);
1070 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
1071 AWT_ASSERT_APPKIT_THREAD;
1072
1073 NSPoint pt = [aWindow mouseLocationOutsideOfEventStream];
1074 underMouse = [[aWindow contentView] hitTest:pt] != nil;
1075 }];
1076
1077 JNF_COCOA_EXIT(env);
1078
1079 return underMouse;
1080 }
1081
1082 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1083 (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1084 {
1085 JNF_COCOA_ENTER(env);
1086
1087 AWTWindow *window = OBJC(windowPtr);
1088 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1089 [window setEnabled: isEnabled];
1090 }];
1091
1092 JNF_COCOA_EXIT(env);
1093 }
1094
|
34 #import "AWTWindow.h"
35 #import "AWTView.h"
36 #import "CMenu.h"
37 #import "CMenuBar.h"
38 #import "LWCToolkit.h"
39 #import "GeomUtilities.h"
40 #import "ThreadUtilities.h"
41 #import "OSVersion.h"
42
43 #define MASK(KEY) \
44 (sun_lwawt_macosx_CPlatformWindow_ ## KEY)
45
46 #define IS(BITS, KEY) \
47 ((BITS & MASK(KEY)) != 0)
48
49 #define SET(BITS, KEY, VALUE) \
50 BITS = VALUE ? BITS | MASK(KEY) : BITS & ~MASK(KEY)
51
52 static JNF_CLASS_CACHE(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow");
53
54 // --------------------------------------------------------------
55 // NSWindow/NSPanel descendants implementation
56 #define AWT_NS_WINDOW_IMPLEMENTATION \
57 - (id) initWithDelegate:(AWTWindow *)delegate \
58 frameRect:(NSRect)contectRect \
59 styleMask:(NSUInteger)styleMask \
60 contentView:(NSView *)view \
61 { \
62 self = [super initWithContentRect:contectRect \
63 styleMask:styleMask \
64 backing:NSBackingStoreBuffered \
65 defer:NO]; \
66 \
67 if (self == nil) return nil; \
68 \
69 [self setDelegate:delegate]; \
70 [self setContentView:view]; \
71 [self setInitialFirstResponder:view]; \
72 [self setReleasedWhenClosed:NO]; \
73 [self setPreservesContentDuringLiveResize:YES]; \
74 \
75 return self; \
76 } \
77 \
78 /* NSWindow overrides */ \
79 - (BOOL) canBecomeKeyWindow { \
80 return [(AWTWindow*)[self delegate] canBecomeKeyWindow]; \
81 } \
82 \
83 - (BOOL) canBecomeMainWindow { \
84 return [(AWTWindow*)[self delegate] canBecomeMainWindow]; \
85 } \
86 \
87 - (BOOL) worksWhenModal { \
88 return [(AWTWindow*)[self delegate] worksWhenModal]; \
89 } \
90 \
91 - (void)sendEvent:(NSEvent *)event { \
92 [(AWTWindow*)[self delegate] sendEvent:event]; \
93 [super sendEvent:event]; \
94 }
95
96 @implementation AWTWindow_Normal
97 AWT_NS_WINDOW_IMPLEMENTATION
98 @end
99 @implementation AWTWindow_Panel
100 AWT_NS_WINDOW_IMPLEMENTATION
101 @end
102 // END of NSWindow/NSPanel descendants implementation
103 // --------------------------------------------------------------
104
105
106 @implementation AWTWindow
107
108 @synthesize nsWindow;
109 @synthesize javaPlatformWindow;
110 @synthesize javaMenuBar;
111 @synthesize javaMinSize;
112 @synthesize javaMaxSize;
113 @synthesize styleBits;
114 @synthesize isEnabled;
115
116 - (void) updateMinMaxSize:(BOOL)resizable {
117 if (resizable) {
118 [self.nsWindow setMinSize:self.javaMinSize];
119 [self.nsWindow setMaxSize:self.javaMaxSize];
120 } else {
121 NSRect currentFrame = [self.nsWindow frame];
122 [self.nsWindow setMinSize:currentFrame.size];
123 [self.nsWindow setMaxSize:currentFrame.size];
124 }
125 }
126
127 // creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
128 + (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
129 NSUInteger type = 0;
130 if (IS(styleBits, DECORATED)) {
131 type |= NSTitledWindowMask;
132 if (IS(styleBits, CLOSEABLE)) type |= NSClosableWindowMask;
133 if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;
134 if (IS(styleBits, RESIZABLE)) type |= NSResizableWindowMask;
135 } else {
136 type |= NSBorderlessWindowMask;
137 }
138
139 if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;
140 if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;
141 if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;
142 if (IS(styleBits, HUD)) type |= NSHUDWindowMask;
143 if (IS(styleBits, SHEET)) type |= NSDocModalWindowMask;
144 if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
145
146 return type;
147 }
148
149 // updates _METHOD_PROP_BITMASK based properties on the window
150 - (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
151 if (IS(mask, RESIZABLE)) {
152 BOOL resizable = IS(bits, RESIZABLE);
153 [self updateMinMaxSize:resizable];
154 [self.nsWindow setShowsResizeIndicator:resizable];
155 }
156
157 if (IS(mask, HAS_SHADOW)) {
158 [self.nsWindow setHasShadow:IS(bits, HAS_SHADOW)];
159 }
160
161 if (IS(mask, ZOOMABLE)) {
162 [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
163 }
164
165 if (IS(mask, ALWAYS_ON_TOP)) {
166 [self.nsWindow setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
167 }
168
169 if (IS(mask, HIDES_ON_DEACTIVATE)) {
170 [self.nsWindow setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
171 }
172
173 if (IS(mask, DRAGGABLE_BACKGROUND)) {
174 [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
175 }
176
177 if (IS(mask, DOCUMENT_MODIFIED)) {
178 [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
179 }
180
181 if ([self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
182 if (IS(mask, FULLSCREENABLE)) {
183 [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
184 } else {
185 [self.nsWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault];
186 }
187 }
188
189 }
190
191 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
192 styleBits:(jint)bits
193 frameRect:(NSRect)rect
194 contentView:(NSView *)view
195 {
196 AWT_ASSERT_APPKIT_THREAD;
197
198 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
199 NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
200 if (contentRect.size.width <= 0.0) {
201 contentRect.size.width = 1.0;
202 }
203 if (contentRect.size.height <= 0.0) {
204 contentRect.size.height = 1.0;
205 }
206
207 self = [super init];
208
209 if (self == nil) return nil; // no hope
210
211 if (IS(bits, UTILITY) ||
212 IS(bits, NONACTIVATING) ||
213 IS(bits, HUD) ||
214 IS(bits, HIDES_ON_DEACTIVATE))
215 {
216 self.nsWindow = [[AWTWindow_Panel alloc] initWithDelegate:self
217 frameRect:contentRect
218 styleMask:styleMask
219 contentView:view];
220 }
221 else
222 {
223 // These windows will appear in the window list in the dock icon menu
224 self.nsWindow = [[AWTWindow_Normal alloc] initWithDelegate:self
225 frameRect:contentRect
226 styleMask:styleMask
227 contentView:view];
228 }
229
230 if (self.nsWindow == nil) return nil; // no hope either
231
232 self.isEnabled = YES;
233 self.javaPlatformWindow = platformWindow;
234 self.styleBits = bits;
235 [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
236
237 return self;
238 }
239
240 // checks that this window is under the mouse cursor and this point is not overlapped by others windows
241 - (BOOL) isTopmostWindowUnderMouse {
242
243 int currentWinID = [self.nsWindow windowNumber];
244
245 NSRect screenRect = [[NSScreen mainScreen] frame];
246 NSPoint nsMouseLocation = [NSEvent mouseLocation];
247 CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
248
249 NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
250
251
252 for (NSDictionary *window in windows) {
253 int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
254 if (layer == 0) {
255 int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];
256 CGRect rect;
257 CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
258 if (CGRectContainsPoint(rect, cgMouseLocation)) {
259 return currentWinID == winID;
260 } else if (currentWinID == winID) {
261 return NO;
262 }
263 }
264 }
265 return NO;
266 }
267
268 - (void) synthesizeMouseEnteredExitedEvents {
269
270 int eventType = 0;
271 BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
272 BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver];
273
274 if (isUnderMouse && !mouseIsOver) {
275 eventType = NSMouseEntered;
276 } else if (!isUnderMouse && mouseIsOver) {
277 eventType = NSMouseExited;
278 } else {
279 return;
280 }
281
282 NSPoint screenLocation = [NSEvent mouseLocation];
283 NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation];
284 int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
285
286 NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
287 location: windowLocation
288 modifierFlags: modifierFlags
289 timestamp: 0
290 windowNumber: [self.nsWindow windowNumber]
291 context: nil
292 eventNumber: 0
293 trackingNumber: 0
294 userData: nil
295 ];
296
297 [[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent];
298 }
299
300 - (void) dealloc {
301 AWT_ASSERT_APPKIT_THREAD;
302
303 JNIEnv *env = [ThreadUtilities getJNIEnv];
304 [self.javaPlatformWindow setJObject:nil withEnv:env];
305
306 self.nsWindow = nil;
307
308 [super dealloc];
309 }
310
311 // NSWindow overrides
312 - (BOOL) canBecomeKeyWindow {
313 AWT_ASSERT_APPKIT_THREAD;
314 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_KEY);
315 }
316
317 - (BOOL) canBecomeMainWindow {
318 AWT_ASSERT_APPKIT_THREAD;
319 return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN);
320 }
321
322 - (BOOL) worksWhenModal {
323 AWT_ASSERT_APPKIT_THREAD;
324 return IS(self.styleBits, MODAL_EXCLUDED);
325 }
326
327
328 // Gesture support
329 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
330 AWT_ASSERT_APPKIT_THREAD;
331
332 JNIEnv *env = [ThreadUtilities getJNIEnv];
333 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
334 if (platformWindow != NULL) {
335 // extract the target AWT Window object out of the CPlatformWindow
336 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
337 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
338 if (awtWindow != NULL) {
339 // translate the point into Java coordinates
340 NSPoint loc = [event locationInWindow];
341 loc.y = [self.nsWindow frame].size.height - loc.y;
342
343 // send up to the GestureHandler to recursively dispatch on the AWT event thread
344 static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
345 static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
346 JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
347 (*env)->DeleteLocalRef(env, awtWindow);
348 }
349 (*env)->DeleteLocalRef(env, platformWindow);
350 }
351 }
352
353 - (void)beginGestureWithEvent:(NSEvent *)event {
354 [self postGesture:event
355 as:com_apple_eawt_event_GestureHandler_PHASE
356 a:-1.0
357 b:0.0];
358 }
359
360 - (void)endGestureWithEvent:(NSEvent *)event {
361 [self postGesture:event
384 a:[event deltaX]
385 b:[event deltaY]];
386 }
387
388
389 // NSWindowDelegate methods
390
391 - (void) _deliverMoveResizeEvent {
392 AWT_ASSERT_APPKIT_THREAD;
393
394 // deliver the event if this is a user-initiated live resize or as a side-effect
395 // of a Java initiated resize, because AppKit can override the bounds and force
396 // the bounds of the window to avoid the Dock or remain on screen.
397 [AWTToolkit eventCountPlusPlus];
398 JNIEnv *env = [ThreadUtilities getJNIEnv];
399 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
400 if (platformWindow == NULL) {
401 // TODO: create generic AWT assert
402 }
403
404 NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
405
406 static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V");
407 JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
408 (jint)frame.origin.x,
409 (jint)frame.origin.y,
410 (jint)frame.size.width,
411 (jint)frame.size.height);
412 (*env)->DeleteLocalRef(env, platformWindow);
413 }
414
415 - (void)windowDidMove:(NSNotification *)notification {
416 AWT_ASSERT_APPKIT_THREAD;
417
418 [self _deliverMoveResizeEvent];
419 }
420
421 - (void)windowDidResize:(NSNotification *)notification {
422 AWT_ASSERT_APPKIT_THREAD;
423
424 [self _deliverMoveResizeEvent];
574 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
575 (*env)->DeleteLocalRef(env, platformWindow);
576 }
577 }
578
579 - (void)windowDidExitFullScreen:(NSNotification *)notification {
580 static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
581 JNIEnv *env = [ThreadUtilities getJNIEnv];
582 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
583 if (platformWindow != NULL) {
584 JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
585 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
586 (*env)->DeleteLocalRef(env, platformWindow);
587 }
588 }
589
590 - (void)sendEvent:(NSEvent *)event {
591 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
592
593 NSPoint p = [NSEvent mouseLocation];
594 NSRect frame = [self.nsWindow frame];
595 NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
596
597 // Check if the click happened in the non-client area (title bar)
598 if (p.y >= (frame.origin.y + contentRect.size.height)) {
599 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
600 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
601 // Currently, no need to deliver the whole NSEvent.
602 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
603 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
604 }
605 }
606 }
607
608 - (void)constrainSize:(NSSize*)size {
609 float minWidth = 0.f, minHeight = 0.f;
610
611 if (IS(self.styleBits, DECORATED)) {
612 NSRect frame = [self.nsWindow frame];
613 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
614
615 float top = frame.size.height - contentRect.size.height;
616 float left = contentRect.origin.x - frame.origin.x;
617 float bottom = contentRect.origin.y - frame.origin.y;
618 float right = frame.size.width - (contentRect.size.width + left);
619
620 // Speculative estimation: 80 - enough for window decorations controls
621 minWidth += left + right + 80;
622 minHeight += top + bottom;
623 }
624
625 minWidth = MAX(1.f, minWidth);
626 minHeight = MAX(1.f, minHeight);
627
628 size->width = MAX(size->width, minWidth);
629 size->height = MAX(size->height, minHeight);
630 }
631
632 - (void) setEnabled: (BOOL)flag {
633 self.isEnabled = flag;
634
635 if (IS(self.styleBits, CLOSEABLE)) {
636 [[self.nsWindow standardWindowButton:NSWindowCloseButton] setEnabled: flag];
637 }
638
639 if (IS(self.styleBits, MINIMIZABLE)) {
640 [[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];
641 }
642
643 if (IS(self.styleBits, ZOOMABLE)) {
644 [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled: flag];
645 }
646
647 if (IS(self.styleBits, RESIZABLE)) {
648 [self updateMinMaxSize:flag];
649 [self.nsWindow setShowsResizeIndicator:flag];
650 }
651 }
652
653 @end // AWTWindow
654
655
656 /*
657 * Class: sun_lwawt_macosx_CPlatformWindow
658 * Method: nativeCreateNSWindow
659 * Signature: (JJIIII)J
660 */
661 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCreateNSWindow
662 (JNIEnv *env, jobject obj, jlong contentViewPtr, jlong styleBits, jdouble x, jdouble y, jdouble w, jdouble h)
663 {
664 __block AWTWindow *window = nil;
665
666 JNF_COCOA_ENTER(env);
667 AWT_ASSERT_NOT_APPKIT_THREAD;
668
669 JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
670 NSView *contentView = OBJC(contentViewPtr);
671 NSRect frameRect = NSMakeRect(x, y, w, h);
672
673 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
674 AWT_ASSERT_APPKIT_THREAD;
675
676 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
677 styleBits:styleBits
678 frameRect:frameRect
679 contentView:contentView];
680
681 if (window) CFRetain(window);
682 [window release]; // GC
683 }];
684
685 JNF_COCOA_EXIT(env);
686
687 return ptr_to_jlong(window ? window.nsWindow : nil);
688 }
689
690 /*
691 * Class: sun_lwawt_macosx_CPlatformWindow
692 * Method: nativeSetNSWindowStyleBits
693 * Signature: (JII)V
694 */
695 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
696 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
697 {
698 JNF_COCOA_ENTER(env);
699 AWT_ASSERT_NOT_APPKIT_THREAD;
700
701 NSWindow *nsWindow = OBJC(windowPtr);
702 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
703 AWT_ASSERT_APPKIT_THREAD;
704
705 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
706
707 // scans the bit field, and only updates the values requested by the mask
708 // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
709 jint newBits = window.styleBits & ~mask | bits & mask;
710
711 // resets the NSWindow's style mask if the mask intersects any of those bits
712 if (mask & MASK(_STYLE_PROP_BITMASK)) {
713 [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
714 }
715
716 // calls methods on NSWindow to change other properties, based on the mask
717 if (mask & MASK(_METHOD_PROP_BITMASK)) {
718 [window setPropertiesForStyleBits:bits mask:mask];
719 }
720
721 window.styleBits = newBits;
722 }];
723
724 JNF_COCOA_EXIT(env);
725 }
726
727 /*
728 * Class: sun_lwawt_macosx_CPlatformWindow
729 * Method: nativeSetNSWindowMenuBar
730 * Signature: (JJ)V
731 */
732 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
733 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
734 {
735 JNF_COCOA_ENTER(env);
736 AWT_ASSERT_NOT_APPKIT_THREAD;
737
738 NSWindow *nsWindow = OBJC(windowPtr);
739 CMenuBar *menuBar = OBJC(menuBarPtr);
740 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
741 AWT_ASSERT_APPKIT_THREAD;
742
743 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
744
745 if ([nsWindow isKeyWindow]) [window.javaMenuBar deactivate];
746 window.javaMenuBar = menuBar;
747
748 // if ([self isKeyWindow]) {
749 [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
750 // }
751 }];
752
753 JNF_COCOA_EXIT(env);
754 }
755
756 /*
757 * Class: sun_lwawt_macosx_CPlatformWindow
758 * Method: nativeGetNSWindowInsets
759 * Signature: (J)Ljava/awt/Insets;
760 */
761 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
762 (JNIEnv *env, jclass clazz, jlong windowPtr)
763 {
764 jobject ret = NULL;
765
766 JNF_COCOA_ENTER(env);
767 AWT_ASSERT_NOT_APPKIT_THREAD;
768
769 NSWindow *nsWindow = OBJC(windowPtr);
770 __block NSRect contentRect = NSZeroRect;
771 __block NSRect frame = NSZeroRect;
772
773 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
774 AWT_ASSERT_APPKIT_THREAD;
775
776 frame = [nsWindow frame];
777 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
778 }];
779
780 jint top = (jint)(frame.size.height - contentRect.size.height);
781 jint left = (jint)(contentRect.origin.x - frame.origin.x);
782 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
783 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
784
785 static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
786 static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
787 ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
788
789 JNF_COCOA_EXIT(env);
790 return ret;
791 }
792
793 /*
794 * Class: sun_lwawt_macosx_CPlatformWindow
795 * Method: nativeSetNSWindowBounds
796 * Signature: (JDDDD)V
797 */
798 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
799 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
800 {
801 JNF_COCOA_ENTER(env);
802 AWT_ASSERT_NOT_APPKIT_THREAD;
803
804 NSRect jrect = NSMakeRect(originX, originY, width, height);
805
806 // TODO: not sure we need displayIfNeeded message in our view
807 NSWindow *nsWindow = OBJC(windowPtr);
808 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
809 AWT_ASSERT_APPKIT_THREAD;
810
811 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
812
813 NSRect rect = ConvertNSScreenRect(NULL, jrect);
814 [window constrainSize:&rect.size];
815
816 [nsWindow setFrame:rect display:YES];
817
818 // only start tracking events if pointer is above the toplevel
819 // TODO: should post an Entered event if YES.
820 NSPoint mLocation = [NSEvent mouseLocation];
821 [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
822
823 // ensure we repaint the whole window after the resize operation
824 // (this will also re-enable screen updates, which were disabled above)
825 // TODO: send PaintEvent
826
827 [window synthesizeMouseEnteredExitedEvents];
828 }];
829
830 JNF_COCOA_EXIT(env);
831 }
832
833 /*
834 * Class: sun_lwawt_macosx_CPlatformWindow
835 * Method: nativeSetNSWindowMinMax
836 * Signature: (JDDDD)V
837 */
838 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
839 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
840 {
841 JNF_COCOA_ENTER(env);
842 AWT_ASSERT_NOT_APPKIT_THREAD;
843
844 if (minW < 1) minW = 1;
845 if (minH < 1) minH = 1;
846 if (maxW < 1) maxW = 1;
847 if (maxH < 1) maxH = 1;
848
849 NSWindow *nsWindow = OBJC(windowPtr);
850 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
851 AWT_ASSERT_APPKIT_THREAD;
852
853 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
854
855 NSSize min = { minW, minH };
856 NSSize max = { maxW, maxH };
857
858 [window constrainSize:&min];
859 [window constrainSize:&max];
860
861 window.javaMinSize = min;
862 window.javaMaxSize = max;
863 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
864 }];
865
866 JNF_COCOA_EXIT(env);
867 }
868
869 /*
870 * Class: sun_lwawt_macosx_CPlatformWindow
871 * Method: nativePushNSWindowToBack
872 * Signature: (J)V
873 */
874 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
875 (JNIEnv *env, jclass clazz, jlong windowPtr)
876 {
877 JNF_COCOA_ENTER(env);
878 AWT_ASSERT_NOT_APPKIT_THREAD;
879
880 NSWindow *nsWindow = OBJC(windowPtr);
881 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
882 AWT_ASSERT_APPKIT_THREAD;
883
884 [nsWindow orderBack:nil];
885 }];
886
887 JNF_COCOA_EXIT(env);
888 }
889
890 /*
891 * Class: sun_lwawt_macosx_CPlatformWindow
892 * Method: nativePushNSWindowToFront
893 * Signature: (J)V
894 */
895 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
896 (JNIEnv *env, jclass clazz, jlong windowPtr)
897 {
898 JNF_COCOA_ENTER(env);
899 AWT_ASSERT_NOT_APPKIT_THREAD;
900
901 NSWindow *nsWindow = OBJC(windowPtr);
902 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
903 AWT_ASSERT_APPKIT_THREAD;
904
905 if (![nsWindow isKeyWindow]) {
906 [nsWindow makeKeyAndOrderFront:nsWindow];
907 } else {
908 [nsWindow orderFront:nsWindow];
909 }
910 }];
911
912 JNF_COCOA_EXIT(env);
913 }
914
915 /*
916 * Class: sun_lwawt_macosx_CPlatformWindow
917 * Method: nativeSetNSWindowTitle
918 * Signature: (JLjava/lang/String;)V
919 */
920 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
921 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
922 {
923 JNF_COCOA_ENTER(env);
924 AWT_ASSERT_NOT_APPKIT_THREAD;
925
926 NSWindow *nsWindow = OBJC(windowPtr);
927 [nsWindow performSelectorOnMainThread:@selector(setTitle:)
928 withObject:JNFJavaToNSString(env, jtitle)
929 waitUntilDone:NO];
930
931 JNF_COCOA_EXIT(env);
932 }
933
934 /*
935 * Class: sun_lwawt_macosx_CPlatformWindow
936 * Method: nativeSetNSWindowAlpha
937 * Signature: (JF)V
938 */
939 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowAlpha
940 (JNIEnv *env, jclass clazz, jlong windowPtr, jfloat alpha)
941 {
942 JNF_COCOA_ENTER(env);
943 AWT_ASSERT_NOT_APPKIT_THREAD;
944
945 NSWindow *nsWindow = OBJC(windowPtr);
946 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
947 AWT_ASSERT_APPKIT_THREAD;
948
949 [nsWindow setAlphaValue:alpha];
950 }];
951
952 JNF_COCOA_EXIT(env);
953 }
954
955 /*
956 * Class: sun_lwawt_macosx_CPlatformWindow
957 * Method: nativeRevalidateNSWindowShadow
958 * Signature: (J)V
959 */
960 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
961 (JNIEnv *env, jclass clazz, jlong windowPtr)
962 {
963 JNF_COCOA_ENTER(env);
964 AWT_ASSERT_NOT_APPKIT_THREAD;
965
966 NSWindow *nsWindow = OBJC(windowPtr);
967 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
968 AWT_ASSERT_APPKIT_THREAD;
969
970 [nsWindow invalidateShadow];
971 }];
972
973 JNF_COCOA_EXIT(env);
974 }
975
976 /*
977 * Class: sun_lwawt_macosx_CPlatformWindow
978 * Method: nativeScreenOn_AppKitThread
979 * Signature: (J)I
980 */
981 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
982 (JNIEnv *env, jclass clazz, jlong windowPtr)
983 {
984 jint ret = 0;
985
986 JNF_COCOA_ENTER(env);
987 AWT_ASSERT_APPKIT_THREAD;
988
989 NSWindow *nsWindow = OBJC(windowPtr);
990 NSDictionary *props = [[nsWindow screen] deviceDescription];
991 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
992
993 JNF_COCOA_EXIT(env);
994
995 return ret;
996 }
997
998 /*
999 * Class: sun_lwawt_macosx_CPlatformWindow
1000 * Method: nativeSetNSWindowMinimizedIcon
1001 * Signature: (JJ)V
1002 */
1003 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
1004 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
1005 {
1006 JNF_COCOA_ENTER(env);
1007 AWT_ASSERT_NOT_APPKIT_THREAD;
1008
1009 NSWindow *nsWindow = OBJC(windowPtr);
1010 NSImage *image = OBJC(nsImagePtr);
1011 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1012 AWT_ASSERT_APPKIT_THREAD;
1013
1014 [nsWindow setMiniwindowImage:image];
1015 }];
1016
1017 JNF_COCOA_EXIT(env);
1018 }
1019
1020 /*
1021 * Class: sun_lwawt_macosx_CPlatformWindow
1022 * Method: nativeSetNSWindowRepresentedFilename
1023 * Signature: (JLjava/lang/String;)V
1024 */
1025 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
1026 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
1027 {
1028 JNF_COCOA_ENTER(env);
1029 AWT_ASSERT_NOT_APPKIT_THREAD;
1030
1031 NSWindow *nsWindow = OBJC(windowPtr);
1032 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
1033 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1034 AWT_ASSERT_APPKIT_THREAD;
1035
1036 [nsWindow setRepresentedURL:url];
1037 }];
1038
1039 JNF_COCOA_EXIT(env);
1040 }
1041
1042 /*
1043 * Class: sun_lwawt_macosx_CPlatformWindow
1044 * Method: nativeSetNSWindowSecurityWarningPositioning
1045 * Signature: (JDDFF)V
1046 */
1047 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowSecurityWarningPositioning
1048 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble x, jdouble y, jfloat biasX, jfloat biasY)
1049 {
1050 JNF_COCOA_ENTER(env);
1051 AWT_ASSERT_NOT_APPKIT_THREAD;
1052
1053 [JNFException raise:env as:kRuntimeException reason:"unimplemented"];
1054
1055 JNF_COCOA_EXIT(env);
1056 }
1057
1058 /*
1059 * Class: sun_lwawt_macosx_CPlatformWindow
1060 * Method: nativeSynthesizeMouseEnteredExitedEvents
1061 * Signature: (J)V
1062 */
1063 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
1064 (JNIEnv *env, jclass clazz, jlong windowPtr)
1065 {
1066 JNF_COCOA_ENTER(env);
1067 AWT_ASSERT_NOT_APPKIT_THREAD;
1068
1069 NSWindow *nsWindow = OBJC(windowPtr);
1070 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1071 AWT_ASSERT_APPKIT_THREAD;
1072
1073 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1074
1075 [window synthesizeMouseEnteredExitedEvents];
1076 }];
1077
1078 JNF_COCOA_EXIT(env);
1079 }
1080
1081 /*
1082 * Class: sun_lwawt_macosx_CPlatformWindow
1083 * Method: nativeGetScreenNSWindowIsOn_AppKitThread
1084 * Signature: (J)I
1085 */
1086 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
1087 (JNIEnv *env, jclass clazz, jlong windowPtr)
1088 {
1089 jint index = -1;
1090
1091 JNF_COCOA_ENTER(env);
1092 AWT_ASSERT_APPKIT_THREAD;
1093
1094 NSWindow *nsWindow = OBJC(windowPtr);
1095 NSScreen* screen = [nsWindow screen];
1096
1097 //+++gdb NOTE: This is using a linear search of the screens. If it should
1098 // prove to be a bottleneck, this can definitely be improved. However,
1099 // many screens should prove to be the exception, rather than the rule.
1100 NSArray* screens = [NSScreen screens];
1101 NSUInteger i;
1102 for (i = 0; i < [screens count]; i++)
1103 {
1104 if ([[screens objectAtIndex:i] isEqualTo:screen])
1105 {
1106 index = i;
1107 break;
1108 }
1109 }
1110
1111 JNF_COCOA_EXIT(env);
1112 return 1;
1113 }
1114
1115
1116 /*
1117 * Class: sun_lwawt_macosx_CPlatformWindow
1118 * Method: _toggleFullScreenMode
1119 * Signature: (J)V
1120 */
1121 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
1122 (JNIEnv *env, jobject peer, jlong windowPtr)
1123 {
1124 JNF_COCOA_ENTER(env);
1125
1126 NSWindow *nsWindow = OBJC(windowPtr);
1127 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
1128 if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
1129
1130 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1131 [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
1132 }];
1133
1134 JNF_COCOA_EXIT(env);
1135 }
1136
1137 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
1138 (JNIEnv *env, jclass clazz, jlong windowPtr)
1139 {
1140 __block jboolean underMouse = JNI_FALSE;
1141
1142 JNF_COCOA_ENTER(env);
1143 AWT_ASSERT_NOT_APPKIT_THREAD;
1144
1145 NSWindow *nsWindow = OBJC(windowPtr);
1146 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
1147 AWT_ASSERT_APPKIT_THREAD;
1148
1149 NSPoint pt = [nsWindow mouseLocationOutsideOfEventStream];
1150 underMouse = [[nsWindow contentView] hitTest:pt] != nil;
1151 }];
1152
1153 JNF_COCOA_EXIT(env);
1154
1155 return underMouse;
1156 }
1157
1158 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled
1159 (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled)
1160 {
1161 JNF_COCOA_ENTER(env);
1162
1163 NSWindow *nsWindow = OBJC(windowPtr);
1164 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
1165 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
1166
1167 [window setEnabled: isEnabled];
1168 }];
1169
1170 JNF_COCOA_EXIT(env);
1171 }
1172
|