Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
/></a>
<a title="Flutter" href="https://flutter.dev/"><img src="https://img.shields.io/badge/Flutter-%2302569B.svg?style=for-the-badge&logo=Flutter&logoColor=white"
alt="Flutter"/></a>
<a title="Latest supported scrcpy version" href="https://github.com/Genymobile/scrcpy/releases"><img src="https://img.shields.io/badge/scrcpy-v3.3.4-green?style=flat-square"
alt="scrcpy v3.3.4"/></a>
<a title="Latest supported scrcpy version" href="https://github.com/Genymobile/scrcpy/releases"><img src="https://img.shields.io/badge/scrcpy-v4.0-green?style=flat-square"
alt="scrcpy v4.0"/></a>
<a title="Snap Store" href="https://snapcraft.io/scrcpy-buddy"><img alt="scrcpy-buddy" src="https://snapcraft.io/scrcpy-buddy/badge.svg" /></a>
<a title="Trending on snap store" href="https://snapcraft.io/scrcpy-buddy"><img alt="scrcpy-buddy" src="https://snapcraft.io/scrcpy-buddy/trending.svg?name=0" /></a>
</p>
Expand All @@ -30,7 +30,7 @@ To use this app, you need the following:

- Run scrcpy on multiple connected devices
- ADB Device management (Switch USB Device to network / disconnect device)
- Auto-refresh devices list
- Auto-refresh devices list
- Profile management (name, customized scrcpy options, default profile)
- Light / Dark theme support
- View console output for devices which are running scrcpy
Expand Down Expand Up @@ -80,7 +80,7 @@ All downloads can be found on the [latest release](https://github.com/Codertainm
#### 🍺 Homebrew

- `brew tap Codertainment/scrcpy_buddy`
- The tap source is available [here](https://github.com/Codertainment/homebrew-scrcpy_buddy/)
- The tap source is available [here](https://github.com/Codertainment/homebrew-scrcpy_buddy/)
- `brew install scrcpy_buddy`

#### Installing from DMG
Expand Down Expand Up @@ -200,8 +200,8 @@ If you have ADB and/or scrcpy setup and installed in your path:
can [set the executable in settings manually](#setting-executable-path-manually-in-settings).
- To find out the installation path, run this command in the terminal:
- e.g.
- For Windows: `where adb`
- For MacOS/Linux: `which adb`
- For Windows: `where adb`
- For MacOS/Linux: `which adb`

## Setting executable path manually in settings

Expand Down
8 changes: 8 additions & 0 deletions assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@
"title": "Stay awake",
"description": "Keep device awake while plugged in\nPrevious value gets restored on exit\nHas no effect is the device is connected through network (Android behavior)"
},
"keepActive": {
"title": "Keep active",
"description": "Prevents the device from turning off or sleeping, by periodically signalling user activity to the system.\nContrary to \"Stay awake\" and \"Screen off timeout\", this does not change any global settings, and it works whether the device is plugged in or not."
},
"turnScreenOff": {
"title": "Turn screen off",
"description": "Turn device screen off immediately on start\nCan be toggled when scrcpy is running via shortcut: MOD + O / MOD + Shift + O"
Expand Down Expand Up @@ -287,6 +291,10 @@
"description": "It is recommended to use virtual display with 'Start app' option available in ",
"button": "'Device' section"
},
"flex": {
"title": "Flexible",
"description": "Allows the virtual display to be flexibly resizeable according to scrcpy window size"
},
"newDisplay": {
"title": "Create virtual display",
"description": "Create and mirror a virtual display instead of the main device screen",
Expand Down
21 changes: 11 additions & 10 deletions docs/scrcpy_options/device.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Device options

| CLI option | Description (short) | Suggested GUI control | Advanced? |
|----------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------|-----------|
| `--stay-awake` / `-w` | Keep device awake while plugged in; restore previous value on exit. [1] | Switch/toggle | No |
| `--turn-screen-off` / `-S` | Turn device screen off immediately on start; can be toggled back via shortcut. | Switch/toggle “Start with screen off” | No |
| `--show-touches` / `-t` | Enable “show touches” developer option while running; restore on exit. | Switch/toggle | No |
| `--start-app=PKG` | Start given app (by package) on start; supports `+` force‑stop and `?` name search prefixes. | Text input with app picker & flags (+ / ?) | No |
| `--screen-off-timeout` | Override Android screen‑off timeout (seconds) while running; restore on exit. | Number input (seconds) | Yes |
| `--power-off-on-close` | Turn device screen off when scrcpy exits. | Switch/toggle | Yes |
| `--no-power-on` | Do not automatically power on / wake device on start. | Switch/toggle | Yes |
| `--list-apps` | List installed apps on the device (for use with `--start-app`). | Button “List apps…” (opens chooser UI) | Yes |
| CLI option | Description (short) | Suggested GUI control | Advanced? |
|----------------------------|--------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|-----------|
| `--stay-awake` / `-w` | Keep device awake while plugged in; restore previous value on exit. [1] | Switch/toggle | No |
| `--keep-active` | To prevent the device from turning off due to inactivity, --keep-active periodically signals user activity to the system | Switch/toggle | No |
| `--turn-screen-off` / `-S` | Turn device screen off immediately on start; can be toggled back via shortcut. | Switch/toggle “Start with screen off” | No |
| `--show-touches` / `-t` | Enable “show touches” developer option while running; restore on exit. | Switch/toggle | No |
| `--start-app=PKG` | Start given app (by package) on start; supports `+` force‑stop and `?` name search prefixes. | Text input with app picker & flags (+ / ?) | No |
| `--screen-off-timeout` | Override Android screen‑off timeout (seconds) while running; restore on exit. | Number input (seconds) | Yes |
| `--power-off-on-close` | Turn device screen off when scrcpy exits. | Switch/toggle | Yes |
| `--no-power-on` | Do not automatically power on / wake device on start. | Switch/toggle | Yes |
| `--list-apps` | List installed apps on the device (for use with `--start-app`). | Button “List apps…” (opens chooser UI) | Yes |
1 change: 1 addition & 0 deletions docs/scrcpy_options/virtualDisplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| `--new-display=WxH` | Create virtual display with explicit width×height. [1] | Width/height number inputs (when virtual display enabled) | No |
| `--new-display=WxH/DPI` | Same as above but with explicit density. [1] | Additional DPI number input | Yes |
| `--new-display=/DPI` | Use main display size but explicit density. [1] | DPI number input (size fields disabled) | Yes |
| `--flex-display` | Allows the virtual display to be resizeable according to scrcpy window size | Switch/toggle | No |
| `--no-vd-system-decorations` | Disable system decorations in virtual display (no launcher/system UI). [1] | Switch/toggle | Yes |
| `--no-vd-destroy-content` | On closing scrcpy, move apps from virtual display back to main display instead of destroying them. [1] | Switch/toggle | Yes |
| `--display-ime-policy=local` | Force IME (on‑screen keyboard) to appear on local display for given display/virtual display. [1] | Dropdown (`default` / `local`) or checkbox “IME on local” | Yes |
1 change: 1 addition & 0 deletions docs/scrcpy_options/window.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
| `--window-height` | Initial window height in pixels. | Number input (px) | Yes |
| `--window-borderless` | Disable window decorations (no border, no title bar). | Switch/toggle | Yes |
| `--disable-screensaver` | Prevent the computer screensaver while scrcpy is running. | Switch/toggle | Yes |
| `--background-color` | Background color for the scrcpy window | Color picker | Yes |
17 changes: 17 additions & 0 deletions lib/application/model/scrcpy/arguments/device/keep_active.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:scrcpy_buddy/application/model/scrcpy/scrcpy_cli_argument.dart';
import 'package:scrcpy_buddy/main.dart';

@scrcpyArg
class KeepActive extends ScrcpyCliArgument<bool> {
@override
List<String> toArgs(bool value) => value ? [argument] : [];

@override
final String argument = '--keep-active';

@override
final String label = 'device.keepActive';

@override
final List<String>? values = null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:scrcpy_buddy/application/model/scrcpy/scrcpy_cli_argument.dart';
import 'package:scrcpy_buddy/main.dart';

@scrcpyArg
class FlexDisplay extends ScrcpyCliArgument<bool> {
@override
List<String> toArgs(bool value) => value ? [argument] : [];

@override
final String argument = '--flex-display';

@override
final String label = 'virtualDisplay.flex';

@override
final List<String>? values = null;
}
2 changes: 2 additions & 0 deletions lib/application/model/scrcpy/scrcpy_arg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export 'arguments/device/stay_awake.dart';
export 'arguments/device/turn_screen_off.dart';
export 'arguments/device/show_touches.dart';
export 'arguments/device/start_app.dart';
export 'arguments/device/keep_active.dart';

// Window
export 'arguments/window/no_window.dart';
Expand All @@ -46,6 +47,7 @@ export 'arguments/v4l2/v4l2_sink.dart';

// Virtual Display
export 'arguments/virtualDisplay/new_display.dart';
export 'arguments/virtualDisplay/flex_display.dart';

/// All {ScrcpyCliArgument}s must be annotated with this annotation.
class ScrcpyArg extends Reflectable {
Expand Down
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import 'package:window_manager/window_manager.dart';

import 'injector.dart';

const supportedScrcpyVersion = "3.3.4";
const supportedScrcpyVersion = "4.0";

const scrcpyArg = ScrcpyArg();

Expand Down
7 changes: 7 additions & 0 deletions lib/presentation/scrcpy_config/device/device_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class _DeviceScreenState extends AppModuleState<DeviceScreen> {
String get module => 'config.device';

final _stayAwake = StayAwake();
final _keepActive = KeepActive();
final _turnScreenOff = TurnScreenOff();
final _showTouches = ShowTouches();
final _startApp = StartApp();
Expand All @@ -43,6 +44,12 @@ class _DeviceScreenState extends AppModuleState<DeviceScreen> {
child: ConfigToggle(state: state, cliArgument: _stayAwake),
),
const ConfigDivider(),
ConfigItem(
icon: WindowsIcons.touch_pointer,
cliArgument: _keepActive,
child: ConfigToggle(state: state, cliArgument: _keepActive),
),
const ConfigDivider(),
ConfigItem(
icon: WindowsIcons.disconnect_display,
cliArgument: _turnScreenOff,
Expand Down
2 changes: 1 addition & 1 deletion lib/presentation/scrcpy_config/v4l2/v4l2_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class _V4l2ScreenState extends AppModuleState<V4l2Screen> {
children: [
ConfigItem(
icon: FluentIcons.funnel_chart,
hasDefault: true,
hasDefault: false,
cliArgument: _sink,
child: ConfigTextBox(
value: state.getFor(_sink),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import 'package:scrcpy_buddy/application/model/scrcpy/scrcpy_arg.dart';
import 'package:scrcpy_buddy/application/profiles_bloc/profiles_bloc.dart';
import 'package:scrcpy_buddy/presentation/extension/translation_extension.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/config_divider.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/config_item.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/config_item_base.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/config_text_box.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/config_toggle.dart';
import 'package:scrcpy_buddy/presentation/scrcpy_config/widgets/link_span.dart';
import 'package:scrcpy_buddy/presentation/widgets/app_widgets.dart';
import 'package:scrcpy_buddy/routes.dart';
Expand All @@ -24,6 +26,7 @@ class _VirtualDisplayScreenState extends AppModuleState<VirtualDisplayScreen> {

late final _profilesBloc = context.read<ProfilesBloc>();
final _newDisplay = NewDisplay();
final _flexDisplay = FlexDisplay();
bool isEnabled = false;
String? resolutionWidth;
String? resolutionHeight;
Expand Down Expand Up @@ -62,10 +65,16 @@ class _VirtualDisplayScreenState extends AppModuleState<VirtualDisplayScreen> {
event = UpdateProfileArgEvent(_newDisplay, "");
} else {
event = UpdateProfileArgEvent(_newDisplay, null);
_disableFlex();
}
_profilesBloc.add(event);
}

void _disableFlex() {
final event = UpdateProfileArgEvent(_flexDisplay, null);
_profilesBloc.add(event);
}

void _updateDpi(String? newDpi) {
dpi = newDpi;
if (dpi != null) {
Expand Down Expand Up @@ -206,6 +215,12 @@ class _VirtualDisplayScreenState extends AppModuleState<VirtualDisplayScreen> {
),
),
const ConfigDivider(),
ConfigItem(
cliArgument: _flexDisplay,
icon: WindowsIcons.resize_mouse_small_mirrored,
child: ConfigToggle(cliArgument: _flexDisplay, state: state, isEnabled: isEnabled),
),
const ConfigDivider(),
ConfigItemBase(
icon: FluentIcons.image_pixel,
titleKey: '${_newDisplay.label}.dpi.title',
Expand Down
5 changes: 3 additions & 2 deletions lib/presentation/scrcpy_config/widgets/config_toggle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import 'package:scrcpy_buddy/application/profiles_bloc/profiles_bloc.dart';
class ConfigToggle extends StatelessWidget {
final ScrcpyCliArgument<bool> cliArgument;
final ProfilesState state;
final bool isEnabled;

const ConfigToggle({super.key, required this.state, required this.cliArgument});
const ConfigToggle({super.key, required this.state, required this.cliArgument, this.isEnabled = true});

@override
Widget build(BuildContext context) {
return ToggleSwitch(
checked: state.getFor(cliArgument) ?? false,
onChanged: (checked) => _onChanged(context, checked),
onChanged: isEnabled ? (checked) => _onChanged(context, checked) : null,
);
}

Expand Down
Loading