Merge pull request #3010 from Cacodemon345/qt-wacom-serial
Add Wacom SD-510C tablet emulation
This commit is contained in:
@@ -1130,6 +1130,8 @@ pc_reset_hard_init(void)
|
||||
#endif
|
||||
|
||||
update_mouse_msg();
|
||||
|
||||
ui_hard_reset_completed();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1277,7 +1279,7 @@ pc_run(void)
|
||||
}
|
||||
|
||||
if (title_update) {
|
||||
mouse_msg_idx = (mouse_type == MOUSE_TYPE_NONE) ? 2 : !!mouse_capture;
|
||||
mouse_msg_idx = ((mouse_type == MOUSE_TYPE_NONE) || (mouse_mode >= 1)) ? 2 : !!mouse_capture;
|
||||
swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps);
|
||||
#ifdef __APPLE__
|
||||
/* Needed due to modifying the UI on the non-main thread is a big no-no. */
|
||||
|
@@ -656,6 +656,8 @@ load_input_devices(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tablet_tool_type = !!ini_section_get_int(cat, "tablet_tool_type", 1);
|
||||
}
|
||||
|
||||
/* Load "Sound" section. */
|
||||
@@ -2338,6 +2340,12 @@ save_input_devices(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (tablet_tool_type != 1) {
|
||||
ini_section_set_int(cat, "tablet_tool_type", tablet_tool_type);
|
||||
} else {
|
||||
ini_section_delete_var(cat, "tablet_tool_type");
|
||||
}
|
||||
|
||||
ini_delete_section_if_empty(config, cat);
|
||||
}
|
||||
|
||||
|
@@ -463,7 +463,7 @@ device_poll(const device_t *d, int x, int y, int z, int b)
|
||||
if (devices[c] != NULL) {
|
||||
if (devices[c] == d) {
|
||||
if (devices[c]->poll)
|
||||
return (devices[c]->poll(x, y, z, b, device_priv[c]));
|
||||
return (devices[c]->poll(x, y, z, b, 0, 0, device_priv[c]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h
|
||||
postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
|
||||
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c
|
||||
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c
|
||||
serial_passthrough.c)
|
||||
mouse_wacom_tablet.c serial_passthrough.c)
|
||||
|
||||
if(ISAMEM_RAMPAGE)
|
||||
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)
|
||||
|
@@ -37,7 +37,14 @@ int mouse_type = 0;
|
||||
int mouse_x,
|
||||
mouse_y,
|
||||
mouse_z,
|
||||
mouse_buttons;
|
||||
mouse_buttons,
|
||||
mouse_mode,
|
||||
mouse_tablet_in_proximity = 0,
|
||||
tablet_tool_type = 1; /* 0 = Puck/Cursor, 1 = Pen */
|
||||
|
||||
double mouse_x_abs,
|
||||
mouse_y_abs;
|
||||
|
||||
|
||||
static const device_t mouse_none_device = {
|
||||
.name = "None",
|
||||
@@ -80,6 +87,7 @@ static mouse_t mouse_devices[] = {
|
||||
{ &mouse_msserial_device },
|
||||
{ &mouse_ltserial_device },
|
||||
{ &mouse_ps2_device },
|
||||
{ &mouse_wacom_device },
|
||||
{ NULL }
|
||||
// clang-format on
|
||||
};
|
||||
@@ -147,6 +155,7 @@ mouse_reset(void)
|
||||
/* Clear local data. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
mouse_buttons = 0x00;
|
||||
mouse_mode = 0;
|
||||
|
||||
/* If no mouse configured, we're done. */
|
||||
if (mouse_type == 0)
|
||||
@@ -184,7 +193,7 @@ mouse_process(void)
|
||||
|
||||
if ((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_priv);
|
||||
mouse_curr->poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_x_abs, mouse_y_abs, mouse_priv);
|
||||
else
|
||||
mouse_dev_poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_priv);
|
||||
|
||||
|
@@ -449,7 +449,7 @@ ms_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
bm_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
int xor ;
|
||||
|
@@ -267,7 +267,7 @@ mouse_reset:
|
||||
}
|
||||
|
||||
static int
|
||||
ps2_poll(int x, int y, int z, int b, void *priv)
|
||||
ps2_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
|
||||
|
@@ -511,7 +511,7 @@ sermouse_command_timer(void *priv)
|
||||
}
|
||||
|
||||
static int
|
||||
sermouse_poll(int x, int y, int z, int b, void *priv)
|
||||
sermouse_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
|
||||
|
432
src/device/mouse_wacom_tablet.c
Normal file
432
src/device/mouse_wacom_tablet.c
Normal file
@@ -0,0 +1,432 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/plat.h>
|
||||
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
|
||||
enum wacom_modes
|
||||
{
|
||||
WACOM_MODE_SUPPRESSED = 0,
|
||||
WACOM_MODE_POINT = 1,
|
||||
WACOM_MODE_STREAM = 2,
|
||||
WACOM_MODE_SWITCH = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
REPORT_PHASE_PREPARE,
|
||||
REPORT_PHASE_TRANSMIT
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type, /* type of this device */
|
||||
port;
|
||||
uint8_t flags, but, /* device flags */
|
||||
status, format,
|
||||
data_len, data[64],
|
||||
data_rec[0x200];
|
||||
int abs_x, abs_y,
|
||||
rel_x, rel_y,
|
||||
oldb, b;
|
||||
|
||||
int data_pos, data_rec_pos, mode, transmission_ongoing, transmission_format, interval;
|
||||
int increment, suppressed_increment;
|
||||
int transmission_stopped;
|
||||
int reset;
|
||||
int transmit_id, transmit_id_pending;
|
||||
int pressure_mode;
|
||||
int suppressed, measurement, always_report;
|
||||
int remote_req, remote_mode;
|
||||
|
||||
int last_abs_x, last_abs_y; /* Suppressed/Increment Mode. */
|
||||
uint32_t settings; /* Settings DWORD */
|
||||
|
||||
double transmit_period;
|
||||
double old_tsc, reset_tsc;
|
||||
pc_timer_t report_timer;
|
||||
|
||||
serial_t *serial;
|
||||
} mouse_wacom_t;
|
||||
|
||||
static double
|
||||
wacom_transmit_period(mouse_wacom_t *dev, int bps, int rps)
|
||||
{
|
||||
double dbps = (double) bps;
|
||||
double temp = 0.0;
|
||||
int word_len = 10;
|
||||
|
||||
if (rps == -1)
|
||||
temp = (double) word_len;
|
||||
else {
|
||||
temp = (double) rps;
|
||||
temp = (9600.0 - (temp * 33.0));
|
||||
temp /= rps;
|
||||
}
|
||||
temp = (1000000.0 / dbps) * temp;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_reset(mouse_wacom_t* wacom)
|
||||
{
|
||||
wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1);
|
||||
wacom->mode = WACOM_MODE_POINT;
|
||||
wacom->data_pos = 0;
|
||||
wacom->transmission_ongoing = 0;
|
||||
wacom->mode = 0;
|
||||
wacom->transmission_stopped = 0;
|
||||
wacom->interval = 0;
|
||||
wacom->transmit_id = 0;
|
||||
wacom->format = 0; /* ASCII */
|
||||
wacom->measurement = 1;
|
||||
wacom->increment = wacom->suppressed_increment = 0;
|
||||
wacom->reset_tsc = tsc;
|
||||
wacom->remote_mode = wacom->remote_req = 0;
|
||||
wacom->always_report = 0;
|
||||
|
||||
mouse_mode = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_callback(struct serial_s *serial, void *priv)
|
||||
{
|
||||
mouse_wacom_t* wacom = (mouse_wacom_t*)priv;
|
||||
|
||||
wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1);
|
||||
timer_stop(&wacom->report_timer);
|
||||
timer_on_auto(&wacom->report_timer, wacom->transmit_period);
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_write(struct serial_s *serial, void *priv, uint8_t data)
|
||||
{
|
||||
mouse_wacom_t* wacom = (mouse_wacom_t*)priv;
|
||||
static int special_command = 0;
|
||||
|
||||
if (data == '~') {
|
||||
special_command = 1;
|
||||
return;
|
||||
}
|
||||
if (special_command) {
|
||||
switch (data) {
|
||||
case '#':
|
||||
{
|
||||
if (!wacom->transmission_ongoing) wacom->transmit_id++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
special_command = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == '@') {
|
||||
wacom->remote_req = 1;
|
||||
wacom->remote_mode = 1;
|
||||
return;
|
||||
}
|
||||
if (data == 0x13) {
|
||||
wacom->transmission_stopped = 1;
|
||||
return;
|
||||
}
|
||||
if (data == 0x11) {
|
||||
wacom->transmission_stopped = 0;
|
||||
wacom->remote_mode = wacom->remote_req = 0;
|
||||
return;
|
||||
}
|
||||
wacom->data_rec[wacom->data_rec_pos++] = data;
|
||||
if (data == '\r' || data == '\n') {
|
||||
wacom->data_rec[wacom->data_rec_pos] = 0;
|
||||
wacom->data_rec_pos = 0;
|
||||
|
||||
if (data == '\n') pclog("Wacom: written %s", wacom->data_rec);
|
||||
else pclog("Wacom: written %s\n", wacom->data_rec);
|
||||
if (!memcmp(wacom->data_rec, "AS", 2)) {
|
||||
wacom->format = (wacom->data_rec[2] == '1');
|
||||
wacom->transmission_ongoing = 0;
|
||||
} else if (!memcmp(wacom->data_rec, "SR", 2)) {
|
||||
wacom->mode = WACOM_MODE_STREAM;
|
||||
wacom->suppressed_increment = 0;
|
||||
} else if (!memcmp(wacom->data_rec, "IN", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "IN%d", &wacom->increment);
|
||||
} else if (!memcmp(wacom->data_rec, "RE", 2) || wacom->data_rec[0] == '$' || wacom->data_rec[0] == '#') {
|
||||
wacom_reset(wacom);
|
||||
} else if (!memcmp(wacom->data_rec, "IT", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "IT%d", &wacom->interval);
|
||||
} else if (!memcmp(wacom->data_rec, "DE", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "DE%d", &mouse_mode);
|
||||
mouse_mode = !mouse_mode;
|
||||
plat_mouse_capture(0);
|
||||
} else if (!memcmp(wacom->data_rec, "SU", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "SU%d", &wacom->suppressed_increment);
|
||||
} else if (!memcmp(wacom->data_rec, "PH", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "PH%d", &wacom->pressure_mode);
|
||||
} else if (!memcmp(wacom->data_rec, "IC", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "IC%d", &wacom->measurement);
|
||||
} else if (!memcmp(wacom->data_rec, "AL", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "AL%d", &wacom->always_report);
|
||||
} else if (!memcmp(wacom->data_rec, "RQ", 2)) {
|
||||
sscanf((const char*)wacom->data_rec, "RQ%d", &wacom->remote_mode);
|
||||
if (wacom->remote_mode) wacom->remote_req = 1;
|
||||
} else if (!memcmp(wacom->data_rec, "SP", 2)) {
|
||||
wacom->transmission_stopped = 1;
|
||||
} else if (!memcmp(wacom->data_rec, "ST", 2)){
|
||||
wacom->transmission_stopped = 0;
|
||||
wacom->remote_mode = wacom->remote_req = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wacom_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv)
|
||||
{
|
||||
mouse_wacom_t* wacom = (mouse_wacom_t*)priv;
|
||||
wacom->abs_x = abs_x * (wacom->measurement ? 4566. : 5800.);
|
||||
wacom->abs_y = abs_y * (wacom->measurement ? 2972. : 3774.);
|
||||
if (wacom->abs_x > (wacom->measurement ? 4566 : 5800)) wacom->abs_x = (wacom->measurement ? 4566 : 5800);
|
||||
if (wacom->abs_y > (wacom->measurement ? 2972 : 3774)) wacom->abs_x = (wacom->measurement ? 2972 : 3774);
|
||||
if (wacom->abs_x < 0) wacom->abs_x = 0;
|
||||
if (wacom->abs_y < 0) wacom->abs_y = 0;
|
||||
wacom->rel_x = x;
|
||||
wacom->rel_y = y;
|
||||
if (wacom->b != b) wacom->oldb = wacom->b;
|
||||
wacom->b = b;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
wacom_switch_off_to_on(int b, int oldb)
|
||||
{
|
||||
if (!(oldb & 0x1) && (b & 1)) return 1;
|
||||
if (!(oldb & 0x2) && (b & 2)) return 1;
|
||||
if (!(oldb & 0x4) && (b & 4)) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
wacom_get_switch(int b)
|
||||
{
|
||||
if (b & 0x4) return 0x23;
|
||||
if (b & 0x2) return 0x22;
|
||||
if (b & 0x1) return 0x21;
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_transmit_prepare(mouse_wacom_t* wacom, int x, int y)
|
||||
{
|
||||
wacom->transmission_ongoing = 1;
|
||||
wacom->data_pos = 0;
|
||||
memset(wacom->data, 0, sizeof(wacom->data));
|
||||
if (wacom->transmit_id) {
|
||||
wacom->transmission_format = 0;
|
||||
snprintf((char*)wacom->data, sizeof(wacom->data), "~#SD51C V3.2.1.01\r");
|
||||
return;
|
||||
}
|
||||
wacom->transmission_format = wacom->format;
|
||||
wacom->last_abs_x = wacom->abs_x;
|
||||
wacom->last_abs_y = wacom->abs_y;
|
||||
wacom->remote_req = 0;
|
||||
|
||||
wacom->oldb = wacom->b;
|
||||
if (wacom->format == 1) {
|
||||
wacom->data[0] = 0xC0;
|
||||
wacom->data[6] = wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t)31 : (uint8_t)-31) : wacom_get_switch(wacom->b);
|
||||
|
||||
wacom->data[5] = (y & 0x7F);
|
||||
wacom->data[4] = ((y & 0x3F80) >> 7) & 0x7F;
|
||||
wacom->data[3] = (((y & 0xC000) >> 14) & 3);
|
||||
|
||||
wacom->data[2] = (x & 0x7F);
|
||||
wacom->data[1] = ((x & 0x3F80) >> 7) & 0x7F;
|
||||
wacom->data[0] |= (((x & 0xC000) >> 14) & 3);
|
||||
|
||||
if (mouse_mode == 0) {
|
||||
wacom->data[0] |= (!!(x < 0)) << 2;
|
||||
wacom->data[3] |= (!!(y < 0)) << 2;
|
||||
}
|
||||
|
||||
if (wacom->pressure_mode) {
|
||||
wacom->data[0] |= 0x10;
|
||||
wacom->data[6] &= 0x7F;
|
||||
}
|
||||
|
||||
if (tablet_tool_type == 1) {
|
||||
wacom->data[0] |= 0x20;
|
||||
}
|
||||
|
||||
if (!mouse_tablet_in_proximity) {
|
||||
wacom->data[0] &= ~0x40;
|
||||
}
|
||||
} else {
|
||||
wacom->data[0] = 0;
|
||||
snprintf((char*)wacom->data, sizeof(wacom->data), "*,%05d,%05d,%d\r\n",
|
||||
wacom->abs_x, wacom->abs_y,
|
||||
wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t)-31 : (uint8_t)15) : ((wacom->b & 0x1) ? 21 : 00));
|
||||
}
|
||||
}
|
||||
|
||||
extern double cpuclock;
|
||||
static void
|
||||
wacom_report_timer(void *priv)
|
||||
{
|
||||
mouse_wacom_t* wacom = (mouse_wacom_t*)priv;
|
||||
double milisecond_diff = ((double)(tsc - wacom->old_tsc)) / cpuclock * 1000.0;
|
||||
int relative_mode = (mouse_mode == 0);
|
||||
int x = (relative_mode ? wacom->rel_x : wacom->abs_x);
|
||||
int y = (relative_mode ? wacom->rel_y : wacom->abs_y);
|
||||
int x_diff = abs(relative_mode ? wacom->rel_x : (wacom->abs_x - wacom->last_abs_x));
|
||||
int y_diff = abs(relative_mode ? wacom->rel_y : (wacom->abs_y - wacom->last_abs_y));
|
||||
int increment = wacom->suppressed_increment ? wacom->suppressed_increment : wacom->increment;
|
||||
|
||||
timer_on_auto(&wacom->report_timer, wacom->transmit_period);
|
||||
if ((((double)(tsc - wacom->reset_tsc)) / cpuclock * 1000.0) <= 10)
|
||||
return;
|
||||
if (wacom->transmit_id && !wacom->transmission_ongoing)
|
||||
goto transmit_prepare;
|
||||
if (wacom->transmission_ongoing)
|
||||
goto transmit;
|
||||
else if (wacom->remote_mode && !wacom->remote_req)
|
||||
return;
|
||||
else {
|
||||
if (wacom->remote_mode && wacom->remote_req) {
|
||||
goto transmit_prepare;
|
||||
}
|
||||
if (wacom->transmission_stopped || (!mouse_tablet_in_proximity && !wacom->always_report))
|
||||
return;
|
||||
|
||||
if (milisecond_diff >= (wacom->interval * 5)) {
|
||||
wacom->old_tsc = tsc;
|
||||
} else
|
||||
return;
|
||||
|
||||
switch (wacom->mode) {
|
||||
case WACOM_MODE_STREAM:
|
||||
default:
|
||||
break;
|
||||
|
||||
case WACOM_MODE_POINT:
|
||||
{
|
||||
if (!(wacom_switch_off_to_on(wacom->b, wacom->oldb)))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
case WACOM_MODE_SWITCH:
|
||||
{
|
||||
if (!wacom->b)
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (increment && !(x_diff > increment || y_diff > increment)) {
|
||||
if (wacom->suppressed_increment && (wacom->b == wacom->oldb))
|
||||
return;
|
||||
|
||||
if (wacom->increment && !wacom_switch_off_to_on(wacom->b, wacom->oldb))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transmit_prepare:
|
||||
wacom_transmit_prepare(wacom, x, y);
|
||||
|
||||
transmit:
|
||||
serial_write_fifo(wacom->serial, wacom->data[wacom->data_pos++]);
|
||||
if ((wacom->transmission_format == 0 && wacom->data[wacom->data_pos] == 0)
|
||||
|| (wacom->transmission_format == 1 && wacom->data_pos == 7)) {
|
||||
wacom->transmission_ongoing = 0;
|
||||
wacom->transmit_id = 0;
|
||||
wacom->data_pos = 0;
|
||||
wacom->old_tsc = tsc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
wacom_init(const device_t *info)
|
||||
{
|
||||
mouse_wacom_t *dev;
|
||||
|
||||
dev = (mouse_wacom_t *) calloc(1, sizeof(mouse_wacom_t));
|
||||
dev->name = info->name;
|
||||
dev->but = 3;
|
||||
|
||||
dev->port = device_get_config_int("port");
|
||||
|
||||
dev->serial = serial_attach(dev->port, wacom_callback, wacom_write, dev);
|
||||
timer_add(&dev->report_timer, wacom_report_timer, dev, 0);
|
||||
mouse_set_buttons(dev->but);
|
||||
|
||||
wacom_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_speed_changed(void *priv)
|
||||
{
|
||||
mouse_wacom_t *dev = (mouse_wacom_t *) priv;
|
||||
|
||||
wacom_callback(dev->serial, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
wacom_close(void *priv)
|
||||
{
|
||||
mouse_wacom_t *dev = (mouse_wacom_t *) priv;
|
||||
|
||||
/* Detach serial port from the mouse. */
|
||||
if (dev && dev->serial && dev->serial->sd)
|
||||
memset(dev->serial->sd, 0, sizeof(serial_device_t));
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static const device_config_t wacom_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "port",
|
||||
.description = "Serial Port",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 0,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "COM1", .value = 0 },
|
||||
{ .description = "COM2", .value = 1 },
|
||||
{ .description = "COM3", .value = 2 },
|
||||
{ .description = "COM4", .value = 3 },
|
||||
{ .description = "" }
|
||||
}
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
const device_t mouse_wacom_device = {
|
||||
.name = "Wacom SD-510C",
|
||||
.internal_name = "wacom_serial",
|
||||
.flags = DEVICE_COM,
|
||||
.local = MOUSE_TYPE_WACOM,
|
||||
.init = wacom_init,
|
||||
.close = wacom_close,
|
||||
.reset = NULL,
|
||||
{ .poll = wacom_poll },
|
||||
.speed_changed = wacom_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = wacom_config
|
||||
};
|
@@ -130,7 +130,7 @@ typedef struct _device_ {
|
||||
void (*reset)(void *priv);
|
||||
union {
|
||||
int (*available)(void);
|
||||
int (*poll)(int x, int y, int z, int b, void *priv);
|
||||
int (*poll)(int x, int y, int z, int b, double abs_x, double abs_y, void *priv);
|
||||
void (*register_pci_slot)(int device, int type, int inta, int intb, int intc, int intd, void *priv);
|
||||
};
|
||||
void (*speed_changed)(void *priv);
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#define MOUSE_TYPE_LOGITECH 9 /* Logitech 2-button Serial Mouse */
|
||||
#define MOUSE_TYPE_LT3BUTTON 10 /* Logitech 3-button Serial Mouse */
|
||||
#define MOUSE_TYPE_PS2 11 /* PS/2 series Bus Mouse */
|
||||
#define MOUSE_TYPE_WACOM 12 /* WACOM tablet */
|
||||
|
||||
#define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */
|
||||
|
||||
@@ -43,7 +44,11 @@ extern "C" {
|
||||
|
||||
extern int mouse_type;
|
||||
extern int mouse_x, mouse_y, mouse_z;
|
||||
extern int mouse_mode; /* 1 = Absolute, 0 = Relative */
|
||||
extern int mouse_tablet_in_proximity;
|
||||
extern double mouse_x_abs, mouse_y_abs;
|
||||
extern int mouse_buttons;
|
||||
extern int tablet_tool_type;
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *mouse_get_device(int mouse);
|
||||
@@ -59,6 +64,7 @@ extern const device_t mouse_mssystems_device;
|
||||
extern const device_t mouse_msserial_device;
|
||||
extern const device_t mouse_ltserial_device;
|
||||
extern const device_t mouse_ps2_device;
|
||||
extern const device_t mouse_wacom_device;
|
||||
#endif
|
||||
|
||||
extern void mouse_init(void);
|
||||
|
@@ -61,6 +61,7 @@ extern void ui_check_menu_item(int id, int checked);
|
||||
|
||||
extern wchar_t *ui_window_title(wchar_t *s);
|
||||
extern void ui_status_update(void);
|
||||
extern void ui_hard_reset_completed(void);
|
||||
extern void ui_init_monitor(int monitor_index);
|
||||
extern void ui_deinit_monitor(int monitor_index);
|
||||
extern int ui_sb_find_part(int tag);
|
||||
|
@@ -250,7 +250,6 @@ main(int argc, char *argv[])
|
||||
auto rawInputFilter = WindowsRawInputFilter::Register(main_window);
|
||||
if (rawInputFilter) {
|
||||
app.installNativeEventFilter(rawInputFilter.get());
|
||||
QObject::disconnect(main_window, &MainWindow::pollMouse, 0, 0);
|
||||
QObject::connect(main_window, &MainWindow::pollMouse, (WindowsRawInputFilter *) rawInputFilter.get(), &WindowsRawInputFilter::mousePoll, Qt::DirectConnection);
|
||||
main_window->setSendKeyboardInput(false);
|
||||
}
|
||||
|
@@ -44,6 +44,7 @@ extern "C" {
|
||||
#endif
|
||||
#include <86box/device.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/vid_ega.h>
|
||||
#include <86box/version.h>
|
||||
@@ -193,6 +194,12 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
vmname.truncate(vmname.size() - 1);
|
||||
this->setWindowTitle(QString("%1 - %2 %3").arg(vmname, EMU_NAME, EMU_VERSION_FULL));
|
||||
|
||||
connect(this, &MainWindow::hardResetCompleted, this, [this]() {
|
||||
ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA));
|
||||
QApplication::setOverrideCursor(Qt::ArrowCursor);
|
||||
ui->menuTablet_tool->menuAction()->setVisible(mouse_mode >= 1);
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::BlockingQueuedConnection);
|
||||
|
||||
connect(this, &MainWindow::setTitle, this, [this, toolbar_label](const QString &title) {
|
||||
@@ -631,6 +638,16 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
actGroup = new QActionGroup(this);
|
||||
actGroup->addAction(ui->actionCursor_Puck);
|
||||
actGroup->addAction(ui->actionPen);
|
||||
|
||||
if (tablet_tool_type == 1) {
|
||||
ui->actionPen->setChecked(true);
|
||||
} else {
|
||||
ui->actionCursor_Puck->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2435,8 +2452,19 @@ MainWindow::on_actionApply_fullscreen_stretch_mode_when_maximized_triggered(bool
|
||||
config_save();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCursor_Puck_triggered()
|
||||
{
|
||||
tablet_tool_type = 0;
|
||||
config_save();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPen_triggered()
|
||||
{
|
||||
tablet_tool_type = 1;
|
||||
config_save();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionACPI_Shutdown_triggered()
|
||||
{
|
||||
acpi_pwrbut_pressed = 1;
|
||||
}
|
||||
|
||||
|
@@ -50,6 +50,7 @@ signals:
|
||||
void destroyRendererMonitor(int monitor_index);
|
||||
void initRendererMonitorForNonQtThread(int monitor_index);
|
||||
void destroyRendererMonitorForNonQtThread(int monitor_index);
|
||||
void hardResetCompleted();
|
||||
|
||||
void setTitle(const QString &title);
|
||||
void setFullscreen(bool state);
|
||||
@@ -135,6 +136,11 @@ protected:
|
||||
void changeEvent(QEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void on_actionPen_triggered();
|
||||
|
||||
private slots:
|
||||
void on_actionCursor_Puck_triggered();
|
||||
|
||||
void on_actionACPI_Shutdown_triggered();
|
||||
|
||||
private slots:
|
||||
|
@@ -61,8 +61,16 @@
|
||||
<property name="title">
|
||||
<string>&Action</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuTablet_tool">
|
||||
<property name="title">
|
||||
<string>Tablet tool</string>
|
||||
</property>
|
||||
<addaction name="actionPen"/>
|
||||
<addaction name="actionCursor_Puck"/>
|
||||
</widget>
|
||||
<addaction name="actionKeyboard_requires_capture"/>
|
||||
<addaction name="actionRight_CTRL_is_left_ALT"/>
|
||||
<addaction name="menuTablet_tool"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionHard_Reset"/>
|
||||
<addaction name="actionCtrl_Alt_Del"/>
|
||||
@@ -851,6 +859,22 @@
|
||||
<string>Apply fullscreen stretch mode when maximized</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCursor_Puck">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cursor/Puck</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPen">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pen</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@@ -58,8 +58,10 @@ double mouse_x_error = 0.0, mouse_y_error = 0.0;
|
||||
}
|
||||
|
||||
struct mouseinputdata {
|
||||
atomic_int deltax, deltay, deltaz;
|
||||
atomic_int mousebuttons;
|
||||
atomic_int deltax, deltay, deltaz;
|
||||
atomic_int mousebuttons;
|
||||
atomic_bool mouse_tablet_in_proximity;
|
||||
std::atomic<double> x_abs, y_abs;
|
||||
};
|
||||
static mouseinputdata mousedata;
|
||||
|
||||
@@ -116,6 +118,7 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index)
|
||||
|
||||
RendererStack::~RendererStack()
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@@ -141,10 +144,17 @@ qt_mouse_capture(int on)
|
||||
void
|
||||
RendererStack::mousePoll()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (mouse_mode == 0) {
|
||||
mouse_x_abs = mousedata.x_abs;
|
||||
mouse_y_abs = mousedata.y_abs;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifndef __APPLE__
|
||||
mouse_x = mousedata.deltax;
|
||||
mouse_y = mousedata.deltay;
|
||||
mouse_z = mousedata.deltaz;
|
||||
mouse_x = mousedata.deltax;
|
||||
mouse_y = mousedata.deltay;
|
||||
mouse_z = mousedata.deltaz;
|
||||
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
|
||||
mouse_buttons = mousedata.mousebuttons;
|
||||
|
||||
@@ -152,6 +162,10 @@ RendererStack::mousePoll()
|
||||
#endif
|
||||
this->mouse_poll_func();
|
||||
|
||||
mouse_x_abs = mousedata.x_abs;
|
||||
mouse_y_abs = mousedata.y_abs;
|
||||
mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity;
|
||||
|
||||
double scaled_x = mouse_x * mouse_sensitivity + mouse_x_error;
|
||||
double scaled_y = mouse_y * mouse_sensitivity + mouse_y_error;
|
||||
|
||||
@@ -166,7 +180,7 @@ int ignoreNextMouseEvent = 1;
|
||||
void
|
||||
RendererStack::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1) && (mouse_get_buttons() != 0)) {
|
||||
if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1) && (mouse_get_buttons() != 0) && mouse_mode == 0) {
|
||||
plat_mouse_capture(1);
|
||||
this->setCursor(Qt::BlankCursor);
|
||||
if (!ignoreNextMouseEvent)
|
||||
@@ -180,7 +194,7 @@ RendererStack::mouseReleaseEvent(QMouseEvent *event)
|
||||
isMouseDown &= ~1;
|
||||
return;
|
||||
}
|
||||
if (mouse_capture) {
|
||||
if (mouse_capture || mouse_mode >= 1) {
|
||||
mousedata.mousebuttons &= ~event->button();
|
||||
}
|
||||
isMouseDown &= ~1;
|
||||
@@ -190,7 +204,7 @@ void
|
||||
RendererStack::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
isMouseDown |= 1;
|
||||
if (mouse_capture) {
|
||||
if (mouse_capture || mouse_mode >= 1) {
|
||||
mousedata.mousebuttons |= event->button();
|
||||
}
|
||||
event->accept();
|
||||
@@ -238,9 +252,26 @@ RendererStack::mouseMoveEvent(QMouseEvent *event)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
RendererStack::enterEvent(QEnterEvent *event)
|
||||
#else
|
||||
RendererStack::enterEvent(QEvent *event)
|
||||
#endif
|
||||
{
|
||||
mousedata.mouse_tablet_in_proximity = 1;
|
||||
|
||||
if (mouse_mode == 1)
|
||||
QApplication::setOverrideCursor(Qt::BlankCursor);
|
||||
}
|
||||
|
||||
void
|
||||
RendererStack::leaveEvent(QEvent *event)
|
||||
{
|
||||
mousedata.mouse_tablet_in_proximity = 0;
|
||||
if (mouse_mode == 1)
|
||||
QApplication::setOverrideCursor(Qt::ArrowCursor);
|
||||
if (QApplication::platformName().contains("wayland")) {
|
||||
event->accept();
|
||||
return;
|
||||
@@ -501,3 +532,16 @@ RendererStack::changeEvent(QEvent *event)
|
||||
config_save();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RendererStack::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
QMouseEvent* mouse_event = (QMouseEvent*)event;
|
||||
if (mouse_mode >= 1) {
|
||||
mousedata.x_abs = (mouse_event->localPos().x()) / (long double)width();
|
||||
mousedata.y_abs = (mouse_event->localPos().y()) / (long double)height();
|
||||
}
|
||||
}
|
||||
return QStackedWidget::event(event);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QStackedWidget>
|
||||
#include <QWidget>
|
||||
#include <QCursor>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
@@ -30,6 +31,11 @@ public:
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
#else
|
||||
void enterEvent(QEvent *event) override;
|
||||
#endif
|
||||
void leaveEvent(QEvent *event) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void changeEvent(QEvent *event) override;
|
||||
@@ -45,6 +51,7 @@ public:
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
enum class Renderer {
|
||||
Software,
|
||||
|
@@ -74,6 +74,12 @@ ui_window_title(wchar_t *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
ui_hard_reset_completed()
|
||||
{
|
||||
emit main_window->hardResetCompleted();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
qt_blit(int x, int y, int w, int h, int monitor_index)
|
||||
{
|
||||
|
@@ -383,6 +383,7 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw)
|
||||
void
|
||||
WindowsRawInputFilter::mousePoll()
|
||||
{
|
||||
if (mouse_mode >= 1) return;
|
||||
if (mouse_capture || video_fullscreen) {
|
||||
static int b = 0;
|
||||
|
||||
|
@@ -1319,3 +1319,8 @@ void
|
||||
ui_sb_mt32lcd(char *str)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ui_hard_reset_completed(void)
|
||||
{
|
||||
}
|
||||
|
@@ -596,6 +596,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm
|
||||
mouse.o \
|
||||
mouse_bus.o \
|
||||
mouse_serial.o mouse_ps2.o \
|
||||
mouse_wacom_tablet.o \
|
||||
phoenix_486_jumper.o serial_passthrough.o
|
||||
|
||||
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||
|
@@ -1603,7 +1603,13 @@ void
|
||||
ui_init_monitor(int monitor_index)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ui_deinit_monitor(int monitor_index)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ui_hard_reset_completed(void)
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user