Skip to content

Commit

Permalink
Update to scrcpy 1.21 + implement some hardware buttons in WPF sample…
Browse files Browse the repository at this point in the history
… app
  • Loading branch information
Fusion86 committed Jan 16, 2022
1 parent d49c368 commit 4abaa91
Show file tree
Hide file tree
Showing 16 changed files with 188 additions and 80 deletions.
2 changes: 1 addition & 1 deletion deps/shared/README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Based on scrcpy, which can be found here -> https://github.com/Genymobile/scrcpy

Binaries downloaded from https://github.com/Genymobile/scrcpy/releases/tag/v1.17
Binaries downloaded from https://github.com/Genymobile/scrcpy/releases/tag/v1.21
Binary file modified deps/shared/scrcpy-server.jar
Binary file not shown.
Binary file modified deps/win64/adb.exe
Binary file not shown.
16 changes: 8 additions & 8 deletions src/ScrcpyNet.Avalonia/ScrcpyDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ protected override void OnKeyUp(KeyEventArgs e)
e.Handled = true;

var msg = new KeycodeControlMessage();
msg.Action = AndroidKeyeventAction.AKEY_EVENT_ACTION_UP;
msg.Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP;
msg.KeyCode = KeycodeHelper.ConvertKey(e.Key);
msg.Metastate = KeycodeHelper.ConvertModifiers(e.KeyModifiers);
scrcpy.SendControlCommand(msg);
Expand All @@ -123,14 +123,14 @@ protected override void OnPointerPressed(PointerPressedEventArgs e)
if (point.Properties.IsRightButtonPressed)
{
e.Handled = true;
var msg = new BackOrScreenOnControlMessage();
scrcpy.SendControlCommand(msg);
scrcpy.SendControlCommand(new BackOrScreenOnControlMessage() { Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN });
scrcpy.SendControlCommand(new BackOrScreenOnControlMessage() { Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP });
}
else if (point.Properties.IsLeftButtonPressed)
{
e.Handled = true;
isTouching = true;
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_DOWN, point.Position);
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_DOWN, point.Position);
}
}

Expand All @@ -147,7 +147,7 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
e.Handled = true;
isTouching = false;
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_UP, point.Position);
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_UP, point.Position);
}
}

Expand All @@ -162,14 +162,14 @@ protected override void OnPointerMoved(PointerEventArgs e)

if (isTouching && point.Position.X >= 0 && point.Position.Y >= 0)
{
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_MOVE, point.Position);
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_MOVE, point.Position);
}
}

base.OnPointerMoved(e);
}

protected void SendTouchCommand(AndroidMotioneventAction action, AVPoint position)
protected void SendTouchCommand(AndroidMotionEventAction action, AVPoint position)
{
if (scrcpy != null && renderTarget != null)
{
Expand All @@ -179,7 +179,7 @@ protected void SendTouchCommand(AndroidMotioneventAction action, AVPoint positio
msg.Position.Point.Y = (int)position.Y;
msg.Position.ScreenSize.Width = (ushort)renderTarget.Bounds.Width;
msg.Position.ScreenSize.Height = (ushort)renderTarget.Bounds.Height;
TouchHelper.ScaleToScreenSize(ref msg.Position, scrcpy.Width, scrcpy.Height);
TouchHelper.ScaleToScreenSize(msg.Position, scrcpy.Width, scrcpy.Height);
scrcpy.SendControlCommand(msg);

log.Debug("Sending {Action} for position {PositionX}, {PositionY}", action, msg.Position.Point.X, msg.Position.Point.Y);
Expand Down
23 changes: 23 additions & 0 deletions src/ScrcpyNet.Sample.ViewModels/ScrcpyViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using SharpAdbClient;
using System;
using System.Reactive;
using System.Threading.Tasks;

namespace ScrcpyNet.Sample.ViewModels
{
Expand All @@ -17,12 +18,15 @@ public class ScrcpyViewModel : ViewModelBase
public ReactiveCommand<DeviceData, Unit> ConnectCommand { get; }
public ReactiveCommand<Unit, Unit> DisconnectCommand { get; }

public ReactiveCommand<AndroidKeycode, Unit> SendKeycodeCommand { get; }

public ScrcpyViewModel()
{
// `outputScheduler: RxApp.TaskpoolScheduler` is only needed for the WPF frontend
// TODO: This code only works ONCE. Aka you can't reconnect after disconnecting.
ConnectCommand = ReactiveCommand.Create<DeviceData>(Connect);
DisconnectCommand = ReactiveCommand.Create(Disconnect);
SendKeycodeCommand = ReactiveCommand.Create<AndroidKeycode>(SendKeycode);
}

private void Connect(DeviceData device)
Expand All @@ -46,5 +50,24 @@ private void Disconnect()
Scrcpy = null;
}
}

private void SendKeycode(AndroidKeycode key)
{
if (Scrcpy == null) return;

Scrcpy.SendControlCommand(new KeycodeControlMessage
{
KeyCode = key,
Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN
});

// No need to wait before sending the KeyUp event.

Scrcpy.SendControlCommand(new KeycodeControlMessage
{
KeyCode = key,
Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP
});
}
}
}
37 changes: 30 additions & 7 deletions src/ScrcpyNet.Sample.Wpf/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ScrcpyNet.Sample.Wpf"
xmlns:vm="clr-namespace:ScrcpyNet.Sample.ViewModels;assembly=ScrcpyNet.Sample.ViewModels"
xmlns:scrcpy="clr-namespace:ScrcpyNet.Wpf;assembly=ScrcpyNet.Wpf"
xmlns:scrcpy="clr-namespace:ScrcpyNet;assembly=ScrcpyNet"
xmlns:scrcpyWpf="clr-namespace:ScrcpyNet.Wpf;assembly=ScrcpyNet.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">

Expand Down Expand Up @@ -65,17 +66,39 @@
CommandParameter="{Binding SelectedDevice}"/>
</StackPanel>

<StackPanel Visibility="{Binding Scrcpy.IsConnected, Converter={StaticResource VisibilityValueConverter}}">
<TextBlock Text="Connected device" FontWeight="Bold"/>
<TextBlock Text="{Binding Scrcpy.DeviceName}" Margin="0,4,0,0"/>
<DockPanel Visibility="{Binding Scrcpy.IsConnected, Converter={StaticResource VisibilityValueConverter}}">
<StackPanel DockPanel.Dock="Top">
<TextBlock Text="Connected device" FontWeight="Bold"/>
<TextBlock Text="{Binding Scrcpy.DeviceName}" Margin="0,4,0,0"/>

<Button Content="Disconnect" Command="{Binding Scrcpy.DisconnectCommand}" Margin="0,4,0,0"/>
</StackPanel>
<Button Content="Disconnect" Command="{Binding Scrcpy.DisconnectCommand}" Margin="0,4,0,0"/>
</StackPanel>

<WrapPanel Margin="-2,6,-2,6">
<WrapPanel.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="2"/>
<Setter Property="Padding" Value="4,1,4,1"/>
<Setter Property="Command" Value="{Binding Scrcpy.SendKeycodeCommand}"/>
</Style>
</WrapPanel.Resources>

<Button Content="Back" CommandParameter="{x:Static scrcpy:AndroidKeycode.AKEYCODE_BACK}"/>
<Button Content="Home" CommandParameter="{x:Static scrcpy:AndroidKeycode.AKEYCODE_HOME}"/>
<Button Content="Tasks" CommandParameter="{x:Static scrcpy:AndroidKeycode.AKEYCODE_APP_SWITCH}"/>

<!-- TODO: I don't know what message to send to lock the screen. -->
<!--<Button Content="Lock"/>-->

<Button Content="Vol +" CommandParameter="{x:Static scrcpy:AndroidKeycode.AKEYCODE_VOLUME_UP}"/>
<Button Content="Vol -" CommandParameter="{x:Static scrcpy:AndroidKeycode.AKEYCODE_VOLUME_DOWN}"/>
</WrapPanel>
</DockPanel>

<!-- TODO: Display errors here (maybe?) -->
<TextBlock Margin="10" Foreground="Red"/>
</StackPanel>

<scrcpy:ScrcpyDisplay Scrcpy="{Binding Scrcpy.Scrcpy}" Grid.Column="1"/>
<scrcpyWpf:ScrcpyDisplay Scrcpy="{Binding Scrcpy.Scrcpy}" Grid.Column="1"/>
</Grid>
</Window>
6 changes: 3 additions & 3 deletions src/ScrcpyNet.Test/ControlMessageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void KeyPressL()
public void KeyReleaseO()
{
var msg = new KeycodeControlMessage();
msg.Action = AndroidKeyeventAction.AKEY_EVENT_ACTION_UP;
msg.Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP;
msg.KeyCode = AndroidKeycode.AKEYCODE_O;
msg.Metastate = AndroidMetastate.AMETA_NUM_LOCK_ON;

Expand All @@ -58,15 +58,15 @@ public void KeyReleaseO()
public void TouchEvent()
{
var msg = new TouchEventControlMessage();
msg.Action = AndroidMotioneventAction.AMOTION_EVENT_ACTION_DOWN;
msg.Action = AndroidMotionEventAction.AMOTION_EVENT_ACTION_DOWN;
msg.PointerId = 0x1234567887654321;
msg.Position.Point.X = 100;
msg.Position.Point.Y = 200;
msg.Position.ScreenSize.Width = 1080;
msg.Position.ScreenSize.Height = 1920;

var expected = new byte[] {
(byte)ControlMessageType.ControlMsgTypeInjectTouchEvent,
(byte)ControlMessageType.InjectTouchEvent,
0x00, // AKEY_EVENT_ACTION_DOWN
0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21, // pointer id
0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xc8, // 100 200
Expand Down
20 changes: 10 additions & 10 deletions src/ScrcpyNet.Wpf/ScrcpyDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ protected override void OnMouseDown(MouseButtonEventArgs e)
if (e.RightButton == MouseButtonState.Pressed)
{
e.Handled = true;
var msg = new BackOrScreenOnControlMessage();
Scrcpy.SendControlCommand(msg);
Scrcpy.SendControlCommand(new BackOrScreenOnControlMessage() { Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN });
Scrcpy.SendControlCommand(new BackOrScreenOnControlMessage() { Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP });
}
else if (e.LeftButton == MouseButtonState.Pressed)
{
e.Handled = true;
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_DOWN, new Point { X = (int)point.X, Y = (int)point.Y });
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_DOWN, new Point { X = (int)point.X, Y = (int)point.Y });
}
}

Expand All @@ -101,7 +101,7 @@ protected override void OnMouseUp(MouseButtonEventArgs e)
{
var point = e.GetPosition(renderTarget);
e.Handled = true;
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_UP, new Point { X = (int)point.X, Y = (int)point.Y });
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_UP, new Point { X = (int)point.X, Y = (int)point.Y });
}

base.OnMouseUp(e);
Expand All @@ -115,7 +115,7 @@ protected override void OnMouseMove(MouseEventArgs e)

if (e.LeftButton == MouseButtonState.Pressed && point.X >= 0 && point.Y >= 0)
{
SendTouchCommand(AndroidMotioneventAction.AMOTION_EVENT_ACTION_MOVE, new Point { X = (int)point.X, Y = (int)point.Y });
SendTouchCommand(AndroidMotionEventAction.AMOTION_EVENT_ACTION_MOVE, new Point { X = (int)point.X, Y = (int)point.Y });
}
}

Expand Down Expand Up @@ -144,7 +144,7 @@ protected override void OnKeyUp(KeyEventArgs e)
e.Handled = true;

var msg = new KeycodeControlMessage();
msg.Action = AndroidKeyeventAction.AKEY_EVENT_ACTION_UP;
msg.Action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP;
msg.KeyCode = KeycodeHelper.ConvertKey(e.Key);
msg.Metastate = KeycodeHelper.ConvertModifiers(e.KeyboardDevice.Modifiers);
Scrcpy.SendControlCommand(msg);
Expand All @@ -153,7 +153,7 @@ protected override void OnKeyUp(KeyEventArgs e)
base.OnKeyUp(e);
}

protected void SendTouchCommand(AndroidMotioneventAction action, Point position)
protected void SendTouchCommand(AndroidMotionEventAction action, Point position)
{
if (Scrcpy != null && renderTarget != null)
{
Expand All @@ -163,7 +163,7 @@ protected void SendTouchCommand(AndroidMotioneventAction action, Point position)
msg.Position.Point.Y = position.Y;
msg.Position.ScreenSize.Width = (ushort)renderTarget.ActualWidth;
msg.Position.ScreenSize.Height = (ushort)renderTarget.ActualHeight;
TouchHelper.ScaleToScreenSize(ref msg.Position, Scrcpy.Width, Scrcpy.Height);
TouchHelper.ScaleToScreenSize(msg.Position, Scrcpy.Width, Scrcpy.Height);
Scrcpy.SendControlCommand(msg);

log.Debug("Sending {Action} for position {PositionX}, {PositionY}", action, msg.Position.Point.X, msg.Position.Point.Y);
Expand Down Expand Up @@ -202,11 +202,11 @@ private unsafe void OnFrame(object? sender, FrameData frameData)
}
catch (TimeoutException)
{
log.Verbose("Ignoring TimeoutException inside OnFrame.");
log.Debug("Ignoring TimeoutException inside OnFrame.");
}
catch (TaskCanceledException)
{
log.Verbose("Ignoring TaskCanceledException inside OnFrame.");
log.Debug("Ignoring TaskCanceledException inside OnFrame.");
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/ScrcpyNet/AndroidInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace ScrcpyNet
{
public enum AndroidKeyeventAction : byte
public enum AndroidKeyEventAction : byte
{
/** The key has been pressed down. */
AKEY_EVENT_ACTION_DOWN = 0,
Expand Down Expand Up @@ -76,7 +76,7 @@ public enum AndroidMetastate : int
AMETA_SCROLL_LOCK_ON = 0x400000,
}

public enum AndroidMotioneventAction
public enum AndroidMotionEventAction
{
/** Bit mask of the parts of the action code that are the action itself. */
AMOTION_EVENT_ACTION_MASK = 0xff,
Expand Down Expand Up @@ -160,7 +160,7 @@ public enum AndroidMotioneventAction
AMOTION_EVENT_ACTION_BUTTON_RELEASE = 12,
};

public enum AndroidMotioneventButtons : int
public enum AndroidMotionEventButtons : int
{
/** primary */
AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
Expand Down
Loading

0 comments on commit 4abaa91

Please sign in to comment.