mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 01:39:21 +02:00
85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import type { StructInit } from "@yume-chan/struct";
|
|
import { s32, struct, u16, u32, u8 } from "@yume-chan/struct";
|
|
|
|
import type { ScrcpyScrollController } from "../../base/index.js";
|
|
import type { ScrcpyInjectScrollControlMessage } from "../../latest.js";
|
|
|
|
export const InjectScrollControlMessage = struct(
|
|
{
|
|
// value of `type` can change between versions
|
|
type: u8,
|
|
pointerX: u32,
|
|
pointerY: u32,
|
|
videoWidth: u16,
|
|
videoHeight: u16,
|
|
scrollX: s32,
|
|
scrollY: s32,
|
|
},
|
|
{ littleEndian: false },
|
|
);
|
|
|
|
export type InjectScrollControlMessage = StructInit<
|
|
typeof InjectScrollControlMessage
|
|
>;
|
|
|
|
/**
|
|
* Old version of Scrcpy server only supports integer values for scroll.
|
|
*
|
|
* Accumulate scroll values and send scroll message when accumulated value
|
|
* reaches 1 or -1.
|
|
*/
|
|
export class ScrollController implements ScrcpyScrollController {
|
|
#accumulatedX = 0;
|
|
#accumulatedY = 0;
|
|
|
|
protected processMessage(
|
|
message: ScrcpyInjectScrollControlMessage,
|
|
): ScrcpyInjectScrollControlMessage | undefined {
|
|
// Ref https://github.com/libsdl-org/SDL/blob/878ea48b607f23e4ec8c12d1395b86ab529e30d0/src/events/SDL_mouse.c#L897-L914
|
|
|
|
if (message.scrollX) {
|
|
if (Math.sign(message.scrollX) !== Math.sign(this.#accumulatedX)) {
|
|
this.#accumulatedX = message.scrollX;
|
|
} else {
|
|
this.#accumulatedX += message.scrollX;
|
|
}
|
|
}
|
|
|
|
if (message.scrollY) {
|
|
if (Math.sign(message.scrollY) !== Math.sign(this.#accumulatedY)) {
|
|
this.#accumulatedY = message.scrollY;
|
|
} else {
|
|
this.#accumulatedY += message.scrollY;
|
|
}
|
|
}
|
|
|
|
const integerX = this.#accumulatedX | 0;
|
|
this.#accumulatedX -= integerX;
|
|
|
|
const integerY = this.#accumulatedY | 0;
|
|
this.#accumulatedY -= integerY;
|
|
|
|
if (integerX === 0 && integerY === 0) {
|
|
return undefined;
|
|
}
|
|
|
|
message.scrollX = integerX;
|
|
message.scrollY = integerY;
|
|
return message;
|
|
}
|
|
|
|
serializeScrollMessage(
|
|
message: ScrcpyInjectScrollControlMessage,
|
|
): Uint8Array | undefined {
|
|
const processed = this.processMessage(message);
|
|
if (!processed) {
|
|
return undefined;
|
|
}
|
|
|
|
return InjectScrollControlMessage.serialize(processed);
|
|
}
|
|
}
|
|
|
|
export function createScrollController(): ScrcpyScrollController {
|
|
return new ScrollController();
|
|
}
|