xref: /aosp_15_r20/external/libchrome-gestures/src/stuck_button_inhibitor_filter_interpreter.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "include/stuck_button_inhibitor_filter_interpreter.h"
6 
7 #include "include/logging.h"
8 #include "include/tracer.h"
9 
10 namespace gestures {
11 
StuckButtonInhibitorFilterInterpreter(Interpreter * next,Tracer * tracer)12 StuckButtonInhibitorFilterInterpreter::StuckButtonInhibitorFilterInterpreter(
13     Interpreter* next, Tracer* tracer)
14     : FilterInterpreter(nullptr, next, tracer, false),
15       incoming_button_must_be_up_(true),
16       sent_buttons_down_(0),
17       next_expects_timer_(false) {
18   InitName();
19 }
20 
SyncInterpretImpl(HardwareState & hwstate,stime_t * timeout)21 void StuckButtonInhibitorFilterInterpreter::SyncInterpretImpl(
22     HardwareState& hwstate, stime_t* timeout) {
23   const char name[] =
24       "StuckButtonInhibitorFilterInterpreter::SyncInterpretImpl";
25   LogHardwareStatePre(name, hwstate);
26 
27   HandleHardwareState(hwstate);
28 
29   stime_t next_timeout = NO_DEADLINE;
30   LogHardwareStatePost(name, hwstate);
31   next_->SyncInterpret(hwstate, &next_timeout);
32   HandleTimeouts(next_timeout, timeout);
33 }
34 
HandleTimerImpl(stime_t now,stime_t * timeout)35 void StuckButtonInhibitorFilterInterpreter::HandleTimerImpl(
36     stime_t now, stime_t* timeout) {
37   const char name[] = "StuckButtonInhibitorFilterInterpreter::HandleTimerImpl";
38   LogHandleTimerPre(name, now, timeout);
39 
40   stime_t next_timeout = NO_DEADLINE;
41   if (next_expects_timer_) {
42     next_->HandleTimer(now, &next_timeout);
43   } else {
44     if (!sent_buttons_down_) {
45       Err("Bug: got callback, but no gesture to send.");
46       return;
47     } else {
48       Err("Mouse button seems stuck down. Sending button-up.");
49       auto button_change = Gesture(kGestureButtonsChange,
50                                    now, now, 0, sent_buttons_down_,
51                                    false); // is_tap
52       LogGestureProduce(name, button_change);
53       ProduceGesture(button_change);
54       sent_buttons_down_ = 0;
55     }
56   }
57   HandleTimeouts(next_timeout, timeout);
58   LogHandleTimerPost(name, now, timeout);
59 }
60 
HandleHardwareState(const HardwareState & hwstate)61 void StuckButtonInhibitorFilterInterpreter::HandleHardwareState(
62     const HardwareState& hwstate) {
63   incoming_button_must_be_up_ =
64       hwstate.touch_cnt == 0 && hwstate.buttons_down == 0;
65 }
66 
ConsumeGesture(const Gesture & gesture)67 void StuckButtonInhibitorFilterInterpreter::ConsumeGesture(
68     const Gesture& gesture) {
69   const char name[] = "StuckButtonInhibitorFilterInterpreter::ConsumeGesture";
70   LogGestureConsume(name, gesture);
71 
72   if (gesture.type == kGestureTypeButtonsChange) {
73     Gesture result = gesture;
74     // process buttons going down
75     if (sent_buttons_down_ & result.details.buttons.down) {
76       Err("Odd. result is sending buttons down that are already down: "
77           "Existing down: %d. New down: %d. fixing.",
78           sent_buttons_down_, result.details.buttons.down);
79       result.details.buttons.down &= ~sent_buttons_down_;
80     }
81     sent_buttons_down_ |= result.details.buttons.down;
82     if ((~sent_buttons_down_) & result.details.buttons.up) {
83       Err("Odd. result is sending buttons up for buttons we didn't send down: "
84           "Existing down: %d. New up: %d.",
85           sent_buttons_down_, result.details.buttons.up);
86       result.details.buttons.up &= sent_buttons_down_;
87     }
88     sent_buttons_down_ &= ~result.details.buttons.up;
89     if (!result.details.buttons.up && !result.details.buttons.down)
90       return; // skip gesture
91     LogGestureProduce(name, result);
92     ProduceGesture(result);
93   } else {
94     LogGestureProduce(name, gesture);
95     ProduceGesture(gesture);
96   }
97 }
98 
HandleTimeouts(stime_t next_timeout,stime_t * timeout)99 void StuckButtonInhibitorFilterInterpreter::HandleTimeouts(
100     stime_t next_timeout, stime_t* timeout) {
101   if (next_timeout >= 0.0) {
102     // next_ is doing stuff, so don't interfere
103     *timeout = next_timeout;
104     next_expects_timer_ = true;
105   } else {
106     next_expects_timer_ = false;
107     if (incoming_button_must_be_up_ && sent_buttons_down_) {
108       // We should lift the buttons before too long.
109       const stime_t kTimeoutLength = 1.0;
110       *timeout = kTimeoutLength;
111     }
112   }
113 }
114 
115 }  // namespace gestures
116