1
0
Fork 0
mirror of https://github.com/rfc2822/GfxTablet synced 2025-10-03 09:39:16 +02:00

Merge pull request #89 from akdor1154/tabletInputFix

Make networktablet act as a Tablet, not a Touchscreen
This commit is contained in:
Ricki 2015-11-30 22:23:39 +01:00
commit 600469eb64
4 changed files with 68 additions and 8 deletions

View file

@ -17,10 +17,17 @@ import at.bitfire.gfxtablet.NetEvent.Type;
public class CanvasView extends View implements SharedPreferences.OnSharedPreferenceChangeListener { public class CanvasView extends View implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "GfxTablet.CanvasView"; private static final String TAG = "GfxTablet.CanvasView";
private enum InRangeStatus {
OutOfRange,
InRange,
FakeInRange
}
final SharedPreferences settings; final SharedPreferences settings;
NetworkClient netClient; NetworkClient netClient;
boolean acceptStylusOnly; boolean acceptStylusOnly;
int maxX, maxY; int maxX, maxY;
InRangeStatus inRangeStatus;
// setup // setup
@ -35,6 +42,7 @@ public class CanvasView extends View implements SharedPreferences.OnSharedPrefer
settings.registerOnSharedPreferenceChangeListener(this); settings.registerOnSharedPreferenceChangeListener(this);
setBackground(); setBackground();
setInputMethods(); setInputMethods();
inRangeStatus = InRangeStatus.OutOfRange;
} }
public void setNetworkClient(NetworkClient networkClient) { public void setNetworkClient(NetworkClient networkClient) {
@ -83,13 +91,23 @@ public class CanvasView extends View implements SharedPreferences.OnSharedPrefer
if (isEnabled()) { if (isEnabled()) {
for (int ptr = 0; ptr < event.getPointerCount(); ptr++) for (int ptr = 0; ptr < event.getPointerCount(); ptr++)
if (!acceptStylusOnly || (event.getToolType(ptr) == MotionEvent.TOOL_TYPE_STYLUS)) { if (!acceptStylusOnly || (event.getToolType(ptr) == MotionEvent.TOOL_TYPE_STYLUS)) {
short nx = normalizeX(event.getX(ptr)),
ny = normalizeY(event.getY(ptr)),
npressure = normalizePressure(event.getPressure(ptr));
Log.v(TAG, String.format("Generic motion event logged: %f|%f, pressure %f", event.getX(ptr), event.getY(ptr), event.getPressure(ptr))); Log.v(TAG, String.format("Generic motion event logged: %f|%f, pressure %f", event.getX(ptr), event.getY(ptr), event.getPressure(ptr)));
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) switch (event.getActionMasked()) {
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, case MotionEvent.ACTION_HOVER_MOVE:
normalizeX(event.getX(ptr)), netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure));
normalizeY(event.getY(ptr)), break;
normalizePressure(event.getPressure(ptr)) case MotionEvent.ACTION_HOVER_ENTER:
)); inRangeStatus = InRangeStatus.InRange;
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, -1, true));
break;
case MotionEvent.ACTION_HOVER_EXIT:
inRangeStatus = InRangeStatus.OutOfRange;
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, -1, false));
break;
}
} }
return true; return true;
} }
@ -110,11 +128,19 @@ public class CanvasView extends View implements SharedPreferences.OnSharedPrefer
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure)); netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure));
break; break;
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
if (inRangeStatus == inRangeStatus.OutOfRange) {
inRangeStatus = inRangeStatus.FakeInRange;
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, (short)0, -1, true));
}
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, true)); netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, true));
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_CANCEL:
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, false)); netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, false));
if (inRangeStatus == inRangeStatus.FakeInRange) {
inRangeStatus = inRangeStatus.OutOfRange;
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, (short)0, -1, false));
}
break; break;
} }

View file

@ -20,8 +20,21 @@ Packet structure, uses network byte order (big endian):
1 unsigned int16 pressure (accepting full range 0..65535, but will clip to 32768 == pressure 1.0f on Android device) 1 unsigned int16 pressure (accepting full range 0..65535, but will clip to 32768 == pressure 1.0f on Android device)
when type == button event: when type == button event:
1 signed int8 number of button, starting with 0 1 signed int8 button id:
-1: stylus in range pseudo-button
0: left click / stylus in contact / button 0
1: extra button 1
2: extra button 2
1 byte button status: 1 byte button status:
0 button is released ("up") 0 button is released ("up")
1 button is pressed ("down") 1 button is pressed ("down")
XInput will ignore BTN_TOUCH events if they are not preceeded by
a BTN_TOOL_PEN event -- this would never happen for a real stylus,
because it would imply the stylus is touching the pad, yet too far
away from the pad to be detected.
A GfxTablet client must therefore be careful to send a "Button -1
down" event before a "Button 0 down" event, to emulate this
behaviour. If they are faking these events, they'll probably want
to likewise send a "Button -1 up" event after a "Button 0 up" event.

View file

@ -35,6 +35,12 @@ void init_device(int fd)
die("error: ioctl UI_SET_EVBIT EV_KEY"); die("error: ioctl UI_SET_EVBIT EV_KEY");
if (ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH) < 0) if (ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH) < 0)
die("error: ioctl UI_SET_KEYBIT"); die("error: ioctl UI_SET_KEYBIT");
if (ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN) < 0)
die("error: ioctl UI_SET_KEYBIT");
if (ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS) < 0)
die("error: ioctl UI_SET_KEYBIT");
if (ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2) < 0)
die("error: ioctl UI_SET_KEYBIT");
// enable 2 main axes + pressure (absolute positioning) // enable 2 main axes + pressure (absolute positioning)
if (ioctl(fd, UI_SET_EVBIT, EV_ABS) < 0) if (ioctl(fd, UI_SET_EVBIT, EV_ABS) < 0)
@ -144,8 +150,19 @@ int main(void)
send_event(device, EV_SYN, SYN_REPORT, 1); send_event(device, EV_SYN, SYN_REPORT, 1);
break; break;
case EVENT_TYPE_BUTTON: case EVENT_TYPE_BUTTON:
// stylus hovering
if (ev_pkt.button == -1)
send_event(device, EV_KEY, BTN_TOOL_PEN, ev_pkt.down);
// stylus touching
if (ev_pkt.button == 0) if (ev_pkt.button == 0)
send_event(device, EV_KEY, BTN_TOUCH, ev_pkt.down); send_event(device, EV_KEY, BTN_TOUCH, ev_pkt.down);
// button 1
if (ev_pkt.button == 1)
send_event(device, EV_KEY, BTN_STYLUS, ev_pkt.down);
// button 2
if (ev_pkt.button == 2)
send_event(device, EV_KEY, BTN_STYLUS2, ev_pkt.down);
printf("sent button: %hhi, %hhu\n", ev_pkt.button, ev_pkt.down);
send_event(device, EV_SYN, SYN_REPORT, 1); send_event(device, EV_SYN, SYN_REPORT, 1);
break; break;

View file

@ -20,7 +20,11 @@ struct event_packet
}; };
struct { /* only required for EVENT_TYPE_BUTTON */ struct { /* only required for EVENT_TYPE_BUTTON */
int8_t button; /* number of button, beginning with 1 */ int8_t button; /* button id:
-1 = stylus in range,
0 = tap/left click/button 0,
1 = button 1,
2 = button 2 */
int8_t down; /* 1 = button down, 0 = button up */ int8_t down; /* 1 = button down, 0 = button up */
}; };
}; };