I noticed that sometimes the Arduino IDE would randomly destroy my code in the editor. It could be as harmless as changing number of spaces between functions, or as bad as renaming my variables or missing code chunks.
It turned out that everytime I press the Serial Monitor keyboard shortcut: CTRL+SHIFT+M
Not only the Serial Monitor would open, but Arduino IDE also types a Carriage Return character WHEREVER my selection happens to be! If I have code selected, it would be removed and replaced with a return.
Not cool...
I'm running Arduino 0018 on 32-bit Windows Vista Ultimate.
On Windows XP, I have noticed the same and was looking for some information before posting this as a bug.
There isn't much information here yet. So lets try to improve this.
What I think is happening, is that pressing Ctrl-Shift-M triggers an event that opens the Serial Monitor, though this event isn't consumed. So then the event continues it's travel through the application and ends up in the textfield where it represents a CR.
A CR can often be entered using Ctrl-M (it's even sometimes represented by ^M, which is a notation for Ctrl-M). You can confirm this by pressing Ctrl-M or Ctrl-Shift-M in Notepad (Windows).
Looking into a solution for a minute, I have come across a consume() method in the ActionEvent. It is however protected, and cannot be called from the Arduino source. I am not familiar with a solution for this.
Any other Java developers who can help solving this really annoying bug?
I might look into it some more later this week. I'll post any updates.
Edit: some findings up till now
I have created a independent test app to try to reproduce the bug in a less-code app.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ConsumeTest extends JFrame {
public ConsumeTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
JMenuItem ctrlMTestItem = new JMenuItem("Ctrl M Test");
int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
modifiers |= ActionEvent.SHIFT_MASK;
ctrlMTestItem.setAccelerator(KeyStroke.getKeyStroke('M', modifiers));
ctrlMTestItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Action taken");
}
});
menu.add(ctrlMTestItem);
setJMenuBar(menuBar);
JTextArea textArea = new JTextArea();
getContentPane().add(textArea);
setPreferredSize(new Dimension(400, 300));
setMinimumSize(new Dimension(400, 300));
}
public static void main(String[] arg) {
new ConsumeTest().setVisible(true);
}
}
When trying to create the bug, I noticed that my app doesn't even insert a newline when pressing Ctrl(-Shift)-M. So my guess is that Arduino interprets the keystroke somehow, and that's where the possible error is. I haven't been able to track down where the Ctrl-M keystroke is handled and the CR is inserted. Any suggestions where this happens? (I have tried to find it in processing.app.syntax.DefaultInputHandler)
In processing.app.syntax.JEditTextarea, in the method processKeyEvent, the KeyEvent is passed through all the handlers.
First by 'super', then editorListener and finally inputHandler.
The consume status possibly set by super.processKeyEvent is, however, ignored.
Unfortunately, when I tried changing the code so it looks at the consumed status after the call to 'super', some other functionality (like cursor keys) no longer works.
Here's what I've tried:
public void processKeyEvent(KeyEvent evt) {
System.out.println("evt.isConsumed (1): " + evt.isConsumed());
// this had to be added in Processing 007X, because the menu key
// events weren't making it up to the frame.
super.processKeyEvent(evt);
System.out.println("evt.isConsumed (2): " + evt.isConsumed());
[glow] // Don't handle events that have been handled already
if(evt.isConsumed()) return;[/glow]
//System.out.println("jedittextarea: " + evt);
//System.out.println();
if (inputHandler == null) return;
switch(evt.getID()) {
case KeyEvent.KEY_TYPED:
if ((editorListener == null) || !editorListener.keyTyped(evt)) {
inputHandler.keyTyped(evt);
}
break;
case KeyEvent.KEY_PRESSED:
if ((editorListener == null) || !editorListener.keyPressed(evt)) {
inputHandler.keyPressed(evt);
}
break;
case KeyEvent.KEY_RELEASED:
inputHandler.keyReleased(evt);
break;
}
}
This bug will probably end up being ignored, since the error actually is in the Processing code. Though there's no real reason to fix it in Processing I guess, since they don't have this conflict.