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 "jni_util.h" 29 30 #import <JavaNativeFoundation/JavaNativeFoundation.h> 31 32 #define MAX_DISPLAYS 64 33 34 /* 35 * Class: sun_awt_CGraphicsEnvironment 36 * Method: getDisplayIDs 37 * Signature: ()[I 38 */ 39 JNIEXPORT jintArray JNICALL 40 Java_sun_awt_CGraphicsEnvironment_getDisplayIDs 41 (JNIEnv *env, jclass class) 42 { 43 jintArray ret = NULL; 44 45 JNF_COCOA_ENTER(env); 46 47 /* Get the count */ 48 CGDisplayCount displayCount; 49 if (CGGetOnlineDisplayList(MAX_DISPLAYS, NULL, &displayCount) != kCGErrorSuccess) { 50 [JNFException raise:env 51 as:kInternalError 52 reason:"CGGetOnlineDisplayList() failed to get display count"]; 53 return NULL; 54 } 55 56 /* Allocate an array and get the size list of display Ids */ 57 CGDirectDisplayID displays[MAX_DISPLAYS]; 58 if (CGGetOnlineDisplayList(displayCount, displays, &displayCount) != kCGErrorSuccess) { 59 [JNFException raise:env 60 as:kInternalError 61 reason:"CGGetOnlineDisplayList() failed to get display list"]; 62 return NULL; 63 } 64 65 CGDisplayCount i; 66 CGDisplayCount displayActiveCount = 0; //Active and sleeping. 67 for (i = 0; i < displayCount; ++i) { 68 if (CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay) { 69 ++displayActiveCount; 70 } else { 71 displays[i] = kCGNullDirectDisplay; 72 } 73 } 74 75 /* Allocate a java array for display identifiers */ 76 ret = JNFNewIntArray(env, displayActiveCount); 77 78 /* Initialize and return the backing int array */ 79 assert(sizeof(jint) >= sizeof(CGDirectDisplayID)); 80 jint *elems = (*env)->GetIntArrayElements(env, ret, 0); 81 CHECK_NULL_RETURN(elems, NULL); 82 83 /* Filter out the mirrored displays */ 84 for (i = 0; i < displayCount; ++i) { 85 if (displays[i] != kCGNullDirectDisplay) { 86 elems[--displayActiveCount] = displays[i]; 87 } 88 } 89 90 (*env)->ReleaseIntArrayElements(env, ret, elems, 0); 91 92 JNF_COCOA_EXIT(env); 93 94 return ret; 95 } 96 97 /* 98 * Class: sun_awt_CGraphicsEnvironment 99 * Method: getMainDisplayID 100 * Signature: ()I 101 */ 102 JNIEXPORT jint JNICALL 103 Java_sun_awt_CGraphicsEnvironment_getMainDisplayID 104 (JNIEnv *env, jclass class) 105 { 106 return CGMainDisplayID(); 107 } 108 109 /* 110 * Post the display reconfiguration event. 111 */ 112 static void displaycb_handle 113 (CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo) 114 { 115 if (flags == kCGDisplayBeginConfigurationFlag) return; 116 117 JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { 118 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; 119 120 jobject graphicsEnv = [wrapper jObjectWithEnv:env]; 121 if (graphicsEnv == NULL) return; // ref already GC'd 122 static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); 123 static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V"); 124 JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, 125 (jint) display, 126 (jboolean) flags & kCGDisplayRemoveFlag); 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 JNF_COCOA_ENTER(env); 142 143 JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain]; 144 145 /* Register the callback */ 146 if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { 147 [JNFException raise:env 148 as:kInternalError 149 reason:"CGDisplayRegisterReconfigurationCallback() failed"]; 150 return 0L; 151 } 152 153 ret = ptr_to_jlong(wrapper); 154 155 JNF_COCOA_EXIT(env); 156 157 return ret; 158 } 159 160 /* 161 * Class: sun_awt_CGraphicsEnvironment 162 * Method: deregisterDisplayReconfiguration 163 * Signature: (J)V 164 */ 165 JNIEXPORT void JNICALL 166 Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration 167 (JNIEnv *env, jobject this, jlong p) 168 { 169 JNF_COCOA_ENTER(env); 170 171 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)jlong_to_ptr(p); 172 if (!wrapper) return; 173 174 /* Remove the registration */ 175 if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { 176 [JNFException raise:env 177 as:kInternalError 178 reason:"CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!"]; 179 return; 180 } 181 182 [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear 183 [wrapper release]; 184 185 JNF_COCOA_EXIT(env); 186 } --- EOF ---