From 2766378cf2ac084172507b900b41a0df0df0096a Mon Sep 17 00:00:00 2001 From: LordCarve <27449516+LordCarve@users.noreply.github.com> Date: Mon, 11 May 2026 18:01:14 +0200 Subject: [PATCH] 14778 - Per-backend pen-to-mouse button mappings --- src/events/SDL_pen.c | 21 ++++++--------------- src/events/SDL_pen_c.h | 4 ++-- src/video/android/SDL_androidpen.c | 13 ++++++++++++- src/video/cocoa/SDL_cocoapen.m | 4 ++-- src/video/emscripten/SDL_emscriptenevents.c | 4 ++-- src/video/wayland/SDL_waylandevents.c | 2 +- src/video/windows/SDL_windowsevents.c | 4 ++-- src/video/x11/SDL_x11xinput2.c | 2 +- 8 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index d70542b9f9..50d8320073 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -562,14 +562,14 @@ void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind } } -void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down) +void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 pen_button, Uint8 mouse_button, bool down) { bool send_event = false; SDL_PenInputFlags input_state = 0; float x = 0.0f; float y = 0.0f; - if ((button < 1) || (button > 5)) { + if ((pen_button < 1) || (pen_button > 5)) { return; // clamp for now. } @@ -583,7 +583,7 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind EnsurePenProximity(timestamp, pen, window); input_state = pen->input_state; - const Uint32 flag = (Uint32) (1u << button); + const Uint32 flag = (Uint32) (1u << pen_button); const bool current = ((input_state & flag) != 0); x = pen->x; y = pen->y; @@ -610,23 +610,14 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind event.pbutton.pen_state = input_state; event.pbutton.x = x; event.pbutton.y = y; - event.pbutton.button = button; + event.pbutton.button = pen_button; event.pbutton.down = down; SDL_PushEvent(&event); - if (window && (!pen_touching || (pen_touching == instance_id))) { + if (window && (!pen_touching || (pen_touching == instance_id)) && mouse_button > 0) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse && mouse->pen_mouse_events) { - static const Uint8 mouse_buttons[] = { - SDL_BUTTON_LEFT, - SDL_BUTTON_RIGHT, - SDL_BUTTON_MIDDLE, - SDL_BUTTON_X1, - SDL_BUTTON_X2 - }; - if (button < SDL_arraysize(mouse_buttons)) { - SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, mouse_buttons[button], down); - } + SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, mouse_button, down); } } } diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h index 0aca9a6db9..586f207a6d 100644 --- a/src/events/SDL_pen_c.h +++ b/src/events/SDL_pen_c.h @@ -78,8 +78,8 @@ extern void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Windo // Backend calls this when a pen's axis changes, to generate events and update state. extern void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, SDL_PenAxis axis, float value); -// Backend calls this when a pen's button changes, to generate events and update state. -extern void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down); +// Backend calls this when a pen's button changes, to generate events and update state. Mouse button is passed explicitly because which pen button corresponds to which mouse button is backend-dependent. +extern void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 pen_button, Uint8 mouse_button, bool down); // Backend calls this when a pen's proximity changes, to generate events and update state. extern void SDL_SendPenProximity(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, bool in, bool immediate); diff --git a/src/video/android/SDL_androidpen.c b/src/video/android/SDL_androidpen.c index 02127bafb6..cfe091c009 100644 --- a/src/video/android/SDL_androidpen.c +++ b/src/video/android/SDL_androidpen.c @@ -69,7 +69,7 @@ void Android_OnPen(SDL_Window *window, int pen_id_in, SDL_PenDeviceType device_t for (Uint8 i = 1; i <= 5; ++i) { Uint8 mask = (1 << i); if (diff & mask) { - SDL_SendPenButton(0, pen, window, i, (button & mask) != 0); + SDL_SendPenButton(0, pen, window, i, Android_PenToMouseButton(i), (button & mask) != 0); } } } @@ -101,4 +101,15 @@ void Android_OnPen(SDL_Window *window, int pen_id_in, SDL_PenDeviceType device_t } } +static inline Uint8 Android_PenToMouseButton(Uint8 pen_button) +{ + switch (pen_button) + { + case 1: return SDL_BUTTON_RIGHT; + case 2: return SDL_BUTTON_MIDDLE; + case 5: return 0; + default: return pen_button + 1; + } +} + #endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/src/video/cocoa/SDL_cocoapen.m b/src/video/cocoa/SDL_cocoapen.m index 91429ae7e6..4c5a4c9ad7 100644 --- a/src/video/cocoa/SDL_cocoapen.m +++ b/src/video/cocoa/SDL_cocoapen.m @@ -138,8 +138,8 @@ static void Cocoa_HandlePenPointEvent(SDL_CocoaWindowData *_data, NSEvent *event SDL_SendPenTouch(timestamp, pen, window, handle->is_eraser, is_touching); SDL_SendPenMotion(timestamp, pen, window, (float) point.x, (float) (window->h - point.y)); - SDL_SendPenButton(timestamp, pen, window, 1, ((buttons & NSEventButtonMaskPenLowerSide) != 0)); - SDL_SendPenButton(timestamp, pen, window, 2, ((buttons & NSEventButtonMaskPenUpperSide) != 0)); + SDL_SendPenButton(timestamp, pen, window, 1, SDL_BUTTON_RIGHT, ((buttons & NSEventButtonMaskPenLowerSide) != 0)); + SDL_SendPenButton(timestamp, pen, window, 2, SDL_BUTTON_MIDDLE, ((buttons & NSEventButtonMaskPenUpperSide) != 0)); SDL_SendPenAxis(timestamp, pen, window, SDL_PEN_AXIS_PRESSURE, [event pressure]); SDL_SendPenAxis(timestamp, pen, window, SDL_PEN_AXIS_ROTATION, [event rotation]); SDL_SendPenAxis(timestamp, pen, window, SDL_PEN_AXIS_XTILT, ((float) tilt.x) * 90.0f); diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 6326d6967e..651f3238ac 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -806,10 +806,10 @@ static void Emscripten_UpdatePenFromEvent(SDL_WindowData *window_data, const Ems SDL_SendPenTouch(0, pen, window_data->window, true, down); } else if (event->button == 1) { bool down = ((event->buttons & 4) != 0); - SDL_SendPenButton(0, pen, window_data->window, 2, down); + SDL_SendPenButton(0, pen, window_data->window, 2, SDL_BUTTON_MIDDLE, down); } else if (event->button == 2) { bool down = ((event->buttons & 2) != 0); - SDL_SendPenButton(0, pen, window_data->window, 1, down); + SDL_SendPenButton(0, pen, window_data->window, 1, SDL_BUTTON_RIGHT, down); } SDL_SendPenAxis(0, pen, window_data->window, SDL_PEN_AXIS_PRESSURE, event->pressure); diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index d2d492afbc..df6a371072 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -3510,7 +3510,7 @@ static void tablet_tool_handle_frame(void *data, struct zwp_tablet_tool_v2 *tool for (int i = 0; i < SDL_arraysize(sdltool->frame.buttons); i++) { const int state = sdltool->frame.buttons[i]; if (state) { - SDL_SendPenButton(timestamp, instance_id, window, (Uint8)(i + 1), state == WAYLAND_TABLET_TOOL_BUTTON_DOWN); + SDL_SendPenButton(timestamp, instance_id, window, (Uint8)(i + 1), (Uint8)(i + 2), state == WAYLAND_TABLET_TOOL_BUTTON_DOWN); } } diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index d9b6520a9a..a7739b999a 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1403,8 +1403,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } SDL_SendPenMotion(timestamp, pen, window, fx, fy); - SDL_SendPenButton(timestamp, pen, window, 1, (pen_info.penFlags & PEN_FLAG_BARREL) != 0); - SDL_SendPenButton(timestamp, pen, window, 2, (pen_info.penFlags & PEN_FLAG_ERASER) != 0); + SDL_SendPenButton(timestamp, pen, window, 1, SDL_BUTTON_RIGHT, (pen_info.penFlags & PEN_FLAG_BARREL) != 0); + SDL_SendPenButton(timestamp, pen, window, 2, SDL_BUTTON_MIDDLE, (pen_info.penFlags & PEN_FLAG_ERASER) != 0); if (pen_info.penMask & PEN_MASK_PRESSURE) { SDL_SendPenAxis(timestamp, pen, window, SDL_PEN_AXIS_PRESSURE, ((float) pen_info.pressure) / 1024.0f); // pen_info.pressure is in the range 0..1024. diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index 56ccee53e5..3502b8615b 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -618,7 +618,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) if (button == 1) { // button 1 is the pen tip SDL_SendPenTouch(0, pen->pen, window, pen->is_eraser, down); } else { - SDL_SendPenButton(0, pen->pen, window, button - 1, down); + SDL_SendPenButton(0, pen->pen, window, button - 1, button, down); } } else if (!pointer_emulated) { // Otherwise assume a regular mouse