From ab61c09bffd8d9fa0bf696e9fbd057a85185dcad Mon Sep 17 00:00:00 2001
From: Tanguy Pruvot <tpruvot@users.noreply.github.com>
Date: Fri, 6 Dec 2019 07:47:50 +0100
Subject: [PATCH] Improve touch buttons behavior (#16109)

---
 Marlin/src/inc/Conditionals_LCD.h             |  2 +-
 Marlin/src/lcd/menu/menu_main.cpp             |  9 +++
 Marlin/src/lcd/ultralcd.cpp                   | 81 +++++++++----------
 Marlin/src/lcd/ultralcd.h                     |  7 +-
 .../Alfawise/U20-bltouch/Configuration.h      |  2 +-
 config/examples/Alfawise/U20/Configuration.h  |  2 +-
 config/examples/Mks/Robin/Configuration.h     |  4 +-
 7 files changed, 57 insertions(+), 50 deletions(-)

diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 543aa7122c..713de59c62 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -290,7 +290,7 @@
 
 #ifndef STD_ENCODER_PULSES_PER_STEP
   #if ENABLED(TOUCH_BUTTONS)
-    #define STD_ENCODER_PULSES_PER_STEP 1
+    #define STD_ENCODER_PULSES_PER_STEP 2
   #else
     #define STD_ENCODER_PULSES_PER_STEP 5
   #endif
diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp
index 9dfa8dc103..fadf0ab030 100644
--- a/Marlin/src/lcd/menu/menu_main.cpp
+++ b/Marlin/src/lcd/menu/menu_main.cpp
@@ -106,7 +106,11 @@ void menu_main() {
     SUBMENU(MSG_TUNE, menu_tune);
   }
   else {
+
     #if !HAS_ENCODER_WHEEL && ENABLED(SDSUPPORT)
+
+      // *** IF THIS SECTION IS CHANGED, REPRODUCE BELOW ***
+
       //
       // Autostart
       //
@@ -134,6 +138,7 @@ void menu_main() {
           ACTION_ITEM(MSG_MEDIA_RELEASED, nullptr);
         #endif
       }
+
     #endif // !HAS_ENCODER_WHEEL && SDSUPPORT
 
     #if MACHINE_CAN_PAUSE
@@ -197,6 +202,9 @@ void menu_main() {
   #endif
 
   #if HAS_ENCODER_WHEEL && ENABLED(SDSUPPORT)
+
+    // *** IF THIS SECTION IS CHANGED, REPRODUCE ABOVE ***
+
     //
     // Autostart
     //
@@ -224,6 +232,7 @@ void menu_main() {
         ACTION_ITEM(MSG_MEDIA_RELEASED, nullptr);
       #endif
     }
+
   #endif // HAS_ENCODER_WHEEL && SDSUPPORT
 
   #if HAS_SERVICE_INTERVALS
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index c2e00fcce6..e8176c1b1b 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -200,6 +200,7 @@ millis_t MarlinUI::next_button_update_ms; // = 0
   #endif
 
   #if ENABLED(TOUCH_BUTTONS)
+    uint8_t MarlinUI::touch_buttons;
     uint8_t MarlinUI::repeat_delay;
   #endif
 
@@ -778,58 +779,46 @@ void MarlinUI::update() {
 
     #if ENABLED(TOUCH_BUTTONS)
 
-      #define TOUCH_MENU_MASK 0x80
-
-      static bool arrow_pressed; // = false
-
-      // Handle touch events which are slow to read
-      if (ELAPSED(ms, next_button_update_ms)) {
-        uint8_t touch_buttons = touch.read_buttons();
-        if (touch_buttons) {
-          RESET_STATUS_TIMEOUT();
-          if (touch_buttons & TOUCH_MENU_MASK) {        // Processing Menu Area touch?
-            if (!wait_for_unclick) {                    // If not waiting for a debounce release:
-              wait_for_unclick = true;                  //  - Set debounce flag to ignore continous clicks
-              wait_for_user = false;                    //  - Any click clears wait for user
-              // TODO for next PR.
-              //uint8_t tpos = touch_buttons & ~(TOUCH_MENU_MASK);  // Safe 7bit touched screen coordinate
-              next_button_update_ms = ms + 500;         // Defer next check for 1/2 second
-              #if HAS_LCD_MENU
-                refresh();
-              #endif
-            }
-            touch_buttons = 0;                          // Swallow the touch
-          }
-          buttons |= (touch_buttons & (EN_C | EN_D));   // Pass on Click and Back buttons
-          if (touch_buttons & (EN_A | EN_B)) {          // A and/or B button?
+      if (touch_buttons) {
+        RESET_STATUS_TIMEOUT();
+        if (buttons & (EN_A | EN_B)) {                    // Menu arrows, in priority
+          if (ELAPSED(ms, next_button_update_ms)) {
             encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * (ENCODER_PULSES_PER_STEP) * encoderDirection;
-            if (touch_buttons & EN_A) encoderDiff *= -1;
-            next_button_update_ms = ms + repeat_delay;  // Assume the repeat delay
-            if (!wait_for_unclick && !arrow_pressed) {  // On click prepare for repeat
-              next_button_update_ms += 250;             // Longer delay on first press
-              arrow_pressed = true;                     // Mark arrow as pressed
+            if (buttons & EN_A) encoderDiff *= -1;
+            next_button_update_ms = ms + repeat_delay;    // Assume the repeat delay
+            if (!wait_for_unclick) {
+              next_button_update_ms += 250;               // Longer delay on first press
+              wait_for_unclick = true;                    // Avoid Back/Select click while repeating
               #if HAS_BUZZER
                 buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ);
               #endif
             }
           }
         }
-        if (!(touch_buttons & (EN_A | EN_B))) arrow_pressed = false;
+        else if (!wait_for_unclick && (buttons & EN_C)) { // OK button, if not waiting for a debounce release:
+          wait_for_unclick = true;                        //  - Set debounce flag to ignore continous clicks
+          lcd_clicked = !wait_for_user && !no_reentry;    //  - Keep the click if not waiting for a user-click
+          wait_for_user = false;                          //  - Any click clears wait for user
+          quick_feedback();                               //  - Always make a click sound
+        }
       }
+      else // keep wait_for_unclick value
 
     #endif // TOUCH_BUTTONS
 
-    // Integrated LCD click handling via button_pressed
-    if (!external_control && button_pressed()) {
-      if (!wait_for_unclick) {                        // If not waiting for a debounce release:
-        wait_for_unclick = true;                      //  - Set debounce flag to ignore continous clicks
-        lcd_clicked = !wait_for_user && !no_reentry;  //  - Keep the click if not waiting for a user-click
-        wait_for_user = false;                        //  - Any click clears wait for user
-        quick_feedback();                             //  - Always make a click sound
+      {
+        // Integrated LCD click handling via button_pressed
+        if (!external_control && button_pressed()) {
+          if (!wait_for_unclick) {                        // If not waiting for a debounce release:
+            wait_for_unclick = true;                      //  - Set debounce flag to ignore continous clicks
+            lcd_clicked = !wait_for_user && !no_reentry;  //  - Keep the click if not waiting for a user-click
+            wait_for_user = false;                        //  - Any click clears wait for user
+            quick_feedback();                             //  - Always make a click sound
+          }
+        }
+        else
+          wait_for_unclick = false;
       }
-    }
-    else
-      wait_for_unclick = false;
 
     if (LCD_BACK_CLICKED()) {
       quick_feedback();
@@ -894,8 +883,13 @@ void MarlinUI::update() {
     next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL;
 
     #if ENABLED(TOUCH_BUTTONS)
-      if (on_status_screen())
-        next_lcd_update_ms += (LCD_UPDATE_INTERVAL) * 2;
+
+      if (on_status_screen()) next_lcd_update_ms += (LCD_UPDATE_INTERVAL) * 2;
+
+      #if HAS_ENCODER_ACTION
+        touch_buttons = touch.read_buttons();
+      #endif
+
     #endif
 
     #if ENABLED(LCD_HAS_STATUS_INDICATORS)
@@ -1249,6 +1243,9 @@ void MarlinUI::update() {
           #if HAS_SLOW_BUTTONS
             | slow_buttons
           #endif
+          #if ENABLED(TOUCH_BUTTONS) && HAS_ENCODER_ACTION
+            | touch_buttons
+          #endif
         );
 
       #elif HAS_ADC_BUTTONS
diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h
index 7fc3a5f731..71e820e57f 100644
--- a/Marlin/src/lcd/ultralcd.h
+++ b/Marlin/src/lcd/ultralcd.h
@@ -27,10 +27,10 @@
   #include "../libs/buzzer.h"
 #endif
 
-#define HAS_DIGITAL_BUTTONS (!HAS_ADC_BUTTONS && ENABLED(NEWPANEL) || BUTTON_EXISTS(EN1, EN2) || ANY_BUTTON(ENC, BACK, UP, DWN, LFT, RT))
-#define HAS_SHIFT_ENCODER   (!HAS_ADC_BUTTONS && (ENABLED(REPRAPWORLD_KEYPAD) || (HAS_SPI_LCD && DISABLED(NEWPANEL))))
-#define HAS_ENCODER_WHEEL  ((!HAS_ADC_BUTTONS && ENABLED(NEWPANEL)) || BUTTON_EXISTS(EN1, EN2))
 #define HAS_ENCODER_ACTION (HAS_LCD_MENU || ENABLED(ULTIPANEL_FEEDMULTIPLY))
+#define HAS_ENCODER_WHEEL  ((!HAS_ADC_BUTTONS && ENABLED(NEWPANEL)) || BUTTON_EXISTS(EN1, EN2))
+#define HAS_DIGITAL_BUTTONS (HAS_ENCODER_WHEEL || ANY_BUTTON(ENC, BACK, UP, DWN, LFT, RT))
+#define HAS_SHIFT_ENCODER   (!HAS_ADC_BUTTONS && (ENABLED(REPRAPWORLD_KEYPAD) || (HAS_SPI_LCD && DISABLED(NEWPANEL))))
 
 // I2C buttons must be read in the main thread
 #define HAS_SLOW_BUTTONS EITHER(LCD_I2C_VIKI, LCD_I2C_PANELOLU2)
@@ -425,6 +425,7 @@ public:
   #if HAS_LCD_MENU
 
     #if ENABLED(TOUCH_BUTTONS)
+      static uint8_t touch_buttons;
       static uint8_t repeat_delay;
     #endif
 
diff --git a/config/examples/Alfawise/U20-bltouch/Configuration.h b/config/examples/Alfawise/U20-bltouch/Configuration.h
index f1e673ea2b..bf75b4e00f 100644
--- a/config/examples/Alfawise/U20-bltouch/Configuration.h
+++ b/config/examples/Alfawise/U20-bltouch/Configuration.h
@@ -2139,7 +2139,7 @@
 #if ENABLED(TOUCH_BUTTONS)
   #define TOUCH_CALIBRATION // Include user calibration widget in menus (Alfawise)
 
-  #define BUTTON_DELAY_EDIT  50 // (ms) Button repeat delay for edit screens
+  #define BUTTON_DELAY_EDIT  75 // (ms) Button repeat delay for edit screens
   #define BUTTON_DELAY_MENU 100 // (ms) Button repeat delay for menus
 
   #if ENABLED(TS_V11)
diff --git a/config/examples/Alfawise/U20/Configuration.h b/config/examples/Alfawise/U20/Configuration.h
index 30ef58f129..a4ca39fe25 100644
--- a/config/examples/Alfawise/U20/Configuration.h
+++ b/config/examples/Alfawise/U20/Configuration.h
@@ -2138,7 +2138,7 @@
 #if ENABLED(TOUCH_BUTTONS)
   #define TOUCH_CALIBRATION // Include user calibration widget in menus (Alfawise)
 
-  #define BUTTON_DELAY_EDIT  50 // (ms) Button repeat delay for edit screens
+  #define BUTTON_DELAY_EDIT  75 // (ms) Button repeat delay for edit screens
   #define BUTTON_DELAY_MENU 100 // (ms) Button repeat delay for menus
 
   #if ENABLED(TS_V11)
diff --git a/config/examples/Mks/Robin/Configuration.h b/config/examples/Mks/Robin/Configuration.h
index fb6156f2ca..63fd7f91c0 100644
--- a/config/examples/Mks/Robin/Configuration.h
+++ b/config/examples/Mks/Robin/Configuration.h
@@ -2059,8 +2059,8 @@
 //
 #define TOUCH_BUTTONS
 #if ENABLED(TOUCH_BUTTONS)
-  #define BUTTON_DELAY_EDIT  50 // (ms) Button repeat delay for edit screens
-  #define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
+  #define BUTTON_DELAY_EDIT  75 // (ms) Button repeat delay for edit screens
+  #define BUTTON_DELAY_MENU 100 // (ms) Button repeat delay for menus
 
   /* MKS Robin TFT v2.0 */
   #define XPT2046_X_CALIBRATION    12013