| /* |
| * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #import "AWT_debug.h" |
| |
| #import "jni_util.h" |
| |
| #import <JavaNativeFoundation/JavaNativeFoundation.h> |
| |
| #define MAX_DISPLAYS 64 |
| |
| /* |
| * Class: sun_awt_CGraphicsEnvironment |
| * Method: getDisplayIDs |
| * Signature: ()[I |
| */ |
| JNIEXPORT jintArray JNICALL |
| Java_sun_awt_CGraphicsEnvironment_getDisplayIDs |
| (JNIEnv *env, jclass class) |
| { |
| jintArray ret = NULL; |
| |
| JNF_COCOA_ENTER(env); |
| |
| /* Get the count */ |
| CGDisplayCount displayCount; |
| if (CGGetOnlineDisplayList(MAX_DISPLAYS, NULL, &displayCount) != kCGErrorSuccess) { |
| [JNFException raise:env |
| as:kInternalError |
| reason:"CGGetOnlineDisplayList() failed to get display count"]; |
| return NULL; |
| } |
| |
| /* Allocate an array and get the size list of display Ids */ |
| CGDirectDisplayID displays[MAX_DISPLAYS]; |
| if (CGGetOnlineDisplayList(displayCount, displays, &displayCount) != kCGErrorSuccess) { |
| [JNFException raise:env |
| as:kInternalError |
| reason:"CGGetOnlineDisplayList() failed to get display list"]; |
| return NULL; |
| } |
| |
| CGDisplayCount i; |
| CGDisplayCount displayActiveCount = 0; //Active and sleeping. |
| for (i = 0; i < displayCount; ++i) { |
| if (CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay) { |
| ++displayActiveCount; |
| } else { |
| displays[i] = kCGNullDirectDisplay; |
| } |
| } |
| |
| /* Allocate a java array for display identifiers */ |
| ret = JNFNewIntArray(env, displayActiveCount); |
| |
| /* Initialize and return the backing int array */ |
| assert(sizeof(jint) >= sizeof(CGDirectDisplayID)); |
| jint *elems = (*env)->GetIntArrayElements(env, ret, 0); |
| CHECK_NULL_RETURN(elems, NULL); |
| |
| /* Filter out the mirrored displays */ |
| for (i = 0; i < displayCount; ++i) { |
| if (displays[i] != kCGNullDirectDisplay) { |
| elems[--displayActiveCount] = displays[i]; |
| } |
| } |
| |
| (*env)->ReleaseIntArrayElements(env, ret, elems, 0); |
| |
| JNF_COCOA_EXIT(env); |
| |
| return ret; |
| } |
| |
| /* |
| * Class: sun_awt_CGraphicsEnvironment |
| * Method: getMainDisplayID |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_CGraphicsEnvironment_getMainDisplayID |
| (JNIEnv *env, jclass class) |
| { |
| return CGMainDisplayID(); |
| } |
| |
| /* |
| * Post the display reconfiguration event. |
| */ |
| static void displaycb_handle |
| (CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo) |
| { |
| if (flags == kCGDisplayBeginConfigurationFlag) return; |
| |
| JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { |
| JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; |
| |
| jobject graphicsEnv = [wrapper jObjectWithEnv:env]; |
| if (graphicsEnv == NULL) return; // ref already GC'd |
| static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); |
| static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V"); |
| JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, |
| (jint) display, |
| (jboolean) flags & kCGDisplayRemoveFlag); |
| }); |
| } |
| |
| /* |
| * Class: sun_awt_CGraphicsEnvironment |
| * Method: registerDisplayReconfiguration |
| * Signature: ()J |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration |
| (JNIEnv *env, jobject this) |
| { |
| jlong ret = 0L; |
| |
| JNF_COCOA_ENTER(env); |
| |
| JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain]; |
| |
| /* Register the callback */ |
| if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { |
| [JNFException raise:env |
| as:kInternalError |
| reason:"CGDisplayRegisterReconfigurationCallback() failed"]; |
| return 0L; |
| } |
| |
| ret = ptr_to_jlong(wrapper); |
| |
| JNF_COCOA_EXIT(env); |
| |
| return ret; |
| } |
| |
| /* |
| * Class: sun_awt_CGraphicsEnvironment |
| * Method: deregisterDisplayReconfiguration |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration |
| (JNIEnv *env, jobject this, jlong p) |
| { |
| JNF_COCOA_ENTER(env); |
| |
| JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)jlong_to_ptr(p); |
| if (!wrapper) return; |
| |
| /* Remove the registration */ |
| if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { |
| [JNFException raise:env |
| as:kInternalError |
| reason:"CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!"]; |
| return; |
| } |
| |
| [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear |
| [wrapper release]; |
| |
| JNF_COCOA_EXIT(env); |
| } |