How can I send a custom SWT key event such that it results in the typing of that exact literal character without any conversion?
We are making a custom on-screen graphical keyboard that allows for multiple possible layouts - QWERTY being the main one, but several others planned, including ones that visually simulate the iPhone keyboard layout or others that are non-standard relative to the PC.
I would like to be able to send any arbitrary character of my choosing as an event, such that it will result in the typing of that exact character. However, whenever I send an event with a given character, SWT seems to automatically interpret and convert it based on the system's keyboard settings and status, changing it to be capitalized/lowercase or using the shifted symbols depending on whether or not the shift key (the real one on the actual keyboard, for instance) is pressed. For instance, passing the character 'T' through a key event will result in either 't' or 'T' depending on the shift key. It performs similarly with the '4' character, doing either '4' or '$' based on shift.
This is problematic, as I wish to perform the shifting of characters manually, and indeed may not wish to use the same shift characters as the standard QWERTY keyboard in any given case (perhaps, for instance, I want '$' to be the shifted (or 'function' key) version of 'R' on a smaller, cellphone-like keyboard). How can I use these events such that it does not assume the usage of QWERTY keys?
The documentation for the 'character' field in the SWT events says the following:
the character represented by the key that was typed. This is the final character that results after all modifiers have been applied. For example, when the user types Ctrl+A, the character value is 0x01. It is important that applications do not attempt to modify the character value based on a stateMask (such as SWT.CTRL) or the resulting character will not be correct.
This makes me believe that it should not be converting my character as it is doing, as I am commanding it to use my "final" result.
I have created a simple, stand-alone example to demonstrate my issue (please note that this is not how I am doing the actual Keyboard, and is only meant to highlight the key event issue):
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Button;
public class KeyboardIssueExample extends Shell {
private Text txtTextArea;
private Composite cmpButtons;
private Button btnBigA;
private Button btnBigS;
private Button btnLittleD;
private Button btnSix;
private Button btnSeven;
private Button btnDollah;
private Button btnStar;
private SelectionListener mainListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent selE) {
Button b = (Button)selE.widget;
char c = b.getText().charAt(0);
sendKey(c);
}
};
/**
* Launch the application.
* @param args
*/
public static void main(String args[]) {
try {
Display display = Display.getDefault();
KeyboardIssueExample shell = new KeyboardIssueExample(display);
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the shell.
* @param display
*/
public KeyboardIssueExample(Display display) {
super(display, SWT.SHELL_TRIM);
createContents();
}
/**
* Create contents of the shell.
*/
protected void createContents() {
setText("SWT Application");
setSize(450, 300);
setLayout(new GridLayout());
txtTextArea = new Text(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
txtTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
cmpButtons = new Composite(this, SWT.NONE);
cmpButtons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
GridLayout gl_cmpButtons = new GridLayout(7, false);
gl_cmpButtons.marginWidth = 0;
gl_cmpButtons.marginHeight = 0;
cmpButtons.setLayout(gl_cmpButtons);
btnBigA = new Button(cmpButtons, SWT.NONE);
btnBigA.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnBigA.setText("A");
btnBigS = new Button(cmpButtons, SWT.NONE);
btnBigS.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnBigS.setText("S");
btnLittleD = new Button(cmpButtons, SWT.NONE);
btnLittleD.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnLittleD.setText("d");
btnSix = new Button(cmpButtons, SWT.NONE);
btnSix.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnSix.setText("6");
btnSeven = new Button(cmpButtons, SWT.NONE);
btnSeven.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnSeven.setText("7");
btnDollah = new Button(cmpButtons, SWT.NONE);
btnDollah.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnDollah.setText("$");
btnStar = new Button(cmpButtons, SWT.NONE);
btnStar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
btnStar.setText("*");
init();
}
private void init() {
btnBigA.addSelectionListener(mainListener);
btnBigS.addSelectionListener(mainListener);
btnLittleD.addSelectionListener(mainListener);
btnSix.addSelectionListener(mainListener);
btnSeven.addSelectionListener(mainListener);
btnDollah.addSelectionListener(mainListener);
btnStar.addSelectionListener(mainListener);
}
@Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
private void sendKey(char c) {
sendKeyEvent(c, SWT.KeyDown);
sendKeyEvent(c, SWT.KeyUp);
}
private void sendKeyEvent(char c, int eventType) {
txtTextArea.forceFocus();
Event event = new Event();
event.type = eventType;
event.character = c;
getDisplay().post(event);
}
}
As you will find, the key events do not respect my own custom usage of capitalization, and instead uses its own. How troublesome.