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#include <JavaNativeFoundation/JavaNativeFoundation.h>
30
31#include "GeomUtilities.h"
32#include "ThreadUtilities.h"
33
34#include "java_awt_Cursor.h"
35
36
37static 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
58static 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
68static void setCursorOnAppKitThread(NSCursor *cursor) {
69    [cursor set];
70}
71
72JNIEXPORT void JNICALL
73Java_sun_lwawt_macosx_CCursorManager_nativeSetBuiltInCursor
74(JNIEnv *env, jclass class, jint type, jstring name)
75{
76JNF_COCOA_ENTER(env);
77
78    NSString *cursorName = JNFJavaToNSString(env, name);
79    SEL cursorSelector = (type == sun_lwawt_macosx_CCursorManager_NAMED_CURSOR) ? lookupCursorSelectorForName(cursorName) : lookupCursorSelectorForType(type);
80    if (cursorSelector == nil) {
81        NSString *reason = [NSString stringWithFormat:@"unimplemented built-in cursor type: %d / %@", type, cursorName];
82        [JNFException raise:env as:kIllegalArgumentException reason:[reason UTF8String]];
83    }
84
85    if (![[NSCursor class] respondsToSelector:cursorSelector]) {
86        [JNFException raise:env as:kNoSuchMethodException reason:"missing NSCursor selector"];
87    }
88
89    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
90        setCursorOnAppKitThread([[NSCursor class] performSelector:cursorSelector]);
91    }];
92
93JNF_COCOA_EXIT(env);
94}
95
96JNIEXPORT void JNICALL
97Java_sun_lwawt_macosx_CCursorManager_nativeSetCustomCursor
98(JNIEnv *env, jclass class, jlong imgPtr, jdouble x, jdouble y)
99{
100JNF_COCOA_ENTER(env);
101    NSImage *image = (NSImage *)jlong_to_ptr(imgPtr);
102
103    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
104        NSCursor *cursor = [[NSCursor alloc] initWithImage:image
105                                                   hotSpot:(NSPoint){ x, y }];
106        setCursorOnAppKitThread(cursor);
107        [cursor release];
108    }];
109
110JNF_COCOA_EXIT(env);
111}
112
113JNIEXPORT jobject JNICALL
114Java_sun_lwawt_macosx_CCursorManager_nativeGetCursorPosition
115(JNIEnv *env, jclass class)
116{
117    jobject jpt = NULL;
118
119JNF_COCOA_ENTER(env);
120
121    CGEventRef event = CGEventCreate(NULL);
122    CGPoint globalPos = CGEventGetLocation(event);
123    CFRelease(event);
124
125    jpt = NSToJavaPoint(env, globalPos);
126
127JNF_COCOA_EXIT(env);
128
129    return jpt;
130}
131
132
133JNIEXPORT void JNICALL
134Java_sun_lwawt_macosx_CCursorManager_nativeSetAllowsCursorSetInBackground
135(JNIEnv *env, jclass class, jboolean allows)
136{
137JNF_COCOA_ENTER(env);
138
139    SEL allowsSetInBackground_SEL = @selector(javaSetAllowsCursorSetInBackground:);
140    if ([[NSCursor class] respondsToSelector:allowsSetInBackground_SEL]) {
141        [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
142            NSMethodSignature *allowsSetInBackground_sig =
143                [[NSCursor class] methodSignatureForSelector:allowsSetInBackground_SEL];
144            NSInvocation *invocation =
145                [NSInvocation invocationWithMethodSignature:allowsSetInBackground_sig];
146            BOOL arg = (BOOL)allows;
147            [invocation setSelector:allowsSetInBackground_SEL];
148            [invocation setArgument:&arg atIndex:2];
149            [invocation invokeWithTarget:[NSCursor class]];
150        }];
151    }
152
153JNF_COCOA_EXIT(env);
154
155}
156