mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	Add "cef/" prefix for CEF #includes in libcef/ directory. Sort #includes by following https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes
		
			
				
	
	
		
			260 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2017 The Chromium Embedded Framework Authors.
 | |
| // Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #include "cef/libcef/browser/osr/motion_event_osr.h"
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| #include "ui/events/base_event_utils.h"
 | |
| #include "ui/events/gesture_detection/gesture_configuration.h"
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| ui::MotionEvent::ToolType CefPointerTypeToMotionEventToolType(
 | |
|     cef_pointer_type_t pointer_type) {
 | |
|   switch (pointer_type) {
 | |
|     case CEF_POINTER_TYPE_TOUCH:
 | |
|       return ui::MotionEvent::ToolType::FINGER;
 | |
|     case CEF_POINTER_TYPE_MOUSE:
 | |
|       return ui::MotionEvent::ToolType::MOUSE;
 | |
|     case CEF_POINTER_TYPE_PEN:
 | |
|       return ui::MotionEvent::ToolType::STYLUS;
 | |
|     case CEF_POINTER_TYPE_ERASER:
 | |
|       return ui::MotionEvent::ToolType::ERASER;
 | |
|     case CEF_POINTER_TYPE_UNKNOWN:
 | |
|       return ui::MotionEvent::ToolType::UNKNOWN;
 | |
|   }
 | |
|   DCHECK(false);
 | |
|   return ui::MotionEvent::ToolType::UNKNOWN;
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| CefMotionEventOSR::CefMotionEventOSR() {
 | |
|   std::fill(id_map_, id_map_ + blink::WebTouchEvent::kTouchesLengthCap, -1);
 | |
| }
 | |
| 
 | |
| CefMotionEventOSR::~CefMotionEventOSR() = default;
 | |
| 
 | |
| int CefMotionEventOSR::GetSourceDeviceId(size_t pointer_index) const {
 | |
|   if (IsValidIndex(pointer_index)) {
 | |
|     return pointer(pointer_index).source_device_id;
 | |
|   } else {
 | |
|     return -1;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Returns true if the touch was valid.
 | |
| bool CefMotionEventOSR::OnTouch(const CefTouchEvent& touch) {
 | |
|   int id = LookupId(touch.id);
 | |
|   bool pointer_id_is_active = id != -1;
 | |
| 
 | |
|   if (touch.type == CEF_TET_PRESSED && pointer_id_is_active) {
 | |
|     // Ignore pressed events for already active touches.
 | |
|     return false;
 | |
|   } else if (touch.type != CEF_TET_PRESSED && !pointer_id_is_active) {
 | |
|     // When a window begins capturing touch events, we could have an active
 | |
|     // touch stream transfered to us, resulting in touch move or touch up
 | |
|     // events without associated touch down events. Ignore them.
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   switch (touch.type) {
 | |
|     case CEF_TET_PRESSED:
 | |
|       id = AddId(touch.id);
 | |
|       if (id == -1) {
 | |
|         return false;
 | |
|       }
 | |
|       if (!AddTouch(touch, id)) {
 | |
|         return false;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case CEF_TET_MOVED: {
 | |
|       // Discard if touch is stationary.
 | |
|       int index = FindPointerIndexOfId(id);
 | |
|       if (IsValidIndex(index) &&
 | |
|           (touch.x == GetX(index) && touch.y == GetY(index))) {
 | |
|         return false;
 | |
|       }
 | |
|     }
 | |
|       [[fallthrough]];
 | |
|     // No break.
 | |
|     case CEF_TET_RELEASED:
 | |
|     case CEF_TET_CANCELLED:
 | |
|       // Removing these touch points needs to be postponed until after the
 | |
|       // MotionEvent has been dispatched. This cleanup occurs in
 | |
|       // CleanupRemovedTouchPoints.
 | |
|       UpdateTouch(touch, id);
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   UpdateCachedAction(touch, id);
 | |
|   set_unique_event_id(ui::GetNextTouchEventId());
 | |
|   set_flags(touch.modifiers);
 | |
|   set_event_time(base::TimeTicks::Now());
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| // We can't cleanup removed touch points immediately upon receipt of a
 | |
| // TouchCancel or TouchRelease, as the MotionEvent needs to be able to report
 | |
| // information about those touch events. Once the MotionEvent has been
 | |
| // processed, we call CleanupRemovedTouchPoints to do the required
 | |
| // book-keeping.
 | |
| void CefMotionEventOSR::CleanupRemovedTouchPoints(const CefTouchEvent& event) {
 | |
|   if (event.type != CEF_TET_RELEASED && event.type != CEF_TET_CANCELLED) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   DCHECK(GetPointerCount());
 | |
| 
 | |
|   int id = LookupId(event.id);
 | |
|   int index_to_delete = FindPointerIndexOfId(id);
 | |
|   set_action_index(-1);
 | |
|   set_action(ui::MotionEvent::Action::NONE);
 | |
|   if (IsValidIndex(index_to_delete)) {
 | |
|     pointer(index_to_delete) = pointer(GetPointerCount() - 1);
 | |
|     PopPointer();
 | |
|     RemoveId(event.id);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Reset unchanged touch point to StateStationary for touchmove and touchcancel.
 | |
| void CefMotionEventOSR::MarkUnchangedTouchPointsAsStationary(
 | |
|     blink::WebTouchEvent* event,
 | |
|     const CefTouchEvent& cef_event) {
 | |
|   int id = LookupId(cef_event.id);
 | |
|   if (event->GetType() == blink::WebInputEvent::Type::kTouchMove ||
 | |
|       event->GetType() == blink::WebInputEvent::Type::kTouchCancel) {
 | |
|     for (size_t i = 0; i < event->touches_length; ++i) {
 | |
|       if (event->touches[i].id != id) {
 | |
|         event->touches[i].state = blink::WebTouchPoint::State::kStateStationary;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| int CefMotionEventOSR::LookupId(int id) {
 | |
|   if (id == -1) {
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
 | |
|     if (id_map_[i] == id) {
 | |
|       return i;
 | |
|     }
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| int CefMotionEventOSR::AddId(int id) {
 | |
|   if (id == -1 || LookupId(id) >= 0) {
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
 | |
|     if (id_map_[i] == -1) {
 | |
|       id_map_[i] = id;
 | |
|       return i;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| void CefMotionEventOSR::RemoveId(int id) {
 | |
|   for (int& i : id_map_) {
 | |
|     if (i == id) {
 | |
|       i = -1;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CefMotionEventOSR::AddTouch(const CefTouchEvent& touch, int id) {
 | |
|   if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   PushPointer(GetPointerPropertiesFromTouchEvent(touch, id));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void CefMotionEventOSR::UpdateTouch(const CefTouchEvent& touch, int id) {
 | |
|   int index_to_update = FindPointerIndexOfId(id);
 | |
|   if (IsValidIndex(index_to_update)) {
 | |
|     pointer(index_to_update) = GetPointerPropertiesFromTouchEvent(touch, id);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefMotionEventOSR::UpdateCachedAction(const CefTouchEvent& touch, int id) {
 | |
|   DCHECK(GetPointerCount());
 | |
|   switch (touch.type) {
 | |
|     case CEF_TET_PRESSED:
 | |
|       if (GetPointerCount() == 1) {
 | |
|         set_action(ui::MotionEvent::Action::DOWN);
 | |
|       } else {
 | |
|         set_action(ui::MotionEvent::Action::POINTER_DOWN);
 | |
|         set_action_index(FindPointerIndexOfId(id));
 | |
|       }
 | |
|       break;
 | |
|     case CEF_TET_RELEASED:
 | |
|       if (GetPointerCount() == 1) {
 | |
|         set_action(ui::MotionEvent::Action::UP);
 | |
|       } else {
 | |
|         set_action(ui::MotionEvent::Action::POINTER_UP);
 | |
|         set_action_index(FindPointerIndexOfId(id));
 | |
|       }
 | |
|       break;
 | |
|     case CEF_TET_CANCELLED:
 | |
|       set_action(ui::MotionEvent::Action::CANCEL);
 | |
|       break;
 | |
|     case CEF_TET_MOVED:
 | |
|       set_action(ui::MotionEvent::Action::MOVE);
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CefMotionEventOSR::IsValidIndex(int index) const {
 | |
|   return (index >= 0) && (index < static_cast<int>(GetPointerCount()));
 | |
| }
 | |
| 
 | |
| ui::PointerProperties CefMotionEventOSR::GetPointerPropertiesFromTouchEvent(
 | |
|     const CefTouchEvent& touch,
 | |
|     int id) {
 | |
|   ui::PointerProperties pointer_properties;
 | |
|   pointer_properties.x = touch.x;
 | |
|   pointer_properties.y = touch.y;
 | |
|   pointer_properties.raw_x = touch.x;
 | |
|   pointer_properties.raw_y = touch.y;
 | |
|   pointer_properties.id = id;
 | |
|   pointer_properties.pressure = touch.pressure;
 | |
|   pointer_properties.source_device_id = 0;
 | |
| 
 | |
|   pointer_properties.SetAxesAndOrientation(touch.radius_x, touch.radius_y,
 | |
|                                            touch.rotation_angle);
 | |
|   if (!pointer_properties.touch_major) {
 | |
|     float default_size;
 | |
|     switch (touch.pointer_type) {
 | |
|       case CEF_POINTER_TYPE_PEN:
 | |
|       case CEF_POINTER_TYPE_ERASER:
 | |
|         // Default size for stylus events is 1x1.
 | |
|         default_size = 1;
 | |
|         break;
 | |
|       default:
 | |
|         default_size =
 | |
|             2.f * ui::GestureConfiguration::GetInstance()->default_radius();
 | |
|         break;
 | |
|     }
 | |
|     pointer_properties.touch_major = pointer_properties.touch_minor =
 | |
|         default_size;
 | |
|     pointer_properties.orientation = 0;
 | |
|   }
 | |
| 
 | |
|   pointer_properties.tool_type =
 | |
|       CefPointerTypeToMotionEventToolType(touch.pointer_type);
 | |
| 
 | |
|   return pointer_properties;
 | |
| }
 |