Skip to content

Commit

Permalink
adbmouse: Add tablet and more bits and buttons.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
joevt authored and dingusdev committed May 6, 2024
1 parent fdf8543 commit 59fba28
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 30 deletions.
3 changes: 3 additions & 0 deletions core/hostevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class MouseEvent {
uint32_t flags;
uint32_t xrel;
uint32_t yrel;
uint32_t xabs;
uint32_t yabs;
uint8_t buttons_state;
};

Expand Down Expand Up @@ -115,6 +117,7 @@ class EventManager {
uint64_t key_downs = 0;
uint64_t key_ups = 0;
uint64_t mouse_motions = 0;
uint8_t buttons_state = 0;
};

#endif // EVENT_MANAGER_H
26 changes: 23 additions & 3 deletions core/hostevents_sdl.cpp
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -89,22 +89,42 @@ 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);
}
break;

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);
}
break;

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);
}
Expand Down
64 changes: 41 additions & 23 deletions devices/common/adb/adbmouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
}
Expand All @@ -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;

// 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;

// 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;
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]);

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;

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;
}

Expand All @@ -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;
}
Expand Down
30 changes: 26 additions & 4 deletions devices/common/adb/adbmouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -49,10 +58,23 @@ class AdbMouse : public AdbDevice {
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

0 comments on commit 59fba28

Please sign in to comment.