fix(scrcpy): ack clipboard handler should be enabled as long as control is enabled

it shouldn't be affected by `clipboardAutosync` option
This commit is contained in:
Simon Chan 2025-09-11 10:02:57 +08:00
parent 4b98c1ba19
commit 443686751a
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
18 changed files with 144 additions and 304 deletions

View file

@ -7,4 +7,5 @@ export {
AckClipboardDeviceMessage,
AckClipboardHandler,
SetClipboardControlMessage,
serializeSetClipboardControlMessage,
} from "./set-clipboard.js";

View file

@ -76,3 +76,16 @@ export class AckClipboardHandler implements ScrcpyDeviceMessageParser {
];
}
}
export function serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
ackHandler: AckClipboardHandler | undefined,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!ackHandler) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true` option",
);
}
return ackHandler.serializeSetClipboardControlMessage(message);
}

View file

@ -32,6 +32,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -62,10 +63,12 @@ export class ScrcpyOptions1_21
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -121,22 +124,9 @@ export class ScrcpyOptions1_21
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -32,6 +32,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -62,10 +63,12 @@ export class ScrcpyOptions1_22
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -121,22 +124,9 @@ export class ScrcpyOptions1_22
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -32,6 +32,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -62,10 +63,12 @@ export class ScrcpyOptions1_23
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -121,22 +124,9 @@ export class ScrcpyOptions1_23
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -32,6 +32,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -62,10 +63,12 @@ export class ScrcpyOptions1_24
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -121,22 +124,9 @@ export class ScrcpyOptions1_24
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -32,6 +32,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -62,10 +63,12 @@ export class ScrcpyOptions1_25
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -121,22 +124,9 @@ export class ScrcpyOptions1_25
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -33,6 +33,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -63,10 +64,12 @@ export class ScrcpyOptions2_0
constructor(init: Init) {
this.value = { ...Defaults, ...init };
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -128,22 +131,9 @@ export class ScrcpyOptions2_0
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -33,6 +33,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -63,10 +64,12 @@ export class ScrcpyOptions2_1<TVideo extends boolean>
constructor(init: Init<TVideo>) {
this.value = { ...Defaults, ...init } as never;
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -128,22 +131,9 @@ export class ScrcpyOptions2_1<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -33,6 +33,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -67,10 +68,12 @@ export class ScrcpyOptions2_2<TVideo extends boolean>
this.value.control = false;
}
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -132,22 +135,9 @@ export class ScrcpyOptions2_2<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -33,6 +33,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
setListDisplays,
setListEncoders,
} from "./impl/index.js";
@ -67,10 +68,12 @@ export class ScrcpyOptions2_3<TVideo extends boolean>
this.value.control = false;
}
if (this.value.control && this.value.clipboardAutosync) {
if (this.value.control) {
if (this.value.clipboardAutosync) {
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
@ -132,22 +135,9 @@ export class ScrcpyOptions2_3<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -83,11 +84,11 @@ export class ScrcpyOptions2_4<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -149,22 +150,9 @@ export class ScrcpyOptions2_4<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions2_6<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions2_6<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions2_7<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions2_7<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions3_0<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions3_0<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions3_1<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions3_1<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions3_2<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions3_2<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}

View file

@ -35,6 +35,7 @@ import {
serialize,
serializeBackOrScreenOnControlMessage,
serializeInjectTouchControlMessage,
serializeSetClipboardControlMessage,
serializeUHidCreateControlMessage,
setListDisplays,
setListEncoders,
@ -87,11 +88,11 @@ export class ScrcpyOptions3_3_1<TVideo extends boolean>
this.#clipboard = this.#deviceMessageParsers.add(
new ClipboardStream(),
);
}
this.#ackClipboardHandler = this.#deviceMessageParsers.add(
new AckClipboardHandler(),
);
}
this.#uHidOutput = this.#deviceMessageParsers.add(
new UHidOutputStream(),
@ -153,22 +154,9 @@ export class ScrcpyOptions3_3_1<TVideo extends boolean>
serializeSetClipboardControlMessage(
message: ScrcpySetClipboardControlMessage,
): Uint8Array | [Uint8Array, Promise<void>] {
if (!this.#ackClipboardHandler) {
if (!this.value.control) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `control: true`",
);
} else if (!this.value.clipboardAutosync) {
throw new Error(
"`serializeSetClipboardControlMessage` requires `clipboardAutosync: true`",
);
} else {
throw new Error("unreachable");
}
}
return this.#ackClipboardHandler.serializeSetClipboardControlMessage(
return serializeSetClipboardControlMessage(
message,
this.#ackClipboardHandler,
);
}