From ff729744e5f56ff86d7e6c92dd2df16995a3be00 Mon Sep 17 00:00:00 2001
From: borland1 <barryorlando@hotmail.com>
Date: Tue, 23 Mar 2021 06:21:11 -0700
Subject: [PATCH] Main / Config Custom Submenus (#18177)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
---
 Marlin/Configuration_adv.h                    |  98 +++++++----
 Marlin/src/inc/Conditionals_adv.h             |   2 +-
 Marlin/src/inc/SanityCheck.h                  | 105 +-----------
 .../screens/custom_user_menus.cpp             |   4 +-
 .../ftdi_eve_touch_ui/screens/main_menu.cpp   |  14 +-
 .../lib/ftdi_eve_touch_ui/screens/screens.h   |   8 +-
 .../lcd/extui/lib/mks_ui/tft_Language_en.h    |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_fr.h    |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_it.h    |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_ru.h    |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_s_cn.h  |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_sp.h    |  12 +-
 .../lcd/extui/lib/mks_ui/tft_Language_t_cn.h  |  12 +-
 Marlin/src/lcd/language/language_cz.h         |   2 +-
 Marlin/src/lcd/language/language_de.h         |   2 +-
 Marlin/src/lcd/language/language_en.h         |   2 +-
 Marlin/src/lcd/language/language_es.h         |   2 +-
 Marlin/src/lcd/language/language_fr.h         |   2 +-
 Marlin/src/lcd/language/language_gl.h         |   2 +-
 Marlin/src/lcd/language/language_it.h         |   2 +-
 Marlin/src/lcd/language/language_jp_kana.h    |   2 +-
 Marlin/src/lcd/language/language_pl.h         |   2 +-
 Marlin/src/lcd/language/language_pt_br.h      |   2 +-
 Marlin/src/lcd/language/language_ro.h         |   2 +-
 Marlin/src/lcd/language/language_ru.h         |   2 +-
 Marlin/src/lcd/language/language_sk.h         |   2 +-
 Marlin/src/lcd/language/language_tr.h         |   2 +-
 Marlin/src/lcd/language/language_uk.h         |   2 +-
 Marlin/src/lcd/language/language_vi.h         |   2 +-
 Marlin/src/lcd/language/language_zh_CN.h      |   2 +-
 Marlin/src/lcd/language/language_zh_TW.h      |   2 +-
 Marlin/src/lcd/menu/menu_configuration.cpp    | 152 +++++++++++++++++
 Marlin/src/lcd/menu/menu_custom.cpp           | 141 ----------------
 Marlin/src/lcd/menu/menu_main.cpp             | 156 +++++++++++++++++-
 .../PlatformIO/scripts/common-dependencies.h  |   3 -
 buildroot/tests/mega2560                      |   4 +-
 36 files changed, 440 insertions(+), 367 deletions(-)
 delete mode 100644 Marlin/src/lcd/menu/menu_custom.cpp

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index fb1f79b230a..328056cb84a 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -3415,6 +3415,71 @@
   #define GCODE_MACROS_SLOT_SIZE  50  // Maximum length of a single macro
 #endif
 
+/**
+ * User-defined menu items to run custom G-code.
+ * Up to 25 may be defined, but the actual number is LCD-dependent.
+ */
+
+// Custom Menu: Main Menu
+//#define CUSTOM_MENU_MAIN
+#if ENABLED(CUSTOM_MENU_MAIN)
+  //#define CUSTOM_MENU_MAIN_TITLE "Custom Commands"
+  #define CUSTOM_MENU_MAIN_SCRIPT_DONE "M117 User Script Done"
+  #define CUSTOM_MENU_MAIN_SCRIPT_AUDIBLE_FEEDBACK
+  //#define CUSTOM_MENU_MAIN_SCRIPT_RETURN   // Return to status screen after a script
+  #define CUSTOM_MENU_MAIN_ONLY_IDLE         // Only show custom menu when the machine is idle
+
+  #define MAIN_MENU_ITEM_1_DESC "Home & UBL Info"
+  #define MAIN_MENU_ITEM_1_GCODE "G28\nG29 W"
+  //#define MAIN_MENU_ITEM_1_CONFIRM          // Show a confirmation dialog before this action
+
+  #define MAIN_MENU_ITEM_2_DESC "Preheat for " PREHEAT_1_LABEL
+  #define MAIN_MENU_ITEM_2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+  //#define MAIN_MENU_ITEM_2_CONFIRM
+
+  //#define MAIN_MENU_ITEM_3_DESC "Preheat for " PREHEAT_2_LABEL
+  //#define MAIN_MENU_ITEM_3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+  //#define MAIN_MENU_ITEM_3_CONFIRM
+
+  //#define MAIN_MENU_ITEM_4_DESC "Heat Bed/Home/Level"
+  //#define MAIN_MENU_ITEM_4_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
+  //#define MAIN_MENU_ITEM_4_CONFIRM
+
+  //#define MAIN_MENU_ITEM_5_DESC "Home & Info"
+  //#define MAIN_MENU_ITEM_5_GCODE "G28\nM503"
+  //#define MAIN_MENU_ITEM_5_CONFIRM
+#endif
+
+// Custom Menu: Configuration Menu
+//#define CUSTOM_MENU_CONFIG
+#if ENABLED(CUSTOM_MENU_CONFIG)
+  //#define CUSTOM_MENU_CONFIG_TITLE "Custom Commands"
+  #define CUSTOM_MENU_CONFIG_SCRIPT_DONE "M117 Wireless Script Done"
+  #define CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK
+  //#define CUSTOM_MENU_CONFIG_SCRIPT_RETURN  // Return to status screen after a script
+  #define CUSTOM_MENU_CONFIG_ONLY_IDLE        // Only show custom menu when the machine is idle
+
+  #define CONFIG_MENU_ITEM_1_DESC "Wifi ON"
+  #define CONFIG_MENU_ITEM_1_GCODE "M118 [ESP110] WIFI-STA pwd=12345678"
+  //#define CONFIG_MENU_ITEM_1_CONFIRM        // Show a confirmation dialog before this action
+
+  #define CONFIG_MENU_ITEM_2_DESC "Bluetooth ON"
+  #define CONFIG_MENU_ITEM_2_GCODE "M118 [ESP110] BT pwd=12345678"
+  //#define CONFIG_MENU_ITEM_2_CONFIRM
+
+  //#define CONFIG_MENU_ITEM_3_DESC "Radio OFF"
+  //#define CONFIG_MENU_ITEM_3_GCODE "M118 [ESP110] OFF pwd=12345678"
+  //#define CONFIG_MENU_ITEM_3_CONFIRM
+
+  //#define CONFIG_MENU_ITEM_4_DESC "Wifi ????"
+  //#define CONFIG_MENU_ITEM_4_GCODE "M118 ????"
+  //#define CONFIG_MENU_ITEM_4_CONFIRM
+
+  //#define CONFIG_MENU_ITEM_5_DESC "Wifi ????"
+  //#define CONFIG_MENU_ITEM_5_GCODE "M118 ????"
+  //#define CONFIG_MENU_ITEM_5_CONFIRM
+#endif
+
 /**
  * User-defined buttons to run custom G-code.
  * Up to 25 may be defined.
@@ -3446,39 +3511,6 @@
   #endif
 #endif
 
-/**
- * User-defined menu items to run custom G-code.
- * Up to 25 may be defined, but the actual number is LCD-dependent.
- */
-//#define CUSTOM_USER_MENUS
-#if ENABLED(CUSTOM_USER_MENUS)
-  //#define CUSTOM_USER_MENU_TITLE "Custom Commands"
-  #define USER_SCRIPT_DONE "M117 User Script Done"
-  #define USER_SCRIPT_AUDIBLE_FEEDBACK
-  //#define USER_SCRIPT_RETURN    // Return to status screen after a script
-  #define CUSTOM_MENU_ONLY_IDLE   // Only show custom menu when the machine is idle
-
-  #define USER_DESC_1 "Home & UBL Info"
-  #define USER_GCODE_1 "G28\nG29W"
-  //#define USER_CONFIRM_1        // Show a confirmation dialog before this action
-
-  #define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL
-  #define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
-  //#define USER_CONFIRM_2
-
-  #define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL
-  #define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
-  //#define USER_CONFIRM_3
-
-  #define USER_DESC_4 "Heat Bed/Home/Level"
-  #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
-  //#define USER_CONFIRM_4
-
-  #define USER_DESC_5 "Home & Info"
-  #define USER_GCODE_5 "G28\nM503"
-  //#define USER_CONFIRM_5
-#endif
-
 /**
  * Host Action Commands
  *
diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h
index 490766bd7a8..5ef0efa9684 100644
--- a/Marlin/src/inc/Conditionals_adv.h
+++ b/Marlin/src/inc/Conditionals_adv.h
@@ -536,7 +536,7 @@
                          (defined(MMU2_SERIAL_PORT) && MMU2_SERIAL_PORT == (N)) || \
                          (defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT == (N))
 
-#if ENABLED(CUSTOM_USER_MENUS)
+#if BOTH(HAS_TFT_LVGL_UI, CUSTOM_MENU_MAIN)
   #define _HAS_1(N) (defined(USER_DESC_##N) && defined(USER_GCODE_##N))
   #define HAS_USER_ITEM(V...) DO(HAS,||,V)
 #else
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index d8111c18da6..a7f726c4b20 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -553,6 +553,8 @@
   #error "Z_AFTER_DEACTIVATE is replaced by Z_IDLE_HEIGHT."
 #elif defined(MEATPACK)
   #error "MEATPACK is now enabled with MEATPACK_ON_SERIAL_PORT_1, MEATPACK_ON_SERIAL_PORT_2, etc."
+#elif defined(CUSTOM_USER_MENUS)
+  #error "CUSTOM_USER_MENUS has been replaced by CUSTOM_MENU_MAIN and CUSTOM_MENU_CONFIG."
 #endif
 
 /**
@@ -2986,109 +2988,6 @@ static_assert(   _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
   #error "GCODE_MACROS_SLOTS must be a number from 1 to 10."
 #endif
 
-#if ENABLED(CUSTOM_USER_MENUS)
-  #ifdef USER_GCODE_1
-    constexpr char _chr1 = USER_GCODE_1[strlen(USER_GCODE_1) - 1];
-    static_assert(_chr1 != '\n' && _chr1 != '\r', "USER_GCODE_1 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_2
-    constexpr char _chr2 = USER_GCODE_2[strlen(USER_GCODE_2) - 1];
-    static_assert(_chr2 != '\n' && _chr2 != '\r', "USER_GCODE_2 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_3
-    constexpr char _chr3 = USER_GCODE_3[strlen(USER_GCODE_3) - 1];
-    static_assert(_chr3 != '\n' && _chr3 != '\r', "USER_GCODE_3 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_4
-    constexpr char _chr4 = USER_GCODE_4[strlen(USER_GCODE_4) - 1];
-    static_assert(_chr4 != '\n' && _chr4 != '\r', "USER_GCODE_4 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_5
-    constexpr char _chr5 = USER_GCODE_5[strlen(USER_GCODE_5) - 1];
-    static_assert(_chr5 != '\n' && _chr5 != '\r', "USER_GCODE_5 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_6
-    constexpr char _chr6 = USER_GCODE_6[strlen(USER_GCODE_6) - 1];
-    static_assert(_chr6 != '\n' && _chr6 != '\r', "USER_GCODE_6 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_7
-    constexpr char _chr7 = USER_GCODE_7[strlen(USER_GCODE_7) - 1];
-    static_assert(_chr7 != '\n' && _chr7 != '\r', "USER_GCODE_7 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_8
-    constexpr char _chr8 = USER_GCODE_8[strlen(USER_GCODE_8) - 1];
-    static_assert(_chr8 != '\n' && _chr8 != '\r', "USER_GCODE_8 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_9
-    constexpr char _chr9 = USER_GCODE_9[strlen(USER_GCODE_9) - 1];
-    static_assert(_chr9 != '\n' && _chr9 != '\r', "USER_GCODE_9 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_10
-    constexpr char _chr10 = USER_GCODE_10[strlen(USER_GCODE_10) - 1];
-    static_assert(_chr10 != '\n' && _chr10 != '\r', "USER_GCODE_10 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_11
-    constexpr char _chr11 = USER_GCODE_11[strlen(USER_GCODE_11) - 1];
-    static_assert(_chr11 != '\n' && _chr11 != '\r', "USER_GCODE_11 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_12
-    constexpr char _chr12 = USER_GCODE_12[strlen(USER_GCODE_12) - 1];
-    static_assert(_chr12 != '\n' && _chr12 != '\r', "USER_GCODE_12 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_13
-    constexpr char _chr13 = USER_GCODE_13[strlen(USER_GCODE_13) - 1];
-    static_assert(_chr13 != '\n' && _chr13 != '\r', "USER_GCODE_13 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_14
-    constexpr char _chr14 = USER_GCODE_14[strlen(USER_GCODE_14) - 1];
-    static_assert(_chr14 != '\n' && _chr14 != '\r', "USER_GCODE_14 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_15
-    constexpr char _chr15 = USER_GCODE_15[strlen(USER_GCODE_15) - 1];
-    static_assert(_chr15 != '\n' && _chr15 != '\r', "USER_GCODE_15 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_16
-    constexpr char _chr16 = USER_GCODE_16[strlen(USER_GCODE_16) - 1];
-    static_assert(_chr16 != '\n' && _chr16 != '\r', "USER_GCODE_16 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_17
-    constexpr char _chr17 = USER_GCODE_17[strlen(USER_GCODE_17) - 1];
-    static_assert(_chr17 != '\n' && _chr17 != '\r', "USER_GCODE_17 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_18
-    constexpr char _chr18 = USER_GCODE_18[strlen(USER_GCODE_18) - 1];
-    static_assert(_chr18 != '\n' && _chr18 != '\r', "USER_GCODE_18 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_19
-    constexpr char _chr19 = USER_GCODE_19[strlen(USER_GCODE_19) - 1];
-    static_assert(_chr19 != '\n' && _chr19 != '\r', "USER_GCODE_19 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_20
-    constexpr char _chr20 = USER_GCODE_20[strlen(USER_GCODE_20) - 1];
-    static_assert(_chr20 != '\n' && _chr20 != '\r', "USER_GCODE_20 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_21
-    constexpr char _chr21 = USER_GCODE_21[strlen(USER_GCODE_21) - 1];
-    static_assert(_chr21 != '\n' && _chr21 != '\r', "USER_GCODE_21 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_22
-    constexpr char _chr22 = USER_GCODE_22[strlen(USER_GCODE_22) - 1];
-    static_assert(_chr22 != '\n' && _chr22 != '\r', "USER_GCODE_22 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_23
-    constexpr char _chr23 = USER_GCODE_23[strlen(USER_GCODE_23) - 1];
-    static_assert(_chr23 != '\n' && _chr23 != '\r', "USER_GCODE_23 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_24
-    constexpr char _chr24 = USER_GCODE_24[strlen(USER_GCODE_24) - 1];
-    static_assert(_chr24 != '\n' && _chr24 != '\r', "USER_GCODE_24 cannot have a newline at the end. Please remove it.");
-  #endif
-  #ifdef USER_GCODE_25
-    constexpr char _chr25 = USER_GCODE_25[strlen(USER_GCODE_25) - 1];
-    static_assert(_chr25 != '\n' && _chr25 != '\r', "USER_GCODE_25 cannot have a newline at the end. Please remove it.");
-  #endif
-#endif
-
 #if ENABLED(BACKLASH_COMPENSATION)
   #ifndef BACKLASH_DISTANCE_MM
     #error "BACKLASH_COMPENSATION requires BACKLASH_DISTANCE_MM."
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/custom_user_menus.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/custom_user_menus.cpp
index ea175706f73..d5d1abdf9d6 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/custom_user_menus.cpp
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/custom_user_menus.cpp
@@ -30,8 +30,8 @@ using namespace ExtUI;
 using namespace Theme;
 
 #define _ITEM_TAG(N) (10+N)
-#define _USER_DESC(N) USER_DESC_##N
-#define _USER_GCODE(N) USER_GCODE_##N
+#define _USER_DESC(N) MAIN_MENU_ITEM_##N##_DESC
+#define _USER_GCODE(N) MAIN_MENU_ITEM_##N##_GCODE
 #define _USER_ITEM(N) .tag(_ITEM_TAG(N)).button(USER_ITEM_POS(N), _USER_DESC(N))
 #define _USER_ACTION(N) case _ITEM_TAG(N): injectCommands_P(PSTR(_USER_GCODE(N))); TERN_(USER_SCRIPT_RETURN, GOTO_SCREEN(StatusScreen)); break;
 
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
index b7914d629be..53d63061758 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
@@ -41,9 +41,9 @@ void MainMenu::onRedraw(draw_mode_t what) {
     #define GRID_COLS 2
     #define ABOUT_PRINTER_POS     BTN_POS(1,1), BTN_SIZE(2,1)
     #define ADVANCED_SETTINGS_POS BTN_POS(1,2), BTN_SIZE(2,1)
-    #if ENABLED(CUSTOM_USER_MENUS)
+    #if ENABLED(CUSTOM_MENU_MAIN)
       #define FILAMENTCHANGE_POS  BTN_POS(1,3), BTN_SIZE(1,1)
-      #define CUSTOM_USER_MENUS_POS BTN_POS(2,3), BTN_SIZE(1,1)
+      #define CUSTOM_MENU_POS BTN_POS(2,3), BTN_SIZE(1,1)
     #else
       #define FILAMENTCHANGE_POS  BTN_POS(1,3), BTN_SIZE(2,1)
     #endif
@@ -63,10 +63,10 @@ void MainMenu::onRedraw(draw_mode_t what) {
     #define CLEAN_NOZZLE_POS      BTN_POS(4,2), BTN_SIZE(3,1)
     #define MOVE_AXIS_POS         BTN_POS(1,3), BTN_SIZE(3,1)
     #define DISABLE_STEPPERS_POS  BTN_POS(4,3), BTN_SIZE(3,1)
-    #if ENABLED(CUSTOM_USER_MENUS)
+    #if ENABLED(CUSTOM_MENU_MAIN)
       #define TEMPERATURE_POS     BTN_POS(1,4), BTN_SIZE(2,1)
       #define FILAMENTCHANGE_POS  BTN_POS(3,4), BTN_SIZE(2,1)
-      #define CUSTOM_USER_MENUS_POS BTN_POS(5,4), BTN_SIZE(2,1)
+      #define CUSTOM_MENU_POS BTN_POS(5,4), BTN_SIZE(2,1)
     #else
       #define TEMPERATURE_POS     BTN_POS(1,4), BTN_SIZE(3,1)
       #define FILAMENTCHANGE_POS  BTN_POS(4,4), BTN_SIZE(3,1)
@@ -91,8 +91,8 @@ void MainMenu::onRedraw(draw_mode_t what) {
        .enabled(TERN_(HAS_LEVELING, 1))
        .tag( 9).button(LEVELING_POS,        GET_TEXT_F(MSG_LEVELING))
        .tag(10).button(ABOUT_PRINTER_POS,   GET_TEXT_F(MSG_INFO_MENU))
-       #if ENABLED(CUSTOM_USER_MENUS)
-        .tag(11).button(CUSTOM_USER_MENUS_POS, GET_TEXT_F(MSG_USER_MENU))
+       #if ENABLED(CUSTOM_MENU_MAIN)
+        .tag(11).button(CUSTOM_MENU_POS, GET_TEXT_F(MSG_CUSTOM_COMMANDS))
        #endif
        .colors(action_btn)
        .tag(1).button(BACK_POS,             GET_TEXT_F(MSG_BACK));
@@ -117,7 +117,7 @@ bool MainMenu::onTouchEnd(uint8_t tag) {
       case 9:  GOTO_SCREEN(LevelingMenu);                             break;
     #endif
     case 10: GOTO_SCREEN(AboutScreen);                                break;
-    #if ENABLED(CUSTOM_USER_MENUS)
+    #if ENABLED(CUSTOM_MENU_MAIN)
       case 11: GOTO_SCREEN(CustomUserMenus);                          break;
     #endif
 
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
index 61d702ebafb..3e69a3ad2f1 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
@@ -22,8 +22,6 @@
 
 #pragma once
 
-#if ENABLED(TOUCH_UI_FTDI_EVE)
-
 #include "../ftdi_eve_lib/ftdi_eve_lib.h"
 #include "../language/language.h"
 #include "../theme/theme.h"
@@ -107,7 +105,7 @@ enum {
   #if ENABLED(SDSUPPORT)
     FILES_SCREEN_CACHE,
   #endif
-  #if ENABLED(CUSTOM_USER_MENUS)
+  #if ENABLED(CUSTOM_MENU_MAIN)
     CUSTOM_USER_MENUS_SCREEN_CACHE,
   #endif
   CHANGE_FILAMENT_SCREEN_CACHE,
@@ -248,7 +246,7 @@ enum {
   #include "files_screen.h"
 #endif
 
-#if ENABLED(CUSTOM_USER_MENUS)
+#if ENABLED(CUSTOM_MENU_MAIN)
   #include "custom_user_menus.h"
 #endif
 
@@ -262,5 +260,3 @@ enum {
 #if NUM_LANGUAGES > 1
   #include "language_menu.h"
 #endif
-
-#endif // TOUCH_UI_FTDI_EVE
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h
index fd5780e1d8d..12a57bd5484 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h
@@ -728,9 +728,9 @@
 #define EEPROM_READ_TIPS_EN   "Read settings from EEPROM?"
 #define EEPROM_REVERT_TIPS_EN "Revert settings to factory defaults?"
 
-#define MORE_CUSTOM1_TEXT_EN  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_EN  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_EN  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_EN  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_EN  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_EN  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_EN  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_EN  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_EN  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_EN  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_EN  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_EN  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h
index 9440b8b0eb2..f0b19d4e027 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h
@@ -260,9 +260,9 @@
 #define EEPROM_READ_TIPS_FR   "Lire les paramètres de l'EEPROM?"
 #define EEPROM_REVERT_TIPS_FR "Rétablir les paramètres par défaut d'usine?"
 
-#define MORE_CUSTOM1_TEXT_FR  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_FR  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_FR  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_FR  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_FR  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_FR  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_FR  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_FR  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_FR  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_FR  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_FR  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_FR  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h
index 9b88de3df44..b74842afef1 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h
@@ -257,9 +257,9 @@
 #define EEPROM_READ_TIPS_IT               "Leggi le impostazioni dalla EEPROM?"
 #define EEPROM_REVERT_TIPS_IT             "Ripristinare le impostazioni predefinite?"
 
-#define MORE_CUSTOM1_TEXT_IT  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_IT  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_IT  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_IT  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_IT  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_IT  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_IT  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_IT  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_IT  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_IT  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_IT  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_IT  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h
index 1989eaef1b5..50e32ac05c9 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h
@@ -255,12 +255,12 @@
 #define EEPROM_SETTINGS_READ_RU       "Чтение настроек из EEPROM"
 #define EEPROM_SETTINGS_REVERT_RU     "Bосстановить заводские настройки по умолчанию"
 
-#define MORE_CUSTOM1_TEXT_RU  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_RU  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_RU  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_RU  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_RU  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_RU  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_RU  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_RU  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_RU  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_RU  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_RU  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_RU  MAIN_MENU_ITEM_6_DESC
 
 #define EEPROM_STORE_TIPS_RU          "Cохранить настройки в EEPROM?"
 #define EEPROM_READ_TIPS_RU           "читать настройки из EEPROM?"
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h
index cc1a8703391..f204933e25c 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h
@@ -495,9 +495,9 @@
 #define EEPROM_READ_TIPS_CN   "是否使用EEPROM参数?"
 #define EEPROM_REVERT_TIPS_CN "是否恢复默认参数?"
 
-#define MORE_CUSTOM1_TEXT_CN  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_CN  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_CN  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_CN  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_CN  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_CN  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_CN  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_CN  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_CN  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_CN  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_CN  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_CN  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h
index 4654abddee1..a75bc69ab73 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h
@@ -266,9 +266,9 @@
 #define EEPROM_READ_TIPS_SP   "Leer la configuración de EEPROM?"
 #define EEPROM_REVERT_TIPS_SP "Revert settings to factory defaults?"
 
-#define MORE_CUSTOM1_TEXT_SP  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_SP  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_SP  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_SP  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_SP  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_SP  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_SP  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_SP  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_SP  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_SP  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_SP  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_SP  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h
index 8057a3110e6..76da2de907b 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h
+++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h
@@ -493,9 +493,9 @@
 #define EEPROM_READ_TIPS_T_CN         "是否使用EEPROM參數?"
 #define EEPROM_REVERT_TIPS_T_CN       "是否恢復默認參數?"
 
-#define MORE_CUSTOM1_TEXT_T_CN  USER_DESC_1
-#define MORE_CUSTOM2_TEXT_T_CN  USER_DESC_2
-#define MORE_CUSTOM3_TEXT_T_CN  USER_DESC_3
-#define MORE_CUSTOM4_TEXT_T_CN  USER_DESC_4
-#define MORE_CUSTOM5_TEXT_T_CN  USER_DESC_5
-#define MORE_CUSTOM6_TEXT_T_CN  USER_DESC_6
+#define MORE_CUSTOM1_TEXT_T_CN  MAIN_MENU_ITEM_1_DESC
+#define MORE_CUSTOM2_TEXT_T_CN  MAIN_MENU_ITEM_2_DESC
+#define MORE_CUSTOM3_TEXT_T_CN  MAIN_MENU_ITEM_3_DESC
+#define MORE_CUSTOM4_TEXT_T_CN  MAIN_MENU_ITEM_4_DESC
+#define MORE_CUSTOM5_TEXT_T_CN  MAIN_MENU_ITEM_5_DESC
+#define MORE_CUSTOM6_TEXT_T_CN  MAIN_MENU_ITEM_6_DESC
diff --git a/Marlin/src/lcd/language/language_cz.h b/Marlin/src/lcd/language/language_cz.h
index adcbba77201..c434f5493b9 100644
--- a/Marlin/src/lcd/language/language_cz.h
+++ b/Marlin/src/lcd/language/language_cz.h
@@ -119,7 +119,7 @@ namespace Language_cz {
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Hodnota Z");
 
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Vlastní příkazy");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Vlastní příkazy");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 test sondy");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 bod");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Odchylka");
diff --git a/Marlin/src/lcd/language/language_de.h b/Marlin/src/lcd/language/language_de.h
index 68791d9eaa1..ebc2445b11e 100644
--- a/Marlin/src/lcd/language/language_de.h
+++ b/Marlin/src/lcd/language/language_de.h
@@ -112,7 +112,7 @@ namespace Language_de {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Index X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Z-Wert");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Benutzer-Menü");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Benutzer-Menü");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Sondentest");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Punkt");
   PROGMEM Language_Str MSG_M48_OUT_OF_BOUNDS               = _UxGT("Zu weit draußen");
diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h
index 72f262c687c..a37f5aa7903 100644
--- a/Marlin/src/lcd/language/language_en.h
+++ b/Marlin/src/lcd/language/language_en.h
@@ -140,7 +140,7 @@ namespace Language_en {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Index X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Z Value");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Custom Commands");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Custom Commands");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Probe Test");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Point");
   PROGMEM Language_Str MSG_M48_OUT_OF_BOUNDS               = _UxGT("Probe out of bounds");
diff --git a/Marlin/src/lcd/language/language_es.h b/Marlin/src/lcd/language/language_es.h
index 58559a4ff50..b2d83aa05ba 100644
--- a/Marlin/src/lcd/language/language_es.h
+++ b/Marlin/src/lcd/language/language_es.h
@@ -115,7 +115,7 @@ namespace Language_es {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Índice X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Índice Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valor Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Com. Personalizados");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Com. Personalizados");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Probar Sonda");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Punto");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Desviación");
diff --git a/Marlin/src/lcd/language/language_fr.h b/Marlin/src/lcd/language/language_fr.h
index 031db358bd3..bdd91d3b297 100644
--- a/Marlin/src/lcd/language/language_fr.h
+++ b/Marlin/src/lcd/language/language_fr.h
@@ -113,7 +113,7 @@ namespace Language_fr {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Index X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valeur Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Commandes perso");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Commandes perso");
 
   PROGMEM Language_Str MSG_LCD_TILTING_MESH                = _UxGT("Mesure point");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("Ecart sonde Z M48");
diff --git a/Marlin/src/lcd/language/language_gl.h b/Marlin/src/lcd/language/language_gl.h
index d0ec16b35f8..5745ce1eb80 100644
--- a/Marlin/src/lcd/language/language_gl.h
+++ b/Marlin/src/lcd/language/language_gl.h
@@ -112,7 +112,7 @@ namespace Language_gl {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Índice X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Índice Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valor Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Comandos Personaliz.");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Comandos Personaliz.");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Probar Sonda");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Punto");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Desviación");
diff --git a/Marlin/src/lcd/language/language_it.h b/Marlin/src/lcd/language/language_it.h
index 5bfb6aa9aa2..be54d5035d2 100644
--- a/Marlin/src/lcd/language/language_it.h
+++ b/Marlin/src/lcd/language/language_it.h
@@ -138,7 +138,7 @@ namespace Language_it {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Indice X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Indice Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valore di Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Comandi personaliz.");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Comandi personaliz.");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("Test sonda M48");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("Punto M48");
   PROGMEM Language_Str MSG_M48_OUT_OF_BOUNDS               = _UxGT("Sonda oltre i limiti");
diff --git a/Marlin/src/lcd/language/language_jp_kana.h b/Marlin/src/lcd/language/language_jp_kana.h
index 8431d86d1c6..e0028e22a2c 100644
--- a/Marlin/src/lcd/language/language_jp_kana.h
+++ b/Marlin/src/lcd/language/language_jp_kana.h
@@ -246,7 +246,7 @@ namespace Language_jp_kana {
   PROGMEM Language_Str MSG_BACK                            = _UxGT("モドリ");
   PROGMEM Language_Str MSG_VELOCITY                        = _UxGT("ソクド");
   PROGMEM Language_Str MSG_STEPS_PER_MM                    = _UxGT("ステップ/mm");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("ユーザーコマンド");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("ユーザーコマンド");
   PROGMEM Language_Str MSG_PRINT_PAUSED                    = _UxGT("プリントガイチジテイシサレマシタ");
   PROGMEM Language_Str MSG_PRINTING                        = _UxGT("プリントチュウ...");
 }
diff --git a/Marlin/src/lcd/language/language_pl.h b/Marlin/src/lcd/language/language_pl.h
index bf7d32e2223..9004722cfcd 100644
--- a/Marlin/src/lcd/language/language_pl.h
+++ b/Marlin/src/lcd/language/language_pl.h
@@ -109,7 +109,7 @@ namespace Language_pl {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Indeks X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Indeks Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Wartość Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Własne Polecenia");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Własne Polecenia");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Test sondy");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Punky");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Odchylenie");
diff --git a/Marlin/src/lcd/language/language_pt_br.h b/Marlin/src/lcd/language/language_pt_br.h
index 4ddf424b3d6..642a7d92031 100644
--- a/Marlin/src/lcd/language/language_pt_br.h
+++ b/Marlin/src/lcd/language/language_pt_br.h
@@ -103,7 +103,7 @@ namespace Language_pt_br {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Índice X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Índice Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valor Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Comando customizado");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Comando customizado");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Teste de sonda");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Ponto");
   PROGMEM Language_Str MSG_IDEX_MENU                       = _UxGT("Modo IDEX");
diff --git a/Marlin/src/lcd/language/language_ro.h b/Marlin/src/lcd/language/language_ro.h
index bd7e1b7a64b..a34717acb51 100644
--- a/Marlin/src/lcd/language/language_ro.h
+++ b/Marlin/src/lcd/language/language_ro.h
@@ -111,7 +111,7 @@ namespace Language_ro {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Index X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Valoare Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Comenzi Personalizate");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Comenzi Personalizate");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Probe Test");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Point");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Deviation");
diff --git a/Marlin/src/lcd/language/language_ru.h b/Marlin/src/lcd/language/language_ru.h
index b3176c0a544..a10f47ef8eb 100644
--- a/Marlin/src/lcd/language/language_ru.h
+++ b/Marlin/src/lcd/language/language_ru.h
@@ -139,7 +139,7 @@ namespace Language_ru {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Индекс X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Индекс Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Значение Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Свои команды");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Свои команды");
 
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 тест Z-зонда");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Отклонение");
diff --git a/Marlin/src/lcd/language/language_sk.h b/Marlin/src/lcd/language/language_sk.h
index a9df28382e8..2e851842e4e 100644
--- a/Marlin/src/lcd/language/language_sk.h
+++ b/Marlin/src/lcd/language/language_sk.h
@@ -140,7 +140,7 @@ namespace Language_sk {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Index X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Index Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Hodnota Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Vlastné príkazy");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Vlastné príkazy");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Test sondy");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Bod");
   PROGMEM Language_Str MSG_M48_OUT_OF_BOUNDS               = _UxGT("Sonda mimo hraníc");
diff --git a/Marlin/src/lcd/language/language_tr.h b/Marlin/src/lcd/language/language_tr.h
index a7a4056c0b2..9d711ff3765 100644
--- a/Marlin/src/lcd/language/language_tr.h
+++ b/Marlin/src/lcd/language/language_tr.h
@@ -114,7 +114,7 @@ namespace Language_tr {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("İndeks X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("İndeks Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Z Değeri");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Özel Komutlar");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Özel Komutlar");
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 Prob Testi");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 Nokta");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("Sapma");
diff --git a/Marlin/src/lcd/language/language_uk.h b/Marlin/src/lcd/language/language_uk.h
index 069ad7066df..be0e420a42f 100644
--- a/Marlin/src/lcd/language/language_uk.h
+++ b/Marlin/src/lcd/language/language_uk.h
@@ -151,7 +151,7 @@ namespace Language_uk {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Індекс X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Індекс Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Значення Z");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Власні команди");
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Власні команди");
 
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 тест зонду");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 точка");
diff --git a/Marlin/src/lcd/language/language_vi.h b/Marlin/src/lcd/language/language_vi.h
index fad32507cee..f0b7f732ed8 100644
--- a/Marlin/src/lcd/language/language_vi.h
+++ b/Marlin/src/lcd/language/language_vi.h
@@ -96,7 +96,7 @@ namespace Language_vi {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("Mục lục X");                            // Index X
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("Mục lục Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Giá trị Z");                            // Z Value
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("Các lệnh tự chọn");                     // Custom Commands
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("Các lệnh tự chọn");                     // Custom Commands
   PROGMEM Language_Str MSG_UBL_DOING_G29                   = _UxGT("Đang chạy G29");                        // Doing G29
   PROGMEM Language_Str MSG_UBL_TOOLS                       = _UxGT("Công cụ UBL");                          // UBL tools
   PROGMEM Language_Str MSG_UBL_LEVEL_BED                   = _UxGT("San Lấp Bàn Thống Nhất (UBL)");         // Unified Bed Leveling
diff --git a/Marlin/src/lcd/language/language_zh_CN.h b/Marlin/src/lcd/language/language_zh_CN.h
index 5e7c5e7cb5e..98f7704efc7 100644
--- a/Marlin/src/lcd/language/language_zh_CN.h
+++ b/Marlin/src/lcd/language/language_zh_CN.h
@@ -109,7 +109,7 @@ namespace Language_zh_CN {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("索引X");
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("索引Y");
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Z 值");
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("定制命令");     // "Custom Commands"
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("定制命令");     // "Custom Commands"
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48探测");
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48点");
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("M48偏差");
diff --git a/Marlin/src/lcd/language/language_zh_TW.h b/Marlin/src/lcd/language/language_zh_TW.h
index f86b15351fd..0ada34a4769 100644
--- a/Marlin/src/lcd/language/language_zh_TW.h
+++ b/Marlin/src/lcd/language/language_zh_TW.h
@@ -107,7 +107,7 @@ namespace Language_zh_TW {
   PROGMEM Language_Str MSG_MESH_X                          = _UxGT("索引 X");    //"Index X"
   PROGMEM Language_Str MSG_MESH_Y                          = _UxGT("索引 Y");    //"Index Y"
   PROGMEM Language_Str MSG_MESH_EDIT_Z                     = _UxGT("Z 值");    //"Z Value"
-  PROGMEM Language_Str MSG_USER_MENU                       = _UxGT("自定命令");     // "Custom Commands"
+  PROGMEM Language_Str MSG_CUSTOM_COMMANDS                 = _UxGT("自定命令");     // "Custom Commands"
   PROGMEM Language_Str MSG_M48_TEST                        = _UxGT("M48 探測測試");   //"M48 Probe Test"
   PROGMEM Language_Str MSG_M48_POINT                       = _UxGT("M48 探測點");    //"M48 Point"
   PROGMEM Language_Str MSG_M48_DEVIATION                   = _UxGT("偏差");    //"Deviation"
diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp
index 179a2c2d558..71f09a5aee2 100644
--- a/Marlin/src/lcd/menu/menu_configuration.cpp
+++ b/Marlin/src/lcd/menu/menu_configuration.cpp
@@ -338,6 +338,148 @@ void menu_advanced_settings();
 
 #endif
 
+#if ENABLED(CUSTOM_MENU_CONFIG)
+
+  void _lcd_custom_menus_configuration_gcode(PGM_P const cmd) {
+    queue.inject_P(cmd);
+    TERN_(CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK, ui.completion_feedback());
+    TERN_(CUSTOM_MENU_CONFIG_SCRIPT_RETURN, ui.return_to_status());
+  }
+
+  void custom_menus_configuration() {
+    START_MENU();
+    BACK_ITEM(MSG_MAIN);
+
+    #define HAS_CUSTOM_ITEM_CONF(N) (defined(CONFIG_MENU_ITEM_##N##_DESC) && defined(CONFIG_MENU_ITEM_##N##_GCODE))
+
+    #define CUSTOM_TEST_CONF(N) do{ \
+      constexpr char c = CONFIG_MENU_ITEM_##N##_GCODE[strlen(CONFIG_MENU_ITEM_##N##_GCODE) - 1]; \
+      static_assert(c != '\n' && c != '\r', "CONFIG_MENU_ITEM_" STRINGIFY(N) "_GCODE cannot have a newline at the end. Please remove it."); \
+    }while(0)
+
+    #ifdef CUSTOM_MENU_CONFIG_SCRIPT_DONE
+      #define _DONE_SCRIPT "\n" CUSTOM_MENU_CONFIG_SCRIPT_DONE
+    #else
+      #define _DONE_SCRIPT ""
+    #endif
+    #define GCODE_LAMBDA_CONF(N) []{ _lcd_custom_menus_configuration_gcode(PSTR(CONFIG_MENU_ITEM_##N##_GCODE _DONE_SCRIPT)); }
+    #define _CUSTOM_ITEM_CONF(N) ACTION_ITEM_P(PSTR(CONFIG_MENU_ITEM_##N##_DESC), GCODE_LAMBDA_CONF(N));
+    #define _CUSTOM_ITEM_CONF_CONFIRM(N)             \
+      SUBMENU_P(PSTR(CONFIG_MENU_ITEM_##N##_DESC), []{ \
+          MenuItem_confirm::confirm_screen(          \
+            GCODE_LAMBDA_CONF(N),                    \
+            ui.goto_previous_screen,                 \
+            PSTR(CONFIG_MENU_ITEM_##N##_DESC "?")      \
+          );                                         \
+        })
+
+    #define CUSTOM_ITEM_CONF(N) do{ if (ENABLED(CONFIG_MENU_ITEM_##N##_CONFIRM)) _CUSTOM_ITEM_CONF_CONFIRM(N); else _CUSTOM_ITEM_CONF(N); }while(0)
+
+    #if HAS_CUSTOM_ITEM_CONF(1)
+      CUSTOM_TEST_CONF(1);
+      CUSTOM_ITEM_CONF(1);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(2)
+      CUSTOM_TEST_CONF(2);
+      CUSTOM_ITEM_CONF(2);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(3)
+      CUSTOM_TEST_CONF(3);
+      CUSTOM_ITEM_CONF(3);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(4)
+      CUSTOM_TEST_CONF(4);
+      CUSTOM_ITEM_CONF(4);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(5)
+      CUSTOM_TEST_CONF(5);
+      CUSTOM_ITEM_CONF(5);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(6)
+      CUSTOM_TEST_CONF(6);
+      CUSTOM_ITEM_CONF(6);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(7)
+      CUSTOM_TEST_CONF(7);
+      CUSTOM_ITEM_CONF(7);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(8)
+      CUSTOM_TEST_CONF(8);
+      CUSTOM_ITEM_CONF(8);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(9)
+      CUSTOM_TEST_CONF(9);
+      CUSTOM_ITEM_CONF(9);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(10)
+      CUSTOM_TEST_CONF(10);
+      CUSTOM_ITEM_CONF(10);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(11)
+      CUSTOM_TEST_CONF(11);
+      CUSTOM_ITEM_CONF(11);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(12)
+      CUSTOM_TEST_CONF(12);
+      CUSTOM_ITEM_CONF(12);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(13)
+      CUSTOM_TEST_CONF(13);
+      CUSTOM_ITEM_CONF(13);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(14)
+      CUSTOM_TEST_CONF(14);
+      CUSTOM_ITEM_CONF(14);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(15)
+      CUSTOM_TEST_CONF(15);
+      CUSTOM_ITEM_CONF(15);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(16)
+      CUSTOM_TEST_CONF(16);
+      CUSTOM_ITEM_CONF(16);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(17)
+      CUSTOM_TEST_CONF(17);
+      CUSTOM_ITEM_CONF(17);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(18)
+      CUSTOM_TEST_CONF(18);
+      CUSTOM_ITEM_CONF(18);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(19)
+      CUSTOM_TEST_CONF(19);
+      CUSTOM_ITEM_CONF(19);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(20)
+      CUSTOM_TEST_CONF(20);
+      CUSTOM_ITEM_CONF(20);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(21)
+      CUSTOM_TEST_CONF(21);
+      CUSTOM_ITEM_CONF(21);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(22)
+      CUSTOM_TEST_CONF(22);
+      CUSTOM_ITEM_CONF(22);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(23)
+      CUSTOM_TEST_CONF(23);
+      CUSTOM_ITEM_CONF(23);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(24)
+      CUSTOM_TEST_CONF(24);
+      CUSTOM_ITEM_CONF(24);
+    #endif
+    #if HAS_CUSTOM_ITEM_CONF(25)
+      CUSTOM_TEST_CONF(25);
+      CUSTOM_ITEM_CONF(25);
+    #endif
+    END_MENU();
+  }
+
+#endif // CUSTOM_MENU_CONFIG
+
 void menu_configuration() {
   const bool busy = printer_busy();
 
@@ -351,6 +493,16 @@ void menu_configuration() {
     SUBMENU(MSG_DEBUG_MENU, menu_debug);
   #endif
 
+  #if ENABLED(CUSTOM_MENU_CONFIG)
+    if (TERN1(CUSTOM_MENU_CONFIG_ONLY_IDLE, !busy)) {
+      #ifdef CUSTOM_MENU_CONFIG_TITLE
+        SUBMENU_P(PSTR(CUSTOM_MENU_CONFIG_TITLE), custom_menus_configuration);
+      #else
+        SUBMENU(MSG_CUSTOM_COMMANDS, custom_menus_configuration);
+      #endif
+    }
+  #endif
+
   SUBMENU(MSG_ADVANCED_SETTINGS, menu_advanced_settings);
 
   #if ENABLED(BABYSTEP_ZPROBE_OFFSET)
diff --git a/Marlin/src/lcd/menu/menu_custom.cpp b/Marlin/src/lcd/menu/menu_custom.cpp
deleted file mode 100644
index cc1a8a6e80e..00000000000
--- a/Marlin/src/lcd/menu/menu_custom.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-//
-// Custom User Menu
-//
-
-#include "../../inc/MarlinConfigPre.h"
-
-#if BOTH(HAS_LCD_MENU, CUSTOM_USER_MENUS)
-
-#include "menu_item.h"
-#include "../../gcode/queue.h"
-
-#ifdef USER_SCRIPT_DONE
-  #define _DONE_SCRIPT "\n" USER_SCRIPT_DONE
-#else
-  #define _DONE_SCRIPT ""
-#endif
-
-void _lcd_user_gcode(PGM_P const cmd) {
-  queue.inject_P(cmd);
-  TERN_(USER_SCRIPT_AUDIBLE_FEEDBACK, ui.completion_feedback());
-  TERN_(USER_SCRIPT_RETURN, ui.return_to_status());
-}
-
-void menu_user() {
-  START_MENU();
-  BACK_ITEM(MSG_MAIN);
-
-  #define GCODE_LAMBDA(N) []{ _lcd_user_gcode(PSTR(USER_GCODE_##N _DONE_SCRIPT)); }
-  #define _USER_ITEM(N) ACTION_ITEM_P(PSTR(USER_DESC_##N), GCODE_LAMBDA(N));
-  #define _USER_ITEM_CONFIRM(N)           \
-    SUBMENU_P(PSTR(USER_DESC_##N), []{    \
-        MenuItem_confirm::confirm_screen( \
-          GCODE_LAMBDA(N),                \
-          ui.goto_previous_screen,        \
-          PSTR(USER_DESC_##N "?")         \
-        );                                \
-      })
-
-  #define USER_ITEM(N) do{ if (ENABLED(USER_CONFIRM_##N)) _USER_ITEM_CONFIRM(N); else _USER_ITEM(N); }while(0)
-
-  #if HAS_USER_ITEM(1)
-    USER_ITEM(1);
-  #endif
-  #if HAS_USER_ITEM(2)
-    USER_ITEM(2);
-  #endif
-  #if HAS_USER_ITEM(3)
-    USER_ITEM(3);
-  #endif
-  #if HAS_USER_ITEM(4)
-    USER_ITEM(4);
-  #endif
-  #if HAS_USER_ITEM(5)
-    USER_ITEM(5);
-  #endif
-  #if HAS_USER_ITEM(6)
-    USER_ITEM(6);
-  #endif
-  #if HAS_USER_ITEM(7)
-    USER_ITEM(7);
-  #endif
-  #if HAS_USER_ITEM(8)
-    USER_ITEM(8);
-  #endif
-  #if HAS_USER_ITEM(9)
-    USER_ITEM(9);
-  #endif
-  #if HAS_USER_ITEM(10)
-    USER_ITEM(10);
-  #endif
-  #if HAS_USER_ITEM(11)
-    USER_ITEM(11);
-  #endif
-  #if HAS_USER_ITEM(12)
-    USER_ITEM(12);
-  #endif
-  #if HAS_USER_ITEM(13)
-    USER_ITEM(13);
-  #endif
-  #if HAS_USER_ITEM(14)
-    USER_ITEM(14);
-  #endif
-  #if HAS_USER_ITEM(15)
-    USER_ITEM(15);
-  #endif
-  #if HAS_USER_ITEM(16)
-    USER_ITEM(16);
-  #endif
-  #if HAS_USER_ITEM(17)
-    USER_ITEM(17);
-  #endif
-  #if HAS_USER_ITEM(18)
-    USER_ITEM(18);
-  #endif
-  #if HAS_USER_ITEM(19)
-    USER_ITEM(19);
-  #endif
-  #if HAS_USER_ITEM(20)
-    USER_ITEM(20);
-  #endif
-  #if HAS_USER_ITEM(21)
-    USER_ITEM(21);
-  #endif
-  #if HAS_USER_ITEM(22)
-    USER_ITEM(22);
-  #endif
-  #if HAS_USER_ITEM(23)
-    USER_ITEM(23);
-  #endif
-  #if HAS_USER_ITEM(24)
-    USER_ITEM(24);
-  #endif
-  #if HAS_USER_ITEM(25)
-    USER_ITEM(25);
-  #endif
-  END_MENU();
-}
-
-#endif // HAS_LCD_MENU && CUSTOM_USER_MENUS
diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp
index d19e236a843..525b8c8a704 100644
--- a/Marlin/src/lcd/menu/menu_main.cpp
+++ b/Marlin/src/lcd/menu/menu_main.cpp
@@ -68,10 +68,6 @@ void menu_motion();
 void menu_temperature();
 void menu_configuration();
 
-#if ENABLED(CUSTOM_USER_MENUS)
-  void menu_user();
-#endif
-
 #if HAS_POWER_MONITOR
   void menu_power_monitor();
 #endif
@@ -105,6 +101,148 @@ void menu_configuration();
   void menu_language();
 #endif
 
+#if ENABLED(CUSTOM_MENU_MAIN)
+
+  void _lcd_custom_menu_main_gcode(PGM_P const cmd) {
+    queue.inject_P(cmd);
+    TERN_(MAIN_MENU_ITEM_SCRIPT_AUDIBLE_FEEDBACK, ui.completion_feedback());
+    TERN_(MAIN_MENU_ITEM_SCRIPT_RETURN, ui.return_to_status());
+  }
+
+  void custom_menus_main() {
+    START_MENU();
+    BACK_ITEM(MSG_MAIN);
+
+    #define HAS_CUSTOM_ITEM_MAIN(N) (defined(MAIN_MENU_ITEM_##N##_DESC) && defined(MAIN_MENU_ITEM_##N##_GCODE))
+
+    #define CUSTOM_TEST_MAIN(N) do{ \
+      constexpr char c = MAIN_MENU_ITEM_##N##_GCODE[strlen(MAIN_MENU_ITEM_##N##_GCODE) - 1]; \
+      static_assert(c != '\n' && c != '\r', "MAIN_MENU_ITEM_" STRINGIFY(N) "_GCODE cannot have a newline at the end. Please remove it."); \
+    }while(0)
+
+    #ifdef MAIN_MENU_ITEM_SCRIPT_DONE
+      #define _DONE_SCRIPT "\n" MAIN_MENU_ITEM_SCRIPT_DONE
+    #else
+      #define _DONE_SCRIPT ""
+    #endif
+    #define GCODE_LAMBDA_MAIN(N) []{ _lcd_custom_menu_main_gcode(PSTR(MAIN_MENU_ITEM_##N##_GCODE _DONE_SCRIPT)); }
+    #define _CUSTOM_ITEM_MAIN(N) ACTION_ITEM_P(PSTR(MAIN_MENU_ITEM_##N##_DESC), GCODE_LAMBDA_MAIN(N));
+    #define _CUSTOM_ITEM_MAIN_CONFIRM(N)             \
+      SUBMENU_P(PSTR(MAIN_MENU_ITEM_##N##_DESC), []{ \
+          MenuItem_confirm::confirm_screen(          \
+            GCODE_LAMBDA_MAIN(N),                    \
+            ui.goto_previous_screen,                 \
+            PSTR(MAIN_MENU_ITEM_##N##_DESC "?")      \
+          );                                         \
+        })
+
+    #define CUSTOM_ITEM_MAIN(N) do{ if (ENABLED(MAIN_MENU_ITEM_##N##_CONFIRM)) _CUSTOM_ITEM_MAIN_CONFIRM(N); else _CUSTOM_ITEM_MAIN(N); }while(0)
+
+    #if HAS_CUSTOM_ITEM_MAIN(1)
+      CUSTOM_TEST_MAIN(1);
+      CUSTOM_ITEM_MAIN(1);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(2)
+      CUSTOM_TEST_MAIN(2);
+      CUSTOM_ITEM_MAIN(2);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(3)
+      CUSTOM_TEST_MAIN(3);
+      CUSTOM_ITEM_MAIN(3);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(4)
+      CUSTOM_TEST_MAIN(4);
+      CUSTOM_ITEM_MAIN(4);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(5)
+      CUSTOM_TEST_MAIN(5);
+      CUSTOM_ITEM_MAIN(5);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(6)
+      CUSTOM_TEST_MAIN(6);
+      CUSTOM_ITEM_MAIN(6);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(7)
+      CUSTOM_TEST_MAIN(7);
+      CUSTOM_ITEM_MAIN(7);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(8)
+      CUSTOM_TEST_MAIN(8);
+      CUSTOM_ITEM_MAIN(8);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(9)
+      CUSTOM_TEST_MAIN(9);
+      CUSTOM_ITEM_MAIN(9);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(10)
+      CUSTOM_TEST_MAIN(10);
+      CUSTOM_ITEM_MAIN(10);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(11)
+      CUSTOM_TEST_MAIN(11);
+      CUSTOM_ITEM_MAIN(11);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(12)
+      CUSTOM_TEST_MAIN(12);
+      CUSTOM_ITEM_MAIN(12);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(13)
+      CUSTOM_TEST_MAIN(13);
+      CUSTOM_ITEM_MAIN(13);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(14)
+      CUSTOM_TEST_MAIN(14);
+      CUSTOM_ITEM_MAIN(14);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(15)
+      CUSTOM_TEST_MAIN(15);
+      CUSTOM_ITEM_MAIN(15);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(16)
+      CUSTOM_TEST_MAIN(16);
+      CUSTOM_ITEM_MAIN(16);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(17)
+      CUSTOM_TEST_MAIN(17);
+      CUSTOM_ITEM_MAIN(17);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(18)
+      CUSTOM_TEST_MAIN(18);
+      CUSTOM_ITEM_MAIN(18);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(19)
+      CUSTOM_TEST_MAIN(19);
+      CUSTOM_ITEM_MAIN(19);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(20)
+      CUSTOM_TEST_MAIN(20);
+      CUSTOM_ITEM_MAIN(20);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(21)
+      CUSTOM_TEST_MAIN(21);
+      CUSTOM_ITEM_MAIN(21);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(22)
+      CUSTOM_TEST_MAIN(22);
+      CUSTOM_ITEM_MAIN(22);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(23)
+      CUSTOM_TEST_MAIN(23);
+      CUSTOM_ITEM_MAIN(23);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(24)
+      CUSTOM_TEST_MAIN(24);
+      CUSTOM_ITEM_MAIN(24);
+    #endif
+    #if HAS_CUSTOM_ITEM_MAIN(25)
+      CUSTOM_TEST_MAIN(25);
+      CUSTOM_ITEM_MAIN(25);
+    #endif
+    END_MENU();
+  }
+
+#endif // CUSTOM_MENU_MAIN
+
 void menu_main() {
   const bool busy = printingIsActive()
     #if ENABLED(SDSUPPORT)
@@ -210,12 +348,12 @@ void menu_main() {
 
   SUBMENU(MSG_CONFIGURATION, menu_configuration);
 
-  #if ENABLED(CUSTOM_USER_MENUS)
-    if (TERN1(CUSTOM_MENU_ONLY_IDLE, !busy)) {
-      #ifdef CUSTOM_USER_MENU_TITLE
-        SUBMENU_P(PSTR(CUSTOM_USER_MENU_TITLE), menu_user);
+  #if ENABLED(CUSTOM_MENU_MAIN)
+    if (TERN1(CUSTOM_MENU_MAIN_ONLY_IDLE, !busy)) {
+      #ifdef CUSTOM_MENU_MAIN_TITLE
+        SUBMENU_P(PSTR(CUSTOM_MENU_MAIN_TITLE), custom_menus_main);
       #else
-        SUBMENU(MSG_USER_MENU, menu_user);
+        SUBMENU(MSG_CUSTOM_COMMANDS, custom_menus_main);
       #endif
     }
   #endif
diff --git a/buildroot/share/PlatformIO/scripts/common-dependencies.h b/buildroot/share/PlatformIO/scripts/common-dependencies.h
index 03fae56fdba..9ab437dd0b1 100644
--- a/buildroot/share/PlatformIO/scripts/common-dependencies.h
+++ b/buildroot/share/PlatformIO/scripts/common-dependencies.h
@@ -67,9 +67,6 @@
   #if ENABLED(CANCEL_OBJECTS)
     #define HAS_MENU_CANCELOBJECT
   #endif
-  #if ENABLED(CUSTOM_USER_MENUS)
-    #define HAS_MENU_CUSTOM
-  #endif
   #if EITHER(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION)
     #define HAS_MENU_DELTA_CALIBRATE
   #endif
diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560
index e3209899ce9..4498492ba5f 100755
--- a/buildroot/tests/mega2560
+++ b/buildroot/tests/mega2560
@@ -21,7 +21,7 @@ opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO LCD_LANGUAGE fr \
 opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT SKEW_CORRECTION \
            REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER LIGHTWEIGHT_UI STATUS_MESSAGE_SCROLLING SHOW_CUSTOM_BOOTSCREEN BOOT_MARLIN_LOGO_SMALL \
            SDSUPPORT SDCARD_SORT_ALPHA USB_FLASH_DRIVE_SUPPORT AUTO_REPORT_SD_STATUS SCROLL_LONG_FILENAMES CANCEL_OBJECTS SOUND_MENU_ITEM \
-           EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_USER_MENUS \
+           EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_MENU_MAIN \
            MULTI_NOZZLE_DUPLICATION CLASSIC_JERK LIN_ADVANCE EXTRA_LIN_ADVANCE_K QUICK_HOME \
            LCD_SET_PROGRESS_MANUALLY PRINT_PROGRESS_SHOW_DECIMALS SHOW_REMAINING_TIME \
            BABYSTEPPING BABYSTEP_XY NANODLP_Z_SYNC I2C_POSITION_ENCODERS M114_DETAIL
@@ -37,7 +37,7 @@ opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER LIGHTWEIGHT_UI SHOW_CUS
            LCD_SET_PROGRESS_MANUALLY PRINT_PROGRESS_SHOW_DECIMALS SHOW_REMAINING_TIME STATUS_MESSAGE_SCROLLING SCROLL_LONG_FILENAMES \
            SDSUPPORT SDCARD_SORT_ALPHA NO_SD_AUTOSTART USB_FLASH_DRIVE_SUPPORT CANCEL_OBJECTS \
            Z_PROBE_SLED AUTO_BED_LEVELING_UBL UBL_HILBERT_CURVE RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT \
-           EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_USER_MENUS \
+           EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_MENU_MAIN \
            MULTI_NOZZLE_DUPLICATION CLASSIC_JERK LIN_ADVANCE QUICK_HOME \
            NANODLP_Z_SYNC I2C_POSITION_ENCODERS M114_DETAIL \
            SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \