1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #import "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 }