Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.

Commit 600469e

Browse files
committed
Merge pull request #89 from akdor1154/tabletInputFix
Make networktablet act as a Tablet, not a Touchscreen
2 parents f957287 + 91c417b commit 600469e

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

app-android/app/src/main/java/at/bitfire/gfxtablet/CanvasView.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,17 @@
1717
public class CanvasView extends View implements SharedPreferences.OnSharedPreferenceChangeListener {
1818
private static final String TAG = "GfxTablet.CanvasView";
1919

20+
private enum InRangeStatus {
21+
OutOfRange,
22+
InRange,
23+
FakeInRange
24+
}
25+
2026
final SharedPreferences settings;
2127
NetworkClient netClient;
2228
boolean acceptStylusOnly;
2329
int maxX, maxY;
30+
InRangeStatus inRangeStatus;
2431

2532

2633
// setup
@@ -35,6 +42,7 @@ public CanvasView(Context context, AttributeSet attributeSet) {
3542
settings.registerOnSharedPreferenceChangeListener(this);
3643
setBackground();
3744
setInputMethods();
45+
inRangeStatus = InRangeStatus.OutOfRange;
3846
}
3947

4048
public void setNetworkClient(NetworkClient networkClient) {
@@ -83,13 +91,23 @@ public boolean onGenericMotionEvent(MotionEvent event) {
8391
if (isEnabled()) {
8492
for (int ptr = 0; ptr < event.getPointerCount(); ptr++)
8593
if (!acceptStylusOnly || (event.getToolType(ptr) == MotionEvent.TOOL_TYPE_STYLUS)) {
94+
short nx = normalizeX(event.getX(ptr)),
95+
ny = normalizeY(event.getY(ptr)),
96+
npressure = normalizePressure(event.getPressure(ptr));
8697
Log.v(TAG, String.format("Generic motion event logged: %f|%f, pressure %f", event.getX(ptr), event.getY(ptr), event.getPressure(ptr)));
87-
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
88-
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION,
89-
normalizeX(event.getX(ptr)),
90-
normalizeY(event.getY(ptr)),
91-
normalizePressure(event.getPressure(ptr))
92-
));
98+
switch (event.getActionMasked()) {
99+
case MotionEvent.ACTION_HOVER_MOVE:
100+
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure));
101+
break;
102+
case MotionEvent.ACTION_HOVER_ENTER:
103+
inRangeStatus = InRangeStatus.InRange;
104+
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, -1, true));
105+
break;
106+
case MotionEvent.ACTION_HOVER_EXIT:
107+
inRangeStatus = InRangeStatus.OutOfRange;
108+
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, -1, false));
109+
break;
110+
}
93111
}
94112
return true;
95113
}
@@ -110,11 +128,19 @@ public boolean onTouchEvent(@NonNull MotionEvent event) {
110128
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure));
111129
break;
112130
case MotionEvent.ACTION_DOWN:
131+
if (inRangeStatus == inRangeStatus.OutOfRange) {
132+
inRangeStatus = inRangeStatus.FakeInRange;
133+
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, (short)0, -1, true));
134+
}
113135
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, true));
114136
break;
115137
case MotionEvent.ACTION_UP:
116138
case MotionEvent.ACTION_CANCEL:
117139
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, false));
140+
if (inRangeStatus == inRangeStatus.FakeInRange) {
141+
inRangeStatus = inRangeStatus.OutOfRange;
142+
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, (short)0, -1, false));
143+
}
118144
break;
119145
}
120146

doc/protocol.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,21 @@ Packet structure, uses network byte order (big endian):
2020
1 unsigned int16 pressure (accepting full range 0..65535, but will clip to 32768 == pressure 1.0f on Android device)
2121

2222
when type == button event:
23-
1 signed int8 number of button, starting with 0
23+
1 signed int8 button id:
24+
-1: stylus in range pseudo-button
25+
0: left click / stylus in contact / button 0
26+
1: extra button 1
27+
2: extra button 2
2428
1 byte button status:
2529
0 button is released ("up")
2630
1 button is pressed ("down")
2731

32+
XInput will ignore BTN_TOUCH events if they are not preceeded by
33+
a BTN_TOOL_PEN event -- this would never happen for a real stylus,
34+
because it would imply the stylus is touching the pad, yet too far
35+
away from the pad to be detected.
36+
37+
A GfxTablet client must therefore be careful to send a "Button -1
38+
down" event before a "Button 0 down" event, to emulate this
39+
behaviour. If they are faking these events, they'll probably want
40+
to likewise send a "Button -1 up" event after a "Button 0 up" event.

driver-uinput/networktablet.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ void init_device(int fd)
3535
die("error: ioctl UI_SET_EVBIT EV_KEY");
3636
if (ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH) < 0)
3737
die("error: ioctl UI_SET_KEYBIT");
38+
if (ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN) < 0)
39+
die("error: ioctl UI_SET_KEYBIT");
40+
if (ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS) < 0)
41+
die("error: ioctl UI_SET_KEYBIT");
42+
if (ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2) < 0)
43+
die("error: ioctl UI_SET_KEYBIT");
3844

3945
// enable 2 main axes + pressure (absolute positioning)
4046
if (ioctl(fd, UI_SET_EVBIT, EV_ABS) < 0)
@@ -144,8 +150,19 @@ int main(void)
144150
send_event(device, EV_SYN, SYN_REPORT, 1);
145151
break;
146152
case EVENT_TYPE_BUTTON:
153+
// stylus hovering
154+
if (ev_pkt.button == -1)
155+
send_event(device, EV_KEY, BTN_TOOL_PEN, ev_pkt.down);
156+
// stylus touching
147157
if (ev_pkt.button == 0)
148158
send_event(device, EV_KEY, BTN_TOUCH, ev_pkt.down);
159+
// button 1
160+
if (ev_pkt.button == 1)
161+
send_event(device, EV_KEY, BTN_STYLUS, ev_pkt.down);
162+
// button 2
163+
if (ev_pkt.button == 2)
164+
send_event(device, EV_KEY, BTN_STYLUS2, ev_pkt.down);
165+
printf("sent button: %hhi, %hhu\n", ev_pkt.button, ev_pkt.down);
149166
send_event(device, EV_SYN, SYN_REPORT, 1);
150167
break;
151168

driver-uinput/protocol.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ struct event_packet
2020
};
2121

2222
struct { /* only required for EVENT_TYPE_BUTTON */
23-
int8_t button; /* number of button, beginning with 1 */
23+
int8_t button; /* button id:
24+
-1 = stylus in range,
25+
0 = tap/left click/button 0,
26+
1 = button 1,
27+
2 = button 2 */
2428
int8_t down; /* 1 = button down, 0 = button up */
2529
};
2630
};

0 commit comments

Comments
 (0)