Commit cb872f62 authored by Alex Cooper's avatar Alex Cooper Committed by Commit Bot

[XR] Ensure that selectend and selectstart events are always paired

Per the spec, a selectend event should always be sent if a selectstart
event has been fired, evenif the gesture is cancelled.  Currently if an
input source was removed but it had sent a selectstart event a selectend
event would never be sent.  This fixes that for both the cases where an
input source is lost, and if the session ends while a controller is
pressed.

Per the HTML interaction spec, since these removals cannot be
guaranteed to have fired as a result of user interaction, the frame
is not notified of UserActivation in this case (and as such the
OnSelectEnd method is not re-used).

Bug: 968291
Change-Id: Ibea99e59ee7a528b7a34db610bfca76c27d495b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1636851Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664805}
parent ce788e39
......@@ -478,7 +478,9 @@ void XRSession::ForceEnd() {
pending_frame_ = false;
for (unsigned i = 0; i < input_sources_->length(); i++) {
(*input_sources_)[i]->SetGamepadConnected(false);
auto* input_source = (*input_sources_)[i];
UpdateSelectStateOnRemoval(input_source);
input_source->SetGamepadConnected(false);
}
input_sources_ = nullptr;
......@@ -794,6 +796,7 @@ void XRSession::OnInputStateChange(
auto* input_source = (*input_sources_)[i];
if (input_source->activeFrameId() != frame_id) {
inactive_sources.push_back(input_source->source_id());
UpdateSelectStateOnRemoval(input_source);
input_source->SetGamepadConnected(false);
removed.push_back(input_source);
}
......@@ -918,6 +921,25 @@ void XRSession::UpdateSelectState(
}
}
void XRSession::UpdateSelectStateOnRemoval(XRInputSource* input_source) {
if (!input_source)
return;
if (input_source->primaryInputPressed()) {
input_source->setPrimaryInputPressed(false);
XRInputSourceEvent* event =
CreateInputSourceEvent(event_type_names::kSelectend, input_source);
DispatchEvent(*event);
if (event->defaultPrevented())
input_source->setSelectionCancelled(true);
// Ensure the frame cannot be used outside of the event handler.
event->frame()->Deactivate();
}
}
XRInputSourceEvent* XRSession::CreateInputSourceEvent(
const AtomicString& type,
XRInputSource* input_source) {
......
......@@ -190,6 +190,7 @@ class XRSession final : public EventTargetWithInlineData,
void UpdateSelectState(XRInputSource*,
const device::mojom::blink::XRInputSourceStatePtr&);
void UpdateSelectStateOnRemoval(XRInputSource*);
XRInputSourceEvent* CreateInputSourceEvent(const AtomicString&,
XRInputSource*);
......
......@@ -76,9 +76,9 @@ let testFunction = function(session, t, fakeDeviceController) {
return session.end().then(() => {
return sessionEndTest("inputsourceschange", ["inputsourceschange", "end"]);
}).then(() => {
return sessionEndTest("selectstart", ["inputsourceschange", "selectstart", "end"]);
return sessionEndTest("selectstart", ["inputsourceschange", "selectstart", "selectend", "end"]);
}).then(() => {
return sessionEndTest("select", ["inputsourceschange", "selectstart", "select", "end"]);
return sessionEndTest("select", ["inputsourceschange", "selectstart", "select", "selectend", "end"]);
}).then(() => {
return sessionEndTest("selectend", ["inputsourceschange", "selectstart", "select", "selectend", "end"]);
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment