diff --git a/README.md b/README.md index af0e54f7..8509dd71 100644 --- a/README.md +++ b/README.md @@ -866,6 +866,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 e8e74f98..0f618cb4 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 28462efd..5587b2d8 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 0a28eda4..f2e5d549 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -134,17 +134,32 @@ scrcpy_otg(struct scrcpy_options *options) { } aoa_initialized = true; - ok = sc_hid_keyboard_init(&s->keyboard, &s->aoa); - if (!ok) { - goto end; - } - keyboard = &s->keyboard; + bool enable_keyboard = + options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID; + bool enable_mouse = + options->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID; - ok = sc_hid_mouse_init(&s->mouse, &s->aoa); - if (!ok) { - goto end; + // If neither --hid-keyboard or --hid-mouse is passed, enable both + if (!enable_keyboard && !enable_mouse) { + enable_keyboard = true; + enable_mouse = true; + } + + 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 a4b37264..cda0da5e 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;