diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 2d088ed30bcb6e57af04dde639a4591fa3b8b9db..0e1e65c87f1721482e28533d50953d83a89a4f64 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -288,7 +288,11 @@
 #endif
 
 #ifndef STD_ENCODER_PULSES_PER_STEP
-  #define STD_ENCODER_PULSES_PER_STEP 5
+  #if ENABLED(TOUCH_BUTTONS)
+    #define STD_ENCODER_PULSES_PER_STEP 1
+  #else
+    #define STD_ENCODER_PULSES_PER_STEP 5
+  #endif
 #endif
 #ifndef STD_ENCODER_STEPS_PER_MENU_ITEM
   #define STD_ENCODER_STEPS_PER_MENU_ITEM 1
diff --git a/Marlin/src/lcd/HD44780/ultralcd_HD44780.cpp b/Marlin/src/lcd/HD44780/ultralcd_HD44780.cpp
index a8cf421dcb8d621bfbc3641d2975694c52d7f08a..b7ebc111a5e64e3db1900eebf196b18a104e7833 100644
--- a/Marlin/src/lcd/HD44780/ultralcd_HD44780.cpp
+++ b/Marlin/src/lcd/HD44780/ultralcd_HD44780.cpp
@@ -371,8 +371,8 @@ bool MarlinUI::detected() {
 #if HAS_SLOW_BUTTONS
   uint8_t MarlinUI::read_slow_buttons() {
     #if ENABLED(LCD_I2C_TYPE_MCP23017)
-      // Reading these buttons this is likely to be too slow to call inside interrupt context
-      // so they are called during normal lcd_update
+      // Reading these buttons is too slow for interrupt context
+      // so they are read during LCD update in the main loop.
       uint8_t slow_bits = lcd.readButtons()
         #if !BUTTON_EXISTS(ENC)
           << B_I2C_BTN_OFFSET
@@ -381,7 +381,7 @@ bool MarlinUI::detected() {
       #if ENABLED(LCD_I2C_VIKI)
         if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked
           slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated
-      #endif // LCD_I2C_VIKI
+      #endif
       return slow_bits;
     #endif // LCD_I2C_TYPE_MCP23017
   }
diff --git a/Marlin/src/lcd/dogm/u8g_dev_tft_320x240_upscale_from_128x64.cpp b/Marlin/src/lcd/dogm/u8g_dev_tft_320x240_upscale_from_128x64.cpp
index 8451a10e0ef741d576f09b57830c184fc3ccabd1..0081b077390f3161db14561ebf0fb9971e93f05e 100644
--- a/Marlin/src/lcd/dogm/u8g_dev_tft_320x240_upscale_from_128x64.cpp
+++ b/Marlin/src/lcd/dogm/u8g_dev_tft_320x240_upscale_from_128x64.cpp
@@ -267,51 +267,102 @@ static const uint8_t ili9341_init_sequence[] = { // 0x9341 - ILI9341
     B01111111,B11111111,B11111111,B11111110,
   };
 
-  static const uint8_t buttonA[] = {
-    B01111111,B11111111,B11111111,B11111110,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B01000000,B00000000,B00000001,
-    B10000000,B11100000,B00000000,B00000001,
-    B10000001,B11110000,B00000000,B00000001,
-    B10000011,B11111000,B00000000,B00000001,
-    B10000111,B11111100,B00111111,B11100001,
-    B10000000,B11100000,B00111111,B11100001,
-    B10000000,B11100000,B00000000,B00000001,
-    B10000000,B11100000,B00000000,B00000001,
-    B10000000,B11100000,B00000000,B00000001,
-    B10000000,B11100000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B01111111,B11111111,B11111111,B11111110,
-  };
+  #if ENABLED(REVERSE_MENU_DIRECTION)
+
+    static const uint8_t buttonA[] = {
+      B01111111,B11111111,B11111111,B11111110,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00111111,B11100001,
+      B10000111,B11111100,B00111111,B11100001,
+      B10000011,B11111000,B00000000,B00000001,
+      B10000001,B11110000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B01000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B01111111,B11111111,B11111111,B11111110,
+    };
+    static const uint8_t buttonB[] = {
+      B01111111,B11111111,B11111111,B11111110,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B01100000,B00000010,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00001111,B10000001,
+      B10000000,B01100000,B00011111,B11000001,
+      B10000111,B11111110,B00111111,B11100001,
+      B10000111,B11111110,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B01111111,B11111111,B11111111,B11111110,
+    };
 
-  static const uint8_t buttonB[] = {
-    B01111111,B11111111,B11111111,B11111110,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B01100000,B00000111,B00000001,
-    B10000000,B01100000,B00000111,B00000001,
-    B10000000,B01100000,B00000111,B00000001,
-    B10000000,B01100000,B00000111,B00000001,
-    B10000111,B11111110,B00000111,B00000001,
-    B10000111,B11111110,B00111111,B11100001,
-    B10000000,B01100000,B00011111,B11000001,
-    B10000000,B01100000,B00001111,B10000001,
-    B10000000,B01100000,B00000111,B00000001,
-    B10000000,B01100000,B00000010,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B10000000,B00000000,B00000000,B00000001,
-    B01111111,B11111111,B11111111,B11111110,
-  };
+  #else
+
+    static const uint8_t buttonA[] = {
+      B01111111,B11111111,B11111111,B11111110,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B01000000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000001,B11110000,B00000000,B00000001,
+      B10000011,B11111000,B00000000,B00000001,
+      B10000111,B11111100,B00111111,B11100001,
+      B10000000,B11100000,B00111111,B11100001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B11100000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B01111111,B11111111,B11111111,B11111110,
+    };
+
+    static const uint8_t buttonB[] = {
+      B01111111,B11111111,B11111111,B11111110,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000111,B11111110,B00000111,B00000001,
+      B10000111,B11111110,B00111111,B11100001,
+      B10000000,B01100000,B00011111,B11000001,
+      B10000000,B01100000,B00001111,B10000001,
+      B10000000,B01100000,B00000111,B00000001,
+      B10000000,B01100000,B00000010,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B10000000,B00000000,B00000000,B00000001,
+      B01111111,B11111111,B11111111,B11111110,
+    };
+
+  #endif
 
   static const uint8_t buttonC[] = {
     B01111111,B11111111,B11111111,B11111110,
@@ -369,11 +420,8 @@ static const uint8_t ili9341_init_sequence[] = { // 0x9341 - ILI9341
 
 // Used to fill RGB565 (16bits) background
 inline void memset2(const void *ptr, uint16_t fill, size_t cnt) {
-  uint16_t* wptr = (uint16_t*) ptr;
-  for (size_t i = 0; i < cnt; i += 2) {
-     *wptr = fill;
-     wptr++;
-  }
+  uint16_t* wptr = (uint16_t*)ptr;
+  for (size_t i = 0; i < cnt; i += 2) { *wptr = fill; wptr++; }
 }
 
 static bool preinit = true;
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 5228292b70203d256b82391c1d920a5b7677ca8a..ba2de995e428824a608e90e6b6df1540d1ffb791 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -116,8 +116,6 @@
   #endif
   #if ENABLED(TOUCH_BUTTONS)
     #include "../feature/touch/xpt2046.h"
-    volatile uint8_t MarlinUI::touch_buttons;
-    uint8_t MarlinUI::read_touch_buttons() { return touch.read_buttons(); }
   #endif
 #endif
 
@@ -135,7 +133,7 @@ uint8_t MarlinUI::lcd_status_update_delay = 1; // First update one loop delayed
   millis_t MarlinUI::next_filament_display; // = 0
 #endif
 
-millis_t next_button_update_ms;
+millis_t MarlinUI::next_button_update_ms; // = 0
 
 #if HAS_GRAPHICAL_LCD
   bool MarlinUI::drawing_screen, MarlinUI::first_page; // = false
@@ -345,9 +343,6 @@ void MarlinUI::init() {
     #if HAS_SLOW_BUTTONS
       slow_buttons = 0;
     #endif
-    #if ENABLED(TOUCH_BUTTONS)
-      touch_buttons = 0;
-    #endif
   #endif
 
   update_buttons();
@@ -746,16 +741,19 @@ void MarlinUI::update() {
   static millis_t next_lcd_update_ms;
   millis_t ms = millis();
 
+  #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS
+    static millis_t return_to_status_ms = 0;
+    #define RESET_STATUS_TIMEOUT() (return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS)
+  #else
+    #define RESET_STATUS_TIMEOUT() NOOP
+  #endif
+
   #ifdef LED_BACKLIGHT_TIMEOUT
     leds.update_timeout(powersupply_on);
   #endif
 
   #if HAS_LCD_MENU
 
-    #if LCD_TIMEOUT_TO_STATUS
-      static millis_t return_to_status_ms = 0;
-    #endif
-
     // Handle any queued Move Axis motion
     manage_manual_move();
 
@@ -764,54 +762,67 @@ void MarlinUI::update() {
     update_buttons();
 
     // If the action button is pressed...
-    static bool wait_for_unclick; // = 0
-    auto generate_click = [&]() {
-      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
-      }
-    };
+    static bool wait_for_unclick; // = false
 
     #if ENABLED(TOUCH_BUTTONS)
-      if (touch_buttons) {
-        if (buttons & EN_C)
-          generate_click();
-        else if (buttons & (EN_A | EN_B)) {             // Ignore the encoder if clicked, to prevent "slippage"
-          const millis_t ms = millis();
-          if (ELAPSED(ms, next_button_update_ms)) {
-            next_button_update_ms = ms + 50;
-            encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * (ENCODER_PULSES_PER_STEP);
-            if (buttons & EN_A) encoderDiff *= -1;
-            if (!wait_for_unclick) {
-              next_button_update_ms += 250;
+
+      #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?
+            encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * (ENCODER_PULSES_PER_STEP) * encoderDirection;
+            if (touch_buttons & EN_A) encoderDiff *= -1;
+            next_button_update_ms = ms + 50;            // 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 HAS_BUZZER
                 buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ);
               #endif
-              wait_for_unclick = true;                  //  - Set debounce flag to ignore continous clicks
             }
           }
         }
+        if (!(touch_buttons & (EN_A | EN_B))) arrow_pressed = false;
       }
-      else
+
     #endif // TOUCH_BUTTONS
-      {
-        //
-        // Integrated LCD click handling via button_pressed()
-        //
-        if (!external_control && button_pressed())
-          generate_click();
-        else
-          wait_for_unclick = false;
-      }
 
-    #if HAS_DIGITAL_BUTTONS && (BUTTON_EXISTS(BACK) || ENABLED(TOUCH_BUTTONS))
-      if (LCD_BACK_CLICKED()) {
-        quick_feedback();
-        goto_previous_screen();
+    // 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
       }
-    #endif
+    }
+    else
+      wait_for_unclick = false;
+
+    if (LCD_BACK_CLICKED()) {
+      quick_feedback();
+      goto_previous_screen();
+    }
 
   #endif // HAS_LCD_MENU
 
@@ -885,23 +896,8 @@ void MarlinUI::update() {
         slow_buttons = read_slow_buttons(); // Buttons that take too long to read in interrupt context
       #endif
 
-      #if ENABLED(TOUCH_BUTTONS)
-        touch_buttons = read_touch_buttons();
-        if (touch_buttons) {
-          #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS
-            return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
-          #endif
-        }
-      #endif
-
       #if ENABLED(REPRAPWORLD_KEYPAD)
-
-        if (handle_keypad()) {
-          #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS
-            return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
-          #endif
-        }
-
+        if (handle_keypad()) RESET_STATUS_TIMEOUT();
       #endif
 
       const float abs_diff = ABS(encoderDiff);
@@ -947,9 +943,7 @@ void MarlinUI::update() {
           encoderDiff = 0;
         }
 
-        #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS
-          return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
-        #endif
+        RESET_STATUS_TIMEOUT();
 
         refresh(LCDVIEW_REDRAW_NOW);
 
@@ -982,9 +976,7 @@ void MarlinUI::update() {
           lcd_status_update_delay = 12;
         }
         refresh(LCDVIEW_REDRAW_NOW);
-        #if LCD_TIMEOUT_TO_STATUS
-          return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
-        #endif
+        RESET_STATUS_TIMEOUT();
       }
     #endif
 
@@ -1058,7 +1050,7 @@ void MarlinUI::update() {
     #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS
       // Return to Status Screen after a timeout
       if (on_status_screen() || defer_return_to_status)
-        return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
+        RESET_STATUS_TIMEOUT();
       else if (ELAPSED(ms, return_to_status_ms))
         return_to_status();
     #endif
@@ -1241,12 +1233,12 @@ void MarlinUI::update() {
           #if HAS_SLOW_BUTTONS
             | slow_buttons
           #endif
-          #if ENABLED(TOUCH_BUTTONS)
-            | touch_buttons
-          #endif
         ;
+
       #elif HAS_ADC_BUTTONS
+
         buttons = 0;
+
       #endif
 
       #if HAS_ADC_BUTTONS
diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h
index 26e9261bd5285aecfb4f87600fa74da7b5ead66a..973fbc451e92de900306425eb2d92e5ce83a43e8 100644
--- a/Marlin/src/lcd/ultralcd.h
+++ b/Marlin/src/lcd/ultralcd.h
@@ -306,6 +306,8 @@ public:
 
     #if HAS_SPI_LCD
 
+      static millis_t next_button_update_ms;
+
       static bool detected();
 
       static LCDViewAction lcdDrawUpdate;
@@ -531,10 +533,6 @@ public:
       static volatile uint8_t slow_buttons;
       static uint8_t read_slow_buttons();
     #endif
-    #if ENABLED(TOUCH_BUTTONS)
-      static volatile uint8_t touch_buttons;
-      static uint8_t read_touch_buttons();
-    #endif
 
     static void update_buttons();
     static inline bool button_pressed() { return BUTTON_CLICK(); }