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 "common.h"
  27 #import "com_sun_glass_ui_Cursor.h"
  28 #import "com_sun_glass_ui_mac_MacCursor.h"
  29 
  30 #import <Cocoa/Cocoa.h>
  31 
  32 #import "GlassMacros.h"
  33 #import "GlassHelper.h"
  34 
  35 //#define VERBOSE
  36 #ifndef VERBOSE
  37     #define LOG(MSG, ...)
  38 #else
  39     #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
  40 #endif
  41 
  42 #define CURSOR_BEST_SIZE 32
  43 
  44 #pragma mark --- Java NSCursor
  45 
  46 @interface NSCursor (Java)
  47 
  48 + (NSCursor*)performJavaSelector:(SEL)aSelector;
  49 
  50 @end
  51 
  52 @implementation NSCursor (Java)
  53 
  54 + (NSCursor*)performJavaSelector:(SEL)aSelector
  55 {
  56     NSCursor *cursor = nil;
  57     if ([GlassHelper InvokeSelectorIfAvailable:aSelector forClass:[NSCursor class] withArgument:NULL withReturnValue:(void**)&cursor] == NO)
  58     {
  59         cursor = [NSCursor arrowCursor];
  60     }
  61     return cursor;
  62 }
  63 
  64 @end
  65 
  66 #pragma mark --- com_sun_glass_ui_mac_MacCursor
  67 
  68 /*
  69  * Class:     com_sun_glass_ui_mac_MacCursor
  70  * Method:    _initIDs
  71  * Signature: ()V
  72  */
  73 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacCursor__1initIDs
  74 (JNIEnv *env, jclass jCursorClass)
  75 {
  76     if (jSizeInit == NULL)
  77     {
  78         jSizeInit = (*env)->GetMethodID(env, [GlassHelper ClassForName:"com.sun.glass.ui.Size" withEnv:env], "<init>", "(II)V");
  79     }
  80 }
  81 
  82 /*
  83  * Class:     com_sun_glass_ui_mac_MacCursor
  84  * Method:    _createCursor
  85  * Signature: (IILcom/sun/glass/ui/Pixels;)J
  86  */
  87 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacCursor__1createCursor
  88 (JNIEnv *env, jclass jCursorClass, jint x, jint y, jobject jPixels)
  89 {
  90     LOG("Java_com_sun_glass_ui_mac_MacCursor__1createCursor");
  91     jlong jcursor = 0;
  92     
  93     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
  94     GLASS_POOL_ENTER;
  95     {
  96         NSImage *image = NULL;
  97         (*env)->CallVoidMethod(env, jPixels, jPixelsAttachData, ptr_to_jlong(&image));
  98         if (image != NULL)
  99         {
 100             NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(x, y)];
 101             jcursor = ptr_to_jlong(cursor);
 102             [image release];
 103         }
 104     }
 105     GLASS_POOL_EXIT;
 106     GLASS_CHECK_EXCEPTION(env);
 107     
 108     return jcursor;
 109 }
 110 
 111 /*
 112  * Class:     com_sun_glass_ui_mac_MacCursor
 113  * Method:    _set
 114  * Signature: (I)V
 115  */
 116 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacCursor__1set
 117 (JNIEnv *env, jclass jCursorClass, jint jtype)
 118 {
 119     LOG("Java_com_sun_glass_ui_mac_MacCursor__1set");
 120     
 121     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 122     GLASS_POOL_ENTER;
 123     {
 124         NSCursor *cursor = nil;
 125         switch (jtype)
 126         {
 127             case com_sun_glass_ui_Cursor_CURSOR_CUSTOM:
 128                 // should never reach here, custom cursors are handled by Java_com_sun_glass_ui_mac_MacCursor__1setCustom
 129             case com_sun_glass_ui_Cursor_CURSOR_DEFAULT:
 130             default:
 131                 cursor = [NSCursor arrowCursor];
 132                 break;
 133             case com_sun_glass_ui_Cursor_CURSOR_TEXT:
 134                 cursor = [NSCursor IBeamCursor];
 135                 break;
 136             case com_sun_glass_ui_Cursor_CURSOR_CROSSHAIR:
 137                 cursor = [NSCursor crosshairCursor];
 138                 break;
 139             case com_sun_glass_ui_Cursor_CURSOR_CLOSED_HAND:
 140                 cursor = [NSCursor closedHandCursor];
 141                 break;
 142             case com_sun_glass_ui_Cursor_CURSOR_OPEN_HAND:
 143                 cursor = [NSCursor openHandCursor];
 144                 break;
 145             case com_sun_glass_ui_Cursor_CURSOR_POINTING_HAND:
 146                 cursor = [NSCursor pointingHandCursor];
 147                 break;
 148             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_LEFT:
 149                 cursor = [NSCursor resizeLeftCursor];
 150                 break;
 151             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_RIGHT:
 152                 cursor = [NSCursor resizeRightCursor];
 153                 break;
 154             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_UP:
 155                 cursor = [NSCursor resizeUpCursor];
 156                 break;
 157             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_DOWN:
 158                 cursor = [NSCursor resizeDownCursor];
 159                 break;
 160             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_LEFTRIGHT:
 161                 cursor = [NSCursor resizeLeftRightCursor];
 162                 break;
 163             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_UPDOWN:
 164                 cursor = [NSCursor resizeUpDownCursor];
 165                 break;
 166             case com_sun_glass_ui_Cursor_CURSOR_DISAPPEAR:
 167                 cursor = [NSCursor disappearingItemCursor];
 168                 break;
 169             case com_sun_glass_ui_Cursor_CURSOR_WAIT:
 170                 cursor = [NSCursor performJavaSelector:@selector(javaBusyButClickableCursor)];
 171                 break;
 172             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_SOUTHWEST:
 173                 cursor = [NSCursor performJavaSelector:@selector(javaResizeSWCursor)];
 174                 break;
 175             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_SOUTHEAST:
 176                 cursor = [NSCursor performJavaSelector:@selector(javaResizeSECursor)];
 177                 break;
 178             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_NORTHWEST:
 179                 cursor = [NSCursor performJavaSelector:@selector(javaResizeNWCursor)];
 180                 break;
 181             case com_sun_glass_ui_Cursor_CURSOR_RESIZE_NORTHEAST:
 182                 cursor = [NSCursor performJavaSelector:@selector(javaResizeNECursor)];
 183                 break;
 184             case com_sun_glass_ui_Cursor_CURSOR_MOVE:
 185                 cursor = [NSCursor performJavaSelector:@selector(javaMoveCursor)];
 186                 break;
 187         }
 188         [cursor set];
 189     }
 190     GLASS_POOL_EXIT;
 191     GLASS_CHECK_EXCEPTION(env);
 192 }
 193 
 194 /*
 195  * Class:     com_sun_glass_ui_mac_MacCursor
 196  * Method:    _setCustom
 197  * Signature: (J)V
 198  */
 199 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacCursor__1setCustom
 200 (JNIEnv *env, jclass jCursorClass, jlong cursorPtr)
 201 {
 202     LOG("Java_com_sun_glass_ui_mac_MacCursor__1setCustom");
 203     
 204     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 205     GLASS_POOL_ENTER;
 206     {
 207         NSCursor *cursor = (NSCursor*)jlong_to_ptr(cursorPtr);
 208         [cursor set];
 209     }
 210     GLASS_POOL_EXIT;
 211     GLASS_CHECK_EXCEPTION(env);
 212 }
 213 
 214 /*
 215  * Class:     com_sun_glass_ui_mac_MacCursor
 216  * Method:    _setVisible
 217  * Signature: (Z)V
 218  */
 219 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacCursor__1setVisible
 220 (JNIEnv *env, jclass jCursorClass, jboolean visible)
 221 {
 222     LOG("Java_com_sun_glass_ui_mac_MacCursor__1setVisible");
 223     
 224     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 225     GLASS_POOL_ENTER;
 226     {
 227         if (visible == JNI_TRUE)
 228         {
 229             [NSCursor unhide];
 230         }
 231         else
 232         {
 233             [NSCursor hide];
 234         }
 235     }
 236     GLASS_POOL_EXIT;
 237     GLASS_CHECK_EXCEPTION(env);
 238 }
 239 
 240 /*
 241  * Class:     com_sun_glass_ui_mac_MacCursor
 242  * Method:    _getBestSize
 243  * Signature: (II)Lcom.sun.glass.ui.Size;
 244  */
 245 JNIEXPORT jobject JNICALL Java_com_sun_glass_ui_mac_MacCursor__1getBestSize
 246 (JNIEnv *env, jclass jCursorClass, jint width, jint height)
 247 {
 248     LOG("Java_com_sun_glass_ui_mac_MacCursor__1getBestSize");
 249     
 250     jobject jsize = NULL;
 251     
 252     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 253     GLASS_POOL_ENTER;
 254     {
 255         jint widthBest = width;
 256         jint heightBest = height;
 257         
 258         NSImage *image = [[[NSCursor arrowCursor] image] retain];
 259         
 260         if (widthBest <= 0)
 261         {
 262             if (image != nil)
 263             {
 264                 widthBest = (jint)[image size].width;
 265             }
 266             else
 267             {
 268                 widthBest = CURSOR_BEST_SIZE;
 269             }
 270         }
 271         
 272         if (heightBest <= 0)
 273         {
 274             if (image != nil)
 275             {
 276                 heightBest = (jint)[image size].height;
 277             }
 278             else
 279             {
 280                 heightBest = CURSOR_BEST_SIZE;
 281             }
 282         }
 283         
 284         [image release];
 285         
 286         jsize = (*env)->NewObject(env, [GlassHelper ClassForName:"com.sun.glass.ui.Size" withEnv:env], jSizeInit, widthBest, heightBest);
 287     }
 288     GLASS_POOL_EXIT;
 289     GLASS_CHECK_EXCEPTION(env);
 290     
 291     return jsize;
 292 }