summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-11 23:39:17 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-11 23:39:17 +0300
commit608b49052178ea74f593c925cdeedf352aa1c357 (patch)
treef6f5d886c2af5f0d34fbcfd4a33cd5209c68ee9e
parent5bbcd2c036dd19d3293d9abc4d44014a5108a5ed (diff)
feat: cross-platform pen pressure, tilt, and stylus handling
- Hook up Cocoa tablet, stylus, and Force Touch pressure/tilt to push_pointer - Ensure Wayland tablet tool pressure resets cleanly on tool up - Visualize pressure-sensitive brush scaling and telemetry in simple_window
-rw-r--r--examples/simple_window.c66
-rw-r--r--src/cocoa/window.m26
-rw-r--r--src/wayland/pointer.c1
3 files changed, 74 insertions, 19 deletions
diff --git a/examples/simple_window.c b/examples/simple_window.c
index a8a2861..a6819f9 100644
--- a/examples/simple_window.c
+++ b/examples/simple_window.c
@@ -8,6 +8,20 @@ static int mouse_x = -1;
static int mouse_y = -1;
static bool mouse_down = false;
static int color_theme = 0;
+static uint16_t pen_pressure = 0;
+static int8_t pen_tilt_x = 0;
+static int8_t pen_tilt_y = 0;
+static enum yasl_pointer_device pointer_device = YASL_PTR_DEV_MOUSE;
+
+static const char *device_name(enum yasl_pointer_device dev)
+{
+ switch (dev) {
+ case YASL_PTR_DEV_PEN: return "Pen/Stylus";
+ case YASL_PTR_DEV_ERASER: return "Eraser";
+ case YASL_PTR_DEV_TOUCH: return "Touch";
+ default: return "Mouse";
+ }
+}
static void on_draw(struct yasl_surface *s, struct yasl_frame *frame, void *ud)
{
@@ -42,12 +56,20 @@ static void on_draw(struct yasl_surface *s, struct yasl_frame *frame, void *ud)
break;
}
- /* Draw interactive pointer indicator */
+ /* Draw interactive pointer / stylus indicator */
if (mouse_x >= 0 && mouse_y >= 0) {
int dx = x - mouse_x;
int dy = y - mouse_y;
int dist_sq = dx * dx + dy * dy;
- int radius = mouse_down ? 36 : 20;
+
+ /* Pressure-sensitive radius: scales dynamically from 8px to 64px */
+ int radius;
+ if (pen_pressure > 0) {
+ radius = 8 + (int)(((uint32_t)pen_pressure * 56) / 65535);
+ } else {
+ radius = mouse_down ? 36 : 18;
+ }
+
if (dist_sq < radius * radius) {
r = (uint8_t)(255 - r / 2);
g = (uint8_t)(255 - g / 2);
@@ -87,7 +109,6 @@ static void on_quit(void *ud)
int main(void)
{
- /* YASL manages its event loop internally when NULL is passed */
struct yasl_display_cbs disp_cbs = { .quit = on_quit };
struct yasl_display_spec disp_spec = {
.app_id = "org.yasl.example",
@@ -100,7 +121,7 @@ int main(void)
}
struct yasl_surface_spec surf_spec = {
- .title = "YASL Interactive Window",
+ .title = "YASL Interactive Window (Pen & Touch Enabled)",
.size = { .x = 640, .y = 480 },
};
struct yasl_surface *s = yasl_surface_create_toplevel(d, &surf_spec);
@@ -119,9 +140,10 @@ int main(void)
yasl_surface_schedule_redraw(s);
printf("=== YASL Demo Running ===\n");
- printf(" - Move or Click mouse inside window to interact\n");
- printf(" - Press Space to cycle background themes\n");
- printf(" - Press Escape or close window to exit\n\n");
+ printf(" - Stylus/Pen: full pressure (0..65535) and tilt detection\n");
+ printf(" - Mouse/Touch: interactive click/motion highlights\n");
+ printf(" - Space: cycle background themes\n");
+ printf(" - Escape: exit\n\n");
while (running) {
yasl_display_dispatch(d);
@@ -138,24 +160,34 @@ int main(void)
}
}
} else if (ev.kind == YASL_INPUT_MOUSE) {
- if (ev.mouse.kind == YASL_PTR_MOTION) {
- mouse_x = ev.mouse.pos.x;
- mouse_y = ev.mouse.pos.y;
- yasl_surface_schedule_redraw(s);
- } else if (ev.mouse.kind == YASL_PTR_PRESS) {
+ mouse_x = ev.mouse.pos.x;
+ mouse_y = ev.mouse.pos.y;
+ pen_pressure = ev.mouse.pen.pressure;
+ pen_tilt_x = ev.mouse.pen.tilt_x;
+ pen_tilt_y = ev.mouse.pen.tilt_y;
+ pointer_device = ev.mouse.device;
+
+ if (ev.mouse.kind == YASL_PTR_PRESS) {
mouse_down = true;
- mouse_x = ev.mouse.pos.x;
- mouse_y = ev.mouse.pos.y;
- yasl_surface_schedule_redraw(s);
+ if (pen_pressure > 0 || pointer_device == YASL_PTR_DEV_PEN) {
+ printf("[Pen Down] Pressure: %5u/65535 (%.1f%%) | Tilt: (%+3d°, %+3d°) | Device: %s\n",
+ pen_pressure, (pen_pressure * 100.0) / 65535.0,
+ pen_tilt_x, pen_tilt_y, device_name(pointer_device));
+ }
} else if (ev.mouse.kind == YASL_PTR_RELEASE) {
mouse_down = false;
- yasl_surface_schedule_redraw(s);
+ pen_pressure = 0;
+ } else if (ev.mouse.kind == YASL_PTR_MOTION && pen_pressure > 0) {
+ printf("[Pen Move] Pressure: %5u/65535 (%.1f%%) | Tilt: (%+3d°, %+3d°) | Device: %s\n",
+ pen_pressure, (pen_pressure * 100.0) / 65535.0,
+ pen_tilt_x, pen_tilt_y, device_name(pointer_device));
} else if (ev.mouse.kind == YASL_PTR_LEAVE) {
mouse_x = -1;
mouse_y = -1;
mouse_down = false;
- yasl_surface_schedule_redraw(s);
+ pen_pressure = 0;
}
+ yasl_surface_schedule_redraw(s);
}
}
diff --git a/src/cocoa/window.m b/src/cocoa/window.m
index 6c28f3f..451f448 100644
--- a/src/cocoa/window.m
+++ b/src/cocoa/window.m
@@ -317,14 +317,36 @@ static void push_pointer(struct yasl_surface *w, NSEvent *ev, enum yasl_pointer_
w->mods = cocoa_mods(ev.modifierFlags);
if (kind != YASL_PTR_LEAVE)
w->pointer = event_pos(w, ev);
+
+ enum yasl_pointer_device device = YASL_PTR_DEV_MOUSE;
+ struct yasl_pointer_pen pen = {0};
+
+ float press = (float)ev.pressure;
+ if (ev.subtype == NSEventSubtypeTabletPoint || press > 0.0f) {
+ if (ev.pointingDeviceType == NSPointingDeviceTypeEraser)
+ device = YASL_PTR_DEV_ERASER;
+ else if (ev.pointingDeviceType == NSPointingDeviceTypePen)
+ device = YASL_PTR_DEV_PEN;
+
+ if (press > 1.0f) press = 1.0f;
+ if (press > 0.0f)
+ pen.pressure = (uint16_t)(press * 65535.0f);
+
+ NSPoint tilt = ev.tilt;
+ pen.tilt_x = (int8_t)(tilt.x * 90.0);
+ pen.tilt_y = (int8_t)(tilt.y * 90.0);
+ }
+
struct yasl_input_event input_ev = {
- .kind = YASL_INPUT_MOUSE,
.surface = w,
+ .kind = YASL_INPUT_MOUSE,
.mouse = {
.pos = w->pointer,
- .button = button,
+ .button = (int16_t)button,
.kind = kind,
+ .device = device,
.mods = w->mods,
+ .pen = pen,
},
};
input_queue_push(&w->input, &input_ev);
diff --git a/src/wayland/pointer.c b/src/wayland/pointer.c
index 006eadd..5f97370 100644
--- a/src/wayland/pointer.c
+++ b/src/wayland/pointer.c
@@ -785,6 +785,7 @@ static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool)
struct seat *s = ((struct tablet_tool *)data)->seat;
struct yasl_surface *w = s->tablet_focus;
if (!w) return;
+ s->pen.pressure = 0;
press_queue_push(&s->tool_presses, w, s->tool_pos, 0, true);
}