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 #include "sun_lwawt_macosx_CCursorManager.h"
  27 
  28 #include <Cocoa/Cocoa.h>
  29 
  30 #include "GeomUtilities.h"
  31 #include "ThreadUtilities.h"
  32 
  33 #include "java_awt_Cursor.h"
  34 
  35 
  36 static SEL lookupCursorSelectorForType(jint type) {
  37     switch (type) {
  38         case java_awt_Cursor_DEFAULT_CURSOR:        return @selector(arrowCursor);
  39         case java_awt_Cursor_CROSSHAIR_CURSOR:      return @selector(crosshairCursor);
  40         case java_awt_Cursor_TEXT_CURSOR:           return @selector(IBeamCursor);
  41         case java_awt_Cursor_WAIT_CURSOR:           return @selector(javaBusyButClickableCursor);
  42         case java_awt_Cursor_SW_RESIZE_CURSOR:      return @selector(javaResizeSWCursor);
  43         case java_awt_Cursor_SE_RESIZE_CURSOR:      return @selector(javaResizeSECursor);
  44         case java_awt_Cursor_NW_RESIZE_CURSOR:      return @selector(javaResizeNWCursor);
  45         case java_awt_Cursor_NE_RESIZE_CURSOR:      return @selector(javaResizeNECursor);
  46         case java_awt_Cursor_N_RESIZE_CURSOR:       return @selector(resizeUpDownCursor);
  47         case java_awt_Cursor_S_RESIZE_CURSOR:       return @selector(resizeUpDownCursor);
  48         case java_awt_Cursor_W_RESIZE_CURSOR:       return @selector(resizeLeftRightCursor);
  49         case java_awt_Cursor_E_RESIZE_CURSOR:       return @selector(resizeLeftRightCursor);
  50         case java_awt_Cursor_HAND_CURSOR:           return @selector(pointingHandCursor);
  51         case java_awt_Cursor_MOVE_CURSOR:           return @selector(javaMoveCursor);
  52     }
  53 
  54     return nil;
  55 }
  56 
  57 static SEL lookupCursorSelectorForName(NSString *name) {
  58     if ([@"DnD.Cursor.CopyDrop" isEqual:name]) return @selector(dragCopyCursor);
  59     if ([@"DnD.Cursor.LinkDrop" isEqual:name]) return @selector(dragLinkCursor);
  60     if ([@"DnD.Cursor.MoveDrop" isEqual:name]) return @selector(_genericDragCursor);
  61     if ([@"DnD.Cursor.CopyNoDrop" isEqual:name]) return @selector(operationNotAllowedCursor);
  62     if ([@"DnD.Cursor.LinkNoDrop" isEqual:name]) return @selector(operationNotAllowedCursor);
  63     if ([@"DnD.Cursor.MoveNoDrop" isEqual:name]) return @selector(operationNotAllowedCursor);
  64     return nil;
  65 }
  66 
  67 static void setCursorOnAppKitThread(NSCursor *cursor) {
  68     [cursor set];
  69 }
  70 
  71 JNIEXPORT void JNICALL
  72 Java_sun_lwawt_macosx_CCursorManager_nativeSetBuiltInCursor
  73 (JNIEnv *env, jclass class, jint type, jstring name)
  74 {
  75 JNI_COCOA_ENTER(env);
  76 
  77     NSString *cursorName = JavaStringToNSString(env, name);
  78     SEL cursorSelector = (type == sun_lwawt_macosx_CCursorManager_NAMED_CURSOR) ? lookupCursorSelectorForName(cursorName) : lookupCursorSelectorForType(type);
  79     if (cursorSelector == nil) {
  80         NSString *reason = [NSString stringWithFormat:@"unimplemented built-in cursor type: %d / %@", type, cursorName];
  81         JNU_ThrowIllegalArgumentException(env, [reason UTF8String]);
  82         return;
  83     }
  84 
  85     if (![[NSCursor class] respondsToSelector:cursorSelector]) {
  86         JNU_ThrowByName(env, "java/lang/NoSuchMethodException", "missing NSCursor selector");
  87         return;
  88     }
  89 
  90     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
  91         setCursorOnAppKitThread([[NSCursor class] performSelector:cursorSelector]);
  92     }];
  93 
  94 JNI_COCOA_EXIT(env);
  95 }
  96 
  97 JNIEXPORT void JNICALL
  98 Java_sun_lwawt_macosx_CCursorManager_nativeSetCustomCursor
  99 (JNIEnv *env, jclass class, jlong imgPtr, jdouble x, jdouble y)
 100 {
 101 JNI_COCOA_ENTER(env);
 102     NSImage *image = (NSImage *)jlong_to_ptr(imgPtr);
 103 
 104     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
 105         NSCursor *cursor = [[NSCursor alloc] initWithImage:image
 106                                                    hotSpot:(NSPoint){ x, y }];
 107         setCursorOnAppKitThread(cursor);
 108         [cursor release];
 109     }];
 110 
 111 JNI_COCOA_EXIT(env);
 112 }
 113 
 114 JNIEXPORT jobject JNICALL
 115 Java_sun_lwawt_macosx_CCursorManager_nativeGetCursorPosition
 116 (JNIEnv *env, jclass class)
 117 {
 118     jobject jpt = NULL;
 119 
 120 JNI_COCOA_ENTER(env);
 121 
 122     CGEventRef event = CGEventCreate(NULL);
 123     CGPoint globalPos = CGEventGetLocation(event);
 124     CFRelease(event);
 125 
 126     jpt = NSToJavaPoint(env, globalPos);
 127 
 128 JNI_COCOA_EXIT(env);
 129 
 130     return jpt;
 131 }
 132 
 133 
 134 JNIEXPORT void JNICALL
 135 Java_sun_lwawt_macosx_CCursorManager_nativeSetAllowsCursorSetInBackground
 136 (JNIEnv *env, jclass class, jboolean allows)
 137 {
 138 JNI_COCOA_ENTER(env);
 139 
 140     SEL allowsSetInBackground_SEL = @selector(javaSetAllowsCursorSetInBackground:);
 141     if ([[NSCursor class] respondsToSelector:allowsSetInBackground_SEL]) {
 142         [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 143             NSMethodSignature *allowsSetInBackground_sig =
 144                 [[NSCursor class] methodSignatureForSelector:allowsSetInBackground_SEL];
 145             NSInvocation *invocation =
 146                 [NSInvocation invocationWithMethodSignature:allowsSetInBackground_sig];
 147             BOOL arg = (BOOL)allows;
 148             [invocation setSelector:allowsSetInBackground_SEL];
 149             [invocation setArgument:&arg atIndex:2];
 150             [invocation invokeWithTarget:[NSCursor class]];
 151         }];
 152     }
 153 
 154 JNI_COCOA_EXIT(env);
 155 
 156 }