diff --git a/README.md b/README.md index 6092c5d5d0..f497cfc150 100644 --- a/README.md +++ b/README.md @@ -864,6 +864,16 @@ scrcpy --otg scrcpy --otg -s 0123456789abcdef ``` +It is possible to enable only HID keyboard or HID mouse: + +```bash +scrcpy --otg --hid-keyboard # keyboard only +scrcpy --otg --hid-mouse # mouse only +scrcpy --otg --hid-keyboard --hid-mouse # keyboard and mouse +# for convenience, enable both by default +scrcpy --otg # keyboard and mouse +``` + Like `--hid-keyboard` and `--hid-mouse`, it only works if the device is connected by USB, and is currently only supported on Linux. diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 7b14cfb0c0..053e71a140 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -170,6 +170,8 @@ In this mode, adb (USB debugging) is not necessary, and mirroring is disabled. LAlt, LSuper or RSuper toggle the mouse capture mode, to give control of the mouse back to the computer. +If any of \fB\-\-hid\-keyboard\fR or \fB\-\-hid\-mouse\fR is set, only enable keyboard or mouse respectively, otherwise enable both. + It may only work over USB, and is currently only supported on Linux. See \fB\-\-hid\-keyboard\fR and \fB\-\-hid\-mouse\fR. diff --git a/app/src/cli.c b/app/src/cli.c index 71c1608611..e85c8730e2 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -287,6 +287,8 @@ static const struct sc_option options[] = { "mirroring is disabled.\n" "LAlt, LSuper or RSuper toggle the mouse capture mode, to give " "control of the mouse back to the computer.\n" + "If any of --hid-keyboard or --hid-mouse is set, only enable " + "keyboard or mouse respectively, otherwise enable both." "It may only work over USB, and is currently only supported " "on Linux.\n" "See --hid-keyboard and --hid-mouse.", diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 6bf8bcf872..2509a1da73 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -125,17 +125,32 @@ scrcpy_otg(struct scrcpy_options *options) { } aoa_initialized = true; - ok = sc_hid_keyboard_init(&s->keyboard, &s->aoa); - if (!ok) { - goto end; + bool enable_keyboard = + options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID; + bool enable_mouse = + options->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID; + + // If neither --hid-keyboard or --hid-mouse is passed, enable both + if (!enable_keyboard && !enable_mouse) { + enable_keyboard = true; + enable_mouse = true; } - keyboard = &s->keyboard; - ok = sc_hid_mouse_init(&s->mouse, &s->aoa); - if (!ok) { - goto end; + if (enable_keyboard) { + ok = sc_hid_keyboard_init(&s->keyboard, &s->aoa); + if (!ok) { + goto end; + } + keyboard = &s->keyboard; + } + + if (enable_mouse) { + ok = sc_hid_mouse_init(&s->mouse, &s->aoa); + if (!ok) { + goto end; + } + mouse = &s->mouse; } - mouse = &s->mouse; ok = sc_aoa_start(&s->aoa); if (!ok) { diff --git a/app/src/usb/screen_otg.c b/app/src/usb/screen_otg.c index a4b3726421..cda0da5ef9 100644 --- a/app/src/usb/screen_otg.c +++ b/app/src/usb/screen_otg.c @@ -6,6 +6,7 @@ static void sc_screen_otg_capture_mouse(struct sc_screen_otg *screen, bool capture) { + assert(screen->mouse); if (SDL_SetRelativeMouseMode(capture)) { LOGE("Could not set relative mouse mode to %s: %s", capture ? "true" : "false", SDL_GetError()); @@ -78,8 +79,10 @@ sc_screen_otg_init(struct sc_screen_otg *screen, LOGW("Could not load icon"); } - // Capture mouse on start - sc_screen_otg_capture_mouse(screen, true); + if (screen->mouse) { + // Capture mouse on start + sc_screen_otg_capture_mouse(screen, true); + } return true; @@ -189,64 +192,74 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) { sc_screen_otg_render(screen); break; case SDL_WINDOWEVENT_FOCUS_LOST: - sc_screen_otg_capture_mouse(screen, false); + if (screen->mouse) { + sc_screen_otg_capture_mouse(screen, false); + } break; } return; - case SDL_KEYDOWN: { - SDL_Keycode key = event->key.keysym.sym; - if (sc_screen_otg_is_mouse_capture_key(key)) { - if (!screen->mouse_capture_key_pressed) { - screen->mouse_capture_key_pressed = key; - } else { - // Another mouse capture key has been pressed, cancel mouse - // (un)capture - screen->mouse_capture_key_pressed = 0; + case SDL_KEYDOWN: + if (screen->mouse) { + SDL_Keycode key = event->key.keysym.sym; + if (sc_screen_otg_is_mouse_capture_key(key)) { + if (!screen->mouse_capture_key_pressed) { + screen->mouse_capture_key_pressed = key; + } else { + // Another mouse capture key has been pressed, cancel + // mouse (un)capture + screen->mouse_capture_key_pressed = 0; + } + // Mouse capture keys are never forwarded to the device + return; } - // Mouse capture keys are never forwarded to the device - return; } - sc_screen_otg_process_key(screen, &event->key); + if (screen->keyboard) { + sc_screen_otg_process_key(screen, &event->key); + } break; - } - case SDL_KEYUP: { - SDL_Keycode key = event->key.keysym.sym; - SDL_Keycode cap = screen->mouse_capture_key_pressed; - screen->mouse_capture_key_pressed = 0; - if (sc_screen_otg_is_mouse_capture_key(key)) { - if (key == cap) { - // A mouse capture key has been pressed then released: - // toggle the capture mouse mode - sc_screen_otg_capture_mouse(screen, - !screen->mouse_captured); + case SDL_KEYUP: + if (screen->mouse) { + SDL_Keycode key = event->key.keysym.sym; + SDL_Keycode cap = screen->mouse_capture_key_pressed; + screen->mouse_capture_key_pressed = 0; + if (sc_screen_otg_is_mouse_capture_key(key)) { + if (key == cap) { + // A mouse capture key has been pressed then released: + // toggle the capture mouse mode + sc_screen_otg_capture_mouse(screen, + !screen->mouse_captured); + } + // Mouse capture keys are never forwarded to the device + return; } - // Mouse capture keys are never forwarded to the device - return; } - sc_screen_otg_process_key(screen, &event->key); + if (screen->keyboard) { + sc_screen_otg_process_key(screen, &event->key); + } break; - } case SDL_MOUSEMOTION: - if (screen->mouse_captured) { + if (screen->mouse && screen->mouse_captured) { sc_screen_otg_process_mouse_motion(screen, &event->motion); } break; case SDL_MOUSEBUTTONDOWN: - if (screen->mouse_captured) { + if (screen->mouse && screen->mouse_captured) { sc_screen_otg_process_mouse_button(screen, &event->button); } break; case SDL_MOUSEBUTTONUP: - if (screen->mouse_captured) { - sc_screen_otg_process_mouse_button(screen, &event->button); - } else { - sc_screen_otg_capture_mouse(screen, true); + if (screen->mouse) { + if (screen->mouse_captured) { + sc_screen_otg_process_mouse_button(screen, &event->button); + } else { + sc_screen_otg_capture_mouse(screen, true); + } } break; case SDL_MOUSEWHEEL: - if (screen->mouse_captured) { + if (screen->mouse && screen->mouse_captured) { sc_screen_otg_process_mouse_wheel(screen, &event->wheel); } break;