More mouse and PIC fixes and the mouse now takes of the ration between guest resolution and actual render area size, multiplied by the DPI, when returning coordinate deltas, also unified the delta return function across the various emulated mice.

This commit is contained in:
OBattler
2023-08-11 04:45:32 +02:00
parent 291dab2334
commit 782015a923
13 changed files with 299 additions and 243 deletions

View File

@@ -32,6 +32,8 @@
#include <86box/timer.h>
#include <86box/gdbstub.h>
#include <86box/mouse.h>
#include <86box/video.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
typedef struct mouse_t {
@@ -43,6 +45,8 @@ atomic_int mouse_x;
atomic_int mouse_y;
atomic_int mouse_z;
atomic_int mouse_buttons;
atomic_int old_mouse_x;
atomic_int old_mouse_y;
int mouse_mode;
int mouse_timed = 1;
int mouse_tablet_in_proximity = 0;
@@ -52,8 +56,10 @@ double mouse_x_abs;
double mouse_y_abs;
double mouse_sensitivity = 1.0;
double mouse_x_error = 0.0;
double mouse_y_error = 0.0;
_Atomic double mouse_x_error = 0.0;
_Atomic double mouse_y_error = 0.0;
_Atomic double mouse_x_raw = 0.0;
_Atomic double mouse_y_raw = 0.0;
pc_timer_t mouse_timer; /* mouse event timer */
@@ -130,12 +136,21 @@ mouse_log(const char *fmt, ...)
# define mouse_log(fmt, ...)
#endif
void
mouse_clear_coords(void)
{
mouse_x = mouse_y = mouse_z = 0;
old_mouse_x = old_mouse_y = 0;
mouse_x_error = mouse_y_error = 0.0;
mouse_x_raw = mouse_y_raw = 0.0;
}
/* Initialize the mouse module. */
void
mouse_init(void)
{
/* Initialize local data. */
mouse_x = mouse_y = mouse_z = 0;
mouse_clear_coords();
mouse_buttons = 0x00;
mouse_type = MOUSE_TYPE_NONE;
@@ -159,6 +174,132 @@ mouse_close(void)
timer_stop(&mouse_timer);
}
static int
mouse_scale_coord_x(int x, int mul)
{
double temp_x = (double) x;
double ratio = (double) monitors[0].mon_unscaled_size_x / (double) monitors[0].mon_res_x;
if (mul)
temp_x *= ratio;
else
temp_x /= ratio;
return (int) temp_x;
}
static int
mouse_scale_coord_y(int y, int mul)
{
double temp_y = (double) y;
double ratio = (double) monitors[0].mon_efscrnsz_y / (double) monitors[0].mon_res_y;
if (mul)
temp_y *= ratio;
else
temp_y /= ratio;
return (int) temp_y;
}
/* It appears all host platforms give us y in the Microsoft format
(positive to the south), so for all non-Microsoft report formsts,
we have to invenrt that. */
void
mouse_subtract_coords(int *delta_x, int *delta_y, int *o_x, int *o_y,
int min, int max, int invert, int abs)
{
int real_x = mouse_x;
int real_y = mouse_y;
int smax_x;
int smax_y;
int rsmin_x;
int rsmin_y;
int smin_x;
int smin_y;
if (invert)
real_y = -real_y;
rsmin_x = mouse_scale_coord_x(min, 0);
rsmin_y = mouse_scale_coord_y(min, 0);
if (abs) {
smax_x = mouse_scale_coord_x(max, 0) + ABS(rsmin_x);
smax_y = mouse_scale_coord_y(max, 0) + ABS(rsmin_y);
max += ABS(min);
real_x += rsmin_x;
real_y += rsmin_y;
smin_x = 0;
smin_y = 0;
} else {
smax_x = mouse_scale_coord_x(max, 0);
smax_y = mouse_scale_coord_y(max, 0);
smin_x = rsmin_x;
smin_y = rsmin_y;
}
/* Default the X and Y overflows to 1. */
if (o_x != NULL)
*o_x = 1;
if (o_y != NULL)
*o_y = 1;
if (real_x > smax_x) {
if (abs)
*delta_x = mouse_scale_coord_x(real_x, 1);
else
*delta_x = max;
real_x -= smax_x;
} else if (real_x < smin_x) {
if (abs)
*delta_x = mouse_scale_coord_x(real_x, 1);
else
*delta_x = min;
real_x += ABS(smin_x);
} else {
if (abs)
*delta_x = mouse_scale_coord_x(real_x, 1);
else
*delta_x = mouse_scale_coord_x(real_x, 1);
real_x = 0;
if (o_x != NULL)
*o_x = 0;
}
if (real_y > smax_y) {
if (abs)
*delta_y = mouse_scale_coord_y(real_y, 1);
else
*delta_y = max;
real_y -= smax_y;
} else if (real_y < smin_y) {
if (abs)
*delta_y = mouse_scale_coord_y(real_y, 1);
else
*delta_y = min;
real_y += ABS(smin_y);
} else {
if (abs)
*delta_y = mouse_scale_coord_y(real_y, 1);
else
*delta_y = mouse_scale_coord_y(real_y, 1);
real_y = 0;
if (o_y != NULL)
*o_y = 0;
}
if (abs) {
real_x -= rsmin_x;
real_y -= rsmin_y;
}
if (invert)
real_y = -real_y;
mouse_x = real_x;
mouse_y = real_y;
}
static void
mouse_timer_poll(UNUSED(void *priv))
{
@@ -178,8 +319,11 @@ mouse_timer_poll(UNUSED(void *priv))
void
mouse_scale(int x, int y)
{
double scaled_x = (((double) x) * mouse_sensitivity) + mouse_x_error;
double scaled_y = (((double) y) * mouse_sensitivity) + mouse_y_error;
double scaled_x = (((double) x) * mouse_sensitivity);
double scaled_y = (((double) y) * mouse_sensitivity);
scaled_x += mouse_x_error;
scaled_y += mouse_y_error;
mouse_x += (int) scaled_x;
mouse_y += (int) scaled_y;
@@ -191,21 +335,25 @@ mouse_scale(int x, int y)
void
mouse_scale_x(int x)
{
double scaled_x = ((double) x) * mouse_sensitivity + mouse_x_error;
double scaled_x = (((double) x) * mouse_sensitivity);
scaled_x += mouse_x_error;
mouse_x += (int) scaled_x;
mouse_x_error = scaled_x - ((double) mouse_x);
mouse_x_error = scaled_x - floor(scaled_x);
}
void
mouse_scale_y(int y)
{
double scaled_y = ((double) y) * mouse_sensitivity + mouse_y_error;
double scaled_y = (((double) y) * mouse_sensitivity);
scaled_y += mouse_y_error;
mouse_y += (int) scaled_y;
mouse_y_error = scaled_y - ((double) mouse_y);
mouse_y_error = scaled_y - floor(scaled_y);
}
void
@@ -248,7 +396,7 @@ mouse_reset(void)
mouse_type, mouse_devices[mouse_type].device->name);
/* Clear local data. */
mouse_x = mouse_y = mouse_z = 0;
mouse_clear_coords();
mouse_buttons = 0x00;
mouse_mode = 0;
mouse_timed = 1;
@@ -292,8 +440,7 @@ mouse_process(void)
if ((mouse_mode >= 1) && mouse_poll_ex)
mouse_poll_ex();
if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) {
else if ((mouse_mode == 0) && ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL))) {
if (mouse_curr->poll != NULL)
mouse_curr->poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_x_abs, mouse_y_abs, mouse_priv);
else

View File

@@ -478,7 +478,9 @@ static int
bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double abs_y), void *priv)
{
mouse_t *dev = (mouse_t *) priv;
int xor ;
int delta_x;
int delta_y;
int xor;
if (!mouse_capture && !video_fullscreen)
return 1;
@@ -514,27 +516,10 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
if (!dev->timer_enabled) {
/* If the counters are not frozen, update them. */
if (!(dev->flags & FLAG_HOLD)) {
if (mouse_x > 127) {
dev->current_x = 127;
mouse_x -= 127;
} else if (mouse_x < 1-128) {
dev->current_x = -128;
mouse_x += 128;
} else {
dev->current_x = mouse_x;
mouse_x = 0;
}
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0);
if (mouse_y > 127) {
dev->current_y = 127;
mouse_y -= 127;
} else if (mouse_y < 1-128) {
dev->current_y = -128;
mouse_y += 128;
} else {
dev->current_y = mouse_y;
mouse_y = 0;
}
dev->current_x = (int8_t) delta_x;
dev->current_y = (int8_t) delta_y;
dev->current_b = dev->mouse_buttons;
}
@@ -561,27 +546,7 @@ bm_update_data(mouse_t *dev)
/* If the counters are not frozen, update them. */
if ((mouse_capture || video_fullscreen) && !(dev->flags & FLAG_HOLD)) {
/* Update the deltas and the delays. */
if (mouse_x > 127) {
delta_x = 127;
mouse_x -= 127;
} else if (mouse_x < -128) {
delta_x = -128;
mouse_x += 128;
} else {
delta_x = mouse_x;
mouse_x = 0;
}
if (mouse_y > 127) {
delta_y = 127;
mouse_y -= 127;
} else if (mouse_y < -128) {
delta_y = -128;
mouse_y += 128;
} else {
delta_y = mouse_y;
mouse_y = 0;
}
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0);
dev->current_x = (int8_t) delta_x;
dev->current_y = (int8_t) delta_y;

View File

@@ -75,35 +75,19 @@ static void
ps2_report_coordinates(atkbc_dev_t *dev, int main)
{
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
int delta_x;
int delta_y;
int overflow_x;
int overflow_y;
int temp_z;
if (mouse_x > 255) {
buff[0] |= 0x40;
buff[1] = 255;
mouse_x -= 255;
} else if (mouse_x < -256) {
buff[0] |= (0x40 | 0x10);
mouse_x += 256;
} else {
if (mouse_x < 0)
buff[0] |= 0x10;
buff[1] = mouse_x;
mouse_x = 0;
}
if (mouse_y < -255) {
buff[0] |= 0x80;
buff[2] = 255;
mouse_y += 255;
} else if (mouse_y > 256) {
buff[0] |= (0x80 | 0x20);
mouse_y -= 256;
} else {
if (mouse_y > 0)
buff[0] |= 0x20;
buff[2] = -mouse_y;
mouse_y = 0;
}
mouse_subtract_coords(&delta_x, &delta_y, &overflow_x, &overflow_y,
-256, 255, 1, 0);
buff[0] = (overflow_y << 7) | (overflow_x << 6) |
((delta_y & 0x0100) >> 3) | ((delta_x & 0x0100) >> 4) |
(mouse_buttons & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
buff[1] = (delta_x & 0x00ff);
buff[2] = (delta_y & 0x00ff);
if (dev->z < -7) {
temp_z = 7;
@@ -116,8 +100,6 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
mouse_z = 0;
}
buff[0] |= (mouse_buttons & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
kbc_at_dev_queue_add(dev, buff[0], main);
kbc_at_dev_queue_add(dev, buff[1], main);
kbc_at_dev_queue_add(dev, buff[2], main);

View File

@@ -82,8 +82,6 @@ typedef struct mouse_t {
int8_t type; /* type of this device */
int8_t port;
int abs_x;
int abs_y;
int old_buttons;
int state;
int bps;
@@ -177,89 +175,13 @@ sermouse_transmit(mouse_t *dev, int len, int from_report, int to_report)
sermouse_set_period(dev, dev->transmit_period);
}
/* It appears all host platforms give us y in the Microsoft format
(positive to the south), so for all non-Microsoft report formsts,
we have to invenrt that. */
static void
sermouse_subtract_coords(mouse_t *dev, int *delta_x, int *delta_y, int min, int max, int invert, int abs)
{
int real_y = mouse_y;
int abs_max = max + ABS(min);
if (invert)
real_y = -real_y;
if (mouse_x > max) {
if (abs) {
dev->abs_x += max;
*delta_x = dev->abs_x;
} else
*delta_x = max;
mouse_x -= max;
} else if (mouse_x < min) {
if (abs) {
dev->abs_x += min;
*delta_x = dev->abs_x;
} else
*delta_x = min;
mouse_x += ABS(min);
} else {
if (abs) {
dev->abs_x += mouse_x;
*delta_x = dev->abs_x;
} else
*delta_x = mouse_x;
mouse_x = 0;
}
if (real_y > max) {
if (abs) {
dev->abs_y += max;
*delta_y = dev->abs_y;
} else
*delta_y = max;
real_y -= max;
} else if (real_y < min) {
if (abs) {
dev->abs_y += min;
*delta_y = dev->abs_y;
} else
*delta_y = min;
real_y += ABS(min);
} else {
if (abs) {
dev->abs_y += real_y;
*delta_y = dev->abs_y;
} else
*delta_y = real_y;
real_y = 0;
}
if (abs) {
if (dev->abs_x < 0)
*delta_x = 0;
else if (dev->abs_x > abs_max)
*delta_x = abs_max;
if (dev->abs_y < 0)
*delta_y = 0;
else if (dev->abs_y > abs_max)
*delta_y = abs_max;
}
if (invert)
real_y = -real_y;
mouse_y = real_y;
}
static uint8_t
sermouse_report_msystems(mouse_t *dev)
{
int delta_x = 0;
int delta_y = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -128, 127, 1, 0);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0);
dev->buf[0] = 0x80;
dev->buf[0] |= (mouse_buttons & 0x01) ? 0x00 : 0x04; /* left button */
@@ -282,7 +204,7 @@ sermouse_report_3bp(mouse_t *dev)
int delta_x = 0;
int delta_y = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -128, 127, 1, 0);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0);
dev->buf[0] = 0x80;
dev->buf[0] |= (mouse_buttons & 0x01) ? 0x04 : 0x00; /* left button */
@@ -303,7 +225,7 @@ sermouse_report_mmseries(mouse_t *dev)
int delta_x = 0;
int delta_y = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -127, 127, 1, 0);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -127, 127, 1, 0);
dev->buf[0] = 0x80;
if (delta_x >= 0)
@@ -328,7 +250,7 @@ sermouse_report_bp1(mouse_t *dev, int abs)
int delta_x = 0;
int delta_y = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -2048, 2047, 1, abs);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -2048, 2047, 1, abs);
dev->buf[0] = 0x80;
dev->buf[0] |= (mouse_buttons & 0x01) ? 0x10 : 0x00; /* left button */
@@ -351,7 +273,7 @@ sermouse_report_ms(mouse_t *dev)
int delta_y = 0;
int delta_z = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -128, 127, 0, 0);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0);
dev->buf[0] = 0x40;
dev->buf[0] |= (((delta_y >> 6) & 0x03) << 2);
@@ -409,7 +331,7 @@ sermouse_report_hex(mouse_t *dev)
int delta_x = 0;
int delta_y = 0;
sermouse_subtract_coords(dev, &delta_x, &delta_y, -128, 127, 1, 0);
mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0);
but |= (mouse_buttons & 0x01) ? 0x04 : 0x00; /* left button */
if (dev->but >= 3)
@@ -669,7 +591,7 @@ ltsermouse_process_command(mouse_t *dev)
case 0x41:
/* Absolute Bit Pad One Packed Binary Format */
dev->abs_x = dev->abs_y = 0;
mouse_clear_coords();
fallthrough;
case 0x42: /* Relative Bit Pad One Packed Binary Format */
case 0x53: /* MM Series Data Format */