|
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 |
|
27 /* |
|
28 Documentation for Drag and Drop (Radar 3065640) |
|
29 There are several problems with Drag and Drop - notably, the mismatch between Java, Cocoa, and Carbon |
|
30 |
|
31 Java reports both the original source actions, and the user-selected actions (selected using KB modifiers) to both the source and target during the drag. AppKit only reports to the destination during the drag. This was solved by directly asking CGS for the KB state during the source's image moved callback. |
|
32 |
|
33 Java uses Shift/Move, Control/Copy and Shift+Control/Link. AppKit uses Command/Move, Alternate/Copy and Control/Link. Carbon uses Command/Move, Alternate/Copy and Command+Alternate/Link. This is bad, because Control overlaps between Java and AppKit. In this case, we choose compatibility between Carbon and Java (Java wins over AppKit wrt Control). This means that drags between Java applications will work correctly, regardless of whether you use the Carbon or the Java key modifiers. Drags to Java applications will work correctly regardless of whether you use the Carbon or the Java key modifiers. Drags from Java applications to non-Java applications will only work if you use the Carbon modifiers. |
|
34 |
|
35 The reason we can't just set the CoreDrag(G/S)etAllowableActions directly (while ignoring the modifier keys) is because Carbon apps traditionally don't pay any attention - they only look at the modifier keys. |
|
36 */ |
|
37 |
|
38 #import <Cocoa/Cocoa.h> |
|
39 #import "DnDUtilities.h" |
|
40 #import "java_awt_dnd_DnDConstants.h" |
|
41 #import "java_awt_event_InputEvent.h" |
|
42 |
|
43 @implementation DnDUtilities |
|
44 |
|
45 // Make sure we don't let other apps see local drags by using a process unique pasteboard type. |
|
46 // This may not work in the Applet case, since they are all running in the same VM |
|
47 + (NSString *) javaPboardType { |
|
48 static NSString *customJavaPboardType = nil; |
|
49 if (customJavaPboardType == nil) |
|
50 customJavaPboardType = [[NSString stringWithFormat:@"NSJavaPboardType-%@", [[NSProcessInfo processInfo] globallyUniqueString]] retain]; |
|
51 return customJavaPboardType; |
|
52 } |
|
53 |
|
54 + (jint)mapNSDragOperationToJava:(NSDragOperation)dragOperation |
|
55 { |
|
56 jint result = java_awt_dnd_DnDConstants_ACTION_NONE; |
|
57 |
|
58 if ((dragOperation & NSDragOperationCopy) != 0) // 1 |
|
59 result = ((dragOperation & NSDragOperationMove) == 0) ? java_awt_dnd_DnDConstants_ACTION_COPY : java_awt_dnd_DnDConstants_ACTION_COPY_OR_MOVE; |
|
60 |
|
61 else if ((dragOperation & NSDragOperationMove) != 0) // 16 |
|
62 result = java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
63 |
|
64 else if ((dragOperation & NSDragOperationLink) != 0) // 2 |
|
65 result = java_awt_dnd_DnDConstants_ACTION_LINK; |
|
66 |
|
67 else if ((dragOperation & NSDragOperationGeneric) != 0) // 4 |
|
68 result = java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
69 |
|
70 // Pre-empted by the above cases: |
|
71 //else if (dragOperation == NSDragOperationEvery) // UINT_MAX |
|
72 // result = java_awt_dnd_DnDConstants_ACTION_COPY_OR_MOVE; |
|
73 |
|
74 // To be rejected: |
|
75 //else if ((dragOperation & NSDragOperationPrivate) != 0) // 8 |
|
76 //else if ((dragOperation & NSDragOperationAll_Obsolete) != 0) // 15 |
|
77 //else if ((dragOperation & NSDragOperationDelete) != 0) // 32 |
|
78 |
|
79 return result; |
|
80 } |
|
81 |
|
82 + (jint)mapNSDragOperationMaskToJava:(NSDragOperation)dragOperation |
|
83 { |
|
84 jint result = java_awt_dnd_DnDConstants_ACTION_NONE; |
|
85 |
|
86 if (dragOperation & NSDragOperationMove) |
|
87 result |= java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
88 |
|
89 if (dragOperation & NSDragOperationCopy) |
|
90 result |= java_awt_dnd_DnDConstants_ACTION_COPY; |
|
91 |
|
92 if (dragOperation & NSDragOperationLink) |
|
93 result |= java_awt_dnd_DnDConstants_ACTION_LINK; |
|
94 |
|
95 // Only look at Generic if none of the other options are specified |
|
96 if ( (dragOperation & NSDragOperationGeneric) && !(dragOperation & (NSDragOperationMove|NSDragOperationCopy|NSDragOperationLink)) ) |
|
97 result |= java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
98 |
|
99 return result; |
|
100 } |
|
101 |
|
102 + (jint)narrowJavaDropActions:(jint)actions |
|
103 { |
|
104 if (YES) { |
|
105 // Order is defined in the java.awt.dnd.DropTargetDropEvent JavaDoc |
|
106 if (actions & java_awt_dnd_DnDConstants_ACTION_MOVE) { |
|
107 return java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
108 } |
|
109 if (actions & java_awt_dnd_DnDConstants_ACTION_COPY) { |
|
110 return java_awt_dnd_DnDConstants_ACTION_COPY; |
|
111 } |
|
112 if (actions & java_awt_dnd_DnDConstants_ACTION_LINK) { |
|
113 return java_awt_dnd_DnDConstants_ACTION_LINK; |
|
114 } |
|
115 } else { |
|
116 // Order is what is most intuitive on Mac OS X |
|
117 if (actions & java_awt_dnd_DnDConstants_ACTION_COPY) { |
|
118 return java_awt_dnd_DnDConstants_ACTION_COPY; |
|
119 } |
|
120 if (actions & java_awt_dnd_DnDConstants_ACTION_LINK) { |
|
121 return java_awt_dnd_DnDConstants_ACTION_LINK; |
|
122 } |
|
123 if (actions & java_awt_dnd_DnDConstants_ACTION_MOVE) { |
|
124 return java_awt_dnd_DnDConstants_ACTION_MOVE; |
|
125 } |
|
126 } |
|
127 |
|
128 return java_awt_dnd_DnDConstants_ACTION_NONE; |
|
129 } |
|
130 |
|
131 + (NSDragOperation)mapJavaDragOperationToNS:(jint)dragOperation |
|
132 { |
|
133 NSDragOperation result = NSDragOperationNone; |
|
134 |
|
135 switch (dragOperation) { |
|
136 case java_awt_dnd_DnDConstants_ACTION_NONE: // 0 |
|
137 result = NSDragOperationNone; |
|
138 break; |
|
139 case java_awt_dnd_DnDConstants_ACTION_COPY: // 1 |
|
140 result = NSDragOperationCopy; |
|
141 break; |
|
142 case java_awt_dnd_DnDConstants_ACTION_MOVE: // 2 |
|
143 result = NSDragOperationMove; |
|
144 break; |
|
145 case java_awt_dnd_DnDConstants_ACTION_COPY_OR_MOVE: // 3 |
|
146 result = NSDragOperationCopy | NSDragOperationMove; |
|
147 break; |
|
148 case java_awt_dnd_DnDConstants_ACTION_LINK: // 1073741824L |
|
149 result = NSDragOperationLink; |
|
150 break; |
|
151 case (java_awt_dnd_DnDConstants_ACTION_COPY_OR_MOVE | java_awt_dnd_DnDConstants_ACTION_LINK): |
|
152 result = NSDragOperationCopy | NSDragOperationMove | NSDragOperationLink; |
|
153 break; |
|
154 } |
|
155 |
|
156 if (result != NSDragOperationNone) { |
|
157 result |= NSDragOperationGeneric; |
|
158 } |
|
159 |
|
160 return result; |
|
161 } |
|
162 |
|
163 // Mouse and key modifiers mapping: |
|
164 + (NSUInteger)mapJavaExtModifiersToNSKeyModifiers:(jint)modifiers |
|
165 { |
|
166 NSUInteger result = 0; |
|
167 |
|
168 if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) |
|
169 result |= NSShiftKeyMask; |
|
170 |
|
171 if ((modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) != 0) |
|
172 result |= NSControlKeyMask; |
|
173 |
|
174 if ((modifiers & java_awt_event_InputEvent_META_DOWN_MASK) != 0) |
|
175 result |= NSCommandKeyMask; |
|
176 |
|
177 if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) |
|
178 result |= NSAlternateKeyMask; |
|
179 |
|
180 if ((modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) != 0) |
|
181 result |= NSAlternateKeyMask; |
|
182 |
|
183 return result; |
|
184 } |
|
185 |
|
186 + (NSUInteger)mapJavaExtModifiersToNSMouseDownButtons:(jint)modifiers |
|
187 { |
|
188 NSUInteger result = NSLeftMouseDown; |
|
189 |
|
190 if ((modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) != 0) |
|
191 result = NSLeftMouseDown; |
|
192 |
|
193 if ((modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) != 0) |
|
194 result = NSOtherMouseDown; |
|
195 |
|
196 if ((modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) != 0) |
|
197 result = NSRightMouseDown; |
|
198 |
|
199 return result; |
|
200 } |
|
201 |
|
202 + (NSUInteger)mapJavaExtModifiersToNSMouseUpButtons:(jint)modifiers |
|
203 { |
|
204 NSUInteger result = NSLeftMouseUp; |
|
205 |
|
206 if ((modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) != 0) |
|
207 result = NSLeftMouseUp; |
|
208 |
|
209 if ((modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) != 0) |
|
210 result = NSOtherMouseUp; |
|
211 |
|
212 if ((modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) != 0) |
|
213 result = NSRightMouseUp; |
|
214 |
|
215 return result; |
|
216 } |
|
217 |
|
218 |
|
219 // Specialized key modifiers mappings (for DragSource.operationChanged) |
|
220 |
|
221 // Returns just the key modifiers from a java modifier flag |
|
222 + (jint)extractJavaExtKeyModifiersFromJavaExtModifiers:(jint)modifiers |
|
223 { |
|
224 // Build the mask |
|
225 static jint mask = java_awt_event_InputEvent_SHIFT_DOWN_MASK | java_awt_event_InputEvent_CTRL_DOWN_MASK | java_awt_event_InputEvent_META_DOWN_MASK | java_awt_event_InputEvent_ALT_DOWN_MASK; |
|
226 //static int mask = java_awt_event_InputEvent_SHIFT_DOWN_MASK | java_awt_event_InputEvent_CTRL_DOWN_MASK; |
|
227 |
|
228 // Get results |
|
229 jint result = modifiers & mask; |
|
230 |
|
231 // Java appears to have 2 ALT buttons - combine them. |
|
232 if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) |
|
233 result |= java_awt_event_InputEvent_ALT_DOWN_MASK; |
|
234 |
|
235 return result; |
|
236 } |
|
237 |
|
238 // Returns just the mouse modifiers from a java modifier flag |
|
239 + (jint)extractJavaExtMouseModifiersFromJavaExtModifiers:(jint)modifiers |
|
240 { |
|
241 // Build the mask |
|
242 static jint mask = java_awt_event_InputEvent_BUTTON1_DOWN_MASK | java_awt_event_InputEvent_BUTTON2_DOWN_MASK | java_awt_event_InputEvent_BUTTON3_DOWN_MASK; |
|
243 |
|
244 // Get results |
|
245 return modifiers & mask; |
|
246 } |
|
247 |
|
248 |
|
249 + (jint)currentJavaExtKeyModifiers |
|
250 { |
|
251 NSUInteger modifiers = [NSEvent modifierFlags]; |
|
252 jint jmodifiers = 0; |
|
253 |
|
254 if(modifiers & NSShiftKeyMask) { |
|
255 jmodifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK; |
|
256 } |
|
257 |
|
258 if(modifiers & NSControlKeyMask) { |
|
259 jmodifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK; |
|
260 } |
|
261 |
|
262 if(modifiers & NSAlternateKeyMask) { |
|
263 jmodifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK; |
|
264 } |
|
265 |
|
266 if(modifiers & NSCommandKeyMask) { |
|
267 jmodifiers |= java_awt_event_InputEvent_META_DOWN_MASK; |
|
268 } |
|
269 |
|
270 return jmodifiers; |
|
271 } |
|
272 |
|
273 |
|
274 + (NSDragOperation) nsDragOperationForModifiers:(NSUInteger)modifiers { |
|
275 |
|
276 // Java first |
|
277 if ( (modifiers & NSShiftKeyMask) && (modifiers & NSControlKeyMask) ) { |
|
278 return NSDragOperationLink; |
|
279 } |
|
280 if (modifiers & NSShiftKeyMask) { |
|
281 return NSDragOperationMove; |
|
282 } |
|
283 if (modifiers & NSControlKeyMask) { |
|
284 return NSDragOperationCopy; |
|
285 } |
|
286 |
|
287 // Then native |
|
288 if ( (modifiers & NSCommandKeyMask) && (modifiers & NSAlternateKeyMask) ) { |
|
289 return NSDragOperationLink; |
|
290 } |
|
291 if (modifiers & NSCommandKeyMask) { |
|
292 return NSDragOperationMove; |
|
293 } |
|
294 if (modifiers & NSAlternateKeyMask) { |
|
295 return NSDragOperationCopy; |
|
296 } |
|
297 |
|
298 // Otherwise, we allow anything |
|
299 return NSDragOperationEvery; |
|
300 } |
|
301 |
|
302 + (jint) javaKeyModifiersForNSDragOperation:(NSDragOperation)dragOperation { |
|
303 if (dragOperation & NSDragOperationMove) |
|
304 return java_awt_event_InputEvent_SHIFT_DOWN_MASK; |
|
305 |
|
306 if (dragOperation & NSDragOperationCopy) |
|
307 return java_awt_event_InputEvent_CTRL_DOWN_MASK; |
|
308 |
|
309 if (dragOperation & NSDragOperationLink) { |
|
310 return java_awt_event_InputEvent_SHIFT_DOWN_MASK | java_awt_event_InputEvent_CTRL_DOWN_MASK; |
|
311 } |
|
312 return 0; |
|
313 } |
|
314 |
|
315 @end |