• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(NULL, 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   HandleHardwareState(*hwstate);
24   stime_t next_timeout = NO_DEADLINE;
25   next_->SyncInterpret(hwstate, &next_timeout);
26   HandleTimeouts(next_timeout, timeout);
27 }
28 
HandleTimerImpl(stime_t now,stime_t * timeout)29 void StuckButtonInhibitorFilterInterpreter::HandleTimerImpl(
30     stime_t now, stime_t* timeout) {
31   if (!next_expects_timer_) {
32     if (!sent_buttons_down_) {
33       Err("Bug: got callback, but no gesture to send.");
34       return;
35     } else {
36       Err("Mouse button seems stuck down. Sending button-up.");
37       ProduceGesture(Gesture(kGestureButtonsChange,
38                              now, now, 0, sent_buttons_down_,
39                              false)); // is_tap
40       sent_buttons_down_ = 0;
41     }
42   }
43   stime_t next_timeout = NO_DEADLINE;
44   next_->HandleTimer(now, &next_timeout);
45   HandleTimeouts(next_timeout, timeout);
46 }
47 
HandleHardwareState(const HardwareState & hwstate)48 void StuckButtonInhibitorFilterInterpreter::HandleHardwareState(
49     const HardwareState& hwstate) {
50   incoming_button_must_be_up_ =
51       hwstate.touch_cnt == 0 && hwstate.buttons_down == 0;
52 }
53 
ConsumeGesture(const Gesture & gesture)54 void StuckButtonInhibitorFilterInterpreter::ConsumeGesture(
55     const Gesture& gesture) {
56   if (gesture.type == kGestureTypeButtonsChange) {
57     Gesture result = gesture;
58     // process buttons going down
59     if (sent_buttons_down_ & result.details.buttons.down) {
60       Err("Odd. result is sending buttons down that are already down: "
61           "Existing down: %d. New down: %d. fixing.",
62           sent_buttons_down_, result.details.buttons.down);
63       result.details.buttons.down &= ~sent_buttons_down_;
64     }
65     sent_buttons_down_ |= result.details.buttons.down;
66     if ((~sent_buttons_down_) & result.details.buttons.up) {
67       Err("Odd. result is sending buttons up for buttons we didn't send down: "
68           "Existing down: %d. New up: %d.",
69           sent_buttons_down_, result.details.buttons.up);
70       result.details.buttons.up &= sent_buttons_down_;
71     }
72     sent_buttons_down_ &= ~result.details.buttons.up;
73     if (!result.details.buttons.up && !result.details.buttons.down)
74       return; // skip gesture
75     ProduceGesture(result);
76   } else {
77     ProduceGesture(gesture);
78   }
79 }
80 
HandleTimeouts(stime_t next_timeout,stime_t * timeout)81 void StuckButtonInhibitorFilterInterpreter::HandleTimeouts(
82     stime_t next_timeout, stime_t* timeout) {
83   if (next_timeout >= 0.0) {
84     // next_ is doing stuff, so don't interfere
85     *timeout = next_timeout;
86     next_expects_timer_ = true;
87   } else {
88     next_expects_timer_ = false;
89     if (incoming_button_must_be_up_ && sent_buttons_down_) {
90       // We should lift the buttons before too long.
91       const stime_t kTimeoutLength = 1.0;
92       *timeout = kTimeoutLength;
93     }
94   }
95 }
96 
97 }  // namespace gestures
98