mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-04-21 01:33:36 +00:00
The HID ids (accessory ids or UHID ids) were defined by the keyboard and mouse implementations. Instead, define them in the common HID part, and make that id part of the sc_hid_event. This prepares the introduction of gamepad support, which will handle several gamepads (and ids) in the common HID gamepad code. PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
105 lines
3.3 KiB
C
105 lines
3.3 KiB
C
#include "keyboard_aoa.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#include "input_events.h"
|
|
#include "util/log.h"
|
|
|
|
/** Downcast key processor to keyboard_aoa */
|
|
#define DOWNCAST(KP) container_of(KP, struct sc_keyboard_aoa, key_processor)
|
|
|
|
static bool
|
|
push_mod_lock_state(struct sc_keyboard_aoa *kb, uint16_t mods_state) {
|
|
struct sc_hid_event hid_event;
|
|
if (!sc_hid_keyboard_event_from_mods(&hid_event, mods_state)) {
|
|
// Nothing to do
|
|
return true;
|
|
}
|
|
|
|
if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) {
|
|
LOGW("Could not request HID event (mod lock state)");
|
|
return false;
|
|
}
|
|
|
|
LOGD("HID keyboard state synchronized");
|
|
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
sc_key_processor_process_key(struct sc_key_processor *kp,
|
|
const struct sc_key_event *event,
|
|
uint64_t ack_to_wait) {
|
|
if (event->repeat) {
|
|
// In USB HID protocol, key repeat is handled by the host (Android), so
|
|
// just ignore key repeat here.
|
|
return;
|
|
}
|
|
|
|
struct sc_keyboard_aoa *kb = DOWNCAST(kp);
|
|
|
|
struct sc_hid_event hid_event;
|
|
|
|
// Not all keys are supported, just ignore unsupported keys
|
|
if (sc_hid_keyboard_event_from_key(&kb->hid, &hid_event, event)) {
|
|
if (!kb->mod_lock_synchronized) {
|
|
// Inject CAPSLOCK and/or NUMLOCK if necessary to synchronize
|
|
// keyboard state
|
|
if (push_mod_lock_state(kb, event->mods_state)) {
|
|
kb->mod_lock_synchronized = true;
|
|
}
|
|
}
|
|
|
|
// If ack_to_wait is != SC_SEQUENCE_INVALID, then Ctrl+v is pressed, so
|
|
// clipboard synchronization has been requested. Wait until clipboard
|
|
// synchronization is acknowledged by the server, otherwise it could
|
|
// paste the old clipboard content.
|
|
|
|
if (!sc_aoa_push_hid_event_with_ack_to_wait(kb->aoa, &hid_event,
|
|
ack_to_wait)) {
|
|
LOGW("Could not request HID event (key)");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
sc_keyboard_aoa_init(struct sc_keyboard_aoa *kb, struct sc_aoa *aoa) {
|
|
kb->aoa = aoa;
|
|
|
|
bool ok = sc_aoa_setup_hid(aoa, SC_HID_ID_KEYBOARD,
|
|
SC_HID_KEYBOARD_REPORT_DESC,
|
|
SC_HID_KEYBOARD_REPORT_DESC_LEN);
|
|
if (!ok) {
|
|
LOGW("Register HID keyboard failed");
|
|
return false;
|
|
}
|
|
|
|
sc_hid_keyboard_init(&kb->hid);
|
|
|
|
kb->mod_lock_synchronized = false;
|
|
|
|
static const struct sc_key_processor_ops ops = {
|
|
.process_key = sc_key_processor_process_key,
|
|
// Never forward text input via HID (all the keys are injected
|
|
// separately)
|
|
.process_text = NULL,
|
|
};
|
|
|
|
// Clipboard synchronization is requested over the control socket, while HID
|
|
// events are sent over AOA, so it must wait for clipboard synchronization
|
|
// to be acknowledged by the device before injecting Ctrl+v.
|
|
kb->key_processor.async_paste = true;
|
|
kb->key_processor.hid = true;
|
|
kb->key_processor.ops = &ops;
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
sc_keyboard_aoa_destroy(struct sc_keyboard_aoa *kb) {
|
|
// Unregister HID keyboard so the soft keyboard shows again on Android
|
|
bool ok = sc_aoa_unregister_hid(kb->aoa, SC_HID_ID_KEYBOARD);
|
|
if (!ok) {
|
|
LOGW("Could not unregister HID keyboard");
|
|
}
|
|
}
|