diff --git a/MenuPage.xaml b/MenuPage.xaml index be5fc77..e9e8f48 100644 --- a/MenuPage.xaml +++ b/MenuPage.xaml @@ -10,7 +10,8 @@ Moonlight - Experimental Software Ahead! Here be dragons! + Experimental Software Ahead! Here be dragons! + Mouse Mode: Press Menu+View+LB+RB+Y to enable it.Move the pointer with the left stick, scroll with the right oneA button is the left mouse button, X is the right one IP Address or Hostname: @@ -21,7 +22,7 @@ Applications - + diff --git a/MoonlightClient.cpp b/MoonlightClient.cpp index 12321d3..d855908 100644 --- a/MoonlightClient.cpp +++ b/MoonlightClient.cpp @@ -178,10 +178,14 @@ void MoonlightClient::SendMousePosition(float deltaX, float deltaY) { LiSendMouseMoveEvent(deltaX, deltaY); } -void MoonlightClient::SendMousePressed() { - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); +void MoonlightClient::SendMousePressed(int button) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, button); } -void MoonlightClient::SendMouseReleased() { - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); +void MoonlightClient::SendMouseReleased(int button) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, button); +} + +void MoonlightClient::SendScroll(float value) { + LiSendScrollEvent((signed char)(value * 2.0f)); } \ No newline at end of file diff --git a/MoonlightClient.h b/MoonlightClient.h index f0cbf17..e1ce820 100644 --- a/MoonlightClient.h +++ b/MoonlightClient.h @@ -28,8 +28,9 @@ namespace moonlight_xbox_dx { std::vector GetLogLines(); void InsertLog(const char* msg); void SendMousePosition(float x, float y); - void SendMousePressed(); - void SendMouseReleased(); + void SendMousePressed(int button); + void SendMouseReleased(int button); + void SendScroll(float value); private: SERVER_DATA serverData; char* connectionPin = NULL; diff --git a/moonlight_xbox_dxMain.cpp b/moonlight_xbox_dxMain.cpp index 13c1286..b7a98d1 100644 --- a/moonlight_xbox_dxMain.cpp +++ b/moonlight_xbox_dxMain.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "moonlight_xbox_dxMain.h" #include "Common\DirectXHelper.h" +using namespace Windows::Gaming::Input; using namespace moonlight_xbox_dx; @@ -62,26 +63,35 @@ void moonlight_xbox_dxMain::StartRenderLoop() m_deviceResources->GetD3DDeviceContext()->Flush(); m_deviceResources->Present(); } - int t2 = GetTickCount64(); - char msg[2084]; - //sprintf(msg, "Got %d ms of rendering time\n", t2 - t1); - //OutputDebugStringA(msg); } }); + m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced); + if (m_inputLoopWorker != nullptr && m_inputLoopWorker->Status == AsyncStatus::Started) { + return; + } + auto inputItemHandler = ref new WorkItemHandler([this](IAsyncAction^ action) + { + // Calculate the updated frame and render once per vertical blanking interval. + while (action->Status == AsyncStatus::Started) + { + ProcessInput(); + Sleep(8); // 8ms = about 120Hz of polling rate (i guess) + } + }); // Run task on a dedicated high priority background thread. - m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced); + m_inputLoopWorker = ThreadPool::RunAsync(inputItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced); } void moonlight_xbox_dxMain::StopRenderLoop() { m_renderLoopWorker->Cancel(); + m_inputLoopWorker->Cancel(); } // Updates the application state once per frame. void moonlight_xbox_dxMain::Update() { - ProcessInput(); // Update scene objects. m_timer.Tick([&]() @@ -95,12 +105,65 @@ void moonlight_xbox_dxMain::Update() // Process all input from the user before updating game state void moonlight_xbox_dxMain::ProcessInput() { + MoonlightClient *client = MoonlightClient::GetInstance(); auto gamepads = Windows::Gaming::Input::Gamepad::Gamepads; if (gamepads->Size == 0)return; Windows::Gaming::Input::Gamepad^ gamepad = gamepads->GetAt(0); auto reading = gamepad->GetCurrentReading(); - client->SendGamepadReading(reading); + //If this combination is pressed on gamed we should handle some magic things :) + GamepadButtons magicKey[] = { GamepadButtons::LeftShoulder,GamepadButtons::RightShoulder,GamepadButtons::Menu,GamepadButtons::View }; + bool isCurrentlyPressed = true; + for (auto k : magicKey) { + if ((reading.Buttons & k) != k) { + isCurrentlyPressed = false; + break; + } + } + if (isCurrentlyPressed) { + if (magicCombinationPressed)return; + if ((reading.Buttons & GamepadButtons::Y) == GamepadButtons::Y) { + client->InsertLog("Mouse mode "); + client->InsertLog(mouseMode ? "disabled\n" : "enabled\n"); + mouseMode = !mouseMode; + magicCombinationPressed = true; + } + } + else { + magicCombinationPressed = false; + } + //If mouse mode is enabled the gamepad acts as a mouse, instead we pass the raw events to the host + if (mouseMode) { + //Position + client->SendMousePosition(reading.LeftThumbstickX * 5, reading.LeftThumbstickY * -5); + //Left Click + if ((reading.Buttons & GamepadButtons::A) == GamepadButtons::A) { + if (!leftMouseButtonPressed) { + leftMouseButtonPressed = true; + client->SendMousePressed(BUTTON_LEFT); + } + } + else if (leftMouseButtonPressed) { + leftMouseButtonPressed = false; + client->SendMouseReleased(BUTTON_LEFT); + } + //Right Click + if ((reading.Buttons & GamepadButtons::X) == GamepadButtons::X) { + if (!rightMouseButtonPressed) { + rightMouseButtonPressed = true; + client->SendMousePressed(BUTTON_RIGHT); + } + } + else if (rightMouseButtonPressed) { + rightMouseButtonPressed = false; + client->SendMouseReleased(BUTTON_RIGHT); + } + //Scroll + client->SendScroll(reading.RightThumbstickY); + } + else { + client->SendGamepadReading(reading); + } } diff --git a/moonlight_xbox_dxMain.h b/moonlight_xbox_dxMain.h index 19ab17a..dc7732d 100644 --- a/moonlight_xbox_dxMain.h +++ b/moonlight_xbox_dxMain.h @@ -36,6 +36,7 @@ namespace moonlight_xbox_dx std::unique_ptr m_fpsTextRenderer; Windows::Foundation::IAsyncAction^ m_renderLoopWorker; + Windows::Foundation::IAsyncAction^ m_inputLoopWorker; Concurrency::critical_section m_criticalSection; // Rendering loop timer. @@ -43,5 +44,9 @@ namespace moonlight_xbox_dx // Track current input pointer position. float m_pointerLocationX; + bool magicCombinationPressed = false; + bool mouseMode = false; + bool leftMouseButtonPressed = false; + bool rightMouseButtonPressed = false; }; } \ No newline at end of file