diff --git a/docs/multitouch.md b/docs/multitouch.md new file mode 100644 index 0000000..28f7fbb --- /dev/null +++ b/docs/multitouch.md @@ -0,0 +1,213 @@ +# Decompiled MotionEvent Handler Analysis + + + +## Overview + + + +This function processes an Android `MotionEvent`, normalizes pointer coordinates to a 0–1 range, packs them into a custom event object, and forwards it to another component. + + + +--- + + + +## What It Does + + + +1. Determines whether the event is a **press/move (1)** or **release (0)**: + + - `ACTION_DOWN`, `ACTION_POINTER_DOWN`, `ACTION_MOVE` → state = 1 + + - `ACTION_UP`, `ACTION_POINTER_UP` → state = 0 + + + +2. Iterates over active pointers (maximum of 5). + + + +3. For each pointer: + + - Gets the pointer ID. + + - If pointer ID ≥ 5 → abort and return `true`. + + - For `ACTION_POINTER_DOWN` / `ACTION_POINTER_UP`, only processes the pointer at `getActionIndex()`. + + + +4. For each processed pointer: + + - Gets raw X/Y coordinates. + + - Subtracts offsets. + + - Normalizes coordinates into `[0, 1]` using width/height bounds. + + - Clamps values to `[0, 1]`. + + + +5. Stores per-pointer data into a custom container: + + - Normalized X + + - Normalized Y + + - State (1 = down/move, 0 = up) + + - Pointer ID + + + +6. Sends the packed structure to another component. + + + +7. Always returns `true`. + + + +--- + + + +## Clean, Readable Version + + + +```java + +public static boolean handleMotionEvent( + + MotionEvent event, + + int offsetX, + + int offsetY, + + int width, + + int height + +) { + + TouchPacket packet = new TouchPacket(); + + + + int action = event.getActionMasked(); + + + + // Determine press state + + int state; + + if (action == MotionEvent.ACTION_DOWN || + + action == MotionEvent.ACTION_POINTER_DOWN || + + action == MotionEvent.ACTION_MOVE) { + + state = 1; // pressed/moving + + } else { + + state = 0; // released + + } + + + + int pointerCount = Math.min(event.getPointerCount(), 5); + + + + for (int i = 0; i < pointerCount; i++) { + + + + int pointerId = event.getPointerId(i); + + + + // Only support pointer IDs 0–4 + + if (pointerId >= 5) { + + return true; + + } + + + + // If pointer down/up, only handle the changed pointer + + if (action == MotionEvent.ACTION_POINTER_DOWN || + + action == MotionEvent.ACTION_POINTER_UP) { + + + + int changedPointerId = + + event.getPointerId(event.getActionIndex()); + + + + if (pointerId != changedPointerId) { + + continue; + + } + + } + + + + float rawX = event.getX(i); + + float rawY = event.getY(i); + + + + int x = (int) rawX - offsetX; + + int y = (int) rawY - offsetY; + + + + float normX = normalize(x, width); + + float normY = normalize(y, height); + + + + packet.addPointer(normX, normY, state, pointerId); + + } + + + + TouchSender.send(packet); + + return true; + +} + + + +private static float normalize(int value, int max) { + + if (value <= 0) return 0f; + + if (value >= max) return 1f; + + return (float) value / (float) max; + +} \ No newline at end of file diff --git a/src/helper/functions.h b/src/helper/functions.h index 88920c8..ed7de18 100644 --- a/src/helper/functions.h +++ b/src/helper/functions.h @@ -2,6 +2,7 @@ #define SRC_HELPER_FUNCTIONS #include +#include #include #if defined(__linux__) || defined(__APPLE__) diff --git a/src/helper/protocol_const.h b/src/helper/protocol_const.h index 23e7551..ba30976 100644 --- a/src/helper/protocol_const.h +++ b/src/helper/protocol_const.h @@ -38,6 +38,8 @@ #define BTN_SIRI 5 #define BTN_MICROPHONE 7 +#define BTN_12 12 +// Navigation buttons #define BTN_LEFT 100 #define BTN_RIGHT 101 #define BTN_SELECT_DOWN 104 @@ -45,10 +47,15 @@ #define BTN_BACK 106 #define BTN_DOWN 114 #define BTN_HOME 200 +// Play control buttons #define BTN_PLAY 201 #define BTN_PAUSE 202 +#define BTN_203 203 // pause/resume?? #define BTN_NEXT_TRACK 204 #define BTN_PREVIOUS_TRACK 205 +// Unknown buttons, volume???? +#define BTN_300 300 +#define BTN_301 301 #define AUDIO_BUFFER_SIZE 2560 diff --git a/src/main.cpp b/src/main.cpp index e26ae66..7311fad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,7 +60,9 @@ void processKey(Protocol &protocol, SDL_Keysym key, RunParams ¶ms) case SDLK_r: params.dirty = true; + protocol.sendKey(BTN_12); return; + case SDLK_h: protocol.sendKey(BTN_HOME); return; diff --git a/src/protocol.cpp b/src/protocol.cpp index 27c6eb5..1a08eb1 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -153,26 +153,26 @@ void Protocol::sendClick(float x, float y, bool down) send(CMD_TOUCH, false, buf, 16); } - -void Protocol::sendMultiTouch(const std::vector& touches) +void Protocol::sendMultiTouch(const Multitouch &touches) { - if (touches.empty()) return; + int count = touches.size(); + if (count == 0) + return; - const size_t touchSize = 16; - const size_t totalSize = touches.size() * touchSize; + uint8_t buf[MUTLITOUCH_MAX_TOUCH * sizeof(Multitouch::Touch)]; + uint8_t *p = buf; - std::vector buf(totalSize); - uint8_t* p = buf.data(); - - for (const auto& t : touches) { - write_float_le(p + 0, t.x); - write_float_le(p + 4, t.y); - write_uint32_le(p + 8, static_cast(t.action)); - write_uint32_le(p + 12, t.id); - p += touchSize; + for (int i = 0; i < count; ++i) + { + const Multitouch::Touch &t = touches[i]; + write_float_le(p + 0, t.x); + write_float_le(p + 4, t.y); + write_uint32_le(p + 8, static_cast(t.state)); + write_uint32_le(p + 12, static_cast(t.id)); + p += 16; } - send(CMD_MULTI_TOUCH, false, buf.data(), totalSize); + send(CMD_MULTI_TOUCH, false, buf, 16 * count); } void Protocol::sendMove(float dx, float dy) diff --git a/src/protocol.h b/src/protocol.h index a0d2648..65c7a39 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -3,6 +3,7 @@ #include "struct/atomic_queue.h" #include "struct/message.h" +#include "struct/multitouch.h" #include "helper/iaudio_sender.h" #include "settings.h" #include "connector.h" @@ -18,20 +19,6 @@ public: Protocol(const Protocol &) = delete; Protocol &operator=(const Protocol &) = delete; - enum Action { - UP = 16, - DOWN = 14, - MOVE = 15 - }; - - struct Touch { - float x; - float y; - Action action; - uint32_t id; - }; - - void start(uint32_t evtStatus, uint32_t evtPhone); void stop(); @@ -40,7 +27,7 @@ public: void sendFile(const char *filename, const char *value); void sendFile(const char *filename, int value); void sendClick(float x, float y, bool down); - void sendMultiTouch(const std::vector& touches); + void sendMultiTouch(const Multitouch &touches); void sendMove(float dx, float dy); void sendAudio(uint8_t *data, uint32_t length) override; diff --git a/src/struct/multitouch.h b/src/struct/multitouch.h new file mode 100644 index 0000000..6ab6980 --- /dev/null +++ b/src/struct/multitouch.h @@ -0,0 +1,41 @@ +#ifndef SRC_STRUCT_MULTITOUCH +#define SRC_STRUCT_MULTITOUCH + +#define MUTLITOUCH_MAX_TOUCH 5 + +class Multitouch +{ +public: + struct Touch + { + float x; + float y; + int state; + int id; + }; + + Multitouch() : _count(0) {} + + bool add(float x, float y, int state, int id) + { + if (_count >= MUTLITOUCH_MAX_TOUCH) + return false; + + _touches[_count++] = { x, y, state, id }; + return true; + } + + int size() const { + return _count; + } + + const Touch& operator[](int index) const { + return _touches[index]; + } + +private: + Touch _touches[MUTLITOUCH_MAX_TOUCH]; + int _count; +}; + +#endif /* SRC_STRUCT_MULTITOUCH */