Commit c642ba45 authored by Michael Spang's avatar Michael Spang Committed by Commit Bot

ozone: evdev: Fix pen-related infinite recursion

If the pen device is disabled while the pen is near the screen it leads
to infinite recursion. This is because we make a call to disable palm
suppression, which revalidates device enablement. Post a task instead
of disabling inline to fix this.

The same thing happens if we lose events since Reinitialize() gained
a call to ReleaseButtons() when pen support was added, which calls
ReportEvents(), which can again call Reinitialize(). To fix that one,
kill ReleaseButtons() as ReleaseTouches() should be sufficient.

BUG=814071
TEST=powerd_dbus_suspend with pen touching screen

Change-Id: I8bb66feddc7961f1fa28d062133671ad1c46948c
Reviewed-on: https://chromium-review.googlesource.com/961386Reviewed-by: default avatarKevin Schoedel <kpschoedel@chromium.org>
Commit-Queue: Michael Spang <spang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543185}
parent ca14de90
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <utility> #include <utility>
#include "base/bind.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
...@@ -509,6 +510,16 @@ void InputDeviceFactoryEvdev::EnablePalmSuppression(bool enabled) { ...@@ -509,6 +510,16 @@ void InputDeviceFactoryEvdev::EnablePalmSuppression(bool enabled) {
return; return;
palm_suppression_enabled_ = enabled; palm_suppression_enabled_ = enabled;
// This function can be called while disabling pen devices, so don't disable
// inline here.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&InputDeviceFactoryEvdev::EnableDevices,
weak_ptr_factory_.GetWeakPtr()));
}
void InputDeviceFactoryEvdev::EnableDevices() {
// TODO(spang): Fix the UI to not dismiss menus when we use
// ApplyInputDeviceSettings() instead of this function.
for (const auto& it : converters_) for (const auto& it : converters_)
it.second->SetEnabled(IsDeviceEnabled(it.second.get())); it.second->SetEnabled(IsDeviceEnabled(it.second.get()));
} }
......
...@@ -63,8 +63,6 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { ...@@ -63,8 +63,6 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev {
base::WeakPtr<InputDeviceFactoryEvdev> GetWeakPtr(); base::WeakPtr<InputDeviceFactoryEvdev> GetWeakPtr();
void EnablePalmSuppression(bool enabled);
private: private:
// Open device at path & starting processing events. // Open device at path & starting processing events.
void AttachInputDevice(std::unique_ptr<EventConverterEvdev> converter); void AttachInputDevice(std::unique_ptr<EventConverterEvdev> converter);
...@@ -94,6 +92,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { ...@@ -94,6 +92,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev {
void SetBoolPropertyForOneType(const EventDeviceType type, void SetBoolPropertyForOneType(const EventDeviceType type,
const std::string& name, const std::string& name,
bool value); bool value);
void EnablePalmSuppression(bool enabled);
void EnableDevices();
// Task runner for our thread. // Task runner for our thread.
scoped_refptr<base::TaskRunner> task_runner_; scoped_refptr<base::TaskRunner> task_runner_;
......
...@@ -58,12 +58,7 @@ struct EVENTS_OZONE_EVDEV_EXPORT InProgressTouchEvdev { ...@@ -58,12 +58,7 @@ struct EVENTS_OZONE_EVDEV_EXPORT InProgressTouchEvdev {
float tilt_y = 0; float tilt_y = 0;
ui::EventPointerType reported_tool_type = ui::EventPointerType reported_tool_type =
ui::EventPointerType::POINTER_TYPE_TOUCH; ui::EventPointerType::POINTER_TYPE_TOUCH;
bool stylus_button = false;
struct ButtonState {
bool down = false;
bool changed = false;
};
ButtonState btn_stylus;
}; };
} // namespace ui } // namespace ui
......
...@@ -228,6 +228,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { ...@@ -228,6 +228,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
MT_TOOL_FINGER); MT_TOOL_FINGER);
events_[i].tool_type = tool_type; events_[i].tool_type = tool_type;
events_[i].major = touch_major; events_[i].major = touch_major;
events_[i].stylus_button = false;
if (events_[i].cancelled) if (events_[i].cancelled)
cancelled_state = true; cancelled_state = true;
} }
...@@ -264,8 +265,6 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { ...@@ -264,8 +265,6 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
} }
void TouchEventConverterEvdev::Reinitialize() { void TouchEventConverterEvdev::Reinitialize() {
ReleaseButtons();
EventDeviceInfo info; EventDeviceInfo info;
if (!info.Initialize(fd_, path_)) { if (!info.Initialize(fd_, path_)) {
LOG(ERROR) << "Failed to synchronize state for touch device: " LOG(ERROR) << "Failed to synchronize state for touch device: "
...@@ -297,7 +296,6 @@ void TouchEventConverterEvdev::OnEnabled() { ...@@ -297,7 +296,6 @@ void TouchEventConverterEvdev::OnEnabled() {
void TouchEventConverterEvdev::OnDisabled() { void TouchEventConverterEvdev::OnDisabled() {
ReleaseTouches(); ReleaseTouches();
ReleaseButtons();
if (enable_palm_suppression_callback_) { if (enable_palm_suppression_callback_) {
enable_palm_suppression_callback_.Run(false); enable_palm_suppression_callback_.Run(false);
} }
...@@ -391,8 +389,7 @@ void TouchEventConverterEvdev::EmulateMultitouchEvent( ...@@ -391,8 +389,7 @@ void TouchEventConverterEvdev::EmulateMultitouchEvent(
void TouchEventConverterEvdev::ProcessKey(const input_event& input) { void TouchEventConverterEvdev::ProcessKey(const input_event& input) {
switch (input.code) { switch (input.code) {
case BTN_STYLUS: case BTN_STYLUS:
events_[current_slot_].btn_stylus.down = input.value; events_[current_slot_].stylus_button = input.value;
events_[current_slot_].btn_stylus.changed = true;
events_[current_slot_].altered = true; events_[current_slot_].altered = true;
break; break;
case BTN_TOOL_PEN: case BTN_TOOL_PEN:
...@@ -520,7 +517,7 @@ void TouchEventConverterEvdev::ReportTouchEvent( ...@@ -520,7 +517,7 @@ void TouchEventConverterEvdev::ReportTouchEvent(
ui::PointerDetails details(event.reported_tool_type, /* pointer_id*/ 0, ui::PointerDetails details(event.reported_tool_type, /* pointer_id*/ 0,
event.radius_x, event.radius_y, event.pressure, event.radius_x, event.radius_y, event.pressure,
/* twist */ 0, event.tilt_x, event.tilt_y); /* twist */ 0, event.tilt_x, event.tilt_y);
int flags = event.btn_stylus.down ? ui::EventFlags::EF_LEFT_MOUSE_BUTTON : 0; int flags = event.stylus_button ? ui::EventFlags::EF_LEFT_MOUSE_BUTTON : 0;
dispatcher_->DispatchTouchEvent(TouchEventParams( dispatcher_->DispatchTouchEvent(TouchEventParams(
input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y), input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y),
details, timestamp, flags)); details, timestamp, flags));
...@@ -587,7 +584,6 @@ void TouchEventConverterEvdev::ReportEvents(base::TimeTicks timestamp) { ...@@ -587,7 +584,6 @@ void TouchEventConverterEvdev::ReportEvents(base::TimeTicks timestamp) {
event->was_touching = event->touching; event->was_touching = event->touching;
event->was_delayed = event->delayed; event->was_delayed = event->delayed;
event->altered = false; event->altered = false;
event->btn_stylus.changed = false;
} }
} }
...@@ -609,6 +605,7 @@ void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) { ...@@ -609,6 +605,7 @@ void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) {
void TouchEventConverterEvdev::ReleaseTouches() { void TouchEventConverterEvdev::ReleaseTouches() {
for (size_t slot = 0; slot < events_.size(); slot++) { for (size_t slot = 0; slot < events_.size(); slot++) {
events_[slot].stylus_button = false;
events_[slot].cancelled = true; events_[slot].cancelled = true;
events_[slot].altered = true; events_[slot].altered = true;
} }
...@@ -616,19 +613,6 @@ void TouchEventConverterEvdev::ReleaseTouches() { ...@@ -616,19 +613,6 @@ void TouchEventConverterEvdev::ReleaseTouches() {
ReportEvents(EventTimeForNow()); ReportEvents(EventTimeForNow());
} }
void TouchEventConverterEvdev::ReleaseButtons() {
for (size_t slot = 0; slot < events_.size(); slot++) {
InProgressTouchEvdev* event = &events_[slot];
if (event->btn_stylus.down) {
event->btn_stylus.down = false;
event->btn_stylus.changed = true;
}
}
ReportEvents(EventTimeForNow());
}
float TouchEventConverterEvdev::ScalePressure(int32_t value) { float TouchEventConverterEvdev::ScalePressure(int32_t value) {
float pressure = value - pressure_min_; float pressure = value - pressure_min_;
if (pressure_max_ - pressure_min_) if (pressure_max_ - pressure_min_)
......
...@@ -90,7 +90,6 @@ class EVENTS_OZONE_EVDEV_EXPORT TouchEventConverterEvdev ...@@ -90,7 +90,6 @@ class EVENTS_OZONE_EVDEV_EXPORT TouchEventConverterEvdev
void UpdateTrackingId(int slot, int tracking_id); void UpdateTrackingId(int slot, int tracking_id);
void ReleaseTouches(); void ReleaseTouches();
void ReleaseButtons();
void CancelAllTouches(); void CancelAllTouches();
bool IsPalm(const InProgressTouchEvdev& touch); bool IsPalm(const InProgressTouchEvdev& touch);
// Normalize pressure value to [0, 1]. // Normalize pressure value to [0, 1].
......
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