Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell_gl.cc

Issue 2768133003: Ensure VR UI does not miss controller button clicks (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/android/vr_shell/vr_shell_gl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h" 5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/android/jni_android.h" 10 #include "base/android/jni_android.h"
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 touch_pending_ = false; 486 touch_pending_ = false;
487 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( 487 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent(
488 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers, 488 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers,
489 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); 489 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF()));
490 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; 490 gesture->sourceDevice = blink::WebGestureDeviceTouchpad;
491 gesture->x = 0; 491 gesture->x = 0;
492 gesture->y = 0; 492 gesture->y = 0;
493 SendGesture(InputTarget::CONTENT, std::move(gesture)); 493 SendGesture(InputTarget::CONTENT, std::move(gesture));
494 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; 494 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture";
495 } 495 }
496
497 return;
cjgrant 2017/03/23 21:24:47 I'm not sure why we were returning here.
mthiesse 2017/03/23 21:34:23 Fine to remove, as long as the check below stays.
498 } 496 }
499 497
500 gvr::Vec3f ergo_neutral_pose; 498 gvr::Vec3f ergo_neutral_pose;
501 if (!controller_->IsConnected()) { 499 if (!controller_->IsConnected()) {
502 // No controller detected, set up a gaze cursor that tracks the 500 // No controller detected, set up a gaze cursor that tracks the
503 // forward direction. 501 // forward direction.
504 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; 502 ergo_neutral_pose = {0.0f, 0.0f, -1.0f};
505 controller_quat_ = GetRotationFromZAxis(forward_vector); 503 controller_quat_ = GetRotationFromZAxis(forward_vector);
506 } else { 504 } else {
507 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; 505 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)};
508 controller_quat_ = controller_->Orientation(); 506 controller_quat_ = controller_->Orientation();
509 } 507 }
510 508
511 gvr::Mat4f mat = QuatToMatrix(controller_quat_); 509 gvr::Mat4f mat = QuatToMatrix(controller_quat_);
512 gvr::Vec3f controller_direction = MatrixVectorMul(mat, ergo_neutral_pose); 510 gvr::Vec3f controller_direction = MatrixVectorMul(mat, ergo_neutral_pose);
513 511
512 HandleControllerAppButtonActivity(controller_direction);
513
514 if (ShouldDrawWebVr()) {
cjgrant 2017/03/23 21:24:47 On second thought, this is bad, and I'll revert th
mthiesse 2017/03/23 21:34:23 On third thought, don't revert this check.
cjgrant 2017/03/23 21:35:35 On third thought, lets keep this, as it moves the
515 return;
516 }
517
514 // If we place the reticle based on elements intersecting the controller beam, 518 // If we place the reticle based on elements intersecting the controller beam,
515 // we can end up with the reticle hiding behind elements, or jumping laterally 519 // we can end up with the reticle hiding behind elements, or jumping laterally
516 // in the field of view. This is physically correct, but hard to use. For 520 // in the field of view. This is physically correct, but hard to use. For
517 // usability, do the following instead: 521 // usability, do the following instead:
518 // 522 //
519 // - Project the controller laser onto a distance-limiting sphere. 523 // - Project the controller laser onto a distance-limiting sphere.
520 // - Create a vector between the eyes and the outer surface point. 524 // - Create a vector between the eyes and the outer surface point.
521 // - If any UI elements intersect this vector, and is within the bounding 525 // - If any UI elements intersect this vector, and is within the bounding
522 // sphere, choose the closest to the eyes, and place the reticle at the 526 // sphere, choose the closest to the eyes, and place the reticle at the
523 // intersection point. 527 // intersection point.
524 528
525 // Compute the distance from the eyes to the distance limiting sphere. Note 529 // Compute the distance from the eyes to the distance limiting sphere. Note
526 // that the sphere is centered at the controller, rather than the eye, for 530 // that the sphere is centered at the controller, rather than the eye, for
527 // simplicity. 531 // simplicity.
528 float distance = scene_->GetBackgroundDistance(); 532 float distance = scene_->GetBackgroundDistance();
529 target_point_ = GetRayPoint(kHandPosition, controller_direction, distance); 533 target_point_ = GetRayPoint(kHandPosition, controller_direction, distance);
530 gvr::Vec3f eye_to_target = target_point_; 534 gvr::Vec3f eye_to_target = target_point_;
531 NormalizeVector(eye_to_target); 535 NormalizeVector(eye_to_target);
532 536
533 // Note that button up/down state is transient, so ButtonDownHappened only
cjgrant 2017/03/23 21:24:47 Broken out to a function for readability.
534 // returns true for a single frame (and we're guaranteed not to miss it).
535 if (controller_->ButtonDownHappened(
536 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
537 controller_start_direction_ = controller_direction;
538 }
539 if (controller_->ButtonUpHappened(
540 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
541 // A gesture is a movement of the controller while holding the App button.
542 // If the angle of the movement is within a threshold, the action is
543 // considered a regular click
544 // TODO(asimjour1): We need to refactor the gesture recognition outside of
545 // VrShellGl.
546 UiInterface::Direction direction = UiInterface::NONE;
547 float gesture_xz_angle;
548 bool valid_angle = XZAngle(controller_start_direction_,
549 controller_direction, &gesture_xz_angle);
550 DCHECK(valid_angle);
551 if (fabs(gesture_xz_angle) > kMinAppButtonGestureAngleRad) {
552 direction = gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT;
553 main_thread_task_runner_->PostTask(
554 FROM_HERE, base::Bind(&VrShell::AppButtonGesturePerformed,
555 weak_vr_shell_, direction));
556 }
557 if (direction == UiInterface::NONE) {
558 main_thread_task_runner_->PostTask(
559 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_));
560 }
561 }
562
563 // Determine which UI element (if any) intersects the line between the eyes 537 // Determine which UI element (if any) intersects the line between the eyes
564 // and the controller target position. 538 // and the controller target position.
565 float closest_element_distance = VectorLength(target_point_); 539 float closest_element_distance = VectorLength(target_point_);
566 target_element_ = nullptr; 540 target_element_ = nullptr;
567 float target_x; 541 float target_x;
568 float target_y; 542 float target_y;
569 543
570 for (const auto& plane : scene_->GetUiElements()) { 544 for (const auto& plane : scene_->GetUiElements()) {
571 if (!plane->IsHitTestable()) 545 if (!plane->IsHitTestable())
572 continue; 546 continue;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 case Fill::SPRITE: 594 case Fill::SPRITE:
621 input_target = InputTarget::UI; 595 input_target = InputTarget::UI;
622 break; 596 break;
623 default: 597 default:
624 break; 598 break;
625 } 599 }
626 } 600 }
627 SendEventsToTarget(input_target, pixel_x, pixel_y); 601 SendEventsToTarget(input_target, pixel_x, pixel_y);
628 } 602 }
629 603
604 void VrShellGl::HandleControllerAppButtonActivity(
605 const gvr::Vec3f& controller_direction) {
606 // Note that button up/down state is transient, so ButtonDownHappened only
607 // returns true for a single frame (and we're guaranteed not to miss it).
608 if (controller_->ButtonDownHappened(
609 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
610 controller_start_direction_ = controller_direction;
611 }
612 if (controller_->ButtonUpHappened(
613 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
614 // A gesture is a movement of the controller while holding the App button.
615 // If the angle of the movement is within a threshold, the action is
616 // considered a regular click
617 // TODO(asimjour1): We need to refactor the gesture recognition outside of
618 // VrShellGl.
619 UiInterface::Direction direction = UiInterface::NONE;
620 float gesture_xz_angle;
621 if (XZAngle(controller_start_direction_, controller_direction,
622 &gesture_xz_angle)) {
623 if (fabs(gesture_xz_angle) > kMinAppButtonGestureAngleRad) {
624 direction =
625 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT;
626 main_thread_task_runner_->PostTask(
627 FROM_HERE, base::Bind(&VrShell::AppButtonGesturePerformed,
628 weak_vr_shell_, direction));
629 }
630 }
631 if (direction == UiInterface::NONE) {
632 main_thread_task_runner_->PostTask(
633 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_));
634 }
635 }
636 }
637
630 void VrShellGl::SendEventsToTarget(InputTarget input_target, 638 void VrShellGl::SendEventsToTarget(InputTarget input_target,
631 int pixel_x, 639 int pixel_x,
632 int pixel_y) { 640 int pixel_y) {
633 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list = 641 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list =
634 controller_->DetectGestures(); 642 controller_->DetectGestures();
635 double timestamp = gesture_list.front()->timeStampSeconds(); 643 double timestamp = gesture_list.front()->timeStampSeconds();
636 644
637 if (touch_pending_) { 645 if (touch_pending_) {
638 touch_pending_ = false; 646 touch_pending_ = false;
639 std::unique_ptr<WebGestureEvent> event(new WebGestureEvent( 647 std::unique_ptr<WebGestureEvent> event(new WebGestureEvent(
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 // object_from_reference_matrix, we're not updating position_external. 818 // object_from_reference_matrix, we're not updating position_external.
811 // TODO: Not sure what object_from_reference_matrix is. The new api removed 819 // TODO: Not sure what object_from_reference_matrix is. The new api removed
812 // it. For now, removing it seems working fine. 820 // it. For now, removing it seems working fine.
813 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 821 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
814 } 822 }
815 823
816 // Update the render position of all UI elements (including desktop). 824 // Update the render position of all UI elements (including desktop).
817 scene_->UpdateTransforms(TimeInMicroseconds()); 825 scene_->UpdateTransforms(TimeInMicroseconds());
818 826
819 { 827 {
828 // TODO(crbug.com/704690): Acquire controller state in a way that's timely
829 // for both the gamepad API and UI input handling.
820 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); 830 TRACE_EVENT0("gpu", "VrShellGl::UpdateController");
831 UpdateController();
821 HandleControllerInput(GetForwardVector(head_pose)); 832 HandleControllerInput(GetForwardVector(head_pose));
822 } 833 }
823 834
824 DrawWorldElements(head_pose); 835 DrawWorldElements(head_pose);
825 836
826 frame.Unbind(); 837 frame.Unbind();
827 838
828 // Draw head-locked elements to a separate, non-reprojected buffer. 839 // Draw head-locked elements to a separate, non-reprojected buffer.
829 if (scene_->HasVisibleHeadLockedElements()) { 840 if (scene_->HasVisibleHeadLockedElements()) {
830 frame.BindBuffer(kFrameHeadlockedBuffer); 841 frame.BindBuffer(kFrameHeadlockedBuffer);
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 1200
1190 // Don't send VSyncs until we have a timebase/interval. 1201 // Don't send VSyncs until we have a timebase/interval.
1191 if (vsync_interval_.is_zero()) 1202 if (vsync_interval_.is_zero())
1192 return; 1203 return;
1193 target = now + vsync_interval_; 1204 target = now + vsync_interval_;
1194 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 1205 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
1195 target = vsync_timebase_ + intervals * vsync_interval_; 1206 target = vsync_timebase_ + intervals * vsync_interval_;
1196 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), 1207 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(),
1197 target - now); 1208 target - now);
1198 1209
1199 // Get controller data now so that it's ready for both WebVR's
1200 // gamepad API input and VrShell's own processing.
1201 UpdateController();
1202
1203 base::TimeDelta time = intervals * vsync_interval_; 1210 base::TimeDelta time = intervals * vsync_interval_;
1204 if (!callback_.is_null()) { 1211 if (!callback_.is_null()) {
1205 SendVSync(time, base::ResetAndReturn(&callback_)); 1212 SendVSync(time, base::ResetAndReturn(&callback_));
1206 } else { 1213 } else {
1207 pending_vsync_ = true; 1214 pending_vsync_ = true;
1208 pending_time_ = time; 1215 pending_time_ = time;
1209 } 1216 }
1210 if (!ShouldDrawWebVr()) { 1217 if (!ShouldDrawWebVr()) {
1211 DrawFrame(-1); 1218 DrawFrame(-1);
1212 } 1219 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 // appropriate recommended render resolution as the default size during 1290 // appropriate recommended render resolution as the default size during
1284 // InitializeGl. Revisit if the initialization order changes. 1291 // InitializeGl. Revisit if the initialization order changes.
1285 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( 1292 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo(
1286 gvr_api_.get(), webvr_surface_size_, device_id); 1293 gvr_api_.get(), webvr_surface_size_, device_id);
1287 main_thread_task_runner_->PostTask( 1294 main_thread_task_runner_->PostTask(
1288 FROM_HERE, 1295 FROM_HERE,
1289 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); 1296 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info)));
1290 } 1297 }
1291 1298
1292 } // namespace vr_shell 1299 } // namespace vr_shell
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/vr_shell_gl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698