1 /* 2 * Copyright (c) 2011, 2014, 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 <JavaNativeFoundation/JavaNativeFoundation.h> 27 28 #import "jni_util.h" 29 #import "LWCToolkit.h" 30 #import "AWT_debug.h" 31 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 JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { 119 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; 120 121 jobject graphicsEnv = [wrapper jObjectWithEnv:env]; 122 if (graphicsEnv == NULL) return; // ref already GC'd 123 static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); 124 static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V"); 125 JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, 126 (jint) display, 127 (jboolean) flags & kCGDisplayRemoveFlag); 128 }); 129 } 130 131 /* 132 * Class: sun_awt_CGraphicsEnvironment 133 * Method: registerDisplayReconfiguration 134 * Signature: ()J 135 */ 136 JNIEXPORT jlong JNICALL 137 Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration 138 (JNIEnv *env, jobject this) 139 { 140 jlong ret = 0L; 141 142 JNF_COCOA_ENTER(env); 143 144 JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain]; 145 146 /* Register the callback */ 147 if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { 148 [JNFException raise:env 149 as:kInternalError 150 reason:"CGDisplayRegisterReconfigurationCallback() failed"]; 151 return 0L; 152 } 153 154 ret = ptr_to_jlong(wrapper); 155 156 JNF_COCOA_EXIT(env); 157 158 return ret; 159 } 160 161 /* 162 * Class: sun_awt_CGraphicsEnvironment 163 * Method: deregisterDisplayReconfiguration 164 * Signature: (J)V 165 */ 166 JNIEXPORT void JNICALL 167 Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration 168 (JNIEnv *env, jobject this, jlong p) 169 { 170 JNF_COCOA_ENTER(env); 171 172 JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)jlong_to_ptr(p); 173 if (!wrapper) return; 174 175 /* Remove the registration */ 176 if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { 177 [JNFException raise:env 178 as:kInternalError 179 reason:"CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!"]; 180 return; 181 } 182 183 [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear 184 [wrapper release]; 185 186 JNF_COCOA_EXIT(env); 187 }