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
62 - (void) updateMinMaxSize:(BOOL)resizable {
63 if (resizable) {
64 [self setMinSize:self.javaMinSize];
65 [self setMaxSize:self.javaMaxSize];
66 } else {
67 NSRect currentFrame = [self frame];
68 [self setMinSize:currentFrame.size];
69 [self setMaxSize:currentFrame.size];
70 }
71 }
72
73 // creates a new NSWindow style mask based on the _STYLE_PROP_BITMASK bits
74 + (NSUInteger) styleMaskForStyleBits:(jint)styleBits {
75 NSUInteger type = 0;
76 if (IS(styleBits, DECORATED)) {
77 type |= NSTitledWindowMask;
78 if (IS(styleBits, CLOSEABLE)) type |= NSClosableWindowMask;
79 if (IS(styleBits, MINIMIZABLE)) type |= NSMiniaturizableWindowMask;
80 if (IS(styleBits, RESIZABLE)) type |= NSResizableWindowMask;
81 } else {
82 type |= NSBorderlessWindowMask;
83 }
84
85 if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;
86 if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;
87 if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;
88 if (IS(styleBits, HUD)) type |= NSHUDWindowMask;
89 if (IS(styleBits, SHEET)) type |= NSDocModalWindowMask;
90 if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
91
92 return type;
93 }
94
95 // updates _METHOD_PROP_BITMASK based properties on the window
96 - (void) setPropertiesForStyleBits:(jint)bits mask:(jint)mask {
97 if (IS(mask, RESIZABLE)) {
98 BOOL resizable = IS(bits, RESIZABLE);
99 [self updateMinMaxSize:resizable];
100 [self setShowsResizeIndicator:resizable];
101 }
102
103 if (IS(mask, HAS_SHADOW)) {
104 [self setHasShadow:IS(bits, HAS_SHADOW)];
105 }
106
107 if (IS(mask, ZOOMABLE)) {
108 [[self standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
109 }
110
111 if (IS(mask, ALWAYS_ON_TOP)) {
112 [self setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
113 }
114
115 if (IS(mask, HIDES_ON_DEACTIVATE)) {
116 [self setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
117 }
118
119 if (IS(mask, DRAGGABLE_BACKGROUND)) {
120 [self setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
121 }
122
123 if (IS(mask, DOCUMENT_MODIFIED)) {
124 [self setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
125 }
126
127 if ([self respondsToSelector:@selector(toggleFullScreen:)]) {
128 if (IS(mask, FULLSCREENABLE)) {
129 [self setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
130 } else {
131 [self setCollectionBehavior:NSWindowCollectionBehaviorDefault];
132 }
133 }
134
135 }
136
137 - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)platformWindow
138 styleBits:(jint)bits
139 frameRect:(NSRect)rect
140 contentView:(NSView *)view
141 {
142 AWT_ASSERT_APPKIT_THREAD;
143
144 NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:bits];
145 NSRect contentRect = rect; //[NSWindow contentRectForFrameRect:rect styleMask:styleMask];
146 if (contentRect.size.width <= 0.0) {
147 contentRect.size.width = 1.0;
148 }
149 if (contentRect.size.height <= 0.0) {
150 contentRect.size.height = 1.0;
151 }
152
153 self = [super initWithContentRect:contentRect
154 styleMask:styleMask
155 backing:NSBackingStoreBuffered
156 defer:NO];
157
158 if (self == nil) return nil; // no hope
159
160 self.javaPlatformWindow = platformWindow;
161 self.styleBits = bits;
162 [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
163
164 [self setDelegate:self];
165 [self setContentView:view];
166 [self setInitialFirstResponder:view];
167 [self setReleasedWhenClosed:NO];
168 [self setPreservesContentDuringLiveResize:YES];
169
170 return self;
171 }
172
173 - (void) dealloc {
174 AWT_ASSERT_APPKIT_THREAD;
175
176 JNIEnv *env = [ThreadUtilities getJNIEnv];
177 [self.javaPlatformWindow setJObject:nil withEnv:env];
178
179 [super dealloc];
180 }
181
182
183 // NSWindow overrides
184 - (BOOL) canBecomeKeyWindow {
185 AWT_ASSERT_APPKIT_THREAD;
186 return IS(self.styleBits, SHOULD_BECOME_KEY);
187 }
188
189 - (BOOL) canBecomeMainWindow {
190 AWT_ASSERT_APPKIT_THREAD;
191 return IS(self.styleBits, SHOULD_BECOME_MAIN);
192 }
193
194 - (BOOL) worksWhenModal {
195 AWT_ASSERT_APPKIT_THREAD;
196 return IS(self.styleBits, MODAL_EXCLUDED);
197 }
198
199
200 // Gesture support
201 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
202 AWT_ASSERT_APPKIT_THREAD;
203
204 JNIEnv *env = [ThreadUtilities getJNIEnv];
205 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
206 if (platformWindow != NULL) {
207 // extract the target AWT Window object out of the CPlatformWindow
208 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
209 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
210 if (awtWindow != NULL) {
211 // translate the point into Java coordinates
212 NSPoint loc = [event locationInWindow];
213 loc.y = [self frame].size.height - loc.y;
214
215 // send up to the GestureHandler to recursively dispatch on the AWT event thread
216 static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
217 static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
218 JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
219 (*env)->DeleteLocalRef(env, awtWindow);
220 }
221 (*env)->DeleteLocalRef(env, platformWindow);
222 }
223 }
224
225 - (void)beginGestureWithEvent:(NSEvent *)event {
226 [self postGesture:event
227 as:com_apple_eawt_event_GestureHandler_PHASE
228 a:-1.0
229 b:0.0];
230 }
231
232 - (void)endGestureWithEvent:(NSEvent *)event {
233 [self postGesture:event
256 a:[event deltaX]
257 b:[event deltaY]];
258 }
259
260
261 // NSWindowDelegate methods
262
263 - (void) _deliverMoveResizeEvent {
264 AWT_ASSERT_APPKIT_THREAD;
265
266 // deliver the event if this is a user-initiated live resize or as a side-effect
267 // of a Java initiated resize, because AppKit can override the bounds and force
268 // the bounds of the window to avoid the Dock or remain on screen.
269 [AWTToolkit eventCountPlusPlus];
270 JNIEnv *env = [ThreadUtilities getJNIEnv];
271 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
272 if (platformWindow == NULL) {
273 // TODO: create generic AWT assert
274 }
275
276 NSRect frame = ConvertNSScreenRect(env, [self frame]);
277
278 static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V");
279 JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
280 (jint)frame.origin.x,
281 (jint)frame.origin.y,
282 (jint)frame.size.width,
283 (jint)frame.size.height);
284 (*env)->DeleteLocalRef(env, platformWindow);
285 }
286
287 - (void)windowDidMove:(NSNotification *)notification {
288 AWT_ASSERT_APPKIT_THREAD;
289
290 [self _deliverMoveResizeEvent];
291 }
292
293 - (void)windowDidResize:(NSNotification *)notification {
294 AWT_ASSERT_APPKIT_THREAD;
295
296 [self _deliverMoveResizeEvent];
446 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
447 (*env)->DeleteLocalRef(env, platformWindow);
448 }
449 }
450
451 - (void)windowDidExitFullScreen:(NSNotification *)notification {
452 static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
453 JNIEnv *env = [ThreadUtilities getJNIEnv];
454 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
455 if (platformWindow != NULL) {
456 JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
457 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
458 (*env)->DeleteLocalRef(env, platformWindow);
459 }
460 }
461
462 - (void)sendEvent:(NSEvent *)event {
463 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
464
465 NSPoint p = [NSEvent mouseLocation];
466 NSRect frame = [self frame];
467 NSRect contentRect = [self contentRectForFrameRect:frame];
468
469 // Check if the click happened in the non-client area (title bar)
470 if (p.y >= (frame.origin.y + contentRect.size.height)) {
471 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
472 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
473 // Currently, no need to deliver the whole NSEvent.
474 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
475 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
476 }
477 }
478 [super sendEvent:event];
479 }
480
481 - (void)constrainSize:(NSSize*)size {
482 float minWidth = 0.f, minHeight = 0.f;
483
484 if (IS(self.styleBits, DECORATED)) {
485 NSRect frame = [self frame];
486 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self styleMask]];
487
488 float top = frame.size.height - contentRect.size.height;
489 float left = contentRect.origin.x - frame.origin.x;
490 float bottom = contentRect.origin.y - frame.origin.y;
491 float right = frame.size.width - (contentRect.size.width + left);
492
493 // Speculative estimation: 80 - enough for window decorations controls
494 minWidth += left + right + 80;
495 minHeight += top + bottom;
496 }
497
498 minWidth = MAX(1.f, minWidth);
499 minHeight = MAX(1.f, minHeight);
500
501 size->width = MAX(size->width, minWidth);
502 size->height = MAX(size->height, minHeight);
503 }
504
505 @end // AWTWindow
506
519 AWT_ASSERT_NOT_APPKIT_THREAD;
520
521 JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
522 NSView *contentView = OBJC(contentViewPtr);
523 NSRect frameRect = NSMakeRect(x, y, w, h);
524
525 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
526 AWT_ASSERT_APPKIT_THREAD;
527
528 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
529 styleBits:styleBits
530 frameRect:frameRect
531 contentView:contentView];
532
533 if (window) CFRetain(window);
534 [window release]; // GC
535 }];
536
537 JNF_COCOA_EXIT(env);
538
539 return ptr_to_jlong(window);
540 }
541
542 /*
543 * Class: sun_lwawt_macosx_CPlatformWindow
544 * Method: nativeSetNSWindowStyleBits
545 * Signature: (JII)V
546 */
547 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
548 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
549 {
550 JNF_COCOA_ENTER(env);
551 AWT_ASSERT_NOT_APPKIT_THREAD;
552
553 AWTWindow *window = OBJC(windowPtr);
554 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
555 AWT_ASSERT_APPKIT_THREAD;
556
557 // scans the bit field, and only updates the values requested by the mask
558 // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
559 jint newBits = window.styleBits & ~mask | bits & mask;
560
561 // resets the NSWindow's style mask if the mask intersects any of those bits
562 if (mask & MASK(_STYLE_PROP_BITMASK)) {
563 [window setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
564 }
565
566 // calls methods on NSWindow to change other properties, based on the mask
567 if (mask & MASK(_METHOD_PROP_BITMASK)) {
568 [window setPropertiesForStyleBits:bits mask:mask];
569 }
570
571 window.styleBits = newBits;
572 }];
573
574 JNF_COCOA_EXIT(env);
575 }
576
577 /*
578 * Class: sun_lwawt_macosx_CPlatformWindow
579 * Method: nativeSetNSWindowMenuBar
580 * Signature: (JJ)V
581 */
582 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
583 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
584 {
585 JNF_COCOA_ENTER(env);
586 AWT_ASSERT_NOT_APPKIT_THREAD;
587
588 AWTWindow *window = OBJC(windowPtr);
589 CMenuBar *menuBar = OBJC(menuBarPtr);
590 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
591 AWT_ASSERT_APPKIT_THREAD;
592
593 if ([window isKeyWindow]) [window.javaMenuBar deactivate];
594 window.javaMenuBar = menuBar;
595
596 // if ([self isKeyWindow]) {
597 [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
598 // }
599 }];
600
601 JNF_COCOA_EXIT(env);
602 }
603
604 /*
605 * Class: sun_lwawt_macosx_CPlatformWindow
606 * Method: nativeGetNSWindowInsets
607 * Signature: (J)Ljava/awt/Insets;
608 */
609 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
610 (JNIEnv *env, jclass clazz, jlong windowPtr)
611 {
612 jobject ret = NULL;
613
614 JNF_COCOA_ENTER(env);
615 AWT_ASSERT_NOT_APPKIT_THREAD;
616
617 AWTWindow *window = OBJC(windowPtr);
618 __block NSRect contentRect = NSZeroRect;
619 __block NSRect frame = NSZeroRect;
620
621 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
622 AWT_ASSERT_APPKIT_THREAD;
623
624 frame = [window frame];
625 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[window styleMask]];
626 }];
627
628 jint top = (jint)(frame.size.height - contentRect.size.height);
629 jint left = (jint)(contentRect.origin.x - frame.origin.x);
630 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
631 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
632
633 static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
634 static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
635 ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
636
637 JNF_COCOA_EXIT(env);
638 return ret;
639 }
640
641 /*
642 * Class: sun_lwawt_macosx_CPlatformWindow
643 * Method: nativeSetNSWindowBounds
644 * Signature: (JDDDD)V
645 */
646 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
647 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
648 {
649 JNF_COCOA_ENTER(env);
650 AWT_ASSERT_NOT_APPKIT_THREAD;
651
652 NSRect jrect = NSMakeRect(originX, originY, width, height);
653
654 // TODO: not sure we need displayIfNeeded message in our view
655 AWTWindow *window = OBJC(windowPtr);
656 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
657 AWT_ASSERT_APPKIT_THREAD;
658
659 NSRect rect = ConvertNSScreenRect(NULL, jrect);
660 [window constrainSize:&rect.size];
661
662 [window setFrame:rect display:YES];
663
664 // only start tracking events if pointer is above the toplevel
665 // TODO: should post an Entered event if YES.
666 NSPoint mLocation = [NSEvent mouseLocation];
667 [window setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
668
669 // ensure we repaint the whole window after the resize operation
670 // (this will also re-enable screen updates, which were disabled above)
671 // TODO: send PaintEvent
672 }];
673
674 JNF_COCOA_EXIT(env);
675 }
676
677 /*
678 * Class: sun_lwawt_macosx_CPlatformWindow
679 * Method: nativeSetNSWindowMinMax
680 * Signature: (JDDDD)V
681 */
682 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
683 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
684 {
685 JNF_COCOA_ENTER(env);
686 AWT_ASSERT_NOT_APPKIT_THREAD;
687
688 if (minW < 1) minW = 1;
689 if (minH < 1) minH = 1;
690 if (maxW < 1) maxW = 1;
691 if (maxH < 1) maxH = 1;
692
693 AWTWindow *window = OBJC(windowPtr);
694 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
695 AWT_ASSERT_APPKIT_THREAD;
696
697 NSSize min = { minW, minH };
698 NSSize max = { maxW, maxH };
699
700 [window constrainSize:&min];
701 [window constrainSize:&max];
702
703 window.javaMinSize = min;
704 window.javaMaxSize = max;
705 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
706 }];
707
708 JNF_COCOA_EXIT(env);
709 }
710
711 /*
712 * Class: sun_lwawt_macosx_CPlatformWindow
713 * Method: nativePushNSWindowToBack
714 * Signature: (J)V
715 */
716 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
717 (JNIEnv *env, jclass clazz, jlong windowPtr)
718 {
719 JNF_COCOA_ENTER(env);
720 AWT_ASSERT_NOT_APPKIT_THREAD;
721
722 AWTWindow *window = OBJC(windowPtr);
723 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
724 AWT_ASSERT_APPKIT_THREAD;
725
726 [window orderBack:nil];
727 }];
728
729 JNF_COCOA_EXIT(env);
730 }
731
732 /*
733 * Class: sun_lwawt_macosx_CPlatformWindow
734 * Method: nativePushNSWindowToFront
735 * Signature: (J)V
736 */
737 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
738 (JNIEnv *env, jclass clazz, jlong windowPtr)
739 {
740 JNF_COCOA_ENTER(env);
741 AWT_ASSERT_NOT_APPKIT_THREAD;
742
743 AWTWindow *window = OBJC(windowPtr);
744 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
745 AWT_ASSERT_APPKIT_THREAD;
746
747 if (![window isKeyWindow]) {
748 [window makeKeyAndOrderFront:window];
749 } else {
750 [window orderFront:window];
751 }
752 }];
753
754 JNF_COCOA_EXIT(env);
755 }
756
757 /*
758 * Class: sun_lwawt_macosx_CPlatformWindow
759 * Method: nativeSetNSWindowTitle
760 * Signature: (JLjava/lang/String;)V
761 */
762 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
763 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
764 {
765 JNF_COCOA_ENTER(env);
766 AWT_ASSERT_NOT_APPKIT_THREAD;
767
768 AWTWindow *window = OBJC(windowPtr);
769 [window performSelectorOnMainThread:@selector(setTitle:)
770 withObject:JNFJavaToNSString(env, jtitle)
771 waitUntilDone:NO];
772
773 JNF_COCOA_EXIT(env);
774 }
775
776 /*
777 * Class: sun_lwawt_macosx_CPlatformWindow
778 * Method: nativeSetNSWindowAlpha
779 * Signature: (JF)V
780 */
781 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowAlpha
782 (JNIEnv *env, jclass clazz, jlong windowPtr, jfloat alpha)
783 {
784 JNF_COCOA_ENTER(env);
785 AWT_ASSERT_NOT_APPKIT_THREAD;
786
787 AWTWindow *window = OBJC(windowPtr);
788 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
789 AWT_ASSERT_APPKIT_THREAD;
790
791 [window setAlphaValue:alpha];
792 }];
793
794 JNF_COCOA_EXIT(env);
795 }
796
797 /*
798 * Class: sun_lwawt_macosx_CPlatformWindow
799 * Method: nativeRevalidateNSWindowShadow
800 * Signature: (J)V
801 */
802 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
803 (JNIEnv *env, jclass clazz, jlong windowPtr)
804 {
805 JNF_COCOA_ENTER(env);
806 AWT_ASSERT_NOT_APPKIT_THREAD;
807
808 AWTWindow *window = OBJC(windowPtr);
809 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
810 AWT_ASSERT_APPKIT_THREAD;
811
812 [window invalidateShadow];
813 }];
814
815 JNF_COCOA_EXIT(env);
816 }
817
818 /*
819 * Class: sun_lwawt_macosx_CPlatformWindow
820 * Method: nativeScreenOn_AppKitThread
821 * Signature: (J)I
822 */
823 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
824 (JNIEnv *env, jclass clazz, jlong windowPtr)
825 {
826 jint ret = 0;
827
828 JNF_COCOA_ENTER(env);
829 AWT_ASSERT_APPKIT_THREAD;
830
831 AWTWindow *window = OBJC(windowPtr);
832 NSDictionary *props = [[window screen] deviceDescription];
833 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
834
835 JNF_COCOA_EXIT(env);
836
837 return ret;
838 }
839
840 /*
841 * Class: sun_lwawt_macosx_CPlatformWindow
842 * Method: nativeSetNSWindowMinimizedIcon
843 * Signature: (JJ)V
844 */
845 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
846 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
847 {
848 JNF_COCOA_ENTER(env);
849 AWT_ASSERT_NOT_APPKIT_THREAD;
850
851 AWTWindow *window = OBJC(windowPtr);
852 NSImage *image = OBJC(nsImagePtr);
853 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
854 AWT_ASSERT_APPKIT_THREAD;
855
856 [window setMiniwindowImage:image];
857 }];
858
859 JNF_COCOA_EXIT(env);
860 }
861
862 /*
863 * Class: sun_lwawt_macosx_CPlatformWindow
864 * Method: nativeSetNSWindowRepresentedFilename
865 * Signature: (JLjava/lang/String;)V
866 */
867 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
868 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
869 {
870 JNF_COCOA_ENTER(env);
871 AWT_ASSERT_NOT_APPKIT_THREAD;
872
873 AWTWindow *window = OBJC(windowPtr);
874 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
875 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
876 AWT_ASSERT_APPKIT_THREAD;
877
878 [window setRepresentedURL:url];
879 }];
880
881 JNF_COCOA_EXIT(env);
882 }
883
884 /*
885 * Class: sun_lwawt_macosx_CPlatformWindow
886 * Method: nativeSetNSWindowSecurityWarningPositioning
887 * Signature: (JDDFF)V
888 */
889 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowSecurityWarningPositioning
890 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble x, jdouble y, jfloat biasX, jfloat biasY)
891 {
892 JNF_COCOA_ENTER(env);
893 AWT_ASSERT_NOT_APPKIT_THREAD;
894
895 [JNFException raise:env as:kRuntimeException reason:"unimplemented"];
896
897 JNF_COCOA_EXIT(env);
898 }
899
900 /*
901 * Class: sun_lwawt_macosx_CPlatformWindow
902 * Method: nativeGetScreenNSWindowIsOn_AppKitThread
903 * Signature: (J)I
904 */
905 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
906 (JNIEnv *env, jclass clazz, jlong windowPtr)
907 {
908 jint index = -1;
909
910 JNF_COCOA_ENTER(env);
911 AWT_ASSERT_APPKIT_THREAD;
912
913 AWTWindow *window = OBJC(windowPtr);
914 NSScreen* screen = [window screen];
915
916 //+++gdb NOTE: This is using a linear search of the screens. If it should
917 // prove to be a bottleneck, this can definitely be improved. However,
918 // many screens should prove to be the exception, rather than the rule.
919 NSArray* screens = [NSScreen screens];
920 NSUInteger i;
921 for (i = 0; i < [screens count]; i++)
922 {
923 if ([[screens objectAtIndex:i] isEqualTo:screen])
924 {
925 index = i;
926 break;
927 }
928 }
929
930 JNF_COCOA_EXIT(env);
931 return 1;
932 }
933
934
935 /*
936 * Class: sun_lwawt_macosx_CPlatformWindow
937 * Method: _toggleFullScreenMode
938 * Signature: (J)V
939 */
940 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
941 (JNIEnv *env, jobject peer, jlong windowPtr)
942 {
943 JNF_COCOA_ENTER(env);
944
945 AWTWindow *window = OBJC(windowPtr);
946 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
947 if (![window respondsToSelector:toggleFullScreenSelector]) return;
948
949 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
950 [window performSelector:toggleFullScreenSelector withObject:nil];
951 }];
952
953 JNF_COCOA_EXIT(env);
954 }
955
956 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
957 (JNIEnv *env, jclass clazz, jlong windowPtr)
958 {
959 __block jboolean underMouse = JNI_FALSE;
960
961 JNF_COCOA_ENTER(env);
962 AWT_ASSERT_NOT_APPKIT_THREAD;
963
964 AWTWindow *aWindow = OBJC(windowPtr);
965 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
966 AWT_ASSERT_APPKIT_THREAD;
967
968 NSPoint pt = [aWindow mouseLocationOutsideOfEventStream];
969 underMouse = [[aWindow contentView] hitTest:pt] != nil;
970 }];
971
972 JNF_COCOA_EXIT(env);
973
974 return underMouse;
975 }
|
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 nsWindow;
57 @synthesize javaPlatformWindow;
58 @synthesize javaMenuBar;
59 @synthesize javaMinSize;
60 @synthesize javaMaxSize;
61 @synthesize styleBits;
62
63 - (void) updateMinMaxSize:(BOOL)resizable {
64 if (resizable) {
65 [self.nsWindow setMinSize:self.javaMinSize];
66 [self.nsWindow setMaxSize:self.javaMaxSize];
67 } else {
68 NSRect currentFrame = [self.nsWindow frame];
69 [self.nsWindow setMinSize:currentFrame.size];
70 [self.nsWindow 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.nsWindow setShowsResizeIndicator:resizable];
102 }
103
104 if (IS(mask, HAS_SHADOW)) {
105 [self.nsWindow setHasShadow:IS(bits, HAS_SHADOW)];
106 }
107
108 if (IS(mask, ZOOMABLE)) {
109 [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:IS(bits, ZOOMABLE)];
110 }
111
112 if (IS(mask, ALWAYS_ON_TOP)) {
113 [self.nsWindow setLevel:IS(bits, ALWAYS_ON_TOP) ? NSFloatingWindowLevel : NSNormalWindowLevel];
114 }
115
116 if (IS(mask, HIDES_ON_DEACTIVATE)) {
117 [self.nsWindow setHidesOnDeactivate:IS(bits, HIDES_ON_DEACTIVATE)];
118 }
119
120 if (IS(mask, DRAGGABLE_BACKGROUND)) {
121 [self.nsWindow setMovableByWindowBackground:IS(bits, DRAGGABLE_BACKGROUND)];
122 }
123
124 if (IS(mask, DOCUMENT_MODIFIED)) {
125 [self.nsWindow setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
126 }
127
128 if ([self.nsWindow respondsToSelector:@selector(toggleFullScreen:)]) {
129 if (IS(mask, FULLSCREENABLE)) {
130 [self.nsWindow setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
131 } else {
132 [self.nsWindow 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 init];
155
156 if (self == nil) return nil; // no hope
157
158 if (IS(bits, UTILITY) ||
159 IS(bits, NONACTIVATING) ||
160 IS(bits, HUD) ||
161 IS(bits, HIDES_ON_DEACTIVATE))
162 {
163 self.nsWindow = [[AWTWindow_Panel alloc] initWithDelegate:self
164 frameRect:contentRect
165 styleMask:styleMask
166 contentView:view];
167 }
168 else
169 {
170 // These windows will appear in the window list in the dock icon menu
171 self.nsWindow = [[AWTWindow_Normal alloc] initWithDelegate:self
172 frameRect:contentRect
173 styleMask:styleMask
174 contentView:view];
175 }
176
177 if (self.nsWindow == nil) return nil; // no hope either
178
179 self.javaPlatformWindow = platformWindow;
180 self.styleBits = bits;
181 [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
182
183 return self;
184 }
185
186 - (void) dealloc {
187 AWT_ASSERT_APPKIT_THREAD;
188
189 JNIEnv *env = [ThreadUtilities getJNIEnv];
190 [self.javaPlatformWindow setJObject:nil withEnv:env];
191
192 self.nsWindow = nil;
193
194 [super dealloc];
195 }
196
197
198 // NSWindow overrides
199 - (BOOL) canBecomeKeyWindow {
200 AWT_ASSERT_APPKIT_THREAD;
201 return IS(self.styleBits, SHOULD_BECOME_KEY);
202 }
203
204 - (BOOL) canBecomeMainWindow {
205 AWT_ASSERT_APPKIT_THREAD;
206 return IS(self.styleBits, SHOULD_BECOME_MAIN);
207 }
208
209 - (BOOL) worksWhenModal {
210 AWT_ASSERT_APPKIT_THREAD;
211 return IS(self.styleBits, MODAL_EXCLUDED);
212 }
213
214
215 // Gesture support
216 - (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b {
217 AWT_ASSERT_APPKIT_THREAD;
218
219 JNIEnv *env = [ThreadUtilities getJNIEnv];
220 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
221 if (platformWindow != NULL) {
222 // extract the target AWT Window object out of the CPlatformWindow
223 static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;");
224 jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target);
225 if (awtWindow != NULL) {
226 // translate the point into Java coordinates
227 NSPoint loc = [event locationInWindow];
228 loc.y = [self.nsWindow frame].size.height - loc.y;
229
230 // send up to the GestureHandler to recursively dispatch on the AWT event thread
231 static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler");
232 static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V");
233 JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b);
234 (*env)->DeleteLocalRef(env, awtWindow);
235 }
236 (*env)->DeleteLocalRef(env, platformWindow);
237 }
238 }
239
240 - (void)beginGestureWithEvent:(NSEvent *)event {
241 [self postGesture:event
242 as:com_apple_eawt_event_GestureHandler_PHASE
243 a:-1.0
244 b:0.0];
245 }
246
247 - (void)endGestureWithEvent:(NSEvent *)event {
248 [self postGesture:event
271 a:[event deltaX]
272 b:[event deltaY]];
273 }
274
275
276 // NSWindowDelegate methods
277
278 - (void) _deliverMoveResizeEvent {
279 AWT_ASSERT_APPKIT_THREAD;
280
281 // deliver the event if this is a user-initiated live resize or as a side-effect
282 // of a Java initiated resize, because AppKit can override the bounds and force
283 // the bounds of the window to avoid the Dock or remain on screen.
284 [AWTToolkit eventCountPlusPlus];
285 JNIEnv *env = [ThreadUtilities getJNIEnv];
286 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
287 if (platformWindow == NULL) {
288 // TODO: create generic AWT assert
289 }
290
291 NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
292
293 static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V");
294 JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
295 (jint)frame.origin.x,
296 (jint)frame.origin.y,
297 (jint)frame.size.width,
298 (jint)frame.size.height);
299 (*env)->DeleteLocalRef(env, platformWindow);
300 }
301
302 - (void)windowDidMove:(NSNotification *)notification {
303 AWT_ASSERT_APPKIT_THREAD;
304
305 [self _deliverMoveResizeEvent];
306 }
307
308 - (void)windowDidResize:(NSNotification *)notification {
309 AWT_ASSERT_APPKIT_THREAD;
310
311 [self _deliverMoveResizeEvent];
461 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_WILL_EXIT withEnv:env];
462 (*env)->DeleteLocalRef(env, platformWindow);
463 }
464 }
465
466 - (void)windowDidExitFullScreen:(NSNotification *)notification {
467 static JNF_MEMBER_CACHE(jm_windowDidExitFullScreen, jc_CPlatformWindow, "windowDidExitFullScreen", "()V");
468 JNIEnv *env = [ThreadUtilities getJNIEnv];
469 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
470 if (platformWindow != NULL) {
471 JNFCallVoidMethod(env, platformWindow, jm_windowDidExitFullScreen);
472 [self _notifyFullScreenOp:com_apple_eawt_FullScreenHandler_FULLSCREEN_DID_EXIT withEnv:env];
473 (*env)->DeleteLocalRef(env, platformWindow);
474 }
475 }
476
477 - (void)sendEvent:(NSEvent *)event {
478 if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
479
480 NSPoint p = [NSEvent mouseLocation];
481 NSRect frame = [self.nsWindow frame];
482 NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame];
483
484 // Check if the click happened in the non-client area (title bar)
485 if (p.y >= (frame.origin.y + contentRect.size.height)) {
486 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
487 jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
488 // Currently, no need to deliver the whole NSEvent.
489 static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
490 JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
491 }
492 }
493 }
494
495 - (void)constrainSize:(NSSize*)size {
496 float minWidth = 0.f, minHeight = 0.f;
497
498 if (IS(self.styleBits, DECORATED)) {
499 NSRect frame = [self.nsWindow frame];
500 NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[self.nsWindow styleMask]];
501
502 float top = frame.size.height - contentRect.size.height;
503 float left = contentRect.origin.x - frame.origin.x;
504 float bottom = contentRect.origin.y - frame.origin.y;
505 float right = frame.size.width - (contentRect.size.width + left);
506
507 // Speculative estimation: 80 - enough for window decorations controls
508 minWidth += left + right + 80;
509 minHeight += top + bottom;
510 }
511
512 minWidth = MAX(1.f, minWidth);
513 minHeight = MAX(1.f, minHeight);
514
515 size->width = MAX(size->width, minWidth);
516 size->height = MAX(size->height, minHeight);
517 }
518
519 @end // AWTWindow
520
533 AWT_ASSERT_NOT_APPKIT_THREAD;
534
535 JNFWeakJObjectWrapper *platformWindow = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
536 NSView *contentView = OBJC(contentViewPtr);
537 NSRect frameRect = NSMakeRect(x, y, w, h);
538
539 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
540 AWT_ASSERT_APPKIT_THREAD;
541
542 window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow
543 styleBits:styleBits
544 frameRect:frameRect
545 contentView:contentView];
546
547 if (window) CFRetain(window);
548 [window release]; // GC
549 }];
550
551 JNF_COCOA_EXIT(env);
552
553 return ptr_to_jlong(window ? window.nsWindow : nil);
554 }
555
556 /*
557 * Class: sun_lwawt_macosx_CPlatformWindow
558 * Method: nativeSetNSWindowStyleBits
559 * Signature: (JII)V
560 */
561 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStyleBits
562 (JNIEnv *env, jclass clazz, jlong windowPtr, jint mask, jint bits)
563 {
564 JNF_COCOA_ENTER(env);
565 AWT_ASSERT_NOT_APPKIT_THREAD;
566
567 NSWindow *nsWindow = OBJC(windowPtr);
568 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
569 AWT_ASSERT_APPKIT_THREAD;
570
571 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
572
573 // scans the bit field, and only updates the values requested by the mask
574 // (this implicity handles the _CALLBACK_PROP_BITMASK case, since those are passive reads)
575 jint newBits = window.styleBits & ~mask | bits & mask;
576
577 // resets the NSWindow's style mask if the mask intersects any of those bits
578 if (mask & MASK(_STYLE_PROP_BITMASK)) {
579 [nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
580 }
581
582 // calls methods on NSWindow to change other properties, based on the mask
583 if (mask & MASK(_METHOD_PROP_BITMASK)) {
584 [window setPropertiesForStyleBits:bits mask:mask];
585 }
586
587 window.styleBits = newBits;
588 }];
589
590 JNF_COCOA_EXIT(env);
591 }
592
593 /*
594 * Class: sun_lwawt_macosx_CPlatformWindow
595 * Method: nativeSetNSWindowMenuBar
596 * Signature: (JJ)V
597 */
598 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMenuBar
599 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong menuBarPtr)
600 {
601 JNF_COCOA_ENTER(env);
602 AWT_ASSERT_NOT_APPKIT_THREAD;
603
604 NSWindow *nsWindow = OBJC(windowPtr);
605 CMenuBar *menuBar = OBJC(menuBarPtr);
606 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
607 AWT_ASSERT_APPKIT_THREAD;
608
609 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
610
611 if ([nsWindow isKeyWindow]) [window.javaMenuBar deactivate];
612 window.javaMenuBar = menuBar;
613
614 // if ([self isKeyWindow]) {
615 [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
616 // }
617 }];
618
619 JNF_COCOA_EXIT(env);
620 }
621
622 /*
623 * Class: sun_lwawt_macosx_CPlatformWindow
624 * Method: nativeGetNSWindowInsets
625 * Signature: (J)Ljava/awt/Insets;
626 */
627 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowInsets
628 (JNIEnv *env, jclass clazz, jlong windowPtr)
629 {
630 jobject ret = NULL;
631
632 JNF_COCOA_ENTER(env);
633 AWT_ASSERT_NOT_APPKIT_THREAD;
634
635 NSWindow *nsWindow = OBJC(windowPtr);
636 __block NSRect contentRect = NSZeroRect;
637 __block NSRect frame = NSZeroRect;
638
639 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
640 AWT_ASSERT_APPKIT_THREAD;
641
642 frame = [nsWindow frame];
643 contentRect = [NSWindow contentRectForFrameRect:frame styleMask:[nsWindow styleMask]];
644 }];
645
646 jint top = (jint)(frame.size.height - contentRect.size.height);
647 jint left = (jint)(contentRect.origin.x - frame.origin.x);
648 jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
649 jint right = (jint)(frame.size.width - (contentRect.size.width + left));
650
651 static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
652 static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
653 ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);
654
655 JNF_COCOA_EXIT(env);
656 return ret;
657 }
658
659 /*
660 * Class: sun_lwawt_macosx_CPlatformWindow
661 * Method: nativeSetNSWindowBounds
662 * Signature: (JDDDD)V
663 */
664 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowBounds
665 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, jdouble width, jdouble height)
666 {
667 JNF_COCOA_ENTER(env);
668 AWT_ASSERT_NOT_APPKIT_THREAD;
669
670 NSRect jrect = NSMakeRect(originX, originY, width, height);
671
672 // TODO: not sure we need displayIfNeeded message in our view
673 NSWindow *nsWindow = OBJC(windowPtr);
674 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
675 AWT_ASSERT_APPKIT_THREAD;
676
677 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
678
679 NSRect rect = ConvertNSScreenRect(NULL, jrect);
680 [window constrainSize:&rect.size];
681
682 [nsWindow setFrame:rect display:YES];
683
684 // only start tracking events if pointer is above the toplevel
685 // TODO: should post an Entered event if YES.
686 NSPoint mLocation = [NSEvent mouseLocation];
687 [nsWindow setAcceptsMouseMovedEvents:NSPointInRect(mLocation, rect)];
688
689 // ensure we repaint the whole window after the resize operation
690 // (this will also re-enable screen updates, which were disabled above)
691 // TODO: send PaintEvent
692 }];
693
694 JNF_COCOA_EXIT(env);
695 }
696
697 /*
698 * Class: sun_lwawt_macosx_CPlatformWindow
699 * Method: nativeSetNSWindowMinMax
700 * Signature: (JDDDD)V
701 */
702 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinMax
703 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble minW, jdouble minH, jdouble maxW, jdouble maxH)
704 {
705 JNF_COCOA_ENTER(env);
706 AWT_ASSERT_NOT_APPKIT_THREAD;
707
708 if (minW < 1) minW = 1;
709 if (minH < 1) minH = 1;
710 if (maxW < 1) maxW = 1;
711 if (maxH < 1) maxH = 1;
712
713 NSWindow *nsWindow = OBJC(windowPtr);
714 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
715 AWT_ASSERT_APPKIT_THREAD;
716
717 AWTWindow *window = (AWTWindow*)[nsWindow delegate];
718
719 NSSize min = { minW, minH };
720 NSSize max = { maxW, maxH };
721
722 [window constrainSize:&min];
723 [window constrainSize:&max];
724
725 window.javaMinSize = min;
726 window.javaMaxSize = max;
727 [window updateMinMaxSize:IS(window.styleBits, RESIZABLE)];
728 }];
729
730 JNF_COCOA_EXIT(env);
731 }
732
733 /*
734 * Class: sun_lwawt_macosx_CPlatformWindow
735 * Method: nativePushNSWindowToBack
736 * Signature: (J)V
737 */
738 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToBack
739 (JNIEnv *env, jclass clazz, jlong windowPtr)
740 {
741 JNF_COCOA_ENTER(env);
742 AWT_ASSERT_NOT_APPKIT_THREAD;
743
744 NSWindow *nsWindow = OBJC(windowPtr);
745 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
746 AWT_ASSERT_APPKIT_THREAD;
747
748 [nsWindow orderBack:nil];
749 }];
750
751 JNF_COCOA_EXIT(env);
752 }
753
754 /*
755 * Class: sun_lwawt_macosx_CPlatformWindow
756 * Method: nativePushNSWindowToFront
757 * Signature: (J)V
758 */
759 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativePushNSWindowToFront
760 (JNIEnv *env, jclass clazz, jlong windowPtr)
761 {
762 JNF_COCOA_ENTER(env);
763 AWT_ASSERT_NOT_APPKIT_THREAD;
764
765 NSWindow *nsWindow = OBJC(windowPtr);
766 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
767 AWT_ASSERT_APPKIT_THREAD;
768
769 if (![nsWindow isKeyWindow]) {
770 [nsWindow makeKeyAndOrderFront:nsWindow];
771 } else {
772 [nsWindow orderFront:nsWindow];
773 }
774 }];
775
776 JNF_COCOA_EXIT(env);
777 }
778
779 /*
780 * Class: sun_lwawt_macosx_CPlatformWindow
781 * Method: nativeSetNSWindowTitle
782 * Signature: (JLjava/lang/String;)V
783 */
784 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowTitle
785 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring jtitle)
786 {
787 JNF_COCOA_ENTER(env);
788 AWT_ASSERT_NOT_APPKIT_THREAD;
789
790 NSWindow *nsWindow = OBJC(windowPtr);
791 [nsWindow performSelectorOnMainThread:@selector(setTitle:)
792 withObject:JNFJavaToNSString(env, jtitle)
793 waitUntilDone:NO];
794
795 JNF_COCOA_EXIT(env);
796 }
797
798 /*
799 * Class: sun_lwawt_macosx_CPlatformWindow
800 * Method: nativeSetNSWindowAlpha
801 * Signature: (JF)V
802 */
803 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowAlpha
804 (JNIEnv *env, jclass clazz, jlong windowPtr, jfloat alpha)
805 {
806 JNF_COCOA_ENTER(env);
807 AWT_ASSERT_NOT_APPKIT_THREAD;
808
809 NSWindow *nsWindow = OBJC(windowPtr);
810 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
811 AWT_ASSERT_APPKIT_THREAD;
812
813 [nsWindow setAlphaValue:alpha];
814 }];
815
816 JNF_COCOA_EXIT(env);
817 }
818
819 /*
820 * Class: sun_lwawt_macosx_CPlatformWindow
821 * Method: nativeRevalidateNSWindowShadow
822 * Signature: (J)V
823 */
824 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSWindowShadow
825 (JNIEnv *env, jclass clazz, jlong windowPtr)
826 {
827 JNF_COCOA_ENTER(env);
828 AWT_ASSERT_NOT_APPKIT_THREAD;
829
830 NSWindow *nsWindow = OBJC(windowPtr);
831 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
832 AWT_ASSERT_APPKIT_THREAD;
833
834 [nsWindow invalidateShadow];
835 }];
836
837 JNF_COCOA_EXIT(env);
838 }
839
840 /*
841 * Class: sun_lwawt_macosx_CPlatformWindow
842 * Method: nativeScreenOn_AppKitThread
843 * Signature: (J)I
844 */
845 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeScreenOn_1AppKitThread
846 (JNIEnv *env, jclass clazz, jlong windowPtr)
847 {
848 jint ret = 0;
849
850 JNF_COCOA_ENTER(env);
851 AWT_ASSERT_APPKIT_THREAD;
852
853 NSWindow *nsWindow = OBJC(windowPtr);
854 NSDictionary *props = [[nsWindow screen] deviceDescription];
855 ret = [[props objectForKey:@"NSScreenNumber"] intValue];
856
857 JNF_COCOA_EXIT(env);
858
859 return ret;
860 }
861
862 /*
863 * Class: sun_lwawt_macosx_CPlatformWindow
864 * Method: nativeSetNSWindowMinimizedIcon
865 * Signature: (JJ)V
866 */
867 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowMinimizedIcon
868 (JNIEnv *env, jclass clazz, jlong windowPtr, jlong nsImagePtr)
869 {
870 JNF_COCOA_ENTER(env);
871 AWT_ASSERT_NOT_APPKIT_THREAD;
872
873 NSWindow *nsWindow = OBJC(windowPtr);
874 NSImage *image = OBJC(nsImagePtr);
875 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
876 AWT_ASSERT_APPKIT_THREAD;
877
878 [nsWindow setMiniwindowImage:image];
879 }];
880
881 JNF_COCOA_EXIT(env);
882 }
883
884 /*
885 * Class: sun_lwawt_macosx_CPlatformWindow
886 * Method: nativeSetNSWindowRepresentedFilename
887 * Signature: (JLjava/lang/String;)V
888 */
889 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowRepresentedFilename
890 (JNIEnv *env, jclass clazz, jlong windowPtr, jstring filename)
891 {
892 JNF_COCOA_ENTER(env);
893 AWT_ASSERT_NOT_APPKIT_THREAD;
894
895 NSWindow *nsWindow = OBJC(windowPtr);
896 NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)];
897 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
898 AWT_ASSERT_APPKIT_THREAD;
899
900 [nsWindow setRepresentedURL:url];
901 }];
902
903 JNF_COCOA_EXIT(env);
904 }
905
906 /*
907 * Class: sun_lwawt_macosx_CPlatformWindow
908 * Method: nativeSetNSWindowSecurityWarningPositioning
909 * Signature: (JDDFF)V
910 */
911 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowSecurityWarningPositioning
912 (JNIEnv *env, jclass clazz, jlong windowPtr, jdouble x, jdouble y, jfloat biasX, jfloat biasY)
913 {
914 JNF_COCOA_ENTER(env);
915 AWT_ASSERT_NOT_APPKIT_THREAD;
916
917 [JNFException raise:env as:kRuntimeException reason:"unimplemented"];
918
919 JNF_COCOA_EXIT(env);
920 }
921
922 /*
923 * Class: sun_lwawt_macosx_CPlatformWindow
924 * Method: nativeGetScreenNSWindowIsOn_AppKitThread
925 * Signature: (J)I
926 */
927 JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
928 (JNIEnv *env, jclass clazz, jlong windowPtr)
929 {
930 jint index = -1;
931
932 JNF_COCOA_ENTER(env);
933 AWT_ASSERT_APPKIT_THREAD;
934
935 NSWindow *nsWindow = OBJC(windowPtr);
936 NSScreen* screen = [nsWindow screen];
937
938 //+++gdb NOTE: This is using a linear search of the screens. If it should
939 // prove to be a bottleneck, this can definitely be improved. However,
940 // many screens should prove to be the exception, rather than the rule.
941 NSArray* screens = [NSScreen screens];
942 NSUInteger i;
943 for (i = 0; i < [screens count]; i++)
944 {
945 if ([[screens objectAtIndex:i] isEqualTo:screen])
946 {
947 index = i;
948 break;
949 }
950 }
951
952 JNF_COCOA_EXIT(env);
953 return 1;
954 }
955
956
957 /*
958 * Class: sun_lwawt_macosx_CPlatformWindow
959 * Method: _toggleFullScreenMode
960 * Signature: (J)V
961 */
962 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow__1toggleFullScreenMode
963 (JNIEnv *env, jobject peer, jlong windowPtr)
964 {
965 JNF_COCOA_ENTER(env);
966
967 NSWindow *nsWindow = OBJC(windowPtr);
968 SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
969 if (![nsWindow respondsToSelector:toggleFullScreenSelector]) return;
970
971 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
972 [nsWindow performSelector:toggleFullScreenSelector withObject:nil];
973 }];
974
975 JNF_COCOA_EXIT(env);
976 }
977
978 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
979 (JNIEnv *env, jclass clazz, jlong windowPtr)
980 {
981 __block jboolean underMouse = JNI_FALSE;
982
983 JNF_COCOA_ENTER(env);
984 AWT_ASSERT_NOT_APPKIT_THREAD;
985
986 NSWindow *nsWindow = OBJC(windowPtr);
987 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
988 AWT_ASSERT_APPKIT_THREAD;
989
990 NSPoint pt = [nsWindow mouseLocationOutsideOfEventStream];
991 underMouse = [[nsWindow contentView] hitTest:pt] != nil;
992 }];
993
994 JNF_COCOA_EXIT(env);
995
996 return underMouse;
997 }
|