mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-17 05:51:44 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f0f43b4da | ||
|
|
04f1cf9b47 | ||
|
|
80c6e03ec4 | ||
|
|
9001a78701 | ||
|
|
703cab8d0d | ||
|
|
3c9cdc9251 | ||
|
|
032805520d | ||
|
|
b37f7cfdb1 | ||
|
|
3668d631ca | ||
|
|
7fa3ea24ac | ||
|
|
8a521cbf64 | ||
|
|
fe9601aa6d |
@@ -1354,6 +1354,7 @@ static int _print_module(const char* fname, address base_address,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path);
|
||||
// Loads .dll/.so and
|
||||
// in case of error it checks if .dll/.so was built for the
|
||||
// same architecture as Hotspot is running on
|
||||
|
||||
@@ -211,17 +211,6 @@ ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
|
||||
assert(_table != NULL && "allocation failed");
|
||||
}
|
||||
|
||||
ImageFileReaderTable::~ImageFileReaderTable() {
|
||||
for (u4 i = 0; i < _count; i++) {
|
||||
ImageFileReader* image = _table[i];
|
||||
|
||||
if (image != NULL) {
|
||||
delete image;
|
||||
}
|
||||
}
|
||||
free(_table);
|
||||
}
|
||||
|
||||
// Add a new image entry to the table.
|
||||
void ImageFileReaderTable::add(ImageFileReader* image) {
|
||||
if (_count == _max) {
|
||||
|
||||
@@ -371,7 +371,12 @@ private:
|
||||
|
||||
public:
|
||||
ImageFileReaderTable();
|
||||
~ImageFileReaderTable();
|
||||
// ~ImageFileReaderTable()
|
||||
// Bug 8166727
|
||||
//
|
||||
// WARNING: Should never close jimage files.
|
||||
// Threads may still be running during shutdown.
|
||||
//
|
||||
|
||||
// Return the number of entries.
|
||||
inline u4 count() { return _count; }
|
||||
|
||||
@@ -100,8 +100,12 @@ public class CEmbeddedFrame extends EmbeddedFrame {
|
||||
deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED);
|
||||
}
|
||||
|
||||
public void handleKeyEvent(NSEvent nsEvent) {
|
||||
responder.handleKeyEvent(nsEvent);
|
||||
public void handleKeyEvent(int eventType, int modifierFlags, String characters,
|
||||
String charsIgnoringMods, boolean isRepeat, short keyCode,
|
||||
boolean needsKeyTyped) {
|
||||
responder.handleKeyEvent(eventType, modifierFlags, characters,
|
||||
charsIgnoringMods, /*charsIgnoringModifiersAndShift*/ null,
|
||||
keyCode, needsKeyTyped, isRepeat);
|
||||
}
|
||||
|
||||
public void handleInputEvent(String text) {
|
||||
|
||||
@@ -29,24 +29,20 @@ import sun.awt.SunToolkit;
|
||||
import sun.awt.event.KeyEventProcessing;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.PlatformEventNotifier;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;import java.util.MissingResourceException;import java.util.ResourceBundle;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Translates NSEvents/NPCocoaEvents into AWT events.
|
||||
*/
|
||||
final class CPlatformResponder {
|
||||
|
||||
private static final PlatformLogger keyboardLog = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformResponder");
|
||||
|
||||
private final PlatformEventNotifier eventNotifier;
|
||||
private final boolean isNpapiCallback;
|
||||
private int lastKeyPressCode = KeyEvent.VK_UNDEFINED;
|
||||
@@ -61,7 +57,6 @@ final class CPlatformResponder {
|
||||
private int lastDraggedRelativeX;
|
||||
private int lastDraggedRelativeY;
|
||||
|
||||
|
||||
CPlatformResponder(final PlatformEventNotifier eventNotifier,
|
||||
final boolean isNpapiCallback) {
|
||||
this.eventNotifier = eventNotifier;
|
||||
@@ -166,41 +161,6 @@ final class CPlatformResponder {
|
||||
-roundDelta, -delta, null);
|
||||
}
|
||||
|
||||
private void handleFlagChangedEvent(int modifierFlags, short keyCode) {
|
||||
int[] in = new int[] {modifierFlags, keyCode};
|
||||
int[] out = new int[3]; // [jkeyCode, jkeyLocation, jkeyType]
|
||||
|
||||
NSEvent.nsKeyModifiersToJavaKeyInfo(in, out);
|
||||
|
||||
int jkeyCode = out[0];
|
||||
int jkeyLocation = out[1];
|
||||
int jeventType = out[2];
|
||||
|
||||
int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags);
|
||||
long when = System.currentTimeMillis();
|
||||
|
||||
if (jeventType == KeyEvent.KEY_PRESSED) {
|
||||
lastKeyPressCode = jkeyCode;
|
||||
}
|
||||
eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers,
|
||||
jkeyCode, KeyEvent.CHAR_UNDEFINED, jkeyLocation);
|
||||
}
|
||||
|
||||
private static char mapNsCharsToCompatibleWithJava (char ch) {
|
||||
switch (ch) {
|
||||
case 0x0003: // NSEnterCharacter
|
||||
case 0x000d: // NSCarriageReturnCharacter
|
||||
return 0x000a; // NSNewlineCharacter
|
||||
// case 0x007f: // NSDeleteCharacter
|
||||
// return 0x0008; // NSBackspaceCharacter
|
||||
case 0xF728: // NSDeleteFunctionKey
|
||||
return 0x0008; // NSDeleteCharacter
|
||||
case 0x0019: // NSBackTabCharacter
|
||||
return 0x0009; // NSTabCharacter
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
private static final String [] cyrillicKeyboardLayouts = new String [] {
|
||||
"com.apple.keylayout.Russian",
|
||||
"com.apple.keylayout.RussianWin",
|
||||
@@ -216,181 +176,6 @@ final class CPlatformResponder {
|
||||
return Arrays.stream(cyrillicKeyboardLayouts).anyMatch(l -> l.equals(LWCToolkit.getKeyboardLayoutId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events.
|
||||
*/
|
||||
void handleKeyEvent(NSEvent nsEvent)
|
||||
{
|
||||
|
||||
if (!KeyEventProcessing.useNationalLayouts || isCyrillicKeyboardLayout()) {
|
||||
handleKeyEvent(
|
||||
nsEvent.getType(),
|
||||
nsEvent.getModifierFlags(),
|
||||
nsEvent.getOldCharacters(),
|
||||
nsEvent.getOldCharactersIgnoringModifiers(),
|
||||
nsEvent.getKeyCode(),
|
||||
true,
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isFlagsChangedEvent =
|
||||
isNpapiCallback ? (nsEvent.getType() == CocoaConstants.NPCocoaEventFlagsChanged) :
|
||||
(nsEvent.getType() == CocoaConstants.NSFlagsChanged);
|
||||
|
||||
int jeventType = KeyEvent.KEY_PRESSED;
|
||||
int jkeyCode = KeyEvent.VK_UNDEFINED;
|
||||
int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN;
|
||||
boolean postsTyped = false;
|
||||
boolean spaceKeyTyped = false;
|
||||
|
||||
|
||||
if (isFlagsChangedEvent) {
|
||||
handleFlagChangedEvent(nsEvent.getModifierFlags(), nsEvent.getKeyCode());
|
||||
return;
|
||||
}
|
||||
|
||||
int jmodifiers = NSEvent.nsToJavaModifiers(nsEvent.getModifierFlags());
|
||||
|
||||
boolean metaAltCtrlAreNotPressed = (jmodifiers &
|
||||
(InputEvent.META_DOWN_MASK
|
||||
| InputEvent.ALT_DOWN_MASK
|
||||
| InputEvent.CTRL_DOWN_MASK)
|
||||
) == 0;
|
||||
|
||||
boolean shiftIsPressed = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
|
||||
|
||||
boolean useShiftedCharacters = metaAltCtrlAreNotPressed && shiftIsPressed;
|
||||
|
||||
boolean shiftAltDownAreNotPressed = (jmodifiers &
|
||||
(InputEvent.META_DOWN_MASK
|
||||
| InputEvent.ALT_DOWN_MASK
|
||||
| InputEvent.SHIFT_DOWN_MASK)
|
||||
) == 0;
|
||||
|
||||
boolean ctrlIsPressed = (jmodifiers & InputEvent.CTRL_DOWN_MASK) != 0;
|
||||
|
||||
boolean isISOControl = false;
|
||||
|
||||
char checkedChar = (nsEvent.getCharacters() == null
|
||||
|| nsEvent.getCharacters().isEmpty()) ? KeyEvent.CHAR_UNDEFINED : nsEvent.getCharacters().charAt(0);
|
||||
|
||||
if (shiftAltDownAreNotPressed && ctrlIsPressed) {
|
||||
if (Character.isISOControl(checkedChar)) {
|
||||
isISOControl = true;
|
||||
}
|
||||
}
|
||||
|
||||
char characterToGetKeyCode = KeyEvent.CHAR_UNDEFINED;
|
||||
|
||||
boolean charactersIgnoringModifiersIsValid = (nsEvent.getCharactersIgnoringModifiers() != null && nsEvent.getCharactersIgnoringModifiers().length() > 0);
|
||||
boolean charactersIsValid = (nsEvent.getCharacters() != null && nsEvent.getCharacters().length() > 0);
|
||||
|
||||
// We use this char to find a character that is printed depending on pressing modifiers
|
||||
characterToGetKeyCode = charactersIgnoringModifiersIsValid
|
||||
? nsEvent.getCharactersIgnoringModifiers().charAt(0)
|
||||
: charactersIsValid ? nsEvent.getCharacters().charAt(0) : KeyEvent.CHAR_UNDEFINED;
|
||||
|
||||
if (useShiftedCharacters && nsEvent.getCharactersIgnoringModifiers() != null && !nsEvent.getCharactersIgnoringModifiers().isEmpty()) {
|
||||
characterToGetKeyCode = nsEvent.getCharactersIgnoringModifiers().charAt(0);
|
||||
} else if (nsEvent.getCharactersIgnoringModifiersAndShift() != null && !nsEvent.getCharactersIgnoringModifiersAndShift().isEmpty()) {
|
||||
characterToGetKeyCode = nsEvent.getCharactersIgnoringModifiersAndShift().charAt(0);
|
||||
} else if (nsEvent.getCharacters() != null && !nsEvent.getCharacters().isEmpty() && metaAltCtrlAreNotPressed && shiftIsPressed) {
|
||||
characterToGetKeyCode = checkedChar;
|
||||
}
|
||||
|
||||
// We use char candidate if modifiers are not used
|
||||
// otherwise, we use char ignoring modifiers
|
||||
int[] in = new int[] {
|
||||
characterToGetKeyCode,
|
||||
nsEvent.isHasDeadKey() ? 1 : 0,
|
||||
nsEvent.getModifierFlags(),
|
||||
nsEvent.getKeyCode(),
|
||||
/*useNationalLayouts*/ 1
|
||||
};
|
||||
|
||||
int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar]
|
||||
|
||||
postsTyped = NSEvent.nsToJavaKeyInfo(in, out);
|
||||
|
||||
char characterToSendWithTheEvent = characterToGetKeyCode;
|
||||
|
||||
if(nsEvent.isHasDeadKey()){
|
||||
characterToSendWithTheEvent = (char) out[2];
|
||||
jkeyCode = nsEvent.getDeadKeyCode();
|
||||
if(characterToSendWithTheEvent == 0){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If Pinyin Simplified input method is selected, CAPS_LOCK key is supposed to switch
|
||||
// input to la tin letters.
|
||||
// It is necessary to use charIgnoringModifiers instead of charCandidate for event
|
||||
// generation in such case to avoid uppercase letters in text components.
|
||||
LWCToolkit lwcToolkit = (LWCToolkit)Toolkit.getDefaultToolkit();
|
||||
if (lwcToolkit.getLockingKeyState(KeyEvent.VK_CAPS_LOCK) &&
|
||||
Locale.SIMPLIFIED_CHINESE.equals(lwcToolkit.getDefaultKeyboardLocale())) {
|
||||
characterToSendWithTheEvent = characterToGetKeyCode;
|
||||
}
|
||||
|
||||
jkeyCode = out[0];
|
||||
|
||||
jkeyLocation = out[1];
|
||||
jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(nsEvent.getType()) :
|
||||
NSEvent.nsToJavaEventType(nsEvent.getType());
|
||||
|
||||
|
||||
if (isISOControl) {
|
||||
characterToSendWithTheEvent = checkedChar;
|
||||
} else {
|
||||
characterToSendWithTheEvent = mapNsCharsToCompatibleWithJava(characterToSendWithTheEvent);
|
||||
}
|
||||
|
||||
String stringWithChar = NSEvent.nsToJavaChar(characterToSendWithTheEvent, nsEvent.getModifierFlags(), spaceKeyTyped);
|
||||
characterToSendWithTheEvent = stringWithChar == null ? KeyEvent.CHAR_UNDEFINED : stringWithChar.charAt(0);
|
||||
|
||||
long when = System.currentTimeMillis();
|
||||
|
||||
if (jeventType == KeyEvent.KEY_PRESSED) {
|
||||
lastKeyPressCode = jkeyCode;
|
||||
}
|
||||
|
||||
eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers,
|
||||
jkeyCode, characterToSendWithTheEvent, jkeyLocation);
|
||||
|
||||
// Current browser may be sending input events, so don't
|
||||
// post the KEY_TYPED here.
|
||||
postsTyped &= true;
|
||||
|
||||
// That's the reaction on the PRESSED (not RELEASED) event as it comes to
|
||||
// appear in MacOSX.
|
||||
// Modifier keys (shift, etc) don't want to send TYPED events.
|
||||
// On the other hand we don't want to generate keyTyped events
|
||||
// for clipboard related shortcuts like Meta + [CVX]
|
||||
if (jeventType == KeyEvent.KEY_PRESSED && postsTyped &&
|
||||
(jmodifiers & KeyEvent.META_DOWN_MASK) == 0) {
|
||||
|
||||
char characterToSendWithTypedEvent = KeyEvent.CHAR_UNDEFINED;
|
||||
|
||||
if (nsEvent.getCharacters()!= null ) {
|
||||
characterToSendWithTypedEvent = mapNsCharsToCompatibleWithJava(checkedChar);
|
||||
stringWithChar = NSEvent.nsToJavaChar(characterToSendWithTypedEvent, nsEvent.getModifierFlags(), spaceKeyTyped);
|
||||
characterToSendWithTypedEvent = stringWithChar == null ? KeyEvent.CHAR_UNDEFINED : stringWithChar.charAt(0);
|
||||
}
|
||||
|
||||
boolean nonInputMethodsModifiersAreNotPressed = (jmodifiers &
|
||||
(InputEvent.META_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)
|
||||
) == 0;
|
||||
|
||||
if (nonInputMethodsModifiersAreNotPressed) {
|
||||
eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, when, jmodifiers,
|
||||
jkeyCode, characterToSendWithTypedEvent,
|
||||
KeyEvent.KEY_LOCATION_UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleInputEvent(String text) {
|
||||
if (text != null) {
|
||||
int index = 0, length = text.length();
|
||||
@@ -412,10 +197,9 @@ final class CPlatformResponder {
|
||||
|
||||
/**
|
||||
* Handles key events.
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
void handleKeyEvent(int eventType, int modifierFlags, String chars, String charsIgnoringModifiers,
|
||||
void handleKeyEvent(int eventType, int modifierFlags, String chars,
|
||||
String charsIgnoringModifiers, String charsIgnoringModifiersAndShift,
|
||||
short keyCode, boolean needsKeyTyped, boolean needsKeyReleased) {
|
||||
boolean isFlagsChangedEvent =
|
||||
isNpapiCallback ? (eventType == CocoaConstants.NPCocoaEventFlagsChanged) :
|
||||
@@ -425,6 +209,9 @@ final class CPlatformResponder {
|
||||
int jkeyCode = KeyEvent.VK_UNDEFINED;
|
||||
int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN;
|
||||
boolean postsTyped = false;
|
||||
boolean spaceKeyTyped = false;
|
||||
|
||||
int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags);
|
||||
|
||||
char testChar = KeyEvent.CHAR_UNDEFINED;
|
||||
boolean isDeadChar = (chars!= null && chars.length() == 0);
|
||||
@@ -441,12 +228,26 @@ final class CPlatformResponder {
|
||||
} else {
|
||||
if (chars != null && chars.length() > 0) {
|
||||
testChar = chars.charAt(0);
|
||||
|
||||
//Check if String chars contains SPACE character.
|
||||
if (chars.trim().isEmpty()) {
|
||||
spaceKeyTyped = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for JBR-2981
|
||||
int metaAltCtrlMods = KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK;
|
||||
boolean metaAltCtrlAreNotPressed = (jmodifiers & metaAltCtrlMods) == 0;
|
||||
boolean useShiftedCharacter = ((jmodifiers & KeyEvent.SHIFT_DOWN_MASK) == KeyEvent.SHIFT_DOWN_MASK) && metaAltCtrlAreNotPressed;
|
||||
|
||||
char testCharIgnoringModifiers = charsIgnoringModifiers != null && charsIgnoringModifiers.length() > 0 ?
|
||||
charsIgnoringModifiers.charAt(0) : KeyEvent.CHAR_UNDEFINED;
|
||||
if (!useShiftedCharacter && charsIgnoringModifiersAndShift != null && charsIgnoringModifiersAndShift.length() > 0) {
|
||||
testCharIgnoringModifiers = charsIgnoringModifiersAndShift.charAt(0);
|
||||
}
|
||||
|
||||
int[] in = new int[] {testCharIgnoringModifiers, isDeadChar ? 1 : 0, modifierFlags, keyCode, /*useNationalLayouts*/ 0};
|
||||
int useNationalLayouts = (KeyEventProcessing.useNationalLayouts && !isCyrillicKeyboardLayout()) ? 1 : 0;
|
||||
int[] in = new int[] {testCharIgnoringModifiers, isDeadChar ? 1 : 0, modifierFlags, keyCode, useNationalLayouts};
|
||||
int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar]
|
||||
|
||||
postsTyped = NSEvent.nsToJavaKeyInfo(in, out);
|
||||
@@ -480,7 +281,7 @@ final class CPlatformResponder {
|
||||
NSEvent.nsToJavaEventType(eventType);
|
||||
}
|
||||
|
||||
char javaChar = NSEvent.nsToJavaCharOld(testChar, modifierFlags);
|
||||
char javaChar = NSEvent.nsToJavaChar(testChar, modifierFlags, spaceKeyTyped);
|
||||
// Some keys may generate a KEY_TYPED, but we can't determine
|
||||
// what that character is. That's likely a bug, but for now we
|
||||
// just check for CHAR_UNDEFINED.
|
||||
@@ -488,8 +289,6 @@ final class CPlatformResponder {
|
||||
postsTyped = false;
|
||||
}
|
||||
|
||||
|
||||
int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags);
|
||||
long when = System.currentTimeMillis();
|
||||
|
||||
if (jeventType == KeyEvent.KEY_PRESSED) {
|
||||
|
||||
@@ -220,8 +220,10 @@ public class CPlatformView extends CFRetainedResource {
|
||||
}
|
||||
}
|
||||
|
||||
private void deliverKeyEvent(NSEvent nsEvent) {
|
||||
responder.handleKeyEvent(nsEvent);
|
||||
private void deliverKeyEvent(NSEvent event) {
|
||||
responder.handleKeyEvent(event.getType(), event.getModifierFlags(), event.getCharacters(),
|
||||
event.getCharactersIgnoringModifiers(), event.getCharactersIgnoringModifiersAndShift(),
|
||||
event.getKeyCode(), true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -298,8 +298,7 @@ final class NSEvent {
|
||||
* There is a small number of NS characters that need to be converted
|
||||
* into other characters before we pass them to AWT.
|
||||
*/
|
||||
static native String nsToJavaChar(char nsChar, int modifierFlags, boolean spaceKeyTyped);
|
||||
static native char nsToJavaCharOld(char nsChar, int modifierFlags);
|
||||
static native char nsToJavaChar(char nsChar, int modifierFlags, boolean spaceKeyTyped);
|
||||
|
||||
static boolean isPopupTrigger(int jmodifiers) {
|
||||
final boolean isRightButtonDown = ((jmodifiers & InputEvent.BUTTON3_DOWN_MASK) != 0);
|
||||
|
||||
@@ -222,6 +222,7 @@ struct CharToVKEntry {
|
||||
static const struct CharToVKEntry charToDeadVKTable[] = {
|
||||
{0x0060, java_awt_event_KeyEvent_VK_DEAD_GRAVE},
|
||||
{0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
|
||||
{0xFFFF, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
|
||||
{0x0384, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, // Unicode "GREEK TONOS" -- Greek keyboard, semicolon key
|
||||
{0x005E, java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
|
||||
{0x007E, java_awt_event_KeyEvent_VK_DEAD_TILDE},
|
||||
@@ -887,42 +888,20 @@ JNF_COCOA_ENTER(env);
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_NSEvent
|
||||
* Method: nsToJavaChar
|
||||
* Signature: (CI)Ljava/lang/String
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_sun_lwawt_macosx_NSEvent_nsToJavaChar
|
||||
(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags, jboolean spaceKeyTyped)
|
||||
{
|
||||
jstring charAsString = NULL;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
NSString * nsStr = [NSString stringWithFormat: @"%C", nsChar];
|
||||
charAsString = JNFNSToJavaString(env, nsStr);
|
||||
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return charAsString;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_NSEvent
|
||||
* Method: nsToJavaChar
|
||||
* Signature: (CI)C
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_lwawt_macosx_NSEvent_nsToJavaCharOld
|
||||
(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags)
|
||||
Java_sun_lwawt_macosx_NSEvent_nsToJavaChar
|
||||
(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags, jboolean spaceKeyTyped)
|
||||
{
|
||||
jchar javaChar = 0;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
javaChar = NsCharToJavaChar(nsChar, modifierFlags, false);
|
||||
javaChar = NsCharToJavaChar(nsChar, modifierFlags, spaceKeyTyped);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
|
||||
@@ -374,6 +374,21 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, N
|
||||
if (![self hasMarkedText] && !fInPressAndHold) {
|
||||
[self deliverJavaKeyEventHelper: event];
|
||||
}
|
||||
// Workaround for 8020209: special case for "Cmd =" and "Cmd ."
|
||||
// because Cocoa calls performKeyEquivalent twice for these keystrokes
|
||||
NSUInteger modFlags = [event modifierFlags] &
|
||||
(NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask | NSControlKeyMask);
|
||||
if (modFlags == NSCommandKeyMask) {
|
||||
NSString *eventChars = [event charactersIgnoringModifiers];
|
||||
if ([eventChars length] == 1) {
|
||||
unichar ch = [eventChars characterAtIndex:0];
|
||||
if (ch == '=' || ch == '.' ||
|
||||
ch == 0x044E) { // small cyrillic u
|
||||
[[NSApp mainMenu] performKeyEquivalent: event];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSUInteger deviceIndependentModifierFlagsMask =
|
||||
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
||||
@@ -507,10 +522,10 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, N
|
||||
|
||||
const UCKeyboardLayout *keyboardLayout = (UCKeyboardLayout*)CFDataGetBytePtr(keyLayoutPtr);
|
||||
|
||||
UInt32 isDeadKeyPressed;
|
||||
UInt32 isDeadKeyPressed = 0;
|
||||
UInt32 lengthOfBuffer = 8;
|
||||
UniChar stringWithChars[lengthOfBuffer];
|
||||
UniCharCount actualLength;
|
||||
UniCharCount actualLength = 0;
|
||||
|
||||
OSStatus status = UCKeyTranslate(
|
||||
keyboardLayout,
|
||||
@@ -844,7 +859,7 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, N
|
||||
{
|
||||
id focused = [self accessibilityFocusedUIElement];
|
||||
if (![focused respondsToSelector:@selector(accessibilitySelectedText)]) return nil;
|
||||
return [focused accessibilitySelectedTextAttribute];
|
||||
return [focused accessibilitySelectedText];
|
||||
}
|
||||
|
||||
// same as above, but converts to RTFD
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#import "JavaOutlineRowAccessibility.h"
|
||||
#import "JavaStaticTextAccessibility.h"
|
||||
#import "JavaNavigableTextAccessibility.h"
|
||||
#import "JavaScrollAreaAccessibility.h"
|
||||
#import "JavaTabGroupAccessibility.h"
|
||||
#import "JavaComboBoxAccessibility.h"
|
||||
#import "JavaComponentAccessibility.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import "AWTView.h"
|
||||
@@ -371,9 +374,9 @@ static jobject sAccessibilityClass = NULL;
|
||||
} else if ([parent isKindOfClass:[JavaOutlineAccessibility class]]) {
|
||||
newChild = [JavaOutlineRowAccessibility alloc];
|
||||
} else if ([javaRole isEqualToString:@"pagetablist"]) {
|
||||
newChild = [TabGroupAccessibility alloc];
|
||||
newChild = [JavaTabGroupAccessibility alloc];
|
||||
} else if ([javaRole isEqualToString:@"scrollpane"]) {
|
||||
newChild = [ScrollAreaAccessibility alloc];
|
||||
newChild = [JavaScrollAreaAccessibility alloc];
|
||||
} else {
|
||||
NSString *nsRole = [sRoles objectForKey:javaRole];
|
||||
if ([nsRole isEqualToString:NSAccessibilityStaticTextRole]) {
|
||||
@@ -386,6 +389,8 @@ static jobject sAccessibilityClass = NULL;
|
||||
newChild = [JavaTableAccessibility alloc];
|
||||
} else if ([nsRole isEqualToString:NSAccessibilityOutlineRole]) {
|
||||
newChild = [JavaOutlineAccessibility alloc];
|
||||
} else if ([nsRole isEqualToString:NSAccessibilityComboBoxRole]) {
|
||||
newChild = [JavaComboBoxAccessibility alloc];
|
||||
} else {
|
||||
newChild = [JavaComponentAccessibility alloc];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaElementAccessibility.h"
|
||||
|
||||
@interface JavaComboBoxAccessibility : JavaElementAccessibility
|
||||
|
||||
@property(readonly) NSString *accessibleSelectedText;
|
||||
|
||||
- (void)accessibleShowMenu;
|
||||
|
||||
@end
|
||||
|
||||
@interface PlatformAxComboBox : PlatformAxElement
|
||||
@end
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaComboBoxAccessibility.h"
|
||||
#import "JavaAccessibilityAction.h"
|
||||
#import "JavaAccessibilityUtilities.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
|
||||
|
||||
static const char* ACCESSIBLE_JCOMBOBOX_NAME = "javax.swing.JComboBox$AccessibleJComboBox";
|
||||
|
||||
@implementation JavaComboBoxAccessibility
|
||||
|
||||
- (NSString *)getPlatformAxElementClassName {
|
||||
return @"PlatformAxComboBox";
|
||||
}
|
||||
|
||||
- (NSString *)accessibleSelectedText {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
JNFClassInfo clsInfo;
|
||||
clsInfo.name = ACCESSIBLE_JCOMBOBOX_NAME;
|
||||
clsInfo.cls = (*env)->GetObjectClass(env, [self axContextWithEnv:env]);
|
||||
JNF_MEMBER_CACHE(jm_getAccessibleSelection, clsInfo, "getAccessibleSelection", "(I)Ljavax/accessibility/Accessible;");
|
||||
jobject axSelectedChild = JNFCallObjectMethod(env, [self axContextWithEnv:env], jm_getAccessibleSelection, 0);
|
||||
if (axSelectedChild == NULL) {
|
||||
return nil;
|
||||
}
|
||||
jobject childName = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, axSelectedChild, fComponent);
|
||||
if (childName == NULL) {
|
||||
(*env)->DeleteLocalRef(env, axSelectedChild);
|
||||
return nil;
|
||||
}
|
||||
NSString *selectedText = JNFObjectToString(env, childName);
|
||||
(*env)->DeleteLocalRef(env, axSelectedChild);
|
||||
(*env)->DeleteLocalRef(env, childName);
|
||||
return selectedText;
|
||||
}
|
||||
|
||||
- (void)accessibleShowMenu {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getAccessibleAction, sjc_CAccessibility, "getAccessibleAction", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleAction;");
|
||||
|
||||
// On MacOSX, text doesn't have actions, in java it does.
|
||||
// cmcnote: NOT TRUE - Editable text has AXShowMenu. Textfields have AXConfirm. Static text has no actions.
|
||||
jobject axAction = JNFCallStaticObjectMethod(env, jm_getAccessibleAction, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (axAction != NULL) {
|
||||
//+++gdb NOTE: In MacOSX, there is just a single Action, not multiple. In java,
|
||||
// the first one seems to be the most basic, so this will be used.
|
||||
// cmcnote: NOT TRUE - Sometimes there are multiple actions, eg sliders have AXDecrement AND AXIncrement (radr://3893192)
|
||||
JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:0 withComponent:fComponent];
|
||||
[action perform];
|
||||
[action release];
|
||||
(*env)->DeleteLocalRef(env, axAction);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlatformAxComboBox
|
||||
|
||||
- (id)accessibilityValue {
|
||||
return [(JavaComboBoxAccessibility *)[self javaBase] accessibleSelectedText];
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformPress {
|
||||
[(JavaComboBoxAccessibility *)[self javaBase] accessibleShowMenu];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isAccessibilityEnabled {
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -104,44 +104,3 @@
|
||||
- (id)accessibilityFocusedUIElement;
|
||||
|
||||
@end
|
||||
|
||||
@interface TabGroupAccessibility : JavaComponentAccessibility {
|
||||
NSInteger _numTabs;
|
||||
}
|
||||
|
||||
- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
|
||||
- (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
|
||||
- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
|
||||
- (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env;
|
||||
|
||||
- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
|
||||
- (NSArray *)accessibilityChildrenAttribute;
|
||||
- (id) accessibilityTabsAttribute;
|
||||
- (BOOL)accessibilityIsTabsAttributeSettable;
|
||||
- (NSArray *)accessibilityContentsAttribute;
|
||||
- (BOOL)accessibilityIsContentsAttributeSettable;
|
||||
- (id) accessibilityValueAttribute;
|
||||
|
||||
@end
|
||||
|
||||
@interface TabGroupControlAccessibility : JavaComponentAccessibility {
|
||||
jobject fTabGroupAxContext;
|
||||
}
|
||||
- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole;
|
||||
- (jobject)tabGroup;
|
||||
- (void)getActionsWithEnv:(JNIEnv *)env;
|
||||
|
||||
- (id)accessibilityValueAttribute;
|
||||
@end
|
||||
|
||||
@interface ScrollAreaAccessibility : JavaComponentAccessibility {
|
||||
|
||||
}
|
||||
- (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env;
|
||||
- (NSArray *)accessibilityContentsAttribute;
|
||||
- (BOOL)accessibilityIsContentsAttributeSettable;
|
||||
- (id)accessibilityVerticalScrollBarAttribute;
|
||||
- (BOOL)accessibilityIsVerticalScrollBarAttributeSettable;
|
||||
- (id)accessibilityHorizontalScrollBarAttribute;
|
||||
- (BOOL)accessibilityIsHorizontalScrollBarAttributeSettable;
|
||||
@end
|
||||
|
||||
@@ -949,390 +949,3 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TabGroupAccessibility
|
||||
|
||||
- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole
|
||||
{
|
||||
self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
|
||||
if (self) {
|
||||
_numTabs = -1; //flag for uninitialized numTabs
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
|
||||
{
|
||||
NSMutableArray *names = (NSMutableArray *)[super initializeAttributeNamesWithEnv:env];
|
||||
|
||||
[names addObject:NSAccessibilityTabsAttribute];
|
||||
[names addObject:NSAccessibilityContentsAttribute];
|
||||
[names addObject:NSAccessibilityValueAttribute];
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext
|
||||
{
|
||||
NSArray *tabs = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
|
||||
// Looking at the JTabbedPane sources, there is always one AccessibleSelection.
|
||||
jobject selAccessible = getAxContextSelection(env, axContext, 0, fComponent);
|
||||
if (selAccessible == NULL) return nil;
|
||||
|
||||
// Go through the tabs and find selAccessible
|
||||
_numTabs = [tabs count];
|
||||
JavaComponentAccessibility *aTab;
|
||||
NSInteger i;
|
||||
for (i = 0; i < _numTabs; i++) {
|
||||
aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i];
|
||||
if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) {
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
return aTab;
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
|
||||
{
|
||||
jobjectArray jtabsAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if(jtabsAndRoles == NULL) return nil;
|
||||
|
||||
jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles);
|
||||
if (arrayLen == 0) {
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return nil;
|
||||
}
|
||||
NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)];
|
||||
|
||||
// all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs
|
||||
jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1.
|
||||
if (jtabJavaRole == NULL) {
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return nil;
|
||||
}
|
||||
jobject jkey = JNFGetObjectField(env, jtabJavaRole, sjf_key);
|
||||
NSString *tabJavaRole = JNFJavaToNSString(env, jkey);
|
||||
(*env)->DeleteLocalRef(env, jkey);
|
||||
|
||||
NSInteger i;
|
||||
NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly
|
||||
for(i = 0; i < arrayLen; i+=2) {
|
||||
jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i);
|
||||
JavaComponentAccessibility *tab = [[[TabGroupControlAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease];
|
||||
(*env)->DeleteLocalRef(env, jtab);
|
||||
[tabs addObject:tab];
|
||||
tabIndex++;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
|
||||
{
|
||||
// Contents are the children of the selected tab.
|
||||
id currentTab = [self currentTabWithEnv:env withAxContext:axContext];
|
||||
if (currentTab == nil) return nil;
|
||||
|
||||
NSArray *contents = [JavaComponentAccessibility childrenOfParent:currentTab withEnv:env withChildrenCode:whichTabs allowIgnored:allowIgnored];
|
||||
if ([contents count] <= 0) return nil;
|
||||
return contents;
|
||||
}
|
||||
|
||||
- (id) accessibilityTabsAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
id tabs = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsTabsAttributeSettable
|
||||
{
|
||||
return NO; //cmcnote: not sure.
|
||||
}
|
||||
|
||||
- (NSInteger)numTabs
|
||||
{
|
||||
if (_numTabs == -1) {
|
||||
_numTabs = [[self accessibilityTabsAttribute] count];
|
||||
}
|
||||
return _numTabs;
|
||||
}
|
||||
|
||||
- (NSArray *) accessibilityContentsAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return cont;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsContentsAttributeSettable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
// axValue is the currently selected tab
|
||||
-(id) accessibilityValueAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
id val = [self currentTabWithEnv:env withAxContext:axContext];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return val;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsValueAttributeSettable
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)accessibilitySetValueAttribute:(id)value //cmcnote: not certain this is ever actually called. investigate.
|
||||
{
|
||||
// set the current tab
|
||||
NSNumber *number = (NSNumber *)value;
|
||||
if (![number boolValue]) return;
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
setAxContextSelection(env, axContext, fIndex, fComponent);
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilityChildrenAttribute
|
||||
{
|
||||
//children = AXTabs + AXContents
|
||||
NSArray *tabs = [self accessibilityTabsAttribute];
|
||||
NSArray *contents = [self accessibilityContentsAttribute];
|
||||
|
||||
NSMutableArray *children = [NSMutableArray arrayWithCapacity:[tabs count] + [contents count]];
|
||||
[children addObjectsFromArray:tabs];
|
||||
[children addObjectsFromArray:contents];
|
||||
|
||||
return (NSArray *)children;
|
||||
}
|
||||
|
||||
// Without this optimization accessibilityChildrenAttribute is called in order to get the entire array of children.
|
||||
// See similar optimization in JavaComponentAccessibility. We have to extend the base implementation here, since
|
||||
// children of tabs are AXTabs + AXContents
|
||||
- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount {
|
||||
NSArray *result = nil;
|
||||
if ( (maxCount == 1) && [attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
// Children codes for ALL, SELECTED, VISIBLE are <0. If the code is >=0, we treat it as an index to a single child
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
|
||||
//children = AXTabs + AXContents
|
||||
NSArray *children = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:index allowIgnored:NO]; // first look at the tabs
|
||||
if ([children count] > 0) {
|
||||
result = children;
|
||||
} else {
|
||||
children= [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:(index-[self numTabs]) allowIgnored:NO];
|
||||
if ([children count] > 0) {
|
||||
result = children;
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
} else {
|
||||
result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component);
|
||||
|
||||
@implementation TabGroupControlAccessibility
|
||||
|
||||
- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole
|
||||
{
|
||||
self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
|
||||
if (self) {
|
||||
if (tabGroup != NULL) {
|
||||
fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroup);
|
||||
} else {
|
||||
fTabGroupAxContext = NULL;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
|
||||
if (fTabGroupAxContext != NULL) {
|
||||
JNFDeleteWeakGlobalRef(env, fTabGroupAxContext);
|
||||
fTabGroupAxContext = NULL;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)accessibilityValueAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent);
|
||||
|
||||
// Returns the current selection of the page tab list
|
||||
id val = [NSNumber numberWithBool:ObjectEquals(env, axContext, selAccessible, fComponent)];
|
||||
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return val;
|
||||
}
|
||||
|
||||
- (void)getActionsWithEnv:(JNIEnv *)env
|
||||
{
|
||||
TabGroupAction *action = [[TabGroupAction alloc] initWithEnv:env withTabGroup:[self tabGroup] withIndex:fIndex withComponent:fComponent];
|
||||
[fActions setObject:action forKey:NSAccessibilityPressAction];
|
||||
[action release];
|
||||
}
|
||||
|
||||
- (jobject)tabGroup
|
||||
{
|
||||
if (fTabGroupAxContext == NULL) {
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env];
|
||||
fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroupAxContext);
|
||||
(*env)->DeleteLocalRef(env, tabGroupAxContext);
|
||||
}
|
||||
return fTabGroupAxContext;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ScrollAreaAccessibility
|
||||
|
||||
- (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
|
||||
{
|
||||
NSMutableArray *names = (NSMutableArray *)[super initializeAttributeNamesWithEnv:env];
|
||||
|
||||
[names addObject:NSAccessibilityHorizontalScrollBarAttribute];
|
||||
[names addObject:NSAccessibilityVerticalScrollBarAttribute];
|
||||
[names addObject:NSAccessibilityContentsAttribute];
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
- (id)accessibilityHorizontalScrollBarAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
if ([children count] <= 0) return nil;
|
||||
|
||||
// The scroll bars are in the children.
|
||||
NSObject *aElement;
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
while ((aElement = [enumerator nextObject])) {
|
||||
if ([aElement respondsToSelector:@selector(accessibilityRoleAttribute)]) {
|
||||
if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
jobject elementAxContext = [((NSObject <JavaBaseProvider> *)aElement).javaBase axContextWithEnv:env];
|
||||
if (isHorizontal(env, elementAxContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
return aElement;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsHorizontalScrollBarAttributeSettable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)accessibilityVerticalScrollBarAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
if ([children count] <= 0) return nil;
|
||||
|
||||
// The scroll bars are in the children.
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
JavaComponentAccessibility *aElement;
|
||||
while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) {
|
||||
if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
jobject elementAxContext = [aElement axContextWithEnv:env];
|
||||
if (isVertical(env, elementAxContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
return aElement;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsVerticalScrollBarAttributeSettable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilityContentsAttribute
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
|
||||
if ([children count] <= 0) return nil;
|
||||
NSArray *contents = [NSMutableArray arrayWithCapacity:[children count]];
|
||||
|
||||
// The scroll bars are in the children. children less the scroll bars is the contents
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
NSObject *aElement;
|
||||
while ((aElement = [enumerator nextObject])) {
|
||||
if ([aElement respondsToSelector:@selector(accessibilityRoleAttribute)]) {
|
||||
if (![[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
// no scroll bars in contents
|
||||
[(NSMutableArray *) contents addObject:aElement];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsContentsAttributeSettable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* Returns Object.equals for the two items
|
||||
* This may use LWCToolkit.invokeAndWait(); don't call while holding fLock
|
||||
* and try to pass a component so the event happens on the correct thread.
|
||||
*/
|
||||
static JNF_CLASS_CACHE(sjc_Object, "java/lang/Object");
|
||||
static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component)
|
||||
{
|
||||
static JNF_MEMBER_CACHE(jm_equals, sjc_Object, "equals", "(Ljava/lang/Object;)Z");
|
||||
|
||||
if ((a == NULL) && (b == NULL)) return YES;
|
||||
if ((a == NULL) || (b == NULL)) return NO;
|
||||
|
||||
if (pthread_main_np() != 0) {
|
||||
// If we are on the AppKit thread
|
||||
static JNF_CLASS_CACHE(sjc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_doEquals, sjc_LWCToolkit, "doEquals", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/awt/Component;)Z");
|
||||
return JNFCallStaticBooleanMethod(env, jm_doEquals, a, b, component); // AWT_THREADING Safe (AWTRunLoopMode)
|
||||
}
|
||||
|
||||
return JNFCallBooleanMethod(env, a, jm_equals, b); // AWT_THREADING Safe (!appKit)
|
||||
}
|
||||
|
||||
@@ -130,4 +130,8 @@ static void RaiseMustOverrideException(NSString *method)
|
||||
return [[self javaBase] accessibilityIndexOfChild:child];
|
||||
}
|
||||
|
||||
- (NSAccessibilityRole)accessibilityRole {
|
||||
return [sRoles objectForKey:[[self javaBase] javaRole]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaElementAccessibility.h"
|
||||
|
||||
@interface JavaScrollAreaAccessibility : JavaElementAccessibility
|
||||
|
||||
@property(readonly) NSArray *accessibleContents;
|
||||
@property(readonly) id accessibleVerticalScrollBar;
|
||||
@property(readonly) id accessibleHorizontalScrollBar;
|
||||
|
||||
@end
|
||||
|
||||
@interface PlatformAxScrollArea : PlatformAxElement
|
||||
@end
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaScrollAreaAccessibility.h"
|
||||
#import "JavaAccessibilityUtilities.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
#import "JavaComponentAccessibility.h"
|
||||
|
||||
@implementation JavaScrollAreaAccessibility
|
||||
|
||||
- (NSString *)getPlatformAxElementClassName {
|
||||
return @"PlatformAxScrollArea";
|
||||
}
|
||||
|
||||
- (NSArray *)accessibleContents {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
NSArray *children = [JavaBaseAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
|
||||
if ([children count] <= 0) return nil;
|
||||
NSArray *contents = [NSMutableArray arrayWithCapacity:[children count]];
|
||||
|
||||
// The scroll bars are in the children. children less the scroll bars is the contents
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
id aElement;
|
||||
while ((aElement = [enumerator nextObject])) {
|
||||
NSString *nsRole = [aElement isKindOfClass:[JavaComponentAccessibility class]] ? [aElement accessibilityRoleAttribute] : [aElement accessibilityRole]; // todo: Remove this solution when JavaComponentAccessibility is removed
|
||||
if (![nsRole isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
// no scroll bars in contents
|
||||
[(NSMutableArray *) contents addObject:aElement];
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
- (id)accessibleVerticalScrollBar {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
NSArray *children = [JavaBaseAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
if ([children count] <= 0) return nil;
|
||||
|
||||
// The scroll bars are in the children.
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
id aElement;
|
||||
while ((aElement = (PlatformAxElement *)[enumerator nextObject])) {
|
||||
NSString *nsRole = [aElement isKindOfClass:[JavaComponentAccessibility class]] ? [aElement accessibilityRoleAttribute] : [aElement accessibilityRole]; // todo: Remove this solution when JavaComponentAccessibility is removed
|
||||
if ([nsRole isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
jobject elementAxContext = [[aElement javaBase] axContextWithEnv:env];
|
||||
if (isVertical(env, elementAxContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
return aElement;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)accessibleHorizontalScrollBar {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
NSArray *children = [JavaBaseAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
if ([children count] <= 0) return nil;
|
||||
|
||||
// The scroll bars are in the children.
|
||||
id aElement;
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
while ((aElement = [enumerator nextObject])) {
|
||||
NSString *nsRole = [aElement isKindOfClass:[JavaComponentAccessibility class]] ? [aElement accessibilityRoleAttribute] : [aElement accessibilityRole]; // todo: Remove this solution when JavaComponentAccessibility is removed
|
||||
if ([nsRole isEqualToString:NSAccessibilityScrollBarRole]) {
|
||||
jobject elementAxContext = [[aElement javaBase] axContextWithEnv:env];
|
||||
if (isHorizontal(env, elementAxContext, fComponent)) {
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
return aElement;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, elementAxContext);
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlatformAxScrollArea
|
||||
|
||||
- (NSArray *)accessibilityContents {
|
||||
return [(JavaScrollAreaAccessibility *)[self javaBase] accessibleContents];
|
||||
}
|
||||
|
||||
- (id)accessibilityVerticalScrollBar {
|
||||
return [(JavaScrollAreaAccessibility *)[self javaBase] accessibleVerticalScrollBar];
|
||||
}
|
||||
|
||||
- (id)accessibilityHorizontalScrollBar {
|
||||
return [(JavaScrollAreaAccessibility *)[self javaBase] accessibleHorizontalScrollBar];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaElementAccessibility.h"
|
||||
|
||||
@interface JavaTabButtonAccessibility : JavaElementAccessibility {
|
||||
jobject fTabGroupAxContext;
|
||||
}
|
||||
|
||||
// from TabGroup controller
|
||||
- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole;
|
||||
|
||||
@property(readonly) jobject tabGroup;
|
||||
@property(readonly) id accessibleValue;
|
||||
- (void)performPressAction;
|
||||
|
||||
@end
|
||||
|
||||
@interface PlatformAxTabButton : PlatformAxElement
|
||||
@end
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaTabButtonAccessibility.h"
|
||||
#import "JavaAccessibilityAction.h"
|
||||
#import "JavaAccessibilityUtilities.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
static BOOL javaObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component);
|
||||
|
||||
@implementation JavaTabButtonAccessibility
|
||||
|
||||
- (NSString *)getPlatformAxElementClassName {
|
||||
return @"PlatformAxTabButton";
|
||||
}
|
||||
|
||||
- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole {
|
||||
self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
|
||||
if (self) {
|
||||
if (tabGroup != NULL) {
|
||||
fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroup);
|
||||
} else {
|
||||
fTabGroupAxContext = NULL;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (jobject)tabGroup {
|
||||
if (fTabGroupAxContext == NULL) {
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
jobject tabGroupAxContext = [(JavaBaseAccessibility *)[self parent] axContextWithEnv:env];
|
||||
fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroupAxContext);
|
||||
(*env)->DeleteLocalRef(env, tabGroupAxContext);
|
||||
}
|
||||
return fTabGroupAxContext;
|
||||
}
|
||||
|
||||
- (id)accessibleValue {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent);
|
||||
|
||||
// Returns the current selection of the page tab list
|
||||
id val = [NSNumber numberWithBool:javaObjectEquals(env, axContext, selAccessible, fComponent)];
|
||||
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return val;
|
||||
}
|
||||
|
||||
- (void)performPressAction {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
TabGroupAction *action = [[TabGroupAction alloc] initWithEnv:env withTabGroup:[self tabGroup] withIndex:fIndex withComponent:fComponent];
|
||||
[action perform];
|
||||
[action release];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlatformAxTabButton
|
||||
|
||||
- (NSAccessibilitySubrole)accessibilitySubrole {
|
||||
return NSAccessibilityTabButtonSubrole;
|
||||
}
|
||||
|
||||
- (id)accessibilityValue {
|
||||
return [(JavaTabButtonAccessibility *)[self javaBase] accessibleValue];
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformPress {
|
||||
[(JavaTabButtonAccessibility *)[self javaBase] performPressAction];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static JNF_CLASS_CACHE(sjc_Object, "java/lang/Object");
|
||||
static BOOL javaObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component) {
|
||||
static JNF_MEMBER_CACHE(jm_equals, sjc_Object, "equals", "(Ljava/lang/Object;)Z");
|
||||
|
||||
if ((a == NULL) && (b == NULL)) return YES;
|
||||
if ((a == NULL) || (b == NULL)) return NO;
|
||||
|
||||
if (pthread_main_np() != 0) {
|
||||
// If we are on the AppKit thread
|
||||
static JNF_CLASS_CACHE(sjc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_doEquals, sjc_LWCToolkit, "doEquals", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/awt/Component;)Z");
|
||||
return JNFCallStaticBooleanMethod(env, jm_doEquals, a, b, component); // AWT_THREADING Safe (AWTRunLoopMode)
|
||||
}
|
||||
|
||||
return JNFCallBooleanMethod(env, a, jm_equals, b); // AWT_THREADING Safe (!appKit)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaElementAccessibility.h"
|
||||
|
||||
@interface JavaTabGroupAccessibility : JavaElementAccessibility {
|
||||
NSInteger _numTabs;
|
||||
}
|
||||
|
||||
- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
|
||||
- (NSArray *)tabButtonsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
|
||||
- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
|
||||
|
||||
@property(readonly) NSArray *accessibleTabs;
|
||||
@property(readonly) NSArray *accessibleContents;
|
||||
@property(readonly) id accessibleValue;
|
||||
@property(readonly) NSInteger numTabs;
|
||||
|
||||
@end
|
||||
|
||||
@interface PlatformAxTabGroup : PlatformAxElement
|
||||
@end
|
||||
@@ -0,0 +1,179 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#import "JavaTabGroupAccessibility.h"
|
||||
#import "JavaTabButtonAccessibility.h"
|
||||
#import "JavaAccessibilityUtilities.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;");
|
||||
|
||||
@implementation JavaTabGroupAccessibility
|
||||
|
||||
- (NSString *)getPlatformAxElementClassName {
|
||||
return @"PlatformAxTabGroup";
|
||||
}
|
||||
|
||||
- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext {
|
||||
NSArray *tabs = [self tabButtonsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
|
||||
// Looking at the JTabbedPane sources, there is always one AccessibleSelection.
|
||||
jobject selAccessible = getAxContextSelection(env, axContext, 0, fComponent);
|
||||
if (selAccessible == NULL) return nil;
|
||||
|
||||
// Go through the tabs and find selAccessible
|
||||
_numTabs = [tabs count];
|
||||
JavaBaseAccessibility *aTab;
|
||||
NSInteger i;
|
||||
for (i = 0; i < _numTabs; i++) {
|
||||
aTab = [(PlatformAxElement *)[tabs objectAtIndex:i] javaBase];
|
||||
if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) {
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
return [aTab platformAxElement];
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, selAccessible);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)tabButtonsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored {
|
||||
jobjectArray jtabsAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if(jtabsAndRoles == NULL) return nil;
|
||||
|
||||
jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles);
|
||||
if (arrayLen == 0) {
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return nil;
|
||||
}
|
||||
NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)];
|
||||
|
||||
// all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs
|
||||
jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1.
|
||||
if (jtabJavaRole == NULL) {
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return nil;
|
||||
}
|
||||
jobject jkey = JNFGetObjectField(env, jtabJavaRole, sjf_key);
|
||||
NSString *tabJavaRole = JNFJavaToNSString(env, jkey);
|
||||
(*env)->DeleteLocalRef(env, jkey);
|
||||
|
||||
NSInteger i;
|
||||
NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly
|
||||
for(i = 0; i < arrayLen; i+=2) {
|
||||
jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i);
|
||||
JavaBaseAccessibility *tab = [[[JavaTabButtonAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease];
|
||||
(*env)->DeleteLocalRef(env, jtab);
|
||||
[tabs addObject:[tab platformAxElement]];
|
||||
tabIndex++;
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, jtabsAndRoles);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored {
|
||||
// Contents are the children of the selected tab.
|
||||
PlatformAxElement *currentTab = [self currentTabWithEnv:env withAxContext:axContext];
|
||||
if (currentTab == nil) return nil;
|
||||
|
||||
NSArray *contents = [JavaBaseAccessibility childrenOfParent:[currentTab javaBase] withEnv:env withChildrenCode:whichTabs allowIgnored:allowIgnored];
|
||||
if ([contents count] <= 0) return nil;
|
||||
return contents;
|
||||
}
|
||||
|
||||
- (NSArray *)accessibleTabs {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
id tabs = [self tabButtonsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
- (NSArray *) accessibleContents {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return cont;
|
||||
}
|
||||
|
||||
-(id) accessibleValue {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
id val = [self currentTabWithEnv:env withAxContext:axContext];
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return val;
|
||||
}
|
||||
|
||||
- (NSInteger)numTabs {
|
||||
return _numTabs;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlatformAxTabGroup
|
||||
|
||||
- (NSArray *)accessibilityTabs {
|
||||
return [(JavaTabGroupAccessibility *)[self javaBase] accessibleTabs];
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilityContents {
|
||||
return [(JavaTabGroupAccessibility *)[self javaBase] accessibleContents];
|
||||
}
|
||||
|
||||
- (id)accessibilityValue {
|
||||
return [(JavaTabGroupAccessibility *)[self javaBase] accessibleValue];
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilityChildren {
|
||||
//children = AXTabs + AXContents
|
||||
NSArray *tabs = [self accessibilityTabs];
|
||||
NSArray *contents = [self accessibilityContents];
|
||||
|
||||
NSMutableArray *children = [NSMutableArray arrayWithCapacity:[tabs count] + [contents count]];
|
||||
[children addObjectsFromArray:tabs];
|
||||
[children addObjectsFromArray:contents];
|
||||
|
||||
return (NSArray *)children;
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilityArrayAttributeValues:(NSAccessibilityAttributeName)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount {
|
||||
NSArray *result = nil;
|
||||
if ( (maxCount == 1) && [attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
// Children codes for ALL, SELECTED, VISIBLE are <0. If the code is >=0, we treat it as an index to a single child
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [(JavaTabGroupAccessibility *)[self javaBase] axContextWithEnv:env];
|
||||
|
||||
//children = AXTabs + AXContents
|
||||
NSArray *children = [(JavaTabGroupAccessibility *)[self javaBase] tabButtonsWithEnv:env
|
||||
withTabGroupAxContext:axContext
|
||||
withTabCode:index
|
||||
allowIgnored:NO]; // first look at the tabs
|
||||
if ([children count] > 0) {
|
||||
result = children;
|
||||
} else {
|
||||
children= [(JavaTabGroupAccessibility *)[self javaBase] contentsWithEnv:env
|
||||
withTabGroupAxContext:axContext
|
||||
withTabCode:(index-[(JavaTabGroupAccessibility *)[self javaBase] numTabs])
|
||||
allowIgnored:NO];
|
||||
if ([children count] > 0) {
|
||||
result = children;
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
} else {
|
||||
result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)setAccessibilityValue:(id)accessibilityValue {
|
||||
NSNumber *number = (NSNumber *)accessibilityValue;
|
||||
if (![number boolValue]) return;
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
setAxContextSelection(env, axContext, [[self javaBase] index], [[self javaBase] component]);
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -57,6 +57,7 @@ static const char* ACCESSIBLE_JTABLE_NAME = "javax.swing.JTable$AccessibleJTable
|
||||
for (int i = 0; i < arrayLen; i++) {
|
||||
[nsArraySelectidRowNumbers addObject:[NSNumber numberWithInt:indexsis[i]]];
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, selectidRowNumbers);
|
||||
return [NSArray<NSNumber *> arrayWithArray:nsArraySelectidRowNumbers];
|
||||
}
|
||||
|
||||
@@ -76,18 +77,17 @@ static const char* ACCESSIBLE_JTABLE_NAME = "javax.swing.JTable$AccessibleJTable
|
||||
for (int i = 0; i < arrayLen; i++) {
|
||||
[nsArraySelectidColumnNumbers addObject:[NSNumber numberWithInt:indexsis[i]]];
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, selectidColumnNumbers);
|
||||
return [NSArray<NSNumber *> arrayWithArray:nsArraySelectidColumnNumbers];
|
||||
}
|
||||
|
||||
- (int)accessibleRowAtIndex:(int)index {
|
||||
printf("Пришёл индекс %d\n", index);
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
JNFClassInfo clsInfo;
|
||||
clsInfo.name = ACCESSIBLE_JTABLE_NAME;
|
||||
clsInfo.cls = (*env)->GetObjectClass(env, [self axContextWithEnv:env]);
|
||||
JNF_MEMBER_CACHE(jm_getAccessibleRowAtIndex, clsInfo, "getAccessibleRowAtIndex", "(I)I");
|
||||
jint rowAtIndex = JNFCallIntMethod(env, [self axContextWithEnv:env], jm_getAccessibleRowAtIndex, (jint)index);
|
||||
printf("Получен индекс %d\n", rowAtIndex);
|
||||
return (int)rowAtIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef JavaTableRowAccessibility_h
|
||||
#define JavaTableRowAccessibility_h
|
||||
|
||||
|
||||
#endif /* JavaTableRowAccessibility_h */
|
||||
#import "JavaElementAccessibility.h"
|
||||
|
||||
@interface JavaTableRowAccessibility : JavaElementAccessibility
|
||||
|
||||
@@ -12,7 +12,7 @@ public class KeyEventProcessing {
|
||||
@Native
|
||||
public final static boolean useNationalLayouts = "true".equals(
|
||||
Util.getProperty(useNationalLayoutsOption,
|
||||
FontUtilities.isMacOSX && !FontUtilities.isMacOSX_aarch64 ? "true" : "false"));
|
||||
FontUtilities.isMacOSX ? "true" : "false"));
|
||||
|
||||
// Used on windows to emulate latin OEM keys on cyrillic keyboards
|
||||
public final static String useLatinNonAlphaNumKeycodesOption = "com.sun.awt.useLatinNonAlphaNumKeycodes";
|
||||
|
||||
@@ -111,11 +111,12 @@ public class FontStrikeDesc {
|
||||
*/
|
||||
public static int getAAHintIntVal(Object aa, Font2D font2D, int ptSize) {
|
||||
|
||||
if (FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP))
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP)))
|
||||
{
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
@@ -153,11 +154,12 @@ public class FontStrikeDesc {
|
||||
FontRenderContext frc) {
|
||||
Object aa = frc.getAntiAliasingHint();
|
||||
|
||||
if (FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP))
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP)))
|
||||
{
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public final class FontUtilities {
|
||||
|
||||
public static boolean isMacOSX;
|
||||
public static boolean isMacOSX14;
|
||||
public static boolean isMacOSX16;
|
||||
public static boolean isMacOSX_aarch64;
|
||||
|
||||
public static boolean useJDKScaler;
|
||||
@@ -83,9 +84,10 @@ public final class FontUtilities {
|
||||
isMacOSX = osName.contains("OS X"); // TODO: MacOSX
|
||||
if (isMacOSX) {
|
||||
// os.version has values like 10.13.6, 10.14.6
|
||||
// If it is not positively recognised as 10.13 or less,
|
||||
// assume it means 10.14 or some later version.
|
||||
// If it is not positively recognised as 10.13 (10.15) or less,
|
||||
// assume it means 10.14 (10.16) or some later version.
|
||||
isMacOSX14 = true;
|
||||
isMacOSX16 = true;
|
||||
String version = System.getProperty("os.version", "");
|
||||
if (version.startsWith("10.")) {
|
||||
version = version.substring(3);
|
||||
@@ -96,6 +98,7 @@ public final class FontUtilities {
|
||||
try {
|
||||
int v = Integer.parseInt(version);
|
||||
isMacOSX14 = (v >= 14);
|
||||
isMacOSX16 = (v >= 16);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,8 +772,9 @@ public final class SunGraphics2D
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FontUtilities.isMacOSX14 &&
|
||||
(aahint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF))
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
aahint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF))
|
||||
{
|
||||
aahint = SunHints.INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
|
||||
@@ -456,7 +456,11 @@ public abstract class SurfaceData
|
||||
} else {
|
||||
solidTextRenderer = new SolidTextRenderer();
|
||||
}
|
||||
lcdTextRenderer = new LCDTextRenderer();
|
||||
if (FontUtilities.isMacOSX16) {
|
||||
lcdTextRenderer = aaTextRenderer;
|
||||
} else {
|
||||
lcdTextRenderer = new LCDTextRenderer();
|
||||
}
|
||||
|
||||
colorPipe = new AlphaColorPipe();
|
||||
// colorShape = colorPrimitives;
|
||||
|
||||
@@ -695,7 +695,7 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
|
||||
return (jlong) 0;
|
||||
}
|
||||
(*env)->GetDoubleArrayRegion(env, matrix, 0, 4, dmat);
|
||||
ptsz = euclidianDistance(dmat[2], dmat[3]); //i.e. y-size
|
||||
ptsz = euclidianDistance(dmat[0], dmat[1]); //i.e. x-size
|
||||
if (ptsz < 1.0) {
|
||||
//text can not be smaller than 1 point
|
||||
ptsz = 1.0;
|
||||
|
||||
53
test/jdk/jb/java/a11y/AccessibleJComboboxTest.java
Normal file
53
test/jdk/jb/java/a11y/AccessibleJComboboxTest.java
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary manual test for JBR-3241
|
||||
* @author Artem.Semenov@jetbrains.com
|
||||
* @run main/manual AccessibleJComboboxTest
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AccessibleJComboboxTest extends AccessibleComponentTest {
|
||||
|
||||
@java.lang.Override
|
||||
public CountDownLatch createCountDownLatch() {
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
void createCombobox() {
|
||||
INSTRUCTIONS = "INSTRUCTIONS:\n"
|
||||
+ "Check a11y of JCombobox.\n\n"
|
||||
+ "Turn screen reader on, and Tab to the combobox.\n\n"
|
||||
+ "If you can hear combobox selected item tab further and press PASS, otherwise press FAIL.";
|
||||
|
||||
JPanel frame = new JPanel();
|
||||
|
||||
String[] NAMES = {"One", "Two", "Three", "Four", "Five"};
|
||||
JComboBox<String> combo = new JComboBox<>(NAMES);
|
||||
|
||||
JLabel label = new JLabel("This is combobox:");
|
||||
label.setLabelFor(combo);
|
||||
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(label);
|
||||
frame.add(combo);
|
||||
exceptionString = "AccessibleJCombobox test failed!";
|
||||
super.createUI(frame, "AccessibleJComboboxTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AccessibleJComboboxTest test = new AccessibleJComboboxTest();
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createCombobox);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
test/jdk/jb/java/a11y/AccessibleJScrollPaneTest.java
Normal file
68
test/jdk/jb/java/a11y/AccessibleJScrollPaneTest.java
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary manual test for JBR-3239
|
||||
* @author Artem.Semenov@jetbrains.com
|
||||
* @run main/manual AccessibleJScrollPaneTest
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AccessibleJScrollPaneTest extends AccessibleComponentTest {
|
||||
|
||||
@java.lang.Override
|
||||
public CountDownLatch createCountDownLatch() {
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
void createScrollPane() {
|
||||
INSTRUCTIONS = "INSTRUCTIONS:\n"
|
||||
+ "Check a11y of JScrollPane in a simple Window.\n\n"
|
||||
+ "Turn screen reader on, and tab to the table.\n"
|
||||
+ "this table has 10 rows and 10 columns, few cells are invisible.\n\n"
|
||||
+ "On Windows press arrow buttons to move through the table.\n\n"
|
||||
+ "On MacOS, use up and down arrow buttons to move through the rows, use VoiceOver fast navigation to move through the columns.\n\n"
|
||||
+ "If you can hear table cells tab further and press PASS, otherwise press FAIL.\n";
|
||||
|
||||
final int n = 10;
|
||||
|
||||
String[][] data = new String[n][n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
data[i][j] = "Cell " + String.valueOf(i) + ":" + String.valueOf(j);
|
||||
}
|
||||
}
|
||||
String[] columnNames = new String[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
columnNames[i] = "Header " + String.valueOf(i);
|
||||
}
|
||||
|
||||
JTable table = new JTable(data, columnNames);
|
||||
table.setPreferredScrollableViewportSize(new Dimension(table.getPreferredScrollableViewportSize().width / 2, table.getRowHeight() * 5));
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new FlowLayout());
|
||||
JScrollPane scrollPane = new JScrollPane(table);
|
||||
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
panel.add(scrollPane);
|
||||
|
||||
exceptionString = "AccessibleJScrollPane test failed!";
|
||||
super.createUI(panel, "AccessibleJScrollTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AccessibleJScrollPaneTest test = new AccessibleJScrollPaneTest();
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createScrollPane);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
test/jdk/jb/java/a11y/AccessibleJTabbedPaneTest.java
Normal file
62
test/jdk/jb/java/a11y/AccessibleJTabbedPaneTest.java
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary manual test for JBR-3240
|
||||
* @author Artem.Semenov@jetbrains.com
|
||||
* @run main/manual AccessibleJTabbedPaneTest
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AccessibleJTabbedPaneTest extends AccessibleComponentTest {
|
||||
|
||||
@Override
|
||||
public CountDownLatch createCountDownLatch() {
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
void createTabPane() {
|
||||
INSTRUCTIONS = "INSTRUCTIONS:\n"
|
||||
+ "Check a11y of JTabbedPane in a simple Window.\n\n"
|
||||
+ "Turn screen reader on, and tab to the JTabbedPane.\n"
|
||||
+ "Use up and down arrow buttons to move through the tabs.\n\n"
|
||||
+ "If you can hear selected tab names tab further and press PASS, otherwise press FAIL.\n";
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
JPanel panel1 = new JPanel();
|
||||
String[] names = {"One", "Two", "Three", "Four", "Five"};
|
||||
JList list = new JList(names);
|
||||
JLabel fieldName = new JLabel("Text field:");
|
||||
JTextField textField = new JTextField();
|
||||
fieldName.setLabelFor(textField);
|
||||
panel1.add(fieldName);
|
||||
panel1.add(textField);
|
||||
panel1.add(list);
|
||||
tabbedPane.addTab("Tab 1", panel1);
|
||||
JPanel panel2 = new JPanel();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
panel2.add(new JCheckBox("CheckBox " + String.valueOf(i + 1)));
|
||||
}
|
||||
tabbedPane.addTab("tab 2", panel2);
|
||||
JPanel panel = new JPanel();
|
||||
panel.add(tabbedPane);
|
||||
|
||||
exceptionString = "AccessibleJTabbedPane test failed!";
|
||||
createUI(panel, "AccessibleJTabbedPaneTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AccessibleJTabbedPaneTest test = new AccessibleJTabbedPaneTest();
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createTabPane);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user