mirror of
https://github.com/moonlight-stream/moonlight-chrome.git
synced 2025-08-16 08:06:19 +00:00
Make mouse locking optional (#518)
Co-authored-by: tomciaaa <tomciaaa@chromebook>
This commit is contained in:
parent
6b053e4e71
commit
765e104cb3
10
index.html
10
index.html
@ -79,6 +79,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-menu-parent">
|
||||
<label id="mouseLockBtn" class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect" for="mouseLockEnabledSwitch">
|
||||
<input type="checkbox" id="mouseLockEnabledSwitch" class="mdl-icon-toggle__input">
|
||||
<i class="mdl-icon-toggle__label material-icons">mouse</i>
|
||||
</label>
|
||||
<div id="mouseLockTooltip" class="mdl-tooltip" for="mouseLockBtn">
|
||||
Enable mouse locking (must disable to use tap-to-click on touchpads)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-menu-parent">
|
||||
<label id="optimizeGamesBtn" class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect" for="optimizeGamesSwitch">
|
||||
<input type="checkbox" id="optimizeGamesSwitch" class="mdl-icon-toggle__input">
|
||||
|
54
input.cpp
54
input.cpp
@ -1,6 +1,7 @@
|
||||
#include "moonlight.hpp"
|
||||
|
||||
#include "ppapi/c/ppb_input_event.h"
|
||||
#include "ppapi/cpp/mouse_cursor.h"
|
||||
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
|
||||
@ -29,6 +30,29 @@ static int ConvertPPButtonToLiButton(PP_InputEvent_MouseButton ppButton) {
|
||||
}
|
||||
}
|
||||
|
||||
void MoonlightInstance::LockMouseOrJustCaptureInput() {
|
||||
if (m_MouseLockingFeatureEnabled) {
|
||||
LockMouse(m_CallbackFactory.NewCallback(&MoonlightInstance::DidLockMouse));
|
||||
}
|
||||
else {
|
||||
pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_NONE);
|
||||
}
|
||||
|
||||
// Assume it worked until we get a callback telling us otherwise;
|
||||
// if not locking mouse this just serves to tell us whether to capture input
|
||||
m_MouseLocked = true;
|
||||
}
|
||||
|
||||
void MoonlightInstance::UnlockMouseOrJustReleaseInput() {
|
||||
if (m_MouseLockingFeatureEnabled) {
|
||||
UnlockMouse();
|
||||
} else {
|
||||
pp::MouseCursor::SetCursor(this, PP_MOUSECURSOR_TYPE_POINTER);
|
||||
}
|
||||
m_MouseLocked = false;
|
||||
m_WaitingForAllModifiersUp = false;
|
||||
}
|
||||
|
||||
void MoonlightInstance::DidLockMouse(int32_t result) {
|
||||
m_MouseLocked = (result == PP_OK);
|
||||
if (m_MouseLocked) {
|
||||
@ -123,6 +147,10 @@ void MoonlightInstance::ReportMouseMovement() {
|
||||
if (m_MouseDeltaX != 0 || m_MouseDeltaY != 0) {
|
||||
LiSendMouseMoveEvent(m_MouseDeltaX, m_MouseDeltaY);
|
||||
m_MouseDeltaX = m_MouseDeltaY = 0;
|
||||
} else if (m_MousePositionX != 0 || m_MousePositionY != 0) {
|
||||
LiSendMousePositionEvent(m_MousePositionX, m_MousePositionY, m_PluginRect.width(), m_PluginRect.height());
|
||||
m_MousePositionX = 0;
|
||||
m_MousePositionY = 0;
|
||||
}
|
||||
if (m_AccumulatedTicks != 0) {
|
||||
// We can have fractional ticks here, so multiply by WHEEL_DELTA
|
||||
@ -137,10 +165,7 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
|
||||
// Lock the mouse cursor when the user clicks on the stream
|
||||
if (!m_MouseLocked) {
|
||||
LockMouse(m_CallbackFactory.NewCallback(&MoonlightInstance::DidLockMouse));
|
||||
|
||||
// Assume it worked until we get a callback telling us otherwise
|
||||
m_MouseLocked = true;
|
||||
LockMouseOrJustCaptureInput();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -154,14 +179,23 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||
if (!m_MouseLocked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
pp::MouseInputEvent mouseEvent(event);
|
||||
pp::Point posDelta = mouseEvent.GetMovement();
|
||||
pp::Point position = mouseEvent.GetPosition();
|
||||
|
||||
// Wait to report mouse movement until the next input polling window
|
||||
// to allow batching to occur which reduces overall input lag.
|
||||
m_MouseDeltaX += posDelta.x();
|
||||
m_MouseDeltaY += posDelta.y();
|
||||
if (m_MouseLocked) {
|
||||
if (m_MouseLockingFeatureEnabled) {
|
||||
m_MouseDeltaX += posDelta.x();
|
||||
m_MouseDeltaY += posDelta.y();
|
||||
} else {
|
||||
m_MousePositionX = position.x();
|
||||
m_MousePositionY = position.y();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -229,9 +263,7 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||
|
||||
// Check if all modifiers are up now
|
||||
if (m_WaitingForAllModifiersUp && modifiers == 0) {
|
||||
UnlockMouse();
|
||||
m_MouseLocked = false;
|
||||
m_WaitingForAllModifiersUp = false;
|
||||
UnlockMouseOrJustReleaseInput();
|
||||
}
|
||||
|
||||
LiSendKeyboardEvent(KEY_PREFIX << 8 | keyCode,
|
||||
@ -284,4 +316,4 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
main.cpp
10
main.cpp
@ -59,7 +59,7 @@ void MoonlightInstance::OnConnectionStopped(uint32_t error) {
|
||||
PP_INPUTEVENT_CLASS_TOUCH);
|
||||
|
||||
// Unlock the mouse
|
||||
UnlockMouse();
|
||||
UnlockMouseOrJustReleaseInput();
|
||||
|
||||
// Notify the JS code that the stream has ended
|
||||
pp::Var response(std::string(MSG_STREAM_TERMINATED) + std::to_string((int)error));
|
||||
@ -200,8 +200,9 @@ void MoonlightInstance::HandleStartStream(int32_t callbackId, pp::VarArray args)
|
||||
std::string bitrate = args.Get(4).AsString();
|
||||
std::string rikey = args.Get(5).AsString();
|
||||
std::string rikeyid = args.Get(6).AsString();
|
||||
std::string appversion = args.Get(7).AsString();
|
||||
std::string gfeversion = args.Get(8).AsString();
|
||||
std::string mouse_lock = args.Get(7).AsString();
|
||||
std::string appversion = args.Get(8).AsString();
|
||||
std::string gfeversion = args.Get(9).AsString();
|
||||
|
||||
pp::Var response("Setting stream width to: " + width);
|
||||
PostMessage(response);
|
||||
@ -221,6 +222,8 @@ void MoonlightInstance::HandleStartStream(int32_t callbackId, pp::VarArray args)
|
||||
PostMessage(response);
|
||||
response = ("Setting gfeversion to: " + gfeversion);
|
||||
PostMessage(response);
|
||||
response = ("Setting mouse lock to: " + mouse_lock);
|
||||
PostMessage(response);
|
||||
|
||||
// Populate the stream configuration
|
||||
LiInitializeStreamConfiguration(&m_StreamConfig);
|
||||
@ -245,6 +248,7 @@ void MoonlightInstance::HandleStartStream(int32_t callbackId, pp::VarArray args)
|
||||
m_Host = host;
|
||||
m_AppVersion = appversion;
|
||||
m_GfeVersion = gfeversion;
|
||||
m_MouseLockingFeatureEnabled = stoi(mouse_lock);
|
||||
|
||||
// Initialize the rendering surface before starting the connection
|
||||
if (InitializeRenderingSurface(m_StreamConfig.width, m_StreamConfig.height)) {
|
||||
|
@ -66,6 +66,8 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||
m_AccumulatedTicks(0),
|
||||
m_MouseDeltaX(0),
|
||||
m_MouseDeltaY(0),
|
||||
m_MousePositionX(0),
|
||||
m_MousePositionY(0),
|
||||
m_LastTouchUpTime(0),
|
||||
m_HttpThreadPoolSequence(0) {
|
||||
// This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!)
|
||||
@ -109,6 +111,8 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||
|
||||
void MouseLockLost();
|
||||
void DidLockMouse(int32_t result);
|
||||
void LockMouseOrJustCaptureInput();
|
||||
void UnlockMouseOrJustReleaseInput();
|
||||
|
||||
void OnConnectionStopped(uint32_t unused);
|
||||
void OnConnectionStarted(uint32_t error);
|
||||
@ -170,6 +174,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||
std::string m_Host;
|
||||
std::string m_AppVersion;
|
||||
std::string m_GfeVersion;
|
||||
bool m_MouseLockingFeatureEnabled;
|
||||
STREAM_CONFIGURATION m_StreamConfig;
|
||||
bool m_Running;
|
||||
|
||||
@ -199,6 +204,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||
bool m_WaitingForAllModifiersUp;
|
||||
float m_AccumulatedTicks;
|
||||
int32_t m_MouseDeltaX, m_MouseDeltaY;
|
||||
int32_t m_MousePositionX, m_MousePositionY;
|
||||
PP_TimeTicks m_LastTouchUpTime;
|
||||
pp::FloatPoint m_LastTouchUpPoint;
|
||||
|
||||
|
@ -15,6 +15,7 @@ function attachListeners() {
|
||||
$('#bitrateSlider').on('input', updateBitrateField); // input occurs every notch you slide
|
||||
//$('#bitrateSlider').on('change', saveBitrate); //FIXME: it seems not working
|
||||
$("#remoteAudioEnabledSwitch").on('click', saveRemoteAudio);
|
||||
$("#mouseLockEnabledSwitch").on('click', saveMouseLock);
|
||||
$('#optimizeGamesSwitch').on('click', saveOptimize);
|
||||
$('#addHostCell').on('click', addHost);
|
||||
$('#backIcon').on('click', showHostsAndSettingsMode);
|
||||
@ -597,6 +598,7 @@ function showHostsAndSettingsMode() {
|
||||
$("#main-navigation").show();
|
||||
$(".nav-menu-parent").show();
|
||||
$("#externalAudioBtn").show();
|
||||
$("#mouseLockBtn").show();
|
||||
$("#main-content").children().not("#listener, #loadingSpinner, #naclSpinner").show();
|
||||
$('#game-grid').hide();
|
||||
$('#backIcon').hide();
|
||||
@ -615,6 +617,7 @@ function showAppsMode() {
|
||||
$("#streamSettings").hide();
|
||||
$(".nav-menu-parent").hide();
|
||||
$("#externalAudioBtn").hide();
|
||||
$("#mouseLockBtn").hide();
|
||||
$("#host-grid").hide();
|
||||
$("#settings").hide();
|
||||
$("#main-content").removeClass("fullscreen");
|
||||
@ -684,7 +687,8 @@ function startGame(host, appID) {
|
||||
var streamHeight = $('#selectResolution').data('value').split(':')[1];
|
||||
// we told the user it was in Mbps. We're dirty liars and use Kbps behind their back.
|
||||
var bitrate = parseInt($("#bitrateSlider").val()) * 1000;
|
||||
console.log('%c[index.js, startGame]', 'color:green;', 'startRequest:' + host.address + ":" + streamWidth + ":" + streamHeight + ":" + frameRate + ":" + bitrate + ":" + optimize);
|
||||
var mouse_lock_enabled = $("#mouseLockEnabledSwitch").parent().hasClass('is-checked') ? "1" : "0";
|
||||
console.log('%c[index.js, startGame]', 'color:green;', 'startRequest:' + host.address + ":" + streamWidth + ":" + streamHeight + ":" + frameRate + ":" + bitrate + ":" + optimize + ":" + mouse_lock_enabled);
|
||||
|
||||
var rikey = generateRemoteInputKey();
|
||||
var rikeyid = generateRemoteInputKeyId();
|
||||
@ -707,7 +711,7 @@ function startGame(host, appID) {
|
||||
}
|
||||
|
||||
sendMessage('startRequest', [host.address, streamWidth, streamHeight, frameRate,
|
||||
bitrate.toString(), rikey, rikeyid.toString(), host.appVersion, host.gfeVersion
|
||||
bitrate.toString(), rikey, rikeyid.toString(), mouse_lock_enabled, host.appVersion, host.gfeVersion
|
||||
]);
|
||||
}, function(failedResumeApp) {
|
||||
console.eror('%c[index.js, startGame]', 'color:green;', 'Failed to resume the app! Returned error was' + failedResumeApp);
|
||||
@ -744,7 +748,7 @@ function startGame(host, appID) {
|
||||
}
|
||||
|
||||
sendMessage('startRequest', [host.address, streamWidth, streamHeight, frameRate,
|
||||
bitrate.toString(), rikey, rikeyid.toString(), host.appVersion
|
||||
bitrate.toString(), rikey, rikeyid.toString(), mouse_lock_enabled, host.appVersion
|
||||
]);
|
||||
}, function(failedLaunchApp) {
|
||||
console.error('%c[index.js, launchApp]', 'color: green;', 'Failed to launch app width id: ' + appID + '\nReturned error was: ' + failedLaunchApp);
|
||||
@ -901,6 +905,16 @@ function saveRemoteAudio() {
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function saveMouseLock() {
|
||||
// MaterialDesignLight uses the mouseup trigger, so we give it some time to change the class name before
|
||||
// checking the new state
|
||||
setTimeout(function() {
|
||||
var mouseLockState = $("#mouseLockEnabledSwitch").parent().hasClass('is-checked');
|
||||
console.log('%c[index.js, saveMouseLock]', 'color: green;', 'Saving mouse lock state : ' + mouseLockState);
|
||||
storeData('mouseLock', mouseLockState, null);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function updateDefaultBitrate() {
|
||||
var res = $('#selectResolution').data('value');
|
||||
var frameRate = $('#selectFramerate').data('value').toString();
|
||||
@ -961,6 +975,17 @@ function onWindowLoad() {
|
||||
}
|
||||
});
|
||||
|
||||
// Load stored mouse lock prefs
|
||||
chrome.storage.sync.get('mouseLock', function(previousValue) {
|
||||
if (previousValue.mouseLock == null) {
|
||||
document.querySelector('#mouseLockBtn').MaterialIconToggle.check();
|
||||
} else if (previousValue.mouseLock == false) {
|
||||
document.querySelector('#mouseLockBtn').MaterialIconToggle.uncheck();
|
||||
} else {
|
||||
document.querySelector('#mouseLockBtn').MaterialIconToggle.check();
|
||||
}
|
||||
});
|
||||
|
||||
// load stored framerate prefs
|
||||
chrome.storage.sync.get('frameRate', function(previousValue) {
|
||||
if (previousValue.frameRate != null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user