8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "AWT_debug.h"
27
28 #import "jni_util.h"
29 #import "ThreadUtilities.h"
30
31 #import <JavaNativeFoundation/JavaNativeFoundation.h>
32
33 #define MAX_DISPLAYS 64
34
35 /*
36 * Class: sun_awt_CGraphicsEnvironment
37 * Method: getDisplayIDs
38 * Signature: ()[I
39 */
40 JNIEXPORT jintArray JNICALL
41 Java_sun_awt_CGraphicsEnvironment_getDisplayIDs
42 (JNIEnv *env, jclass class)
43 {
44 jintArray ret = NULL;
45
46 JNF_COCOA_ENTER(env);
47
48 /* Get the count */
49 CGDisplayCount displayCount;
50 if (CGGetOnlineDisplayList(MAX_DISPLAYS, NULL, &displayCount) != kCGErrorSuccess) {
51 [JNFException raise:env
52 as:kInternalError
53 reason:"CGGetOnlineDisplayList() failed to get display count"];
54 return NULL;
55 }
56
57 /* Allocate an array and get the size list of display Ids */
58 CGDirectDisplayID displays[MAX_DISPLAYS];
59 if (CGGetOnlineDisplayList(displayCount, displays, &displayCount) != kCGErrorSuccess) {
60 [JNFException raise:env
61 as:kInternalError
62 reason:"CGGetOnlineDisplayList() failed to get display list"];
63 return NULL;
64 }
65
66 CGDisplayCount i;
67 CGDisplayCount displayActiveCount = 0; //Active and sleeping.
68 for (i = 0; i < displayCount; ++i) {
69 if (CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay) {
70 ++displayActiveCount;
71 } else {
72 displays[i] = kCGNullDirectDisplay;
73 }
74 }
75
76 /* Allocate a java array for display identifiers */
77 ret = JNFNewIntArray(env, displayActiveCount);
78
79 /* Initialize and return the backing int array */
80 assert(sizeof(jint) >= sizeof(CGDirectDisplayID));
81 jint *elems = (*env)->GetIntArrayElements(env, ret, 0);
82 CHECK_NULL_RETURN(elems, NULL);
83
84 /* Filter out the mirrored displays */
85 for (i = 0; i < displayCount; ++i) {
86 if (displays[i] != kCGNullDirectDisplay) {
87 elems[--displayActiveCount] = displays[i];
88 }
89 }
90
91 (*env)->ReleaseIntArrayElements(env, ret, elems, 0);
92
93 JNF_COCOA_EXIT(env);
94
95 return ret;
96 }
97
98 /*
99 * Class: sun_awt_CGraphicsEnvironment
100 * Method: getMainDisplayID
101 * Signature: ()I
102 */
103 JNIEXPORT jint JNICALL
104 Java_sun_awt_CGraphicsEnvironment_getMainDisplayID
105 (JNIEnv *env, jclass class)
106 {
107 return CGMainDisplayID();
108 }
109
110 /*
111 * Post the display reconfiguration event.
112 */
113 static void displaycb_handle
114 (CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
115 {
116 if (flags == kCGDisplayBeginConfigurationFlag) return;
117
118 [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
119
120 JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) {
121 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo;
122
123 jobject graphicsEnv = [wrapper jObjectWithEnv:env];
124 if (graphicsEnv == NULL) return; // ref already GC'd
125 static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
126 static JNF_MEMBER_CACHE(jm_displayReconfiguration,
127 jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V");
128 JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
129 (jint) display, (jboolean) flags & kCGDisplayRemoveFlag);
130 (*env)->DeleteLocalRef(env, graphicsEnv);
131 });
132 }];
133 }
134
135 /*
136 * Class: sun_awt_CGraphicsEnvironment
137 * Method: registerDisplayReconfiguration
138 * Signature: ()J
139 */
140 JNIEXPORT jlong JNICALL
141 Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration
142 (JNIEnv *env, jobject this)
143 {
144 jlong ret = 0L;
145
146 JNF_COCOA_ENTER(env);
147
148 JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain];
149
150 /* Register the callback */
151 if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
152 [JNFException raise:env
153 as:kInternalError
154 reason:"CGDisplayRegisterReconfigurationCallback() failed"];
155 return 0L;
156 }
157
158 ret = ptr_to_jlong(wrapper);
159
160 JNF_COCOA_EXIT(env);
161
162 return ret;
163 }
164
165 /*
166 * Class: sun_awt_CGraphicsEnvironment
167 * Method: deregisterDisplayReconfiguration
168 * Signature: (J)V
169 */
170 JNIEXPORT void JNICALL
171 Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration
172 (JNIEnv *env, jobject this, jlong p)
173 {
174 JNF_COCOA_ENTER(env);
175
176 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)jlong_to_ptr(p);
177 if (!wrapper) return;
178
179 /* Remove the registration */
180 if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
181 [JNFException raise:env
182 as:kInternalError
183 reason:"CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!"];
184 return;
185 }
186
187 [wrapper setJObject:NULL withEnv:env]; // more efficient to pre-clear
188 [wrapper release];
189
190 JNF_COCOA_EXIT(env);
191 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "AWT_debug.h"
27
28 #import "JNIUtilities.h"
29 #import "ThreadUtilities.h"
30
31 #define MAX_DISPLAYS 64
32
33 /*
34 * Class: sun_awt_CGraphicsEnvironment
35 * Method: getDisplayIDs
36 * Signature: ()[I
37 */
38 JNIEXPORT jintArray JNICALL
39 Java_sun_awt_CGraphicsEnvironment_getDisplayIDs
40 (JNIEnv *env, jclass class)
41 {
42 jintArray ret = NULL;
43
44 JNI_COCOA_ENTER(env);
45
46 /* Get the count */
47 CGDisplayCount displayCount;
48 if (CGGetOnlineDisplayList(MAX_DISPLAYS, NULL, &displayCount) != kCGErrorSuccess) {
49 JNU_ThrowInternalError(env, "CGGetOnlineDisplayList() failed to get display count");
50 return NULL;
51 }
52
53 /* Allocate an array and get the size list of display Ids */
54 CGDirectDisplayID displays[MAX_DISPLAYS];
55 if (CGGetOnlineDisplayList(displayCount, displays, &displayCount) != kCGErrorSuccess) {
56 JNU_ThrowInternalError(env, "CGGetOnlineDisplayList() failed to get display list");
57 return NULL;
58 }
59
60 CGDisplayCount i;
61 CGDisplayCount displayActiveCount = 0; //Active and sleeping.
62 for (i = 0; i < displayCount; ++i) {
63 if (CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay) {
64 ++displayActiveCount;
65 } else {
66 displays[i] = kCGNullDirectDisplay;
67 }
68 }
69
70 /* Allocate a java array for display identifiers */
71 ret = (*env)->NewIntArray(env, displayActiveCount);
72 CHECK_NULL_RETURN(ret, NULL);
73
74 /* Initialize and return the backing int array */
75 assert(sizeof(jint) >= sizeof(CGDirectDisplayID));
76 jint *elems = (*env)->GetIntArrayElements(env, ret, 0);
77 CHECK_NULL_RETURN(elems, NULL);
78
79 /* Filter out the mirrored displays */
80 for (i = 0; i < displayCount; ++i) {
81 if (displays[i] != kCGNullDirectDisplay) {
82 elems[--displayActiveCount] = displays[i];
83 }
84 }
85
86 (*env)->ReleaseIntArrayElements(env, ret, elems, 0);
87
88 JNI_COCOA_EXIT(env);
89
90 return ret;
91 }
92
93 /*
94 * Class: sun_awt_CGraphicsEnvironment
95 * Method: getMainDisplayID
96 * Signature: ()I
97 */
98 JNIEXPORT jint JNICALL
99 Java_sun_awt_CGraphicsEnvironment_getMainDisplayID
100 (JNIEnv *env, jclass class)
101 {
102 return CGMainDisplayID();
103 }
104
105 /*
106 * Post the display reconfiguration event.
107 */
108 static void displaycb_handle
109 (CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
110 {
111 if (flags == kCGDisplayBeginConfigurationFlag) return;
112
113 [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
114
115 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
116 jobject cgeRef = (jobject)userInfo;
117
118 jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef);
119 if (graphicsEnv == NULL) return; // ref already GC'd
120 DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
121 DECLARE_METHOD(jm_displayReconfiguration,
122 jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V");
123 (*env)->CallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
124 (jint) display, (jboolean) flags & kCGDisplayRemoveFlag);
125 (*env)->DeleteLocalRef(env, graphicsEnv);
126 CHECK_EXCEPTION();
127 }];
128 }
129
130 /*
131 * Class: sun_awt_CGraphicsEnvironment
132 * Method: registerDisplayReconfiguration
133 * Signature: ()J
134 */
135 JNIEXPORT jlong JNICALL
136 Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration
137 (JNIEnv *env, jobject this)
138 {
139 jlong ret = 0L;
140
141 JNI_COCOA_ENTER(env);
142
143 jobject cgeRef = (*env)->NewWeakGlobalRef(env, this);
144
145 /* Register the callback */
146 if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, cgeRef) != kCGErrorSuccess) {
147 JNU_ThrowInternalError(env, "CGDisplayRegisterReconfigurationCallback() failed");
148 return 0L;
149 }
150
151 ret = ptr_to_jlong(cgeRef);
152
153 JNI_COCOA_EXIT(env);
154
155 return ret;
156 }
157
158 /*
159 * Class: sun_awt_CGraphicsEnvironment
160 * Method: deregisterDisplayReconfiguration
161 * Signature: (J)V
162 */
163 JNIEXPORT void JNICALL
164 Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration
165 (JNIEnv *env, jobject this, jlong p)
166 {
167 JNI_COCOA_ENTER(env);
168
169 jobject cgeRef = (jobject)jlong_to_ptr(p);
170 if (!cgeRef) return;
171
172 /* Remove the registration */
173 if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, cgeRef) != kCGErrorSuccess) {
174 JNU_ThrowInternalError(env, "CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!");
175 return;
176 }
177
178 (*env)->DeleteWeakGlobalRef(env, cgeRef);
179
180 JNI_COCOA_EXIT(env);
181 }
|