Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m
41152 views
1
/*
2
* Copyright (c) 2011, 2019, 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 <Carbon/Carbon.h>
27
#import "CMenuItem.h"
28
#import "CMenu.h"
29
#import "AWTEvent.h"
30
#import "AWTWindow.h"
31
#import "ThreadUtilities.h"
32
#import "JNIUtilities.h"
33
34
#import "java_awt_Event.h"
35
#import "java_awt_event_KeyEvent.h"
36
#import "sun_lwawt_macosx_CMenuItem.h"
37
38
#define NOT_A_CHECKBOXMENU -2
39
40
41
@implementation CMenuItem
42
43
- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{
44
AWT_ASSERT_APPKIT_THREAD;
45
self = [super initWithPeer:peer];
46
if (self) {
47
if (asSeparator) {
48
fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem];
49
[fMenuItem retain];
50
} else {
51
fMenuItem = [[NSMenuItem alloc] init];
52
[fMenuItem setAction:@selector(handleAction:)];
53
[fMenuItem setTarget:self];
54
}
55
fIsCheckbox = NO;
56
fIsEnabled = YES;
57
}
58
return self;
59
}
60
61
// This is because NSApplication doesn't check the target's window when sending
62
// actions; they only check the target itself. We always return YES,
63
// since we shouldn't even be installed unless our window is active.
64
- (BOOL) worksWhenModal {
65
return YES;
66
}
67
68
// Events
69
- (void)handleAction:(NSMenuItem *)sender {
70
AWT_ASSERT_APPKIT_THREAD;
71
JNIEnv *env = [ThreadUtilities getJNIEnv];
72
JNI_COCOA_ENTER(env);
73
74
// If we are called as a result of user pressing a shortcut, do nothing,
75
// because AVTView has already sent corresponding key event to the Java
76
// layer from performKeyEquivalent.
77
// There is an exception from the rule above, though: if a window with
78
// a menu gets minimized by user and there are no other windows to take
79
// focus, the window's menu won't be removed from the global menu bar.
80
// However, the Java layer won't handle invocation by a shortcut coming
81
// from this "frameless" menu, because there are no active windows. This
82
// means we have to handle it here.
83
NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
84
85
if ([currEvent type] == NSKeyDown) {
86
// The action event can be ignored only if the key window is an AWT window.
87
// Otherwise, the action event is the only notification and must be processed.
88
NSWindow *keyWindow = [NSApp keyWindow];
89
if (keyWindow != nil && [AWTWindow isAWTWindow: keyWindow]) {
90
return;
91
}
92
}
93
94
if (fIsCheckbox) {
95
DECLARE_CLASS(jc_CCheckboxMenuItem, "sun/lwawt/macosx/CCheckboxMenuItem");
96
DECLARE_METHOD(jm_ckHandleAction, jc_CCheckboxMenuItem, "handleAction", "(Z)V");
97
98
// Send the opposite of what's currently checked -- the action
99
// indicates what state we're going to.
100
NSInteger state = [sender state];
101
jboolean newState = (state == NSOnState ? JNI_FALSE : JNI_TRUE);
102
(*env)->CallVoidMethod(env, fPeer, jm_ckHandleAction, newState);
103
} else {
104
DECLARE_CLASS(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
105
DECLARE_METHOD(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
106
107
NSUInteger modifiers = [currEvent modifierFlags];
108
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
109
110
(*env)->CallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
111
}
112
CHECK_EXCEPTION();
113
JNI_COCOA_EXIT(env);
114
}
115
116
- (void) setJavaLabel:(NSString *)theLabel shortcut:(NSString *)theKeyEquivalent modifierMask:(jint)modifiers {
117
118
NSUInteger modifierMask = 0;
119
120
if (![theKeyEquivalent isEqualToString:@""]) {
121
// Force the key equivalent to lower case if not using the shift key.
122
// Otherwise AppKit will draw a Shift glyph in the menu.
123
if ((modifiers & java_awt_event_KeyEvent_SHIFT_MASK) == 0) {
124
theKeyEquivalent = [theKeyEquivalent lowercaseString];
125
}
126
127
// Hack for the question mark -- SHIFT and / means use the question mark.
128
if ((modifiers & java_awt_event_KeyEvent_SHIFT_MASK) != 0 &&
129
[theKeyEquivalent isEqualToString:@"/"])
130
{
131
theKeyEquivalent = @"?";
132
modifiers &= ~java_awt_event_KeyEvent_SHIFT_MASK;
133
}
134
135
modifierMask = JavaModifiersToNsKeyModifiers(modifiers, NO);
136
}
137
138
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
139
[fMenuItem setKeyEquivalent:theKeyEquivalent];
140
[fMenuItem setKeyEquivalentModifierMask:modifierMask];
141
[fMenuItem setTitle:theLabel];
142
}];
143
}
144
145
- (void) setJavaImage:(NSImage *)theImage {
146
147
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
148
[fMenuItem setImage:theImage];
149
}];
150
}
151
152
- (void) setJavaToolTipText:(NSString *)theText {
153
154
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
155
[fMenuItem setToolTip:theText];
156
}];
157
}
158
159
160
- (void)setJavaEnabled:(BOOL) enabled {
161
162
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
163
@synchronized(self) {
164
fIsEnabled = enabled;
165
166
// Warning: This won't work if the parent menu is disabled.
167
// See [CMenu syncFromJava]. We still need to call it here so
168
// the NSMenuItem itself gets properly updated.
169
[fMenuItem setEnabled:fIsEnabled];
170
}
171
}];
172
}
173
174
- (BOOL)isEnabled {
175
176
BOOL enabled = NO;
177
@synchronized(self) {
178
enabled = fIsEnabled;
179
}
180
return enabled;
181
}
182
183
184
- (void)setJavaState:(BOOL)newState {
185
186
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
187
[fMenuItem setState:(newState ? NSOnState : NSOffState)];
188
}];
189
}
190
191
- (void)dealloc {
192
[fMenuItem setAction:NULL];
193
[fMenuItem setTarget:nil];
194
[fMenuItem release];
195
fMenuItem = nil;
196
197
[super dealloc];
198
}
199
200
- (void)addNSMenuItemToMenu:(NSMenu *)inMenu {
201
[inMenu addItem:fMenuItem];
202
}
203
204
- (NSMenuItem *)menuItem {
205
return [[fMenuItem retain] autorelease];
206
}
207
208
- (void)setIsCheckbox {
209
fIsCheckbox = YES;
210
}
211
212
- (NSString *)description {
213
return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem];
214
}
215
216
@end
217
218
/** Convert a Java keycode for SetMenuItemCmd */
219
static unichar AWTKeyToMacShortcut(jint awtKey, BOOL doShift) {
220
unichar macKey = 0;
221
222
if ((awtKey >= java_awt_event_KeyEvent_VK_0 && awtKey <= java_awt_event_KeyEvent_VK_9) ||
223
(awtKey >= java_awt_event_KeyEvent_VK_A && awtKey <= java_awt_event_KeyEvent_VK_Z))
224
{
225
// These ranges are the same in ASCII
226
macKey = awtKey;
227
} else if (awtKey >= java_awt_event_KeyEvent_VK_F1 && awtKey <= java_awt_event_KeyEvent_VK_F12) {
228
// Support for F1 - F12 has been around since Java 1.0 and fall into a lower range.
229
macKey = awtKey - java_awt_event_KeyEvent_VK_F1 + NSF1FunctionKey;
230
} else if (awtKey >= java_awt_event_KeyEvent_VK_F13 && awtKey <= java_awt_event_KeyEvent_VK_F24) {
231
// Support for F13-F24 came in Java 1.2 and are at a different range.
232
macKey = awtKey - java_awt_event_KeyEvent_VK_F13 + NSF13FunctionKey;
233
} else {
234
// Special characters
235
switch (awtKey) {
236
case java_awt_event_KeyEvent_VK_BACK_QUOTE : macKey = '`'; break;
237
case java_awt_event_KeyEvent_VK_QUOTE : macKey = '\''; break;
238
239
case java_awt_event_KeyEvent_VK_ESCAPE : macKey = 0x1B; break;
240
case java_awt_event_KeyEvent_VK_SPACE : macKey = ' '; break;
241
case java_awt_event_KeyEvent_VK_PAGE_UP : macKey = NSPageUpFunctionKey; break;
242
case java_awt_event_KeyEvent_VK_PAGE_DOWN : macKey = NSPageDownFunctionKey; break;
243
case java_awt_event_KeyEvent_VK_END : macKey = NSEndFunctionKey; break;
244
case java_awt_event_KeyEvent_VK_HOME : macKey = NSHomeFunctionKey; break;
245
246
case java_awt_event_KeyEvent_VK_LEFT : macKey = NSLeftArrowFunctionKey; break;
247
case java_awt_event_KeyEvent_VK_UP : macKey = NSUpArrowFunctionKey; break;
248
case java_awt_event_KeyEvent_VK_RIGHT : macKey = NSRightArrowFunctionKey; break;
249
case java_awt_event_KeyEvent_VK_DOWN : macKey = NSDownArrowFunctionKey; break;
250
251
case java_awt_event_KeyEvent_VK_COMMA : macKey = ','; break;
252
253
// Mac OS doesn't distinguish between the two '-' keys...
254
case java_awt_event_KeyEvent_VK_MINUS :
255
case java_awt_event_KeyEvent_VK_SUBTRACT : macKey = '-'; break;
256
257
// or the two '.' keys...
258
case java_awt_event_KeyEvent_VK_DECIMAL :
259
case java_awt_event_KeyEvent_VK_PERIOD : macKey = '.'; break;
260
261
// or the two '/' keys.
262
case java_awt_event_KeyEvent_VK_DIVIDE :
263
case java_awt_event_KeyEvent_VK_SLASH : macKey = '/'; break;
264
265
case java_awt_event_KeyEvent_VK_SEMICOLON : macKey = ';'; break;
266
case java_awt_event_KeyEvent_VK_EQUALS : macKey = '='; break;
267
268
case java_awt_event_KeyEvent_VK_OPEN_BRACKET : macKey = '['; break;
269
case java_awt_event_KeyEvent_VK_BACK_SLASH : macKey = '\\'; break;
270
case java_awt_event_KeyEvent_VK_CLOSE_BRACKET : macKey = ']'; break;
271
272
case java_awt_event_KeyEvent_VK_MULTIPLY : macKey = '*'; break;
273
case java_awt_event_KeyEvent_VK_ADD : macKey = '+'; break;
274
275
case java_awt_event_KeyEvent_VK_HELP : macKey = NSHelpFunctionKey; break;
276
case java_awt_event_KeyEvent_VK_TAB : macKey = NSTabCharacter; break;
277
case java_awt_event_KeyEvent_VK_ENTER : macKey = NSNewlineCharacter; break;
278
case java_awt_event_KeyEvent_VK_BACK_SPACE : macKey = NSBackspaceCharacter; break;
279
case java_awt_event_KeyEvent_VK_DELETE : macKey = NSDeleteCharacter; break;
280
case java_awt_event_KeyEvent_VK_CLEAR : macKey = NSClearDisplayFunctionKey; break;
281
case java_awt_event_KeyEvent_VK_AMPERSAND : macKey = '&'; break;
282
case java_awt_event_KeyEvent_VK_ASTERISK : macKey = '*'; break;
283
case java_awt_event_KeyEvent_VK_QUOTEDBL : macKey = '\"'; break;
284
case java_awt_event_KeyEvent_VK_LESS : macKey = '<'; break;
285
case java_awt_event_KeyEvent_VK_GREATER : macKey = '>'; break;
286
case java_awt_event_KeyEvent_VK_BRACELEFT : macKey = '{'; break;
287
case java_awt_event_KeyEvent_VK_BRACERIGHT : macKey = '}'; break;
288
case java_awt_event_KeyEvent_VK_AT : macKey = '@'; break;
289
case java_awt_event_KeyEvent_VK_COLON : macKey = ':'; break;
290
case java_awt_event_KeyEvent_VK_CIRCUMFLEX : macKey = '^'; break;
291
case java_awt_event_KeyEvent_VK_DOLLAR : macKey = '$'; break;
292
case java_awt_event_KeyEvent_VK_EXCLAMATION_MARK : macKey = '!'; break;
293
case java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS : macKey = '('; break;
294
case java_awt_event_KeyEvent_VK_NUMBER_SIGN : macKey = '#'; break;
295
case java_awt_event_KeyEvent_VK_PLUS : macKey = '+'; break;
296
case java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS: macKey = ')'; break;
297
case java_awt_event_KeyEvent_VK_UNDERSCORE : macKey = '_'; break;
298
}
299
}
300
return macKey;
301
}
302
303
/*
304
* Class: sun_lwawt_macosx_CMenuItem
305
* Method: nativeSetLabel
306
* Signature: (JLjava/lang/String;CII)V
307
*/
308
JNIEXPORT void JNICALL
309
Java_sun_lwawt_macosx_CMenuItem_nativeSetLabel
310
(JNIEnv *env, jobject peer,
311
jlong menuItemObj, jstring label,
312
jchar shortcutKey, jint shortcutKeyCode, jint mods)
313
{
314
JNI_COCOA_ENTER(env);
315
NSString *theLabel = JavaStringToNSString(env, label);
316
NSString *theKeyEquivalent = nil;
317
unichar macKey = shortcutKey;
318
319
if (macKey == 0) {
320
macKey = AWTKeyToMacShortcut(shortcutKeyCode, (mods & java_awt_event_KeyEvent_SHIFT_MASK) != 0);
321
}
322
323
if (macKey != 0) {
324
unichar equivalent[1] = {macKey};
325
theKeyEquivalent = [NSString stringWithCharacters:equivalent length:1];
326
} else {
327
theKeyEquivalent = @"";
328
}
329
330
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaLabel:theLabel shortcut:theKeyEquivalent modifierMask:mods];
331
JNI_COCOA_EXIT(env);
332
}
333
334
/*
335
* Class: sun_lwawt_macosx_CMenuItem
336
* Method: nativeSetTooltip
337
* Signature: (JLjava/lang/String;)V
338
*/
339
JNIEXPORT void JNICALL
340
Java_sun_lwawt_macosx_CMenuItem_nativeSetTooltip
341
(JNIEnv *env, jobject peer, jlong menuItemObj, jstring tooltip)
342
{
343
JNI_COCOA_ENTER(env);
344
NSString *theTooltip = JavaStringToNSString(env, tooltip);
345
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaToolTipText:theTooltip];
346
JNI_COCOA_EXIT(env);
347
}
348
349
/*
350
* Class: sun_lwawt_macosx_CMenuItem
351
* Method: nativeSetImage
352
* Signature: (JJ)V
353
*/
354
JNIEXPORT void JNICALL
355
Java_sun_lwawt_macosx_CMenuItem_nativeSetImage
356
(JNIEnv *env, jobject peer, jlong menuItemObj, jlong image)
357
{
358
JNI_COCOA_ENTER(env);
359
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaImage:(NSImage*)jlong_to_ptr(image)];
360
JNI_COCOA_EXIT(env);
361
}
362
363
/*
364
* Class: sun_lwawt_macosx_CMenuItem
365
* Method: nativeCreate
366
* Signature: (JZ)J
367
*/
368
JNIEXPORT jlong JNICALL
369
Java_sun_lwawt_macosx_CMenuItem_nativeCreate
370
(JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
371
{
372
373
__block CMenuItem *aCMenuItem = nil;
374
BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO;
375
CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
376
JNI_COCOA_ENTER(env);
377
378
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
379
380
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
381
aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal
382
asSeparator: asSeparator];
383
// the CMenuItem is released in CMenuComponent.dispose()
384
}];
385
386
if (aCMenuItem == nil) {
387
return 0L;
388
}
389
390
// and add it to the parent item.
391
[parentCMenu addJavaMenuItem: aCMenuItem];
392
393
// setLabel will be called after creation completes.
394
395
JNI_COCOA_EXIT(env);
396
return ptr_to_jlong(aCMenuItem);
397
}
398
399
/*
400
* Class: sun_lwawt_macosx_CMenuItem
401
* Method: nativeSetEnabled
402
* Signature: (JZ)V
403
*/
404
JNIEXPORT void JNICALL
405
Java_sun_lwawt_macosx_CMenuItem_nativeSetEnabled
406
(JNIEnv *env, jobject peer, jlong menuItemObj, jboolean enable)
407
{
408
JNI_COCOA_ENTER(env);
409
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
410
[item setJavaEnabled: (enable == JNI_TRUE)];
411
JNI_COCOA_EXIT(env);
412
}
413
414
/*
415
* Class: sun_lwawt_macosx_CCheckboxMenuItem
416
* Method: nativeSetState
417
* Signature: (IZ)V
418
*/
419
JNIEXPORT void JNICALL
420
Java_sun_lwawt_macosx_CCheckboxMenuItem_nativeSetState
421
(JNIEnv *env, jobject peer, jlong menuItemObj, jboolean state)
422
{
423
JNI_COCOA_ENTER(env);
424
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
425
[item setJavaState: (state == JNI_TRUE)];
426
JNI_COCOA_EXIT(env);
427
}
428
429
/*
430
* Class: sun_lwawt_macosx_CCheckboxMenuItem
431
* Method: nativeSetState
432
* Signature: (IZ)V
433
*/
434
JNIEXPORT void JNICALL
435
Java_sun_lwawt_macosx_CCheckboxMenuItem_nativeSetIsCheckbox
436
(JNIEnv *env, jobject peer, jlong menuItemObj)
437
{
438
JNI_COCOA_ENTER(env);
439
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
440
[item setIsCheckbox];
441
JNI_COCOA_EXIT(env);
442
}
443
444