/// <summary> /// Send mouse move event to the streaming PC /// </summary> private void MouseMove(object sender, PointerRoutedEventArgs e) { // Only use this fake relative mode on non-mice if (e.Pointer.PointerDeviceType != PointerDeviceType.Mouse) { PointerPoint ptrPt = e.GetCurrentPoint(StreamDisplay); short eventX = (short)ptrPt.Position.X; short eventY = (short)ptrPt.Position.Y; if (eventX != lastX || eventY != lastY) { hasMoved = true; short xToSend = (short)(eventX - lastX); short yToSend = (short)(eventY - lastY); // Send the values to the streaming PC so it can register mouse movement MoonlightCommonRuntimeComponent.SendMouseMoveEvent(xToSend, yToSend); lastX = eventX; lastY = eventY; } // Prevent most handlers along the event route from handling the same event again. e.Handled = true; } }
private void WindowKeyDownHandler(CoreWindow sender, KeyEventArgs args) { // Watch for Ctrl+Alt+Shift to toggle mouse binding if ((KeyboardHelper.GetModifierFlags() & (byte)(Modifier.ModifierShift | Modifier.ModifierAlt | Modifier.ModifierCtrl)) == (byte)(Modifier.ModifierShift | Modifier.ModifierAlt | Modifier.ModifierCtrl)) { if (capturingMouse) { ReleaseMouse(); } else { CaptureMouse(); } } short key = KeyboardHelper.TranslateVirtualKey(args.VirtualKey); if (key != 0) { MoonlightCommonRuntimeComponent.SendKeyboardEvent(key, (byte)KeyAction.Down, KeyboardHelper.GetModifierFlags()); args.Handled = true; } }
private void RelativeMouseMoved(MouseDevice device, MouseEventArgs e) { if (!capturingMouse) { return; } MoonlightCommonRuntimeComponent.SendMouseMoveEvent((short)e.MouseDelta.X, (short)e.MouseDelta.Y); }
protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); ReleaseMouse(); StopMediaPlayer(); MoonlightCommonRuntimeComponent.StopConnection(); }
private void WindowKeyUpHandler(CoreWindow sender, KeyEventArgs args) { short key = KeyboardHelper.TranslateVirtualKey(args.VirtualKey); if (key != 0) { MoonlightCommonRuntimeComponent.SendKeyboardEvent(key, (byte)KeyAction.Up, KeyboardHelper.GetModifierFlags()); args.Handled = true; } }
/// <summary> /// Send mouse wheel event to the streaming PC /// </summary> private void MouseWheel(object sender, PointerRoutedEventArgs e) { Pointer ptr = e.Pointer; PointerPoint ptrPt = e.GetCurrentPoint(StreamDisplay); PointerPointProperties props = ptrPt.Properties; // GameStream only supports vertical scrolling for now if (!props.IsHorizontalMouseWheel) { MoonlightCommonRuntimeComponent.SendScrollEvent((short)(props.MouseWheelDelta / 120)); } }
/// <summary> /// Send mouse click event to the streaming PC /// </summary> private void MouseUp(object sender, PointerRoutedEventArgs e) { PointerPoint ptrPt = e.GetCurrentPoint(StreamDisplay); if (e.Pointer.PointerDeviceType != PointerDeviceType.Mouse) { if (!hasMoved) { // We haven't moved so send a click MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Press, (int)MouseButton.Left); // Sleep here because some games do input detection by polling using (EventWaitHandle tmpEvent = new ManualResetEvent(false)) { tmpEvent.WaitOne(TimeSpan.FromMilliseconds(100)); } // Raise the mouse button MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Release, (int)MouseButton.Left); } } else { // Send changes and update the current state int deltaButtons = mouseButtonFlag ^ GetButtonFlags(ptrPt); if ((deltaButtons & MOUSE_BUTTON_LEFT) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Release, (int)MouseButton.Left); } if ((deltaButtons & MOUSE_BUTTON_MIDDLE) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Release, (int)MouseButton.Middle); } if ((deltaButtons & MOUSE_BUTTON_RIGHT) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Release, (int)MouseButton.Right); } mouseButtonFlag = GetButtonFlags(ptrPt); } e.Handled = true; }
/// <summary> /// Connection terminated callback /// </summary> /// <param name="errorCode">Error code for connection terminated</param> public void ClConnectionTerminated(int errorCode) { Debug.WriteLine("Connection terminated: " + errorCode); if (controllers != null) { // Stop controller code controllers.Stop(); } var unused = Task.Run(() => { // This needs to be done on a separate thread MoonlightCommonRuntimeComponent.StopConnection(); }); DialogUtils.DisplayDialog(this.Dispatcher, "Connection terminated unexpectedly", "Connection Terminated", (command) => { this.Frame.Navigate(typeof(MainPage), null); }); }
/// <summary> /// Send mouse down event to the streaming PC /// </summary> private void MouseDown(object sender, PointerRoutedEventArgs e) { Pointer ptr = e.Pointer; PointerPoint ptrPt = e.GetCurrentPoint(StreamDisplay); // If using a mouse, then get the correct button if (ptr.PointerDeviceType == PointerDeviceType.Mouse) { // Send changes and update the current state int deltaButtons = mouseButtonFlag ^ GetButtonFlags(ptrPt); if ((deltaButtons & MOUSE_BUTTON_LEFT) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Press, (int)MouseButton.Left); } if ((deltaButtons & MOUSE_BUTTON_MIDDLE) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Press, (int)MouseButton.Middle); } if ((deltaButtons & MOUSE_BUTTON_RIGHT) != 0) { MoonlightCommonRuntimeComponent.SendMouseButtonEvent((byte)MouseButtonAction.Press, (int)MouseButton.Right); } mouseButtonFlag = GetButtonFlags(ptrPt); } else { // We haven't moved yet hasMoved = false; lastX = (short)ptrPt.Position.X; lastY = (short)ptrPt.Position.Y; } e.Handled = true; }
private async Task PollControllerWorker() { int[] lastPacketNumber = new int[4]; while (!stopPolling) { // Wait before collecting new data await Task.Delay(10); // Read input from all controllers foreach (Controller controller in controllers) { short controllerIndex = (short)controller.UserIndex; // Don't do anything if no controller is connected if (controller.IsConnected == false) { if (lastPacketNumber[controllerIndex] != 0) { // Set all inputs back to zero MoonlightCommonRuntimeComponent.SendControllerInput(controllerIndex, 0, 0, 0, 0, 0, 0); lastPacketNumber[controllerIndex] = 0; } // Not connected continue; } // Snapshot the state State state = controller.GetState(); if (state.PacketNumber != lastPacketNumber[controllerIndex]) { int buttonFlags = 0; // Remember the packet number so we don't have to do extra work // if the controller state doesn't change lastPacketNumber[controllerIndex] = state.PacketNumber; // Convert XInput constants to our button flags if ((state.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0) { buttonFlags |= (short)ButtonFlags.Up; } if ((state.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0) { buttonFlags |= (short)ButtonFlags.Down; } if ((state.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0) { buttonFlags |= (short)ButtonFlags.Left; } if ((state.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0) { buttonFlags |= (short)ButtonFlags.Right; } if ((state.Gamepad.Buttons & GamepadButtonFlags.A) != 0) { buttonFlags |= (short)ButtonFlags.A; } if ((state.Gamepad.Buttons & GamepadButtonFlags.B) != 0) { buttonFlags |= (short)ButtonFlags.B; } if ((state.Gamepad.Buttons & GamepadButtonFlags.X) != 0) { buttonFlags |= (short)ButtonFlags.X; } if ((state.Gamepad.Buttons & GamepadButtonFlags.Y) != 0) { buttonFlags |= (int)ButtonFlags.Y; } if ((state.Gamepad.Buttons & GamepadButtonFlags.LeftShoulder) != 0) { buttonFlags |= (short)ButtonFlags.LB; } if ((state.Gamepad.Buttons & GamepadButtonFlags.RightShoulder) != 0) { buttonFlags |= (short)ButtonFlags.RB; } if ((state.Gamepad.Buttons & GamepadButtonFlags.Back) != 0) { buttonFlags |= (short)ButtonFlags.Back; } if ((state.Gamepad.Buttons & GamepadButtonFlags.Start) != 0) { buttonFlags |= (short)ButtonFlags.Play; } if ((state.Gamepad.Buttons & GamepadButtonFlags.LeftThumb) != 0) { buttonFlags |= (short)ButtonFlags.LS; } if ((state.Gamepad.Buttons & GamepadButtonFlags.RightThumb) != 0) { buttonFlags |= (short)ButtonFlags.RS; } // Send the controller input packet MoonlightCommonRuntimeComponent.SendMultiControllerInput( controllerIndex, (short)buttonFlags, state.Gamepad.LeftTrigger, state.Gamepad.RightTrigger, state.Gamepad.LeftThumbX, state.Gamepad.LeftThumbY, state.Gamepad.RightThumbX, state.Gamepad.RightThumbY); } } } }
/// <summary> /// Starts the connection by calling into Moonlight Common /// </summary> private async Task StartConnection(MoonlightStreamConfiguration streamConfig) { NvHttp nv = null; await SetStateText("Resolving hostname..."); try { nv = new NvHttp(context.computer.IpAddress); } catch (ArgumentNullException) { stageFailureText = "Error resolving hostname"; ConnectionFailed(); return; } String serverIp = null; try { serverIp = await nv.ResolveServerIPAddress(); } catch (Exception) { stageFailureText = "Error resolving hostname"; ConnectionFailed(); return; } // Set up callbacks MoonlightDecoderRenderer drCallbacks = new MoonlightDecoderRenderer(DrSetup, DrCleanup, DrSubmitDecodeUnit); MoonlightAudioRenderer arCallbacks = new MoonlightAudioRenderer(ArInit, ArCleanup, ArPlaySample); MoonlightConnectionListener clCallbacks = new MoonlightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed, ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage); // Launch Steam await SetStateText("Launching Steam"); if (await StartOrResumeApp(nv, streamConfig) == false) { Debug.WriteLine("Can't find app"); stageFailureText = "Error launching App"; ConnectionFailed(); return; } // Call into Common to start the connection Debug.WriteLine("Starting connection"); MoonlightCommonRuntimeComponent.StartConnection(serverIp, streamConfig, clCallbacks, drCallbacks, arCallbacks, serverMajorVersion); if (stageFailureText != null) { Debug.WriteLine("Stage failed"); ConnectionFailed(); return; } else { ConnectionSuccess(); } }
/// <summary> /// Clean up resources /// </summary> private void Cleanup() { MoonlightCommonRuntimeComponent.StopConnection(); hasMoved = false; }