adbmouse: Add tablet and more bits and buttons.

Add absolute coordinates for tablets. Absolute coordinates is relative to window so it can't work for multiple displays? Doesn't work for single display without mouse driver modification.
Add arbitrary number of buttons. Previously, only one mouse button was supported.
Add arbitrary number of bits. Previously, only 7 bits per axis was supported which is good enough for relative movement but not absolute movement.
This commit is contained in:
joevt 2024-05-05 18:31:38 -07:00 committed by dingusdev
parent fdf8543c7e
commit 59fba285b5
4 changed files with 91 additions and 28 deletions

View File

@ -50,6 +50,8 @@ public:
uint32_t flags;
uint32_t xrel;
uint32_t yrel;
uint32_t xabs;
uint32_t yabs;
uint8_t buttons_state;
};
@ -115,6 +117,7 @@ private:
uint64_t key_downs = 0;
uint64_t key_ups = 0;
uint64_t mouse_motions = 0;
uint8_t buttons_state = 0;
};
#endif // EVENT_MANAGER_H

View File

@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-23 divingkatae and maximum
Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -89,6 +89,8 @@ void EventManager::poll_events()
MouseEvent me;
me.xrel = event.motion.xrel;
me.yrel = event.motion.yrel;
me.xabs = event.motion.x;
me.yabs = event.motion.y;
me.flags = MOUSE_EVENT_MOTION;
this->_mouse_signal.emit(me);
}
@ -96,7 +98,16 @@ void EventManager::poll_events()
case SDL_MOUSEBUTTONDOWN: {
MouseEvent me;
me.buttons_state = 1;
Uint8 adb_button;
switch (event.button.button) {
case SDL_BUTTON_LEFT : adb_button = 0; break;
case SDL_BUTTON_MIDDLE : adb_button = 2; break;
case SDL_BUTTON_RIGHT : adb_button = 1; break;
default : adb_button = event.button.button - 1;
}
me.buttons_state = (this->buttons_state |= (1 << adb_button));
me.xabs = event.button.x;
me.yabs = event.button.y;
me.flags = MOUSE_EVENT_BUTTON;
this->_mouse_signal.emit(me);
}
@ -104,7 +115,16 @@ void EventManager::poll_events()
case SDL_MOUSEBUTTONUP: {
MouseEvent me;
me.buttons_state = 0;
Uint8 adb_button;
switch (event.button.button) {
case SDL_BUTTON_LEFT : adb_button = 0; break;
case SDL_BUTTON_MIDDLE : adb_button = 2; break;
case SDL_BUTTON_RIGHT : adb_button = 1; break;
default : adb_button = event.button.button - 1;
}
me.buttons_state = (this->buttons_state &= ~(1 << adb_button));
me.xabs = event.button.x;
me.yabs = event.button.y;
me.flags = MOUSE_EVENT_BUTTON;
this->_mouse_signal.emit(me);
}

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <devices/common/adb/adbbus.h>
#include <devices/deviceregistry.h>
#include <core/hostevents.h>
#include <memaccess.h>
#include <loguru.hpp>
AdbMouse::AdbMouse(std::string name) : AdbDevice(name) {
@ -37,8 +38,14 @@ void AdbMouse::event_handler(const MouseEvent& event) {
if (event.flags & MOUSE_EVENT_MOTION) {
this->x_rel += event.xrel;
this->y_rel += event.yrel;
this->x_abs = event.xabs;
this->y_abs = event.yabs;
if (this->device_class == TABLET)
this->changed = true;
} else if (event.flags & MOUSE_EVENT_BUTTON) {
this->buttons_state = event.buttons_state;
this->buttons_state = event.buttons_state & ((1 << this->num_buttons) - 1);
this->x_abs = event.xabs;
this->y_abs = event.yabs;
this->changed = true;
}
}
@ -50,38 +57,50 @@ void AdbMouse::reset() {
this->srq_flag = 1; // enable service requests
this->x_rel = 0;
this->y_rel = 0;
this->x_abs = 0;
this->y_abs = 0;
this->buttons_state = 0;
this->changed = false;
}
bool AdbMouse::get_register_0() {
if (this->x_rel || this->y_rel || this->changed) {
uint8_t* p;
uint8_t* out_buf = this->host_obj->get_output_buf();
uint8_t button1_state = (this->buttons_state ^ 1) << 7;
static const uint8_t buttons_to_bits[] = {0, 7, 7, 10, 10, 13, 13, 16, 16};
static const uint8_t bits_to_bits[] = {0, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 13, 13, 13, 16, 16, 16};
int total_bits = std::max(buttons_to_bits[this->num_buttons], bits_to_bits[this->num_bits]);
// report Y-axis motion
if (this->y_rel < -64)
out_buf[0] = 0x40 | button1_state;
else if (this->y_rel > 63)
out_buf[0] = 0x3F | button1_state;
else
out_buf[0] = (this->y_rel & 0x7F) | button1_state;
for (int axis = 0; axis < 2; axis++) {
int bits = this->num_bits;
int32_t val = axis ? this->device_class == TABLET ? this->x_abs : this->x_rel
: this->device_class == TABLET ? this->y_abs : this->y_rel;
if (val < (-1 << (bits - 1)))
val = -1 << (bits - 1);
else if (val >= (1 << (bits - 1)))
val = (1 << (bits - 1)) - 1;
int bits_remaining = total_bits;
p = &out_buf[axis];
int button = axis;
bits = 7;
// report X-axis motion
if (this->x_rel < -64)
out_buf[1] = 0x40 | 0x80;
else if (this->x_rel > 63)
out_buf[1] = 0x3F | 0x80;
else
out_buf[1] = (this->x_rel & 0x7F) | 0x80;
while (bits_remaining > 0) {
*p = (val & ((1 << bits) - 1)) | (((this->buttons_state >> button) ^ 1) << bits) | (*p << (bits + 1));
val >>= bits;
bits_remaining -= bits;
p = bits == 7 ? &out_buf[2] : p + 1;
button += 2;
bits = 3;
}
}
// reset accumulated motion data and button change flag
this->x_rel = 0;
this->y_rel = 0;
this->changed = false;
this->host_obj->set_output_count(2);
this->host_obj->set_output_count(p - out_buf);
return true;
}
@ -96,10 +115,9 @@ bool AdbMouse::get_register_1() {
out_buf[2] = 'p';
out_buf[3] = 'l';
// Slightly higher resolution of 300 units per inch
out_buf[4] = 300 >> 8;
out_buf[5] = 300 & 0xFF;
out_buf[6] = 1; // mouse
out_buf[7] = 1; // 1 button
WRITE_WORD_BE_A(&out_buf[4], resolution);
out_buf[6] = device_class;
out_buf[7] = num_buttons;
this->host_obj->set_output_count(8);
return true;
}

View File

@ -30,9 +30,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <memory>
#include <string>
//#define ABSOLUTE
class MouseEvent;
class AdbMouse : public AdbDevice {
enum DeviceClass {
TABLET = 0,
MOUSE = 1,
TRACKBALL = 2,
};
public:
AdbMouse(std::string name);
~AdbMouse() = default;
@ -49,10 +58,23 @@ public:
void set_register_3() override;
private:
int32_t x_rel = 0;
int32_t y_rel = 0;
uint8_t buttons_state = 0;
bool changed = false;
int32_t x_rel = 0;
int32_t y_rel = 0;
int32_t x_abs = 0;
int32_t y_abs = 0;
uint8_t buttons_state = 0;
bool changed = false;
#ifdef ABSOLUTE
uint8_t device_class = TABLET;
int num_buttons = 3;
int num_bits = 16;
uint16_t resolution = 72;
#else
uint8_t device_class = MOUSE;
int num_buttons = 3;
int num_bits = 10;
uint16_t resolution = 300;
#endif
};
#endif // ADB_MOUSE_H