mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Refactor IScreenCapturer.
This commit is contained in:
parent
dd3b9083bd
commit
b2c9536e23
@ -9,14 +9,12 @@ namespace Remotely.Desktop.Core.Interfaces
|
||||
event EventHandler<Rectangle> ScreenChanged;
|
||||
|
||||
bool CaptureFullscreen { get; set; }
|
||||
Bitmap CurrentFrame { get; set; }
|
||||
Rectangle CurrentScreenBounds { get; }
|
||||
Bitmap PreviousFrame { get; set; }
|
||||
string SelectedScreen { get; }
|
||||
|
||||
IEnumerable<string> GetDisplayNames();
|
||||
|
||||
void GetNextFrame();
|
||||
Bitmap GetNextFrame();
|
||||
|
||||
int GetScreenCount();
|
||||
|
||||
|
||||
@ -209,13 +209,13 @@ namespace Remotely.Desktop.Core.Services
|
||||
|
||||
});
|
||||
|
||||
Connection.On("ReceiveRtcAnswer", (string sdp, string viewerID) =>
|
||||
Connection.On("ReceiveRtcAnswer", async (string sdp, string viewerID) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
|
||||
{
|
||||
viewer.RtcSession.SetRemoteDescription("answer", sdp);
|
||||
await viewer.RtcSession.SetRemoteDescription("answer", sdp);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@ -13,6 +13,7 @@ using System.Collections.Concurrent;
|
||||
using Remotely.Desktop.Core.Enums;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Win32;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Remotely.Desktop.Core.Services
|
||||
{
|
||||
@ -35,6 +36,8 @@ namespace Remotely.Desktop.Core.Services
|
||||
|
||||
try
|
||||
{
|
||||
Bitmap currentFrame = null;
|
||||
Bitmap previousFrame = null;
|
||||
byte[] encodedImageBytes;
|
||||
var fpsQueue = new Queue<DateTimeOffset>();
|
||||
mode = Conductor.Mode;
|
||||
@ -76,12 +79,17 @@ namespace Remotely.Desktop.Core.Services
|
||||
await viewer.SendScreenSize(bounds.Width, bounds.Height);
|
||||
};
|
||||
|
||||
await viewer.SendScreenCapture(
|
||||
ImageUtils.EncodeBitmap(viewer.Capturer.CurrentFrame, viewer.EncoderParams),
|
||||
viewer.Capturer.CurrentScreenBounds.Left,
|
||||
viewer.Capturer.CurrentScreenBounds.Top,
|
||||
viewer.Capturer.CurrentScreenBounds.Width,
|
||||
viewer.Capturer.CurrentScreenBounds.Height);
|
||||
using (var initialFrame = viewer.Capturer.GetNextFrame())
|
||||
{
|
||||
await viewer.SendScreenCapture(
|
||||
ImageUtils.EncodeBitmap(initialFrame, viewer.EncoderParams),
|
||||
viewer.Capturer.CurrentScreenBounds.Left,
|
||||
viewer.Capturer.CurrentScreenBounds.Top,
|
||||
viewer.Capturer.CurrentScreenBounds.Width,
|
||||
viewer.Capturer.CurrentScreenBounds.Height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
while (!viewer.DisconnectRequested && viewer.IsConnected)
|
||||
{
|
||||
@ -105,16 +113,19 @@ namespace Remotely.Desktop.Core.Services
|
||||
|
||||
viewer.ThrottleIfNeeded();
|
||||
|
||||
viewer.Capturer.GetNextFrame();
|
||||
previousFrame?.Dispose();
|
||||
previousFrame = (Bitmap)currentFrame?.Clone();
|
||||
currentFrame?.Dispose();
|
||||
currentFrame = viewer.Capturer.GetNextFrame();
|
||||
|
||||
var diffArea = ImageUtils.GetDiffArea(viewer.Capturer.CurrentFrame, viewer.Capturer.PreviousFrame, viewer.Capturer.CaptureFullscreen);
|
||||
var diffArea = ImageUtils.GetDiffArea(currentFrame, previousFrame, viewer.Capturer.CaptureFullscreen);
|
||||
|
||||
if (diffArea.IsEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using (var newImage = viewer.Capturer.CurrentFrame.Clone(diffArea, PixelFormat.Format32bppArgb))
|
||||
using (var newImage = currentFrame.Clone(diffArea, PixelFormat.Format32bppArgb))
|
||||
{
|
||||
if (viewer.Capturer.CaptureFullscreen)
|
||||
{
|
||||
|
||||
@ -8,47 +8,51 @@ using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Remotely.Desktop.Linux.Services
|
||||
{
|
||||
public class ScreenCapturerLinux : IScreenCapturer
|
||||
{
|
||||
private readonly SemaphoreSlim screenCaptureLock = new SemaphoreSlim(1);
|
||||
private readonly Dictionary<string, int> x11Screens = new Dictionary<string, int>();
|
||||
public ScreenCapturerLinux()
|
||||
{
|
||||
Display = LibX11.XOpenDisplay(null);
|
||||
Init();
|
||||
GetNextFrame();
|
||||
}
|
||||
|
||||
public event EventHandler<Rectangle> ScreenChanged;
|
||||
|
||||
public bool CaptureFullscreen { get; set; }
|
||||
public Bitmap CurrentFrame { get; set; }
|
||||
public Rectangle CurrentScreenBounds { get; private set; }
|
||||
public IntPtr Display { get; private set; }
|
||||
public Bitmap PreviousFrame { get; set; }
|
||||
public string SelectedScreen { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
CurrentFrame.Dispose();
|
||||
PreviousFrame.Dispose();
|
||||
LibX11.XCloseDisplay(Display);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetDisplayNames() => x11Screens.Keys;
|
||||
|
||||
public void GetNextFrame()
|
||||
public Bitmap GetNextFrame()
|
||||
{
|
||||
try
|
||||
{
|
||||
PreviousFrame?.Dispose();
|
||||
PreviousFrame = (Bitmap)CurrentFrame.Clone();
|
||||
RefreshCurrentFrame();
|
||||
screenCaptureLock.Wait();
|
||||
|
||||
return GetX11Screen();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex);
|
||||
Init();
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
screenCaptureLock.Release();
|
||||
}
|
||||
}
|
||||
public int GetScreenCount()
|
||||
@ -84,8 +88,6 @@ namespace Remotely.Desktop.Linux.Services
|
||||
x11Screens.Add(i.ToString(), i);
|
||||
}
|
||||
SetSelectedScreen(x11Screens.Keys.First());
|
||||
CurrentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
PreviousFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -121,19 +123,21 @@ namespace Remotely.Desktop.Linux.Services
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshCurrentFrame()
|
||||
private Bitmap GetX11Screen()
|
||||
{
|
||||
var currentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
|
||||
var window = LibX11.XRootWindow(Display, x11Screens[SelectedScreen]);
|
||||
|
||||
var imagePointer = LibX11.XGetImage(Display, window, 0, 0, CurrentScreenBounds.Width, CurrentScreenBounds.Height, ~0, 2);
|
||||
var image = Marshal.PtrToStructure<LibX11.XImage>(imagePointer);
|
||||
|
||||
var bd = CurrentFrame.LockBits(new Rectangle(0, 0, CurrentFrame.Width, CurrentFrame.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
var bd = currentFrame.LockBits(new Rectangle(0, 0, CurrentScreenBounds.Width, CurrentScreenBounds.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
unsafe
|
||||
{
|
||||
byte* scan1 = (byte*)bd.Scan0.ToPointer();
|
||||
byte* scan2 = (byte*)image.data.ToPointer();
|
||||
var bytesPerPixel = Bitmap.GetPixelFormatSize(CurrentFrame.PixelFormat) / 8;
|
||||
var bytesPerPixel = Bitmap.GetPixelFormatSize(currentFrame.PixelFormat) / 8;
|
||||
var totalSize = bd.Height * bd.Width * bytesPerPixel;
|
||||
for (int counter = 0; counter < totalSize - bytesPerPixel; counter++)
|
||||
{
|
||||
@ -141,8 +145,10 @@ namespace Remotely.Desktop.Linux.Services
|
||||
}
|
||||
}
|
||||
|
||||
CurrentFrame.UnlockBits(bd);
|
||||
currentFrame.UnlockBits(bd);
|
||||
LibX11.XDestroyImage(imagePointer);
|
||||
|
||||
return currentFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Remotely.Desktop.Win.Services
|
||||
@ -43,37 +44,33 @@ namespace Remotely.Desktop.Win.Services
|
||||
{
|
||||
private readonly Dictionary<string, int> bitBltScreens = new Dictionary<string, int>();
|
||||
private readonly Dictionary<string, DirectXOutput> directxScreens = new Dictionary<string, DirectXOutput>();
|
||||
private readonly SemaphoreSlim screenCaptureLock = new SemaphoreSlim(1);
|
||||
|
||||
public ScreenCapturerWin()
|
||||
{
|
||||
Init();
|
||||
GetBitBltFrame();
|
||||
SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
|
||||
}
|
||||
|
||||
public event EventHandler<Rectangle> ScreenChanged;
|
||||
|
||||
public bool CaptureFullscreen { get; set; } = true;
|
||||
public Bitmap CurrentFrame { get; set; }
|
||||
public Rectangle CurrentScreenBounds { get; private set; } = Screen.PrimaryScreen.Bounds;
|
||||
public bool NeedsInit { get; set; } = true;
|
||||
public Bitmap PreviousFrame { get; set; }
|
||||
public string SelectedScreen { get; private set; } = Screen.PrimaryScreen.DeviceName;
|
||||
private Graphics Graphic { get; set; }
|
||||
public void Dispose()
|
||||
{
|
||||
SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
|
||||
ClearDirectXOutputs();
|
||||
|
||||
CurrentFrame?.Dispose();
|
||||
PreviousFrame?.Dispose();
|
||||
}
|
||||
public IEnumerable<string> GetDisplayNames() => Screen.AllScreens.Select(x => x.DeviceName);
|
||||
|
||||
public void GetNextFrame()
|
||||
public Bitmap GetNextFrame()
|
||||
{
|
||||
try
|
||||
{
|
||||
screenCaptureLock.Wait();
|
||||
|
||||
Win32Interop.SwitchToInputDesktop();
|
||||
|
||||
if (NeedsInit)
|
||||
@ -82,25 +79,33 @@ namespace Remotely.Desktop.Win.Services
|
||||
Init();
|
||||
}
|
||||
|
||||
PreviousFrame?.Dispose();
|
||||
PreviousFrame = (Bitmap)CurrentFrame.Clone();
|
||||
|
||||
// Sometimes DX will result in a timeout, even when there are changes
|
||||
// on the screen. I've observed this when a laptop lid is closed, or
|
||||
// on some machines that aren't connected to a monitor. This will
|
||||
// have it fall back to BitBlt in those cases.
|
||||
if (!directxScreens.ContainsKey(SelectedScreen) ||
|
||||
GetDirectXFrame() == GetDirectXFrameResult.Timeout)
|
||||
if (directxScreens.ContainsKey(SelectedScreen))
|
||||
{
|
||||
GetBitBltFrame();
|
||||
var directXResult = GetDirectXFrame();
|
||||
|
||||
if (directXResult.result == GetDirectXFrameResult.Success)
|
||||
{
|
||||
return directXResult.frame;
|
||||
}
|
||||
}
|
||||
|
||||
return GetBitBltFrame();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Write(e);
|
||||
NeedsInit = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
screenCaptureLock.Release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetScreenCount() => Screen.AllScreens.Length;
|
||||
@ -111,9 +116,6 @@ namespace Remotely.Desktop.Win.Services
|
||||
|
||||
public void Init()
|
||||
{
|
||||
CurrentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
PreviousFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
|
||||
InitBitBlt();
|
||||
InitDirectX();
|
||||
|
||||
@ -147,14 +149,17 @@ namespace Remotely.Desktop.Win.Services
|
||||
directxScreens.Clear();
|
||||
}
|
||||
|
||||
private void GetBitBltFrame()
|
||||
private Bitmap GetBitBltFrame()
|
||||
{
|
||||
try
|
||||
{
|
||||
Win32Interop.SwitchToInputDesktop();
|
||||
PreviousFrame.Dispose();
|
||||
PreviousFrame = (Bitmap)CurrentFrame.Clone();
|
||||
Graphic.CopyFromScreen(CurrentScreenBounds.Left, CurrentScreenBounds.Top, 0, 0, new Size(CurrentScreenBounds.Width, CurrentScreenBounds.Height));
|
||||
var currentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
using (var graphic = Graphics.FromImage(currentFrame))
|
||||
{
|
||||
graphic.CopyFromScreen(CurrentScreenBounds.Left, CurrentScreenBounds.Top, 0, 0, new Size(CurrentScreenBounds.Width, CurrentScreenBounds.Height));
|
||||
}
|
||||
return currentFrame;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -167,6 +172,8 @@ namespace Remotely.Desktop.Win.Services
|
||||
}
|
||||
NeedsInit = true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private enum GetDirectXFrameResult
|
||||
@ -176,7 +183,7 @@ namespace Remotely.Desktop.Win.Services
|
||||
Timeout,
|
||||
}
|
||||
|
||||
private GetDirectXFrameResult GetDirectXFrame()
|
||||
private (GetDirectXFrameResult result, Bitmap frame) GetDirectXFrame()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -193,13 +200,13 @@ namespace Remotely.Desktop.Win.Services
|
||||
{
|
||||
if (result.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Code)
|
||||
{
|
||||
return GetDirectXFrameResult.Timeout;
|
||||
return (GetDirectXFrameResult.Timeout, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Write($"TryAcquireFrame error. Code: {result.Code}");
|
||||
NeedsInit = true;
|
||||
return GetDirectXFrameResult.Failure;
|
||||
return (GetDirectXFrameResult.Failure, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,9 +217,11 @@ namespace Remotely.Desktop.Win.Services
|
||||
duplicatedOutput.ReleaseFrame();
|
||||
}
|
||||
catch { }
|
||||
return GetDirectXFrameResult.Failure;
|
||||
return (GetDirectXFrameResult.Failure, null);
|
||||
}
|
||||
|
||||
|
||||
var currentFrame = new Bitmap(CurrentScreenBounds.Width, CurrentScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Copy resource into memory that can be accessed by the CPU
|
||||
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
|
||||
{
|
||||
@ -225,7 +234,7 @@ namespace Remotely.Desktop.Win.Services
|
||||
var boundsRect = new Rectangle(0, 0, texture2D.Description.Width, texture2D.Description.Height);
|
||||
|
||||
// Copy pixels from screen capture Texture to GDI bitmap
|
||||
var mapDest = CurrentFrame.LockBits(boundsRect, ImageLockMode.WriteOnly, CurrentFrame.PixelFormat);
|
||||
var mapDest = currentFrame.LockBits(boundsRect, ImageLockMode.WriteOnly, currentFrame.PixelFormat);
|
||||
var sourcePtr = mapSource.DataPointer;
|
||||
var destPtr = mapDest.Scan0;
|
||||
for (int y = 0; y < texture2D.Description.Height; y++)
|
||||
@ -239,13 +248,13 @@ namespace Remotely.Desktop.Win.Services
|
||||
}
|
||||
|
||||
// Release source and dest locks
|
||||
CurrentFrame.UnlockBits(mapDest);
|
||||
currentFrame.UnlockBits(mapDest);
|
||||
device.ImmediateContext.UnmapSubresource(texture2D, 0);
|
||||
|
||||
screenResource.Dispose();
|
||||
duplicatedOutput.ReleaseFrame();
|
||||
|
||||
return GetDirectXFrameResult.Success;
|
||||
return (GetDirectXFrameResult.Success, currentFrame);
|
||||
}
|
||||
catch (SharpDXException e)
|
||||
{
|
||||
@ -253,16 +262,15 @@ namespace Remotely.Desktop.Win.Services
|
||||
{
|
||||
Logger.Write(e);
|
||||
NeedsInit = true;
|
||||
return GetDirectXFrameResult.Failure;
|
||||
return (GetDirectXFrameResult.Failure, null);
|
||||
}
|
||||
return GetDirectXFrameResult.Timeout;
|
||||
return (GetDirectXFrameResult.Timeout, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitBitBlt()
|
||||
{
|
||||
bitBltScreens.Clear();
|
||||
Graphic = Graphics.FromImage(CurrentFrame);
|
||||
for (var i = 0; i < Screen.AllScreens.Length; i++)
|
||||
{
|
||||
bitBltScreens.Add(Screen.AllScreens[i].DeviceName, i);
|
||||
|
||||
@ -191,6 +191,7 @@
|
||||
|
||||
<div id="screenViewerWrapper" class="center-aligned">
|
||||
<canvas id="screenViewer" hidden="hidden"></canvas>
|
||||
<video id="videoScreenViewer" hidden="hidden"></video>
|
||||
<input id="fileTransferInput" hidden="hidden" type="file" multiple />
|
||||
<textarea id="touchKeyboardTextArea" value=" #"> #</textarea>
|
||||
</div>
|
||||
|
||||
@ -121,7 +121,8 @@ button {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
#screenViewer {
|
||||
|
||||
#screenViewer, #videoScreenViewer {
|
||||
max-width: 99vw;
|
||||
max-height: 99vh;
|
||||
z-index: 1;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { AudioButton, ChangeScreenButton, HorizontalBars, ScreenSelectBar, ClipboardTransferButton, ClipboardTransferBar, TypeClipboardButton, ShowMessage, ConnectButton, CtrlAltDelButton, DisconnectButton, FileTransferButton, FileTransferInput, FitToScreenButton, ScreenViewer, BlockInputButton, InviteButton, KeyboardButton, TouchKeyboardTextArea, MenuFrame, MenuButton, QualityButton, QualityBar, QualitySlider, AutoQualityAdjustCheckBox, ScreenViewerWrapper, WindowsSessionSelect, RecordSessionButton, DownloadRecordingButton } from "./UI.js";
|
||||
import { AudioButton, ChangeScreenButton, HorizontalBars, ScreenSelectBar, ClipboardTransferButton, ClipboardTransferBar, TypeClipboardButton, ShowMessage, ConnectButton, CtrlAltDelButton, DisconnectButton, FileTransferButton, FileTransferInput, FitToScreenButton, ScreenViewer, BlockInputButton, InviteButton, KeyboardButton, TouchKeyboardTextArea, MenuFrame, MenuButton, QualityButton, QualityBar, QualitySlider, AutoQualityAdjustCheckBox, ScreenViewerWrapper, WindowsSessionSelect, RecordSessionButton, DownloadRecordingButton, VideoScreenViewer } from "./UI.js";
|
||||
import { Sound } from "../Sound.js";
|
||||
import { MainRc } from "./Main.js";
|
||||
import { UploadFiles } from "./FileUploader.js";
|
||||
@ -84,10 +84,14 @@ export function ApplyInputHandlers() {
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
ScreenViewer.style.removeProperty("max-width");
|
||||
ScreenViewer.style.removeProperty("max-height");
|
||||
VideoScreenViewer.style.removeProperty("max-width");
|
||||
VideoScreenViewer.style.removeProperty("max-height");
|
||||
}
|
||||
else {
|
||||
ScreenViewer.style.maxWidth = "unset";
|
||||
ScreenViewer.style.maxHeight = "unset";
|
||||
VideoScreenViewer.style.maxWidth = "unset";
|
||||
VideoScreenViewer.style.maxHeight = "unset";
|
||||
}
|
||||
});
|
||||
BlockInputButton.addEventListener("click", (ev) => {
|
||||
@ -149,175 +153,177 @@ export function ApplyInputHandlers() {
|
||||
AutoQualityAdjustCheckBox.addEventListener("change", ev => {
|
||||
MainRc.MessageSender.SendAutoQualityAdjust(AutoQualityAdjustCheckBox.checked);
|
||||
});
|
||||
ScreenViewer.addEventListener("pointermove", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("pointerdown", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("pointerenter", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("mousemove", function (e) {
|
||||
e.preventDefault();
|
||||
if (Date.now() - lastPointerMove < 25) {
|
||||
return;
|
||||
}
|
||||
lastPointerMove = Date.now();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
});
|
||||
ScreenViewer.addEventListener("mousedown", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(e.button, percentX, percentY);
|
||||
});
|
||||
ScreenViewer.addEventListener("mouseup", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(e.button, percentX, percentY);
|
||||
});
|
||||
ScreenViewer.addEventListener("click", function (e) {
|
||||
if (cancelNextViewerClick) {
|
||||
cancelNextViewerClick = false;
|
||||
return;
|
||||
}
|
||||
if (currentPointerDevice == "mouse") {
|
||||
[ScreenViewer, VideoScreenViewer].forEach(viewer => {
|
||||
viewer.addEventListener("pointermove", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
viewer.addEventListener("pointerdown", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
viewer.addEventListener("pointerenter", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
viewer.addEventListener("mousemove", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
else if (currentPointerDevice == "touch" && currentTouchCount == 0) {
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendTap(percentX, percentY);
|
||||
}
|
||||
});
|
||||
ScreenViewer.addEventListener("touchstart", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
if (currentTouchCount == 1) {
|
||||
startLongPressTimeout = window.setTimeout(() => {
|
||||
var percentX = e.touches[0].pageX / ScreenViewer.clientWidth;
|
||||
var percentY = e.touches[0].pageY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(2, percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseUp(2, percentX, percentY);
|
||||
}, 1000);
|
||||
}
|
||||
if (currentTouchCount > 1) {
|
||||
cancelNextViewerClick = true;
|
||||
}
|
||||
if (currentTouchCount == 2) {
|
||||
startPinchPoint1 = { X: e.touches[0].pageX, Y: e.touches[0].pageY, IsEmpty: false };
|
||||
startPinchPoint2 = { X: e.touches[1].pageX, Y: e.touches[1].pageY, IsEmpty: false };
|
||||
lastPinchDistance = GetDistanceBetween(startPinchPoint1.X, startPinchPoint1.Y, startPinchPoint2.X, startPinchPoint2.Y);
|
||||
lastPinchCenterX = (startPinchPoint1.X + startPinchPoint2.X) / 2;
|
||||
lastPinchCenterY = (startPinchPoint1.Y + startPinchPoint2.Y) / 2;
|
||||
}
|
||||
isDragging = false;
|
||||
KeyboardButton.removeAttribute("hidden");
|
||||
var focusedInput = document.querySelector("input:focus");
|
||||
if (focusedInput) {
|
||||
focusedInput.blur();
|
||||
}
|
||||
});
|
||||
ScreenViewer.addEventListener("touchmove", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
clearTimeout(startLongPressTimeout);
|
||||
if (e.touches.length == 2) {
|
||||
var pinchPoint1 = {
|
||||
X: e.touches[0].pageX,
|
||||
Y: e.touches[0].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchPoint2 = {
|
||||
X: e.touches[1].pageX,
|
||||
Y: e.touches[1].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchDistance = GetDistanceBetween(pinchPoint1.X, pinchPoint1.Y, pinchPoint2.X, pinchPoint2.Y);
|
||||
var pinchCenterX = (pinchPoint1.X + pinchPoint2.X) / 2;
|
||||
var pinchCenterY = (pinchPoint1.Y + pinchPoint2.Y) / 2;
|
||||
ScreenViewerWrapper.scrollBy(lastPinchCenterX - pinchCenterX, lastPinchCenterY - pinchCenterY);
|
||||
lastPinchCenterX = pinchCenterX;
|
||||
lastPinchCenterY = pinchCenterY;
|
||||
if (Math.abs(pinchDistance - lastPinchDistance) > 5) {
|
||||
isPinchZooming = true;
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
FitToScreenButton.click();
|
||||
}
|
||||
var currentWidth = ScreenViewer.clientWidth;
|
||||
var currentHeight = ScreenViewer.clientHeight;
|
||||
var clientAdjustedScrollLeftPercent = (ScreenViewerWrapper.scrollLeft + (ScreenViewerWrapper.clientWidth * .5)) / ScreenViewerWrapper.scrollWidth;
|
||||
var clientAdjustedScrollTopPercent = (ScreenViewerWrapper.scrollTop + (ScreenViewerWrapper.clientHeight * .5)) / ScreenViewerWrapper.scrollHeight;
|
||||
var currentWidthPercent = Number(ScreenViewer.style.width.slice(0, -1));
|
||||
var newWidthPercent = Math.max(100, (currentWidthPercent + (pinchDistance - lastPinchDistance) * (currentWidthPercent / 100)));
|
||||
newWidthPercent = Math.min(5000, newWidthPercent);
|
||||
ScreenViewer.style.width = String(newWidthPercent) + "%";
|
||||
var heightChange = ScreenViewer.clientHeight - currentHeight;
|
||||
var widthChange = ScreenViewer.clientWidth - currentWidth;
|
||||
var pinchAdjustX = pinchCenterX / window.innerWidth - .5;
|
||||
var pinchAdjustY = pinchCenterY / window.innerHeight - .5;
|
||||
var scrollByX = widthChange * (clientAdjustedScrollLeftPercent + (pinchAdjustX * ScreenViewerWrapper.clientWidth / ScreenViewerWrapper.scrollWidth));
|
||||
var scrollByY = heightChange * (clientAdjustedScrollTopPercent + (pinchAdjustY * ScreenViewerWrapper.clientHeight / ScreenViewerWrapper.scrollHeight));
|
||||
ScreenViewerWrapper.scrollBy(scrollByX, scrollByY);
|
||||
lastPinchDistance = pinchDistance;
|
||||
if (Date.now() - lastPointerMove < 25) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isDragging) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var screenViewerLeft = ScreenViewer.getBoundingClientRect().left;
|
||||
var screenViewerTop = ScreenViewer.getBoundingClientRect().top;
|
||||
var pagePercentX = (e.touches[0].pageX - screenViewerLeft) / ScreenViewer.clientWidth;
|
||||
var pagePercentY = (e.touches[0].pageY - screenViewerTop) / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(pagePercentX, pagePercentY);
|
||||
}
|
||||
});
|
||||
ScreenViewer.addEventListener("touchend", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
clearTimeout(startLongPressTimeout);
|
||||
if (e.touches.length == 1 && !isPinchZooming) {
|
||||
isDragging = true;
|
||||
var percentX = (e.touches[0].pageX - ScreenViewer.getBoundingClientRect().left) / ScreenViewer.clientWidth;
|
||||
var percentY = (e.touches[0].pageY - ScreenViewer.getBoundingClientRect().top) / ScreenViewer.clientHeight;
|
||||
lastPointerMove = Date.now();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseDown(0, percentX, percentY);
|
||||
return;
|
||||
}
|
||||
if (currentTouchCount == 0) {
|
||||
cancelNextViewerClick = false;
|
||||
isPinchZooming = false;
|
||||
startPinchPoint1 = null;
|
||||
startPinchPoint2 = null;
|
||||
}
|
||||
if (isDragging) {
|
||||
var percentX = (e.changedTouches[0].pageX - ScreenViewer.getBoundingClientRect().left) / ScreenViewer.clientWidth;
|
||||
var percentY = (e.changedTouches[0].pageY - ScreenViewer.getBoundingClientRect().top) / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(0, percentX, percentY);
|
||||
}
|
||||
isDragging = false;
|
||||
});
|
||||
ScreenViewer.addEventListener("contextmenu", (ev) => {
|
||||
ev.preventDefault();
|
||||
});
|
||||
ScreenViewer.addEventListener("wheel", function (e) {
|
||||
e.preventDefault();
|
||||
MainRc.MessageSender.SendMouseWheel(e.deltaX, e.deltaY);
|
||||
});
|
||||
viewer.addEventListener("mousedown", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(e.button, percentX, percentY);
|
||||
});
|
||||
viewer.addEventListener("mouseup", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(e.button, percentX, percentY);
|
||||
});
|
||||
viewer.addEventListener("click", function (e) {
|
||||
if (cancelNextViewerClick) {
|
||||
cancelNextViewerClick = false;
|
||||
return;
|
||||
}
|
||||
if (currentPointerDevice == "mouse") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
else if (currentPointerDevice == "touch" && currentTouchCount == 0) {
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendTap(percentX, percentY);
|
||||
}
|
||||
});
|
||||
viewer.addEventListener("touchstart", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
if (currentTouchCount == 1) {
|
||||
startLongPressTimeout = window.setTimeout(() => {
|
||||
var percentX = e.touches[0].pageX / viewer.clientWidth;
|
||||
var percentY = e.touches[0].pageY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(2, percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseUp(2, percentX, percentY);
|
||||
}, 1000);
|
||||
}
|
||||
if (currentTouchCount > 1) {
|
||||
cancelNextViewerClick = true;
|
||||
}
|
||||
if (currentTouchCount == 2) {
|
||||
startPinchPoint1 = { X: e.touches[0].pageX, Y: e.touches[0].pageY, IsEmpty: false };
|
||||
startPinchPoint2 = { X: e.touches[1].pageX, Y: e.touches[1].pageY, IsEmpty: false };
|
||||
lastPinchDistance = GetDistanceBetween(startPinchPoint1.X, startPinchPoint1.Y, startPinchPoint2.X, startPinchPoint2.Y);
|
||||
lastPinchCenterX = (startPinchPoint1.X + startPinchPoint2.X) / 2;
|
||||
lastPinchCenterY = (startPinchPoint1.Y + startPinchPoint2.Y) / 2;
|
||||
}
|
||||
isDragging = false;
|
||||
KeyboardButton.removeAttribute("hidden");
|
||||
var focusedInput = document.querySelector("input:focus");
|
||||
if (focusedInput) {
|
||||
focusedInput.blur();
|
||||
}
|
||||
});
|
||||
viewer.addEventListener("touchmove", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
clearTimeout(startLongPressTimeout);
|
||||
if (e.touches.length == 2) {
|
||||
var pinchPoint1 = {
|
||||
X: e.touches[0].pageX,
|
||||
Y: e.touches[0].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchPoint2 = {
|
||||
X: e.touches[1].pageX,
|
||||
Y: e.touches[1].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchDistance = GetDistanceBetween(pinchPoint1.X, pinchPoint1.Y, pinchPoint2.X, pinchPoint2.Y);
|
||||
var pinchCenterX = (pinchPoint1.X + pinchPoint2.X) / 2;
|
||||
var pinchCenterY = (pinchPoint1.Y + pinchPoint2.Y) / 2;
|
||||
ScreenViewerWrapper.scrollBy(lastPinchCenterX - pinchCenterX, lastPinchCenterY - pinchCenterY);
|
||||
lastPinchCenterX = pinchCenterX;
|
||||
lastPinchCenterY = pinchCenterY;
|
||||
if (Math.abs(pinchDistance - lastPinchDistance) > 5) {
|
||||
isPinchZooming = true;
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
FitToScreenButton.click();
|
||||
}
|
||||
var currentWidth = viewer.clientWidth;
|
||||
var currentHeight = viewer.clientHeight;
|
||||
var clientAdjustedScrollLeftPercent = (ScreenViewerWrapper.scrollLeft + (ScreenViewerWrapper.clientWidth * .5)) / ScreenViewerWrapper.scrollWidth;
|
||||
var clientAdjustedScrollTopPercent = (ScreenViewerWrapper.scrollTop + (ScreenViewerWrapper.clientHeight * .5)) / ScreenViewerWrapper.scrollHeight;
|
||||
var currentWidthPercent = Number(viewer.style.width.slice(0, -1));
|
||||
var newWidthPercent = Math.max(100, (currentWidthPercent + (pinchDistance - lastPinchDistance) * (currentWidthPercent / 100)));
|
||||
newWidthPercent = Math.min(5000, newWidthPercent);
|
||||
viewer.style.width = String(newWidthPercent) + "%";
|
||||
var heightChange = viewer.clientHeight - currentHeight;
|
||||
var widthChange = viewer.clientWidth - currentWidth;
|
||||
var pinchAdjustX = pinchCenterX / window.innerWidth - .5;
|
||||
var pinchAdjustY = pinchCenterY / window.innerHeight - .5;
|
||||
var scrollByX = widthChange * (clientAdjustedScrollLeftPercent + (pinchAdjustX * ScreenViewerWrapper.clientWidth / ScreenViewerWrapper.scrollWidth));
|
||||
var scrollByY = heightChange * (clientAdjustedScrollTopPercent + (pinchAdjustY * ScreenViewerWrapper.clientHeight / ScreenViewerWrapper.scrollHeight));
|
||||
ScreenViewerWrapper.scrollBy(scrollByX, scrollByY);
|
||||
lastPinchDistance = pinchDistance;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isDragging) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var screenViewerLeft = viewer.getBoundingClientRect().left;
|
||||
var screenViewerTop = viewer.getBoundingClientRect().top;
|
||||
var pagePercentX = (e.touches[0].pageX - screenViewerLeft) / viewer.clientWidth;
|
||||
var pagePercentY = (e.touches[0].pageY - screenViewerTop) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(pagePercentX, pagePercentY);
|
||||
}
|
||||
});
|
||||
viewer.addEventListener("touchend", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
clearTimeout(startLongPressTimeout);
|
||||
if (e.touches.length == 1 && !isPinchZooming) {
|
||||
isDragging = true;
|
||||
var percentX = (e.touches[0].pageX - viewer.getBoundingClientRect().left) / viewer.clientWidth;
|
||||
var percentY = (e.touches[0].pageY - viewer.getBoundingClientRect().top) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseDown(0, percentX, percentY);
|
||||
return;
|
||||
}
|
||||
if (currentTouchCount == 0) {
|
||||
cancelNextViewerClick = false;
|
||||
isPinchZooming = false;
|
||||
startPinchPoint1 = null;
|
||||
startPinchPoint2 = null;
|
||||
}
|
||||
if (isDragging) {
|
||||
var percentX = (e.changedTouches[0].pageX - viewer.getBoundingClientRect().left) / viewer.clientWidth;
|
||||
var percentY = (e.changedTouches[0].pageY - viewer.getBoundingClientRect().top) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(0, percentX, percentY);
|
||||
}
|
||||
isDragging = false;
|
||||
});
|
||||
viewer.addEventListener("contextmenu", (ev) => {
|
||||
ev.preventDefault();
|
||||
});
|
||||
viewer.addEventListener("wheel", function (e) {
|
||||
e.preventDefault();
|
||||
MainRc.MessageSender.SendMouseWheel(e.deltaX, e.deltaY);
|
||||
});
|
||||
});
|
||||
TouchKeyboardTextArea.addEventListener("input", (ev) => {
|
||||
if (TouchKeyboardTextArea.value.length == 1) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -27,7 +27,8 @@
|
||||
ScreenViewerWrapper,
|
||||
WindowsSessionSelect,
|
||||
RecordSessionButton,
|
||||
DownloadRecordingButton
|
||||
DownloadRecordingButton,
|
||||
VideoScreenViewer
|
||||
} from "./UI.js";
|
||||
import { Sound } from "../Sound.js";
|
||||
import { MainRc } from "./Main.js";
|
||||
@ -118,10 +119,14 @@ export function ApplyInputHandlers() {
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
ScreenViewer.style.removeProperty("max-width");
|
||||
ScreenViewer.style.removeProperty("max-height");
|
||||
VideoScreenViewer.style.removeProperty("max-width");
|
||||
VideoScreenViewer.style.removeProperty("max-height");
|
||||
}
|
||||
else {
|
||||
ScreenViewer.style.maxWidth = "unset";
|
||||
ScreenViewer.style.maxHeight = "unset";
|
||||
VideoScreenViewer.style.maxWidth = "unset";
|
||||
VideoScreenViewer.style.maxHeight = "unset";
|
||||
}
|
||||
});
|
||||
BlockInputButton.addEventListener("click", (ev) => {
|
||||
@ -183,208 +188,226 @@ export function ApplyInputHandlers() {
|
||||
AutoQualityAdjustCheckBox.addEventListener("change", ev => {
|
||||
MainRc.MessageSender.SendAutoQualityAdjust(AutoQualityAdjustCheckBox.checked);
|
||||
});
|
||||
ScreenViewer.addEventListener("pointermove", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("pointerdown", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("pointerenter", function (e) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
ScreenViewer.addEventListener("mousemove", function (e) {
|
||||
e.preventDefault();
|
||||
if (Date.now() - lastPointerMove < 25) {
|
||||
return;
|
||||
}
|
||||
lastPointerMove = Date.now();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
});
|
||||
ScreenViewer.addEventListener("mousedown", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(e.button, percentX, percentY);
|
||||
});
|
||||
ScreenViewer.addEventListener("mouseup", function (e) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(e.button, percentX, percentY);
|
||||
});
|
||||
|
||||
ScreenViewer.addEventListener("click", function (e) {
|
||||
if (cancelNextViewerClick) {
|
||||
cancelNextViewerClick = false;
|
||||
return;
|
||||
}
|
||||
if (currentPointerDevice == "mouse") {
|
||||
[ ScreenViewer, VideoScreenViewer ].forEach(viewer => {
|
||||
viewer.addEventListener("pointermove", function (e: PointerEvent) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
|
||||
viewer.addEventListener("pointerdown", function (e: PointerEvent) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
|
||||
viewer.addEventListener("pointerenter", function (e: PointerEvent) {
|
||||
currentPointerDevice = e.pointerType;
|
||||
});
|
||||
|
||||
viewer.addEventListener("mousemove", function (e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
else if (currentPointerDevice == "touch" && currentTouchCount == 0) {
|
||||
var percentX = e.offsetX / ScreenViewer.clientWidth;
|
||||
var percentY = e.offsetY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendTap(percentX, percentY);
|
||||
}
|
||||
});
|
||||
|
||||
ScreenViewer.addEventListener("touchstart", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
if (currentTouchCount == 1) {
|
||||
startLongPressTimeout = window.setTimeout(() => {
|
||||
var percentX = e.touches[0].pageX / ScreenViewer.clientWidth;
|
||||
var percentY = e.touches[0].pageY / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(2, percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseUp(2, percentX, percentY);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
if (currentTouchCount > 1) {
|
||||
cancelNextViewerClick = true;
|
||||
}
|
||||
if (currentTouchCount == 2) {
|
||||
startPinchPoint1 = { X: e.touches[0].pageX, Y: e.touches[0].pageY, IsEmpty: false };
|
||||
startPinchPoint2 = { X: e.touches[1].pageX, Y: e.touches[1].pageY, IsEmpty: false };
|
||||
lastPinchDistance = GetDistanceBetween(startPinchPoint1.X,
|
||||
startPinchPoint1.Y,
|
||||
startPinchPoint2.X,
|
||||
startPinchPoint2.Y);
|
||||
lastPinchCenterX = (startPinchPoint1.X + startPinchPoint2.X) / 2;
|
||||
lastPinchCenterY = (startPinchPoint1.Y + startPinchPoint2.Y) / 2;
|
||||
}
|
||||
isDragging = false;
|
||||
KeyboardButton.removeAttribute("hidden");
|
||||
var focusedInput = document.querySelector("input:focus") as HTMLInputElement;
|
||||
if (focusedInput) {
|
||||
focusedInput.blur();
|
||||
}
|
||||
});
|
||||
|
||||
ScreenViewer.addEventListener("touchmove", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
clearTimeout(startLongPressTimeout);
|
||||
|
||||
if (e.touches.length == 2) {
|
||||
var pinchPoint1 = {
|
||||
X: e.touches[0].pageX,
|
||||
Y: e.touches[0].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchPoint2 = {
|
||||
X: e.touches[1].pageX,
|
||||
Y: e.touches[1].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchDistance = GetDistanceBetween(pinchPoint1.X,
|
||||
pinchPoint1.Y,
|
||||
pinchPoint2.X,
|
||||
pinchPoint2.Y);
|
||||
|
||||
|
||||
var pinchCenterX = (pinchPoint1.X + pinchPoint2.X) / 2;
|
||||
var pinchCenterY = (pinchPoint1.Y + pinchPoint2.Y) / 2;
|
||||
|
||||
ScreenViewerWrapper.scrollBy(lastPinchCenterX - pinchCenterX,
|
||||
lastPinchCenterY - pinchCenterY);
|
||||
|
||||
lastPinchCenterX = pinchCenterX;
|
||||
lastPinchCenterY = pinchCenterY;
|
||||
|
||||
if (Math.abs(pinchDistance - lastPinchDistance) > 5) {
|
||||
isPinchZooming = true;
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
FitToScreenButton.click();
|
||||
}
|
||||
|
||||
var currentWidth = ScreenViewer.clientWidth;
|
||||
var currentHeight = ScreenViewer.clientHeight;
|
||||
|
||||
var clientAdjustedScrollLeftPercent = (ScreenViewerWrapper.scrollLeft + (ScreenViewerWrapper.clientWidth * .5)) / ScreenViewerWrapper.scrollWidth;
|
||||
var clientAdjustedScrollTopPercent = (ScreenViewerWrapper.scrollTop + (ScreenViewerWrapper.clientHeight * .5)) / ScreenViewerWrapper.scrollHeight;
|
||||
|
||||
var currentWidthPercent = Number(ScreenViewer.style.width.slice(0, -1));
|
||||
var newWidthPercent = Math.max(100, (currentWidthPercent + (pinchDistance - lastPinchDistance) * (currentWidthPercent / 100)));
|
||||
newWidthPercent = Math.min(5000, newWidthPercent);
|
||||
ScreenViewer.style.width = String(newWidthPercent) + "%";
|
||||
|
||||
var heightChange = ScreenViewer.clientHeight - currentHeight;
|
||||
var widthChange = ScreenViewer.clientWidth - currentWidth;
|
||||
|
||||
var pinchAdjustX = pinchCenterX / window.innerWidth - .5;
|
||||
var pinchAdjustY = pinchCenterY / window.innerHeight - .5;
|
||||
|
||||
var scrollByX = widthChange * (clientAdjustedScrollLeftPercent + (pinchAdjustX * ScreenViewerWrapper.clientWidth / ScreenViewerWrapper.scrollWidth));
|
||||
var scrollByY = heightChange * (clientAdjustedScrollTopPercent + (pinchAdjustY * ScreenViewerWrapper.clientHeight / ScreenViewerWrapper.scrollHeight));
|
||||
|
||||
ScreenViewerWrapper.scrollBy(scrollByX, scrollByY);
|
||||
|
||||
lastPinchDistance = pinchDistance;
|
||||
if (Date.now() - lastPointerMove < 25) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isDragging) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var screenViewerLeft = ScreenViewer.getBoundingClientRect().left;
|
||||
var screenViewerTop = ScreenViewer.getBoundingClientRect().top;
|
||||
var pagePercentX = (e.touches[0].pageX - screenViewerLeft) / ScreenViewer.clientWidth;
|
||||
var pagePercentY = (e.touches[0].pageY - screenViewerTop) / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(pagePercentX, pagePercentY);
|
||||
}
|
||||
});
|
||||
ScreenViewer.addEventListener("touchend", function (e) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
clearTimeout(startLongPressTimeout);
|
||||
|
||||
if (e.touches.length == 1 && !isPinchZooming) {
|
||||
isDragging = true;
|
||||
var percentX = (e.touches[0].pageX - ScreenViewer.getBoundingClientRect().left) / ScreenViewer.clientWidth;
|
||||
var percentY = (e.touches[0].pageY - ScreenViewer.getBoundingClientRect().top) / ScreenViewer.clientHeight;
|
||||
lastPointerMove = Date.now();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseDown(0, percentX, percentY);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (currentTouchCount == 0) {
|
||||
cancelNextViewerClick = false;
|
||||
isPinchZooming = false;
|
||||
startPinchPoint1 = null;
|
||||
startPinchPoint2 = null;
|
||||
}
|
||||
|
||||
if (isDragging) {
|
||||
var percentX = (e.changedTouches[0].pageX - ScreenViewer.getBoundingClientRect().left) / ScreenViewer.clientWidth;
|
||||
var percentY = (e.changedTouches[0].pageY - ScreenViewer.getBoundingClientRect().top) / ScreenViewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(0, percentX, percentY);
|
||||
}
|
||||
viewer.addEventListener("mousedown", function (e: MouseEvent) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(e.button, percentX, percentY);
|
||||
});
|
||||
|
||||
viewer.addEventListener("mouseup", function (e: MouseEvent) {
|
||||
if (currentPointerDevice == "touch") {
|
||||
return;
|
||||
}
|
||||
if (e.button != 0 && e.button != 2) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(e.button, percentX, percentY);
|
||||
});
|
||||
|
||||
viewer.addEventListener("click", function (e: MouseEvent) {
|
||||
if (cancelNextViewerClick) {
|
||||
cancelNextViewerClick = false;
|
||||
return;
|
||||
}
|
||||
if (currentPointerDevice == "mouse") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
else if (currentPointerDevice == "touch" && currentTouchCount == 0) {
|
||||
var percentX = e.offsetX / viewer.clientWidth;
|
||||
var percentY = e.offsetY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendTap(percentX, percentY);
|
||||
}
|
||||
});
|
||||
|
||||
viewer.addEventListener("touchstart", function (e: TouchEvent) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
if (currentTouchCount == 1) {
|
||||
startLongPressTimeout = window.setTimeout(() => {
|
||||
var percentX = e.touches[0].pageX / viewer.clientWidth;
|
||||
var percentY = e.touches[0].pageY / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseDown(2, percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseUp(2, percentX, percentY);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
if (currentTouchCount > 1) {
|
||||
cancelNextViewerClick = true;
|
||||
}
|
||||
if (currentTouchCount == 2) {
|
||||
startPinchPoint1 = { X: e.touches[0].pageX, Y: e.touches[0].pageY, IsEmpty: false };
|
||||
startPinchPoint2 = { X: e.touches[1].pageX, Y: e.touches[1].pageY, IsEmpty: false };
|
||||
lastPinchDistance = GetDistanceBetween(startPinchPoint1.X,
|
||||
startPinchPoint1.Y,
|
||||
startPinchPoint2.X,
|
||||
startPinchPoint2.Y);
|
||||
lastPinchCenterX = (startPinchPoint1.X + startPinchPoint2.X) / 2;
|
||||
lastPinchCenterY = (startPinchPoint1.Y + startPinchPoint2.Y) / 2;
|
||||
}
|
||||
isDragging = false;
|
||||
KeyboardButton.removeAttribute("hidden");
|
||||
var focusedInput = document.querySelector("input:focus") as HTMLInputElement;
|
||||
if (focusedInput) {
|
||||
focusedInput.blur();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
viewer.addEventListener("touchmove", function (e: TouchEvent) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
clearTimeout(startLongPressTimeout);
|
||||
|
||||
if (e.touches.length == 2) {
|
||||
var pinchPoint1 = {
|
||||
X: e.touches[0].pageX,
|
||||
Y: e.touches[0].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchPoint2 = {
|
||||
X: e.touches[1].pageX,
|
||||
Y: e.touches[1].pageY,
|
||||
IsEmpty: false
|
||||
};
|
||||
var pinchDistance = GetDistanceBetween(pinchPoint1.X,
|
||||
pinchPoint1.Y,
|
||||
pinchPoint2.X,
|
||||
pinchPoint2.Y);
|
||||
|
||||
|
||||
var pinchCenterX = (pinchPoint1.X + pinchPoint2.X) / 2;
|
||||
var pinchCenterY = (pinchPoint1.Y + pinchPoint2.Y) / 2;
|
||||
|
||||
ScreenViewerWrapper.scrollBy(lastPinchCenterX - pinchCenterX,
|
||||
lastPinchCenterY - pinchCenterY);
|
||||
|
||||
lastPinchCenterX = pinchCenterX;
|
||||
lastPinchCenterY = pinchCenterY;
|
||||
|
||||
if (Math.abs(pinchDistance - lastPinchDistance) > 5) {
|
||||
isPinchZooming = true;
|
||||
if (FitToScreenButton.classList.contains("toggled")) {
|
||||
FitToScreenButton.click();
|
||||
}
|
||||
|
||||
var currentWidth = viewer.clientWidth;
|
||||
var currentHeight = viewer.clientHeight;
|
||||
|
||||
var clientAdjustedScrollLeftPercent = (ScreenViewerWrapper.scrollLeft + (ScreenViewerWrapper.clientWidth * .5)) / ScreenViewerWrapper.scrollWidth;
|
||||
var clientAdjustedScrollTopPercent = (ScreenViewerWrapper.scrollTop + (ScreenViewerWrapper.clientHeight * .5)) / ScreenViewerWrapper.scrollHeight;
|
||||
|
||||
var currentWidthPercent = Number(viewer.style.width.slice(0, -1));
|
||||
var newWidthPercent = Math.max(100, (currentWidthPercent + (pinchDistance - lastPinchDistance) * (currentWidthPercent / 100)));
|
||||
newWidthPercent = Math.min(5000, newWidthPercent);
|
||||
viewer.style.width = String(newWidthPercent) + "%";
|
||||
|
||||
var heightChange = viewer.clientHeight - currentHeight;
|
||||
var widthChange = viewer.clientWidth - currentWidth;
|
||||
|
||||
var pinchAdjustX = pinchCenterX / window.innerWidth - .5;
|
||||
var pinchAdjustY = pinchCenterY / window.innerHeight - .5;
|
||||
|
||||
var scrollByX = widthChange * (clientAdjustedScrollLeftPercent + (pinchAdjustX * ScreenViewerWrapper.clientWidth / ScreenViewerWrapper.scrollWidth));
|
||||
var scrollByY = heightChange * (clientAdjustedScrollTopPercent + (pinchAdjustY * ScreenViewerWrapper.clientHeight / ScreenViewerWrapper.scrollHeight));
|
||||
|
||||
ScreenViewerWrapper.scrollBy(scrollByX, scrollByY);
|
||||
|
||||
lastPinchDistance = pinchDistance;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isDragging) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var screenViewerLeft = viewer.getBoundingClientRect().left;
|
||||
var screenViewerTop = viewer.getBoundingClientRect().top;
|
||||
var pagePercentX = (e.touches[0].pageX - screenViewerLeft) / viewer.clientWidth;
|
||||
var pagePercentY = (e.touches[0].pageY - screenViewerTop) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(pagePercentX, pagePercentY);
|
||||
}
|
||||
});
|
||||
|
||||
viewer.addEventListener("touchend", function (e: TouchEvent) {
|
||||
currentTouchCount = e.touches.length;
|
||||
|
||||
clearTimeout(startLongPressTimeout);
|
||||
|
||||
if (e.touches.length == 1 && !isPinchZooming) {
|
||||
isDragging = true;
|
||||
var percentX = (e.touches[0].pageX - viewer.getBoundingClientRect().left) / viewer.clientWidth;
|
||||
var percentY = (e.touches[0].pageY - viewer.getBoundingClientRect().top) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseMove(percentX, percentY);
|
||||
MainRc.MessageSender.SendMouseDown(0, percentX, percentY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTouchCount == 0) {
|
||||
cancelNextViewerClick = false;
|
||||
isPinchZooming = false;
|
||||
startPinchPoint1 = null;
|
||||
startPinchPoint2 = null;
|
||||
}
|
||||
|
||||
if (isDragging) {
|
||||
var percentX = (e.changedTouches[0].pageX - viewer.getBoundingClientRect().left) / viewer.clientWidth;
|
||||
var percentY = (e.changedTouches[0].pageY - viewer.getBoundingClientRect().top) / viewer.clientHeight;
|
||||
MainRc.MessageSender.SendMouseUp(0, percentX, percentY);
|
||||
}
|
||||
|
||||
isDragging = false;
|
||||
});
|
||||
|
||||
|
||||
viewer.addEventListener("contextmenu", (ev) => {
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
viewer.addEventListener("wheel", function (e: WheelEvent) {
|
||||
e.preventDefault();
|
||||
MainRc.MessageSender.SendMouseWheel(e.deltaX, e.deltaY);
|
||||
});
|
||||
|
||||
isDragging = false;
|
||||
});
|
||||
ScreenViewer.addEventListener("contextmenu", (ev) => {
|
||||
ev.preventDefault();
|
||||
});
|
||||
ScreenViewer.addEventListener("wheel", function (e) {
|
||||
e.preventDefault();
|
||||
MainRc.MessageSender.SendMouseWheel(e.deltaX, e.deltaY);
|
||||
});
|
||||
|
||||
|
||||
TouchKeyboardTextArea.addEventListener("input", (ev) => {
|
||||
if (TouchKeyboardTextArea.value.length == 1) {
|
||||
MainRc.MessageSender.SendKeyPress("Backspace");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -24,7 +24,6 @@ import { FileTransferProgress } from "./UI.js";
|
||||
import { BinaryDtoType } from "../Enums/BinaryDtoType.js";
|
||||
|
||||
export class MessageSender {
|
||||
|
||||
GetWindowsSessions() {
|
||||
this.SendToAgent(() => MainRc.RtcSession.SendDto(new WindowsSessionsDto()),
|
||||
() => MainRc.RCHubConnection.GetWindowsSessions());
|
||||
|
||||
@ -27,11 +27,13 @@ export class RCHubConnection {
|
||||
UI.StatusMessage.innerHTML = `Connection error: ${err.message}`;
|
||||
UI.Screen2DContext.clearRect(0, 0, UI.ScreenViewer.width, UI.ScreenViewer.height);
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.ConnectBox.style.removeProperty("display");
|
||||
});
|
||||
this.Connection.closedCallbacks.push((ev) => {
|
||||
UI.Screen2DContext.clearRect(0, 0, UI.ScreenViewer.width, UI.ScreenViewer.height);
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.ConnectBox.style.removeProperty("display");
|
||||
});
|
||||
MainRc.ClipboardWatcher.WatchClipboard();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@ import { Sound } from "../Sound.js";
|
||||
import { ShowMessage } from "../UI.js";
|
||||
import { IceServerModel } from "../Models/IceServerModel.js";
|
||||
import { RemoteControlMode } from "../Enums/RemoteControlMode.js";
|
||||
import { WindowsSessionsDto, WindowsSession } from "./RtcDtos.js";
|
||||
import { WindowsSession } from "./RtcDtos.js";
|
||||
|
||||
var signalR = window["signalR"];
|
||||
|
||||
@ -41,11 +41,13 @@ export class RCHubConnection {
|
||||
UI.StatusMessage.innerHTML = `Connection error: ${err.message}`;
|
||||
UI.Screen2DContext.clearRect(0, 0, UI.ScreenViewer.width, UI.ScreenViewer.height);
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.ConnectBox.style.removeProperty("display");
|
||||
});
|
||||
this.Connection.closedCallbacks.push((ev) => {
|
||||
UI.Screen2DContext.clearRect(0, 0, UI.ScreenViewer.width, UI.ScreenViewer.height);
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
|
||||
UI.ConnectBox.style.removeProperty("display");
|
||||
});
|
||||
|
||||
|
||||
@ -48,6 +48,14 @@ export class RtcSession {
|
||||
this.PeerConnection.onicecandidate = async (ev) => {
|
||||
await MainRc.RCHubConnection.SendIceCandidate(ev.candidate);
|
||||
};
|
||||
UI.VideoScreenViewer.onloadedmetadata = (ev) => {
|
||||
UI.VideoScreenViewer.play();
|
||||
};
|
||||
this.PeerConnection.ontrack = (event) => {
|
||||
UI.VideoScreenViewer.srcObject = new MediaStream([event.track]);
|
||||
UI.VideoScreenViewer.removeAttribute("hidden");
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
};
|
||||
}
|
||||
Disconnect() {
|
||||
this.PeerConnection.close();
|
||||
|
||||
@ -1 +1 @@
|
||||
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}
|
||||
@ -8,7 +8,7 @@ export class RtcSession {
|
||||
DataChannel: RTCDataChannel;
|
||||
MessagePack: any = window['MessagePack'];
|
||||
Init(iceServers: IceServerModel[]) {
|
||||
|
||||
|
||||
this.PeerConnection = new RTCPeerConnection({
|
||||
iceServers: iceServers.map(x => {
|
||||
return {
|
||||
@ -55,6 +55,15 @@ export class RtcSession {
|
||||
this.PeerConnection.onicecandidate = async (ev) => {
|
||||
await MainRc.RCHubConnection.SendIceCandidate(ev.candidate);
|
||||
};
|
||||
|
||||
UI.VideoScreenViewer.onloadedmetadata = (ev) => {
|
||||
UI.VideoScreenViewer.play();
|
||||
}
|
||||
this.PeerConnection.ontrack = (event) => {
|
||||
UI.VideoScreenViewer.srcObject = new MediaStream([event.track]);
|
||||
UI.VideoScreenViewer.removeAttribute("hidden");
|
||||
UI.ScreenViewer.setAttribute("hidden", "hidden");
|
||||
};
|
||||
}
|
||||
|
||||
Disconnect() {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { ScreenViewer } from "./UI.js";
|
||||
import { GetCurrentViewer } from "./UI.js";
|
||||
export class SessionRecorder {
|
||||
constructor() {
|
||||
this.RecordedData = [];
|
||||
}
|
||||
Start() {
|
||||
if (!window["MediaRecorder"] || !ScreenViewer.captureStream) {
|
||||
if (!window["MediaRecorder"] || !GetCurrentViewer().captureStream) {
|
||||
alert("Session recording isn't supported on this browser.");
|
||||
return;
|
||||
}
|
||||
@ -12,7 +12,7 @@ export class SessionRecorder {
|
||||
this.Recorder.stop();
|
||||
}
|
||||
this.RecordedData = [];
|
||||
this.Stream = ScreenViewer.captureStream(10);
|
||||
this.Stream = GetCurrentViewer().captureStream(10);
|
||||
var options = { mimeType: 'video/webm' };
|
||||
this.Recorder = new window["MediaRecorder"](this.Stream, options);
|
||||
this.Recorder.ondataavailable = (event) => {
|
||||
|
||||
@ -1 +1 @@
|
||||
{"version":3,"file":"SessionRecorder.js","sourceRoot":"","sources":["SessionRecorder.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"SessionRecorder.js","sourceRoot":"","sources":["SessionRecorder.ts"],"names":[],"mappings":"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"}
|
||||
@ -1,4 +1,4 @@
|
||||
import { ScreenViewer } from "./UI.js";
|
||||
import { GetCurrentViewer } from "./UI.js";
|
||||
|
||||
export class SessionRecorder {
|
||||
private Recorder: any;
|
||||
@ -6,7 +6,7 @@ export class SessionRecorder {
|
||||
private RecordedData: Array<any> = [];
|
||||
|
||||
Start() {
|
||||
if (!window["MediaRecorder"] || !(ScreenViewer as any).captureStream) {
|
||||
if (!window["MediaRecorder"] || !(GetCurrentViewer() as any).captureStream) {
|
||||
alert("Session recording isn't supported on this browser.");
|
||||
return;
|
||||
}
|
||||
@ -16,7 +16,7 @@ export class SessionRecorder {
|
||||
}
|
||||
|
||||
this.RecordedData = [];
|
||||
this.Stream = (ScreenViewer as any).captureStream(10);
|
||||
this.Stream = (GetCurrentViewer() as any).captureStream(10);
|
||||
var options = { mimeType: 'video/webm' };
|
||||
this.Recorder = new window["MediaRecorder"](this.Stream, options);
|
||||
this.Recorder.ondataavailable = (event) => {
|
||||
|
||||
@ -9,6 +9,7 @@ export var ConnectButton = document.getElementById("connectButton");
|
||||
export var RequesterNameInput = document.getElementById("nameInput");
|
||||
export var StatusMessage = document.getElementById("statusMessage");
|
||||
export var ScreenViewer = document.getElementById("screenViewer");
|
||||
export var VideoScreenViewer = document.getElementById("videoScreenViewer");
|
||||
export var ScreenViewerWrapper = document.getElementById("screenViewerWrapper");
|
||||
export var Screen2DContext = ScreenViewer.getContext("2d");
|
||||
export var HorizontalBars = document.querySelectorAll(".horizontal-button-bar");
|
||||
@ -41,6 +42,12 @@ export var ToastsWrapper = document.getElementById("toastsWrapper");
|
||||
export var WindowsSessionSelect = document.getElementById("windowsSessionSelect");
|
||||
export var RecordSessionButton = document.getElementById("recordSessionButton");
|
||||
export var DownloadRecordingButton = document.getElementById("downloadRecordingButton");
|
||||
export function GetCurrentViewer() {
|
||||
if (ScreenViewer.hasAttribute("hidden")) {
|
||||
return VideoScreenViewer;
|
||||
}
|
||||
return ScreenViewer;
|
||||
}
|
||||
export function Prompt(promptMessage) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var modalDiv = document.createElement("div");
|
||||
@ -73,6 +80,8 @@ export function Prompt(promptMessage) {
|
||||
export function SetScreenSize(width, height) {
|
||||
ScreenViewer.width = width;
|
||||
ScreenViewer.height = height;
|
||||
VideoScreenViewer.width = width;
|
||||
VideoScreenViewer.height = height;
|
||||
Screen2DContext.clearRect(0, 0, width, height);
|
||||
}
|
||||
export function ShowMessage(message) {
|
||||
@ -85,15 +94,16 @@ export function ShowMessage(message) {
|
||||
}, 5000);
|
||||
}
|
||||
export function UpdateCursor(imageBytes, hotSpotX, hotSpotY, cssOverride) {
|
||||
var targetElement = GetCurrentViewer();
|
||||
if (cssOverride) {
|
||||
ScreenViewer.style.cursor = cssOverride;
|
||||
targetElement.style.cursor = cssOverride;
|
||||
}
|
||||
else if (imageBytes.byteLength == 0) {
|
||||
ScreenViewer.style.cursor = "default";
|
||||
targetElement.style.cursor = "default";
|
||||
}
|
||||
else {
|
||||
var base64 = ConvertUInt8ArrayToBase64(imageBytes);
|
||||
ScreenViewer.style.cursor = `url('data:image/png;base64,${base64}') ${hotSpotX} ${hotSpotY}, default`;
|
||||
targetElement.style.cursor = `url('data:image/png;base64,${base64}') ${hotSpotX} ${hotSpotY}, default`;
|
||||
}
|
||||
}
|
||||
export function UpdateDisplays(selectedDisplay, displayNames) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,9 +1,5 @@
|
||||
import { MainRc } from "./Main.js";
|
||||
import { RemoteControlMode } from "../Enums/RemoteControlMode.js";
|
||||
import { Point } from "../Models/Point.js";
|
||||
import { GetDistanceBetween, ConvertUInt8ArrayToBase64 } from "../Utilities.js";
|
||||
import { UploadFiles } from "./FileUploader.js";
|
||||
import { Sound } from "../Sound.js";
|
||||
import { ConvertUInt8ArrayToBase64 } from "../Utilities.js";
|
||||
import { WindowsSession, SessionType } from "./RtcDtos.js";
|
||||
|
||||
export var AudioButton = document.getElementById("audioButton") as HTMLButtonElement;
|
||||
@ -14,6 +10,7 @@ export var ConnectButton = document.getElementById("connectButton") as HTMLButto
|
||||
export var RequesterNameInput = document.getElementById("nameInput") as HTMLInputElement;
|
||||
export var StatusMessage = document.getElementById("statusMessage") as HTMLDivElement;
|
||||
export var ScreenViewer = document.getElementById("screenViewer") as HTMLCanvasElement;
|
||||
export var VideoScreenViewer = document.getElementById("videoScreenViewer") as HTMLVideoElement;
|
||||
export var ScreenViewerWrapper = document.getElementById("screenViewerWrapper") as HTMLDivElement;
|
||||
export var Screen2DContext = ScreenViewer.getContext("2d");
|
||||
export var HorizontalBars = document.querySelectorAll(".horizontal-button-bar");
|
||||
@ -47,6 +44,13 @@ export var WindowsSessionSelect = document.getElementById("windowsSessionSelect"
|
||||
export var RecordSessionButton = document.getElementById("recordSessionButton") as HTMLButtonElement;
|
||||
export var DownloadRecordingButton = document.getElementById("downloadRecordingButton") as HTMLButtonElement;
|
||||
|
||||
export function GetCurrentViewer(): HTMLElement {
|
||||
if (ScreenViewer.hasAttribute("hidden")) {
|
||||
return VideoScreenViewer;
|
||||
}
|
||||
return ScreenViewer;
|
||||
}
|
||||
|
||||
export function Prompt(promptMessage: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
var modalDiv = document.createElement("div");
|
||||
@ -89,6 +93,8 @@ export function Prompt(promptMessage: string): Promise<string> {
|
||||
export function SetScreenSize(width: number, height: number) {
|
||||
ScreenViewer.width = width;
|
||||
ScreenViewer.height = height;
|
||||
VideoScreenViewer.width = width;
|
||||
VideoScreenViewer.height = height;
|
||||
Screen2DContext.clearRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
@ -103,15 +109,17 @@ export function ShowMessage(message: string) {
|
||||
}
|
||||
|
||||
export function UpdateCursor(imageBytes: Uint8Array, hotSpotX: number, hotSpotY: number, cssOverride: string) {
|
||||
var targetElement = GetCurrentViewer();
|
||||
|
||||
if (cssOverride) {
|
||||
ScreenViewer.style.cursor = cssOverride;
|
||||
targetElement.style.cursor = cssOverride;
|
||||
}
|
||||
else if (imageBytes.byteLength == 0) {
|
||||
ScreenViewer.style.cursor = "default";
|
||||
targetElement.style.cursor = "default";
|
||||
}
|
||||
else {
|
||||
var base64 = ConvertUInt8ArrayToBase64(imageBytes);
|
||||
ScreenViewer.style.cursor = `url('data:image/png;base64,${base64}') ${hotSpotX} ${hotSpotY}, default`;
|
||||
targetElement.style.cursor = `url('data:image/png;base64,${base64}') ${hotSpotX} ${hotSpotY}, default`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Remotely.Desktop.Core.Utilities;
|
||||
using Remotely.Desktop.Win.Services;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class CaptureTests
|
||||
{
|
||||
[TestMethod]
|
||||
[Ignore("Debug only.")]
|
||||
public async Task Capture()
|
||||
{
|
||||
var capturer = new ScreenCapturerWin();
|
||||
capturer.GetNextFrame();
|
||||
Process.Start("msg", "* test");
|
||||
await Task.Delay(500);
|
||||
capturer.GetNextFrame();
|
||||
var diffArea = ImageUtils.GetDiffArea(capturer.CurrentFrame, capturer.PreviousFrame, false);
|
||||
if (diffArea.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (var newImage = capturer.CurrentFrame.Clone(diffArea, PixelFormat.Format32bppArgb))
|
||||
{
|
||||
if (capturer.CaptureFullscreen)
|
||||
{
|
||||
capturer.CaptureFullscreen = false;
|
||||
}
|
||||
|
||||
newImage.Save(Path.Combine(Path.GetTempPath(), "!ImageDiff.jpg"), ImageFormat.Jpeg);
|
||||
capturer.CurrentFrame.Save(Path.Combine(Path.GetTempPath(), "!Current.jpg"), ImageFormat.Jpeg);
|
||||
capturer.PreviousFrame.Save(Path.Combine(Path.GetTempPath(), "!Previous.jpg"), ImageFormat.Jpeg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private double MeasureCommand(Action command)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
command.Invoke();
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"Command time: {stopwatch.Elapsed.TotalMilliseconds}");
|
||||
return stopwatch.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user