Skip to content

Commit

Permalink
8267374: macOS: Option+Up/Down Arrow don't traverse to beginning/end …
Browse files Browse the repository at this point in the history
…of line in JTextArea

Reviewed-by: prr
  • Loading branch information
prsadhuk committed Sep 5, 2022
1 parent 8df671c commit 955baa3
Show file tree
Hide file tree
Showing 8 changed files with 381 additions and 30 deletions.
Expand Up @@ -90,6 +90,8 @@ void setDefaultAction(final String keymapName) {
"alt KP_LEFT", DefaultEditorKit.previousWordAction,
"alt RIGHT", DefaultEditorKit.nextWordAction,
"alt KP_RIGHT", DefaultEditorKit.nextWordAction,
"alt UP", DefaultEditorKit.beginLineUpAction,
"alt DOWN", DefaultEditorKit.endLineDownAction,
"shift alt LEFT", DefaultEditorKit.selectionPreviousWordAction,
"shift alt KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
"shift alt RIGHT", DefaultEditorKit.selectionNextWordAction,
Expand Down
18 changes: 2 additions & 16 deletions src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m
Expand Up @@ -296,14 +296,6 @@
java_awt_event_InputEvent_ALT_MASK,
java_awt_event_KeyEvent_VK_ALT
},
{
NSAlternateKeyMask,
0,
61,
java_awt_event_InputEvent_ALT_DOWN_MASK | java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK,
java_awt_event_InputEvent_ALT_MASK | java_awt_event_InputEvent_ALT_GRAPH_MASK,
java_awt_event_KeyEvent_VK_ALT | java_awt_event_KeyEvent_VK_ALT_GRAPH
},
// NSNumericPadKeyMask
{
NSHelpKeyMask,
Expand All @@ -317,7 +309,6 @@
{0, 0, 0, 0, 0, 0}
};

static BOOL leftAltKeyPressed;

/*
* Almost all unicode characters just go from NS to Java with no translation.
Expand Down Expand Up @@ -548,17 +539,15 @@ static unichar NsGetDeadKeyChar(unsigned short keyCode)
// *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
//}
if (eventKeyCode == cur->leftKeyCode) {
leftAltKeyPressed = YES;
*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
} else if (eventKeyCode == cur->rightKeyCode) {
*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
} else if (cur->nsMask == NSAlternateKeyMask) {
leftAltKeyPressed = NO;
continue;
}
*javaKeyType = (cur->nsMask & nsFlags) ?
java_awt_event_KeyEvent_KEY_PRESSED :
java_awt_event_KeyEvent_KEY_RELEASED;
java_awt_event_KeyEvent_KEY_PRESSED :
java_awt_event_KeyEvent_KEY_RELEASED;
break;
}
}
Expand All @@ -578,9 +567,6 @@ jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods)
//right alt, but that should be ok, since right alt contains left alt
//mask value.
javaModifiers |= isExtMods ? cur->javaExtMask : cur->javaMask;
if (cur->nsMask == NSAlternateKeyMask && leftAltKeyPressed) {
break; //since right alt key struct is defined last, break out of the loop }
}
}
}

Expand Down
232 changes: 232 additions & 0 deletions src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java
Expand Up @@ -642,6 +642,24 @@ public void write(Writer out, Document doc, int pos, int len)
*/
public static final String endLineAction = "caret-end-line";

/**
* Name of the {@code Action} for moving the caret
* to the beginning of the current line or up to the
* beginning of the previous line if the caret is
* already at the beginning of the line.
* @see #getActions
*/
public static final String beginLineUpAction = "caret-begin-line-and-up";

/**
* Name of the {@code Action} for moving the caret
* to the end of the current line or down to the
* end of the next line if the caret is already
* at the end of the line.
* @see #getActions
*/
public static final String endLineDownAction = "caret-end-line-and-down";

/**
* Name of the <code>Action</code> for moving the caret
* to the beginning of a line, extending the selection.
Expand Down Expand Up @@ -798,7 +816,11 @@ public void write(Writer out, Document doc, int pos, int len)
new PreviousWordAction(selectionPreviousWordAction, true),
new NextWordAction(selectionNextWordAction, true),
new BeginLineAction(beginLineAction, false),
new BeginLineUpAction(beginLineUpAction, false,
SwingConstants.NORTH),
new EndLineAction(endLineAction, false),
new EndLineDownAction(endLineDownAction, false,
SwingConstants.SOUTH),
new BeginLineAction(selectionBeginLineAction, true),
new EndLineAction(selectionEndLineAction, true),
new BeginParagraphAction(beginParagraphAction, false),
Expand Down Expand Up @@ -2040,6 +2062,216 @@ public void actionPerformed(ActionEvent e) {
private boolean select;
}

/*
* Position the caret to the end of the line and down one line.
* @see DefaultEditorKit#endLineAction
* @see DefaultEditorKit#selectEndLineAction
* @see DefaultEditorKit#getActions
*/
@SuppressWarnings("serial") // Superclass is not serializable across versions
static class EndLineDownAction extends TextAction {

/**
* Create this action with the appropriate identifier.
* @param nm the name of the action, Action.NAME.
* @param select whether to extend the selection when
* changing the caret position.
* @param direction the direction to move the caret
*/
EndLineDownAction(String nm, boolean select, int direction) {
super(nm);
this.select = select;
this.direction = direction;
firstTime = true;
}

/** The operation to perform when this action is triggered. */
@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
JTextComponent target = getTextComponent(e);
if (target != null) {
try {
int offs = target.getCaretPosition();
int endOffs = Utilities.getRowEnd(target, offs);
if (offs != endOffs) {
if (select) {
target.moveCaretPosition(endOffs);
} else {
target.setCaretPosition(endOffs);
}
} else {
Caret caret = target.getCaret();
DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ?
(DefaultCaret) caret : null;
int dot = caret.getDot();
Position.Bias[] bias = new Position.Bias[1];
Point magicPosition = caret.getMagicCaretPosition();

if (magicPosition == null &&
(direction == SwingConstants.NORTH ||
direction == SwingConstants.SOUTH)) {
Rectangle r = (bidiCaret != null) ?
target.getUI().modelToView(target, dot,
bidiCaret.getDotBias()) :
target.modelToView(dot);
magicPosition = new Point(r.x, r.y);
}
NavigationFilter filter = target.getNavigationFilter();

if (filter != null) {
dot = filter.getNextVisualPositionFrom
(target, dot, (bidiCaret != null) ?
bidiCaret.getDotBias() :
Position.Bias.Forward, direction, bias);
} else {
dot = target.getUI().getNextVisualPositionFrom
(target, dot, (bidiCaret != null) ?
bidiCaret.getDotBias() :
Position.Bias.Forward, direction, bias);
}
if (bias[0] == null) {
bias[0] = Position.Bias.Forward;
}
if (bidiCaret != null) {
if (select) {
bidiCaret.moveDot(dot, bias[0]);
} else {
bidiCaret.setDot(dot, bias[0]);
}
} else {
if (select) {
caret.moveDot(dot);
} else {
caret.setDot(dot);
}
}
if (magicPosition != null &&
(direction == SwingConstants.NORTH ||
direction == SwingConstants.SOUTH)) {
target.getCaret().setMagicCaretPosition(magicPosition);
}
offs = target.getCaretPosition();
endOffs = Utilities.getRowEnd(target, offs);
if (select) {
target.moveCaretPosition(endOffs);
} else {
target.setCaretPosition(endOffs);
}
}
} catch (BadLocationException ex) {
}
}
}

private boolean select;
private int direction;
private boolean firstTime;
}

/*
* Position the caret to the start of the line and up one line.
* @see DefaultEditorKit#beginLineAction
* @see DefaultEditorKit#selectBeginLineAction
* @see DefaultEditorKit#getActions
*/
@SuppressWarnings("serial") // Superclass is not serializable across versions
static class BeginLineUpAction extends TextAction {

/**
* Create this action with the appropriate identifier.
* @param nm the name of the action, Action.NAME.
* @param select whether to extend the selection when
* changing the caret position.
* @param direction the direction to move the caret
*/
BeginLineUpAction(String nm, boolean select, int direction) {
super(nm);
this.select = select;
this.direction = direction;
}

/** The operation to perform when this action is triggered. */
@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
JTextComponent target = getTextComponent(e);
if (target != null) {
try {
int offs = target.getCaretPosition();
int begOffs = Utilities.getRowStart(target, offs);
if (offs != begOffs) {
if (select) {
target.moveCaretPosition(begOffs);
} else {
target.setCaretPosition(begOffs);
}
} else {
if (select) {
target.moveCaretPosition(begOffs);
} else {
target.setCaretPosition(begOffs);
}
Caret caret = target.getCaret();
DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ?
(DefaultCaret) caret : null;
int dot = caret.getDot();
Position.Bias[] bias = new Position.Bias[1];
Point magicPosition = caret.getMagicCaretPosition();

if (magicPosition == null &&
(direction == SwingConstants.NORTH ||
direction == SwingConstants.SOUTH)) {
Rectangle r = (bidiCaret != null) ?
target.getUI().modelToView(target, dot,
bidiCaret.getDotBias()) :
target.modelToView(dot);
magicPosition = new Point(r.x, r.y);
}

NavigationFilter filter = target.getNavigationFilter();

if (filter != null) {
dot = filter.getNextVisualPositionFrom
(target, dot, (bidiCaret != null) ?
bidiCaret.getDotBias() :
Position.Bias.Forward, direction, bias);
} else {
dot = target.getUI().getNextVisualPositionFrom
(target, dot, (bidiCaret != null) ?
bidiCaret.getDotBias() :
Position.Bias.Forward, direction, bias);
}
if (bias[0] == null) {
bias[0] = Position.Bias.Forward;
}
if (bidiCaret != null) {
if (select) {
bidiCaret.moveDot(dot, bias[0]);
} else {
bidiCaret.setDot(dot, bias[0]);
}
} else {
if (select) {
caret.moveDot(dot);
} else {
caret.setDot(dot);
}
}
if (magicPosition != null &&
(direction == SwingConstants.NORTH ||
direction == SwingConstants.SOUTH)) {
target.getCaret().setMagicCaretPosition(magicPosition);
}
}
} catch (BadLocationException ex) {
}
}
}

private boolean select;
private int direction;
private boolean firstLine;
}

/*
* Position the caret to the beginning of the paragraph.
* @see DefaultEditorKit#beginParagraphAction
Expand Down
36 changes: 24 additions & 12 deletions test/jdk/java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java
Expand Up @@ -69,24 +69,36 @@ public static void main(String[] args) throws Exception {
}

public ModifierRobotKeyTest() throws Exception {
modifierKeys = new int[4];
modifierKeys[0] = KeyEvent.VK_SHIFT;
modifierKeys[1] = KeyEvent.VK_CONTROL;
modifierKeys[2] = KeyEvent.VK_ALT;
modifierKeys[3] = KeyEvent.VK_ALT_GRAPH;

inputMasks = new int[4];
inputMasks[0] = InputEvent.SHIFT_MASK;
inputMasks[1] = InputEvent.CTRL_MASK;
inputMasks[2] = InputEvent.ALT_MASK;
inputMasks[3] = InputEvent.ALT_GRAPH_MASK;
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("os x")) {
modifierKeys = new int[3];
modifierKeys[0] = KeyEvent.VK_SHIFT;
modifierKeys[1] = KeyEvent.VK_CONTROL;
modifierKeys[2] = KeyEvent.VK_ALT;

inputMasks = new int[3];
inputMasks[0] = InputEvent.SHIFT_MASK;
inputMasks[1] = InputEvent.CTRL_MASK;
inputMasks[2] = InputEvent.ALT_MASK;
} else {
modifierKeys = new int[4];
modifierKeys[0] = KeyEvent.VK_SHIFT;
modifierKeys[1] = KeyEvent.VK_CONTROL;
modifierKeys[2] = KeyEvent.VK_ALT;
modifierKeys[3] = KeyEvent.VK_ALT_GRAPH;

inputMasks = new int[4];
inputMasks[0] = InputEvent.SHIFT_MASK;
inputMasks[1] = InputEvent.CTRL_MASK;
inputMasks[2] = InputEvent.ALT_MASK;
inputMasks[3] = InputEvent.ALT_GRAPH_MASK;
}

modifierStatus = new boolean[modifierKeys.length];

textKeys = new int[2];
textKeys[0] = KeyEvent.VK_A;

String os = System.getProperty("os.name").toLowerCase();

if (os.contains("os x"))
textKeys[1] = KeyEvent.VK_K;
Expand Down
Expand Up @@ -24,6 +24,7 @@
/*
@test
@bug 8041928 8158616
@requires (os.family != "mac")
@summary Confirm that the Alt-Gr Modifier bit is set correctly.
@run main/manual AltGraphModifierTest
*/
Expand Down Expand Up @@ -255,4 +256,4 @@ public void actionPerformed(ActionEvent e) {
AltGraphModifierTest.fail("User Clicked Fail");
}
}
}
}
1 change: 1 addition & 0 deletions test/jdk/java/awt/keyboard/8218917/AltKeyBug.java
Expand Up @@ -24,6 +24,7 @@
/*
* @test
* @key headful
* @requires (os.family != "mac")
* @bug 8218917
* @summary Tests whether sending an ALT_GRAPH key once, will result in the
* system reporting only ALT_GRAPH even if an ALT was sent and vice versa.
Expand Down
1 change: 0 additions & 1 deletion test/jdk/java/awt/keyboard/AllKeyCode/AllKeyCode.java
Expand Up @@ -150,7 +150,6 @@ public class AllKeyCode extends Frame {
KeyEvent.VK_F18,
KeyEvent.VK_F19,
KeyEvent.VK_F20,
KeyEvent.VK_ALT_GRAPH
};

keyPressedIndex = -1;
Expand Down

1 comment on commit 955baa3

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.