#include #include #include static bool failed, smoke_test; 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(void *ud, struct yasl_surface *s, struct yasl_frame *frame) { (void)ud; int w = frame->target.size.x; int h = frame->target.size.y; uint32_t *pixels = frame->target.pixels; if (!pixels || w <= 0 || h <= 0) return; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { uint8_t r, g, b; uint8_t u = (uint8_t)((x * 255) / (w > 0 ? w : 1)); uint8_t v = (uint8_t)((y * 255) / (h > 0 ? h : 1)); switch (color_theme % 3) { case 0: r = u; g = v; b = 160; break; case 1: r = 40; g = u; b = v; break; default: r = v; g = 60; b = u; break; } /* 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; /* 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); b = (uint8_t)(255 - b / 2); } } pixels[y * w + x] = (255u << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; } } if (!yasl_frame_present(frame, NULL, 0)) { fprintf(stderr, "Failed to present frame\n"); failed = true; } if (failed) yasl_app_exit(yasl_surface_display(s), YASL_APP_ERROR); else if (smoke_test) yasl_surface_destroy(s); } static enum yasl_app_result on_init(void *ud, struct yasl_display *display) { (void)ud; struct yasl_window_spec window_spec = { .title = "YASL Interactive Window (Pen & Touch Enabled)", .size_logical = { .x = 640, .y = 480 }, }; struct yasl_surface *s = yasl_surface_create_toplevel(display, &window_spec); if (!s) { fprintf(stderr, "Failed to create surface\n"); failed = true; return YASL_APP_ERROR; } yasl_surface_request_frame(s); printf("=== YASL Demo Running ===\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"); return YASL_APP_CONTINUE; } static void pointer_sample(struct yasl_vector2i pos, enum yasl_pointer_device device, struct yasl_pointer_pen pen) { mouse_x = pos.x; mouse_y = pos.y; pointer_device = device; pen_pressure = pen.pressure; pen_tilt_x = pen.tilt_x; pen_tilt_y = pen.tilt_y; } static enum yasl_app_result on_event(void *ud, const struct yasl_event *ev) { (void)ud; switch (ev->type) { case YASL_EVENT_WINDOW_CLOSE: return YASL_APP_QUIT; case YASL_EVENT_WINDOW_RESIZE: { uint32_t flags = yasl_surface_state(ev->surface); const char *mode = flags & YASL_STATE_FULLSCREEN ? "fullscreen" : flags & YASL_STATE_MAXIMIZED ? "maximized" : flags & YASL_STATE_TILED ? "tiled" : "windowed"; printf("[YASL] Resized to %dx%d (scale: %.2fx, %s)\n", ev->resize.geometry.size.x, ev->resize.geometry.size.y, (double)ev->resize.geometry.scale_120 / YASL_SCALE_UNIT, mode); break; } case YASL_EVENT_KEY: if (ev->key.action != YASL_KEY_PRESS) return YASL_APP_CONTINUE; if (ev->key.key == YASL_KEY_ESCAPE) return YASL_APP_QUIT; if (ev->key.key == YASL_KEY_SPACE || ev->key.key == YASL_KEY_ENTER) color_theme++; break; case YASL_EVENT_POINTER_DOWN: case YASL_EVENT_POINTER_UP: case YASL_EVENT_POINTER_MOTION: pointer_sample(ev->pointer.pos, ev->pointer.device, ev->pointer.pen); if (ev->type == YASL_EVENT_POINTER_DOWN && ev->pointer.button == YASL_BUTTON_PRIMARY) { mouse_down = true; } else if (ev->type == YASL_EVENT_POINTER_UP && ev->pointer.button == YASL_BUTTON_PRIMARY) { mouse_down = false; pen_pressure = 0; } break; case YASL_EVENT_FOCUS: if (ev->focus.focused) return YASL_APP_CONTINUE; /* Fall through to cancel held input on focus loss. */ [[fallthrough]]; case YASL_EVENT_INPUT_RESET: case YASL_EVENT_POINTER_LEAVE: mouse_x = mouse_y = -1; mouse_down = false; pen_pressure = 0; break; default: return YASL_APP_CONTINUE; } if (pen_pressure > 0) { printf("[Pen] 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)); } yasl_surface_request_frame(ev->surface); return YASL_APP_CONTINUE; } int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "--smoke-test") == 0) smoke_test = true; else if (argc != 1) { fprintf(stderr, "Usage: %s [--smoke-test]\n", argv[0]); return 1; } struct yasl_app_desc desc = { .app_id = "org.yasl.example", .init = on_init, .event = on_event, .frame = on_draw, }; int result = yasl_run(&desc); if (result) perror("yasl_run"); return result || failed ? 1 : 0; }