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