From 0bd2261be7975b79bce855c828c03e2b95d673b1 Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Wed, 10 Apr 2019 16:49:44 -0700 Subject: [PATCH] Fixed a mouse input bug when the virtual screen's left-most coordinate is in the negative. Refactored ICapturer virtual screen methods. --- README.md | 15 ++++++- Remotely_ScreenCast.Core/Capture/ICapturer.cs | 3 +- .../Capture/ScreenCaster.cs | 13 +------ .../Sockets/CasterSocket.cs | 18 ++++----- .../Capture/X11Capture.cs | 21 ++++------ .../Capture/BitBltCapture.cs | 9 +---- Remotely_ScreenCast.Win/Capture/DXCapture.cs | 9 +---- Remotely_ScreenCast.Win/Input/WinInput.cs | 39 +++++++++++++------ Remotely_Server/CurrentVersion.txt | 2 +- 9 files changed, 63 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 73a8a58e..75b6de10 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,12 @@ The following steps will configure your Windows 10 machine for building the Remo * The output folder will now contain the server, with the clients in the Downloads folder. ## Hosting a Server (Windows) +* Create a site in IIS that will run Remotely. +* Run Install-RemotelyServer.ps1 (as an administrator), which is in the [Utilities folder in source control](https://raw.githubusercontent.com/Jay-Rad/Remotely/master/Utilities/Install-RemotelyServer.ps1). * Download and install the .NET Core Runtime (not the SDK). * Link: https://dotnet.microsoft.com/download * This includes the Hosting Bundle for Windows, which allows you to run ASP.NET Core in IIS. -* Create a site in IIS that will run Remotely. -* Run Install-RemotelyServer.ps1 (as an administrator), which is in the [Utilities folder in source control](https://raw.githubusercontent.com/Jay-Rad/Remotely/master/Utilities/Install-RemotelyServer.ps1). + * Important: If you installed .NET Core Runtime before installing all the required IIS features (which is done in the script), you may need to run a repair on the .NET Core Runtime installation. * Change values in appsettings.json for your environment. * If using SQLite configuration, make sure the ApplicationPool's account has write access to the DB file location. * The script will do this for you, assuming all default settings. @@ -50,6 +51,16 @@ The following steps will configure your Windows 10 machine for building the Remo * After creating your account on the website, you can set "AllowSelfRegistration" to false in appsettings.json to disable registration. * Documentation for hosting behind Nginx can be found here: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2 +## Logging +* On clients, logs are kept in %temp%\Remotely_Logs.txt. + * For the Agent running as a Windows service, this maps to C:\Windows\Temp\Remotely_Logs.txt. +* On the server, some event information is explicitly written to the EventLogs table in the database. +* Built-in ASP.NET Core logs are written to the console (stdout). You can redirect this to a file if desired. + * In IIS, this can be done in the web.config file by setting stdoutLogEnabled to true. +* On Windows Servers, the above logs are also written to the Windows Event Log. +* You can configure logging levels and other settings in appsetttings.json. + * More information: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.2 + ## Remote Control Requirements * Windows: Only the latest version of Windows 10 is tested. * Requires .NET Framework 4.7.2. diff --git a/Remotely_ScreenCast.Core/Capture/ICapturer.cs b/Remotely_ScreenCast.Core/Capture/ICapturer.cs index 7206f2d6..9204a6e5 100644 --- a/Remotely_ScreenCast.Core/Capture/ICapturer.cs +++ b/Remotely_ScreenCast.Core/Capture/ICapturer.cs @@ -17,8 +17,7 @@ namespace Remotely_ScreenCast.Core.Capture int SelectedScreen { get; } void SetSelectedScreen(int screenNumber); int GetScreenCount(); - double GetVirtualScreenHeight(); - double GetVirtualScreenWidth(); + Rectangle GetVirtualScreenBounds(); void Capture(); void Init(); diff --git a/Remotely_ScreenCast.Core/Capture/ScreenCaster.cs b/Remotely_ScreenCast.Core/Capture/ScreenCaster.cs index d5b141e7..08091f2d 100644 --- a/Remotely_ScreenCast.Core/Capture/ScreenCaster.cs +++ b/Remotely_ScreenCast.Core/Capture/ScreenCaster.cs @@ -152,17 +152,6 @@ namespace Remotely_ScreenCast.Core.Capture } } - public static Tuple GetAbsolutePercentFromRelativePercent(double percentX, double percentY, ICapturer capturer) - { - var absoluteX = (capturer.CurrentScreenBounds.Width * percentX) + capturer.CurrentScreenBounds.Left; - var absoluteY = (capturer.CurrentScreenBounds.Height * percentY) + capturer.CurrentScreenBounds.Top; - return new Tuple(absoluteX / capturer.GetVirtualScreenWidth(), absoluteY / capturer.GetVirtualScreenHeight()); - } - public static Tuple GetAbsolutePointFromRelativePercent(double percentX, double percentY, ICapturer capturer) - { - var absoluteX = (capturer.CurrentScreenBounds.Width * percentX) + capturer.CurrentScreenBounds.Left; - var absoluteY = (capturer.CurrentScreenBounds.Height * percentY) + capturer.CurrentScreenBounds.Top; - return new Tuple(absoluteX, absoluteY); - } + } } diff --git a/Remotely_ScreenCast.Core/Sockets/CasterSocket.cs b/Remotely_ScreenCast.Core/Sockets/CasterSocket.cs index a2c19790..a8d08684 100644 --- a/Remotely_ScreenCast.Core/Sockets/CasterSocket.cs +++ b/Remotely_ScreenCast.Core/Sockets/CasterSocket.cs @@ -86,8 +86,7 @@ namespace Remotely_ScreenCast.Core.Sockets { if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl) { - var xyPercents = ScreenCaster.GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); - KeyboardMouseInput.SendMouseMove(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendMouseMove(percentX, percentY, viewer); } }); @@ -95,14 +94,13 @@ namespace Remotely_ScreenCast.Core.Sockets { if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl) { - var xyPercents = ScreenCaster.GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); if (button == 0) { - KeyboardMouseInput.SendLeftMouseDown(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendLeftMouseDown(percentX, percentY, viewer); } else if (button == 2) { - KeyboardMouseInput.SendRightMouseDown(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendRightMouseDown(percentX, percentY, viewer); } } }); @@ -111,14 +109,13 @@ namespace Remotely_ScreenCast.Core.Sockets { if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl) { - var xyPercents = ScreenCaster.GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); if (button == 0) { - KeyboardMouseInput.SendLeftMouseUp(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendLeftMouseUp(percentX, percentY, viewer); } else if (button == 2) { - KeyboardMouseInput.SendRightMouseUp(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendRightMouseUp(percentX, percentY, viewer); } } }); @@ -204,9 +201,8 @@ namespace Remotely_ScreenCast.Core.Sockets { if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl) { - var xyPercents = ScreenCaster.GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); - KeyboardMouseInput.SendLeftMouseDown(xyPercents.Item1, xyPercents.Item2, viewer); - KeyboardMouseInput.SendLeftMouseUp(xyPercents.Item1, xyPercents.Item2, viewer); + KeyboardMouseInput.SendLeftMouseDown(percentX, percentY, viewer); + KeyboardMouseInput.SendLeftMouseUp(percentX, percentY, viewer); } }); Connection.On("SharedFileIDs", (List fileIDs) => { diff --git a/Remotely_ScreenCast.Linux/Capture/X11Capture.cs b/Remotely_ScreenCast.Linux/Capture/X11Capture.cs index 324e53da..b8c79fb3 100644 --- a/Remotely_ScreenCast.Linux/Capture/X11Capture.cs +++ b/Remotely_ScreenCast.Linux/Capture/X11Capture.cs @@ -51,24 +51,19 @@ namespace Remotely_ScreenCast.Linux.Capture return LibX11.XScreenCount(Display); } - public double GetVirtualScreenHeight() + public Rectangle GetVirtualScreenBounds() { - double height = 0; - for (var i = 0; i < GetScreenCount(); i++) - { - height += LibX11.XHeightOfScreen(LibX11.XScreenOfDisplay(Display, i)); - } - return height; - } - - public double GetVirtualScreenWidth() - { - double width = 0; + int width = 0; for (var i = 0; i < GetScreenCount(); i++) { width += LibX11.XWidthOfScreen(LibX11.XScreenOfDisplay(Display, i)); } - return width; + int height = 0; + for (var i = 0; i < GetScreenCount(); i++) + { + height += LibX11.XHeightOfScreen(LibX11.XScreenOfDisplay(Display, i)); + } + return new Rectangle(0, 0, width, height); } public void Init() diff --git a/Remotely_ScreenCast.Win/Capture/BitBltCapture.cs b/Remotely_ScreenCast.Win/Capture/BitBltCapture.cs index abde830e..556a70d3 100644 --- a/Remotely_ScreenCast.Win/Capture/BitBltCapture.cs +++ b/Remotely_ScreenCast.Win/Capture/BitBltCapture.cs @@ -65,14 +65,9 @@ namespace Remotely_ScreenCast.Win.Capture return Screen.AllScreens.Length; } - public double GetVirtualScreenHeight() + public Rectangle GetVirtualScreenBounds() { - return SystemInformation.VirtualScreen.Height; - } - - public double GetVirtualScreenWidth() - { - return SystemInformation.VirtualScreen.Width; + return SystemInformation.VirtualScreen; } public void Init() diff --git a/Remotely_ScreenCast.Win/Capture/DXCapture.cs b/Remotely_ScreenCast.Win/Capture/DXCapture.cs index 18600414..b37102fd 100644 --- a/Remotely_ScreenCast.Win/Capture/DXCapture.cs +++ b/Remotely_ScreenCast.Win/Capture/DXCapture.cs @@ -125,14 +125,9 @@ namespace Remotely_ScreenCast.Win.Capture return Screen.AllScreens.Length; } - public double GetVirtualScreenHeight() + public Rectangle GetVirtualScreenBounds() { - return SystemInformation.VirtualScreen.Height; - } - - public double GetVirtualScreenWidth() - { - return SystemInformation.VirtualScreen.Width; + return SystemInformation.VirtualScreen; } public void Init() diff --git a/Remotely_ScreenCast.Win/Input/WinInput.cs b/Remotely_ScreenCast.Win/Input/WinInput.cs index 75d48595..d964ee16 100644 --- a/Remotely_ScreenCast.Win/Input/WinInput.cs +++ b/Remotely_ScreenCast.Win/Input/WinInput.cs @@ -3,6 +3,7 @@ using Remotely_ScreenCast.Core.Models; using System; using Remotely_Shared.Win32; using static Remotely_Shared.Win32.User32; +using Remotely_ScreenCast.Core.Capture; namespace Remotely_ScreenCast.Win.Input { @@ -10,45 +11,50 @@ namespace Remotely_ScreenCast.Win.Input { public uint SendLeftMouseDown(double percentX, double percentY, Viewer viewer) { + var xyPercent = GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); // Coordinates must be normalized. The bottom-right coordinate is mapped to 65535. - var normalizedX = percentX * 65535D; - var normalizedY = percentY * 65535D; + var normalizedX = xyPercent.Item1 * 65535D; + var normalizedY = xyPercent.Item2 * 65535D; var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.LEFTDOWN | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = GetMessageExtraInfo() } }; var input = new INPUT() { type = InputType.MOUSE, U = union }; return SendInput(1, new INPUT[] { input }, INPUT.Size); } public uint SendLeftMouseUp(double percentX, double percentY, Viewer viewer) { + var xyPercent = GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); // Coordinates must be normalized. The bottom-right coordinate is mapped to 65535. - var normalizedX = percentX * 65535D; - var normalizedY = percentY * 65535D; + var normalizedX = xyPercent.Item1 * 65535D; + var normalizedY = xyPercent.Item2 * 65535D; var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.LEFTUP | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = GetMessageExtraInfo() } }; var input = new INPUT() { type = InputType.MOUSE, U = union }; return SendInput(1, new INPUT[] { input }, INPUT.Size); } public uint SendRightMouseDown(double percentX, double percentY, Viewer viewer) { + var xyPercent = GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); // Coordinates must be normalized. The bottom-right coordinate is mapped to 65535. - var normalizedX = percentX * 65535D; - var normalizedY = percentY * 65535D; + var normalizedX = xyPercent.Item1 * 65535D; + var normalizedY = xyPercent.Item2 * 65535D; var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.RIGHTDOWN | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = GetMessageExtraInfo() } }; var input = new INPUT() { type = InputType.MOUSE, U = union }; return SendInput(1, new INPUT[] { input }, INPUT.Size); } public uint SendRightMouseUp(double percentX, double percentY, Viewer viewer) { + var xyPercent = GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); // Coordinates must be normalized. The bottom-right coordinate is mapped to 65535. - var normalizedX = percentX * 65535D; - var normalizedY = percentY * 65535D; + var normalizedX = xyPercent.Item1 * 65535D; + var normalizedY = xyPercent.Item2 * 65535D; var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.RIGHTUP | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = GetMessageExtraInfo() } }; var input = new INPUT() { type = InputType.MOUSE, U = union }; return SendInput(1, new INPUT[] { input }, INPUT.Size); } public uint SendMouseMove(double percentX, double percentY, Viewer viewer) { + var xyPercent = GetAbsolutePercentFromRelativePercent(percentX, percentY, viewer.Capturer); // Coordinates must be normalized. The bottom-right coordinate is mapped to 65535. - var normalizedX = percentX * 65535D; - var normalizedY = percentY * 65535D; + var normalizedX = xyPercent.Item1 * 65535D; + var normalizedY = xyPercent.Item2 * 65535D; var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.MOVE | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = GetMessageExtraInfo() } }; var input = new INPUT() { type = InputType.MOUSE, U = union }; return SendInput(1, new INPUT[] { input }, INPUT.Size); @@ -220,6 +226,17 @@ namespace Remotely_ScreenCast.Win.Input return keyCode; } - + public Tuple GetAbsolutePercentFromRelativePercent(double percentX, double percentY, ICapturer capturer) + { + var absoluteX = (capturer.CurrentScreenBounds.Width * percentX) + capturer.CurrentScreenBounds.Left - capturer.GetVirtualScreenBounds().Left; + var absoluteY = (capturer.CurrentScreenBounds.Height * percentY) + capturer.CurrentScreenBounds.Top - capturer.GetVirtualScreenBounds().Top; + return new Tuple(absoluteX / capturer.GetVirtualScreenBounds().Width, absoluteY / capturer.GetVirtualScreenBounds().Height); + } + public Tuple GetAbsolutePointFromRelativePercent(double percentX, double percentY, ICapturer capturer) + { + var absoluteX = (capturer.CurrentScreenBounds.Width * percentX) + capturer.CurrentScreenBounds.Left; + var absoluteY = (capturer.CurrentScreenBounds.Height * percentY) + capturer.CurrentScreenBounds.Top; + return new Tuple(absoluteX, absoluteY); + } } } diff --git a/Remotely_Server/CurrentVersion.txt b/Remotely_Server/CurrentVersion.txt index 3583a26c..195b6b75 100644 --- a/Remotely_Server/CurrentVersion.txt +++ b/Remotely_Server/CurrentVersion.txt @@ -1 +1 @@ -2019.04.10.0649 +2019.04.10.0829