VAqua.libkeywindowpatch.CMenuItemCategory.m Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vaqua Show documentation
Show all versions of vaqua Show documentation
An improved native Swing look and feel for macOS
The newest version!
/*
* Copyright (c) 2018-2023 Alan Snyder.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the license agreement. For details see
* accompanying license terms.
*/
#import
#include
#import
#include "jnix.h"
#import "KeyWindowPatch.h"
#import "CMenuItemCategory.h"
static unichar CHAR_UNDEFINED = 0xFFFF;
// The following functions and class are located in JDK dynamic libraries.
extern unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers);
jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods);
jlong UTC(NSEvent *event);
@implementation CMenuItem (CMenuItemCategory)
- (void)handleAction:(NSMenuItem *)sender
{
#ifdef DEBUG_PATCH
NSLog(@"Patched CMenuItem called");
#endif
//AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = GET_APPKIT_JNI_ENVIRONMENT();
COCOA_ENTER();
// If we are called as a result of user pressing a shortcut, do nothing,
// because AVTView has already sent corresponding key event to the Java
// layer from performKeyEquivalent.
// There is an exception from the rule above, though: if a window with
// a menu gets minimized by user and there are no other windows to take
// focus, the window's menu won't be removed from the global menu bar.
// However, the Java layer won't handle invocation by a shortcut coming
// from this "frameless" menu, because there are no active windows. This
// means we have to handle it here.
NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
if (fIsCheckbox) {
static jclass jc_CCheckboxMenuItem;
static jmethodID jm_ckHandleAction;
GET_CLASS(jc_CCheckboxMenuItem, "sun/lwawt/macosx/CCheckboxMenuItem");
GET_METHOD(jm_ckHandleAction, jc_CCheckboxMenuItem, "handleAction", "(Z)V");
// Send the opposite of what's currently checked -- the action
// indicates what state we're going to.
NSInteger state = [sender state];
jboolean newState = (state == NSOnState ? JNI_FALSE : JNI_TRUE);
(*env)->CallVoidMethod(env, fPeer, jm_ckHandleAction, newState);
}
else {
if ([currEvent type] == NSKeyDown) {
// Event available through sender variable hence NSApplication
// not needed for checking the keyboard input sans the modifier keys
// Also, the method used to fetch eventKey earlier would be locale dependent
// With earlier implementation, if MenuKey: e EventKey: ा ; if input method
// is not U.S. (Devanagari in this case)
// With current implementation, EventKey = MenuKey = e irrespective of
// input method
NSString *eventKey = [sender keyEquivalent];
// Apple uses characters from private Unicode range for some of the
// keys, so we need to do the same translation here that we do
// for the regular key down events
if ([eventKey length] == 1) {
unichar origChar = [eventKey characterAtIndex:0];
unichar newChar = NsCharToJavaChar(origChar, 0);
if (newChar == CHAR_UNDEFINED) {
newChar = origChar;
}
eventKey = [NSString stringWithCharacters: &newChar length: 1];
}
// Here is the change. The action event can be ignored only if the window is an AWT window.
// Otherwise, the action event is the only notification and must be processed.
NSWindow *keyWindow = [NSApp keyWindow];
if (keyWindow != nil && [[keyWindow delegate] respondsToSelector: @selector(sendEvent:)]) {
return;
}
}
static jclass jc_CMenuItem;
static jmethodID jm_handleAction;
GET_CLASS(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
GET_METHOD(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
NSUInteger modifiers = [currEvent modifierFlags];
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
(*env)->CallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
}
COCOA_EXIT();
}
@end
jlong UTC(NSEvent *event) {
struct timeval tv;
if (gettimeofday(&tv, NULL) == 0) {
long long sec = (long long)tv.tv_sec;
return (sec*1000) + (tv.tv_usec/1000);
}
return 0;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy