diff --git a/src/inputdevice.cpp b/src/inputdevice.cpp index b37c7fbf3..8b4f888e7 100644 --- a/src/inputdevice.cpp +++ b/src/inputdevice.cpp @@ -2537,6 +2537,9 @@ static bool mousehack_last_abs_valid; static int mousehack_native_origin_x, mousehack_native_origin_y; static bool mousehack_native_source_origin_valid; static bool mousehack_position_is_native; +#ifdef AMIBERRY +static int mousehack_last_mouse; +#endif static int tablet_maxx, tablet_maxy, tablet_maxz; static int tablet_resx, tablet_resy; static int tablet_maxax, tablet_maxay, tablet_maxaz; @@ -2669,6 +2672,9 @@ static void mousehack_reset (void) mousehack_native_origin_x = mousehack_native_origin_y = 0; mousehack_native_source_origin_valid = false; mousehack_position_is_native = false; +#ifdef AMIBERRY + mousehack_last_mouse = 0; +#endif dimensioninfo_dbl = 0; mousehack_alive_cnt = 0; vp_xoffset = vp_yoffset = 0; @@ -3150,6 +3156,37 @@ void inputdevice_tablet_info (int maxx, int maxy, int maxz, int maxax, int maxay inputdevice_update_tablet_params(); } +#ifdef AMIBERRY +// Native-screen magic mouse: the guest only services the absolute +// IECLASS_POINTERPOS events from the virtual mouse driver at a low rate +// (Intuition processes them behind its input handling), so the pointer +// moves in visible steps (#2279). The hardware mouse counters, in contrast, +// are serviced every vsync exactly like normal mouse input. Feed the delta +// between two consecutively delivered absolute positions into the relative +// mouse pipeline so the pointer tracks every counter update; the absolute +// events still anchor the exact position, so there is no double movement. +static void mousehack_send_native_relative_delta (int mouse, int dx, int dy) +{ + const int delta[2] = { dx, dy }; + struct uae_input_device *id = &mice[mouse]; + + for (int axis = 0; axis < 2; axis++) { + const int v = delta[axis]; + if (!v) { + continue; + } + // The delta is already exact in the absolute coordinate space that the + // guest's IECLASS_POINTERPOS events anchor to, so per-axis invert flags + // must not apply here; inverting only the delta would move the pointer + // opposite to the absolute position between guest driver updates. + for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) { + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, + HANDLE_IE_FLAG_CANSTOPPLAYBACK); + } + } +} +#endif // AMIBERRY + static void inputdevice_mh_abs (int x, int y, uae_u32 buttonbits, bool position_valid) { #ifdef AMIBERRY @@ -3188,12 +3225,25 @@ static void inputdevice_mh_abs (int x, int y, uae_u32 buttonbits, bool position_ #endif mousehack_enable (); +#ifdef AMIBERRY + const int previous_abs_x = mousehack_last_abs_x; + const int previous_abs_y = mousehack_last_abs_y; + const bool previous_abs_valid = mousehack_last_abs_valid; +#endif // AMIBERRY // Keep the coordinate delivered after native screen-origin and host-hotspot // compensation. The guest positions its native sprite from this coordinate, // so their delta is the cursor hotspot. mousehack_last_abs_x = x; mousehack_last_abs_y = y; mousehack_last_abs_valid = position_valid && mousehack_address; +#ifdef AMIBERRY + if (position_valid && previous_abs_valid && currprefs.input_tablet == TABLET_MOUSEHACK + && mousehack_alive () && mousehack_position_is_native + && mousehack_last_mouse >= 0 && mousehack_last_mouse < MAX_INPUT_DEVICES + && mice[mousehack_last_mouse].enabled) { + mousehack_send_native_relative_delta (mousehack_last_mouse, x - previous_abs_x, y - previous_abs_y); + } +#endif // AMIBERRY if (mousehack_address) { uae_u8 tmp1[4], tmp2[4]; uae_u8 *p = mousehack_address; @@ -10467,8 +10517,12 @@ void setmousestate (int mouse, int axis, int data, int isabs) lastmx = data; else lastmy = data; - if (axis) + if (axis) { +#ifdef AMIBERRY + mousehack_last_mouse = mouse; +#endif mousehack_helper (mice2[mouse].buttonmask); + } } #if OUTPUTDEBUG OutputDebugString(_T("-> exit2\n")); @@ -10500,8 +10554,12 @@ void setmousestate (int mouse, int axis, int data, int isabs) } else { lastmy = data; } - if (axis) + if (axis) { +#ifdef AMIBERRY + mousehack_last_mouse = mouse; +#endif mousehack_helper (mice2[mouse].buttonmask); + } if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive() && axis < 2) { #if OUTPUTDEBUG OutputDebugString(_T("-> exit4\n"));