JDevlieghere created this revision.
JDevlieghere added reviewers: clayborg, teemperor, labath.
JDevlieghere added a project: LLDB.

Add mouse support to the `IOHandlerCursesGUI` and make it possible to select 
items in the top menu bar by clicking on them. This patch only makes the top 
level items clickable and does not (yet) make it possible to click on items in 
the submenu.

This patch is mostly me being curious about the `IOHandlerCursesGUI` and trying 
to understand how it works.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D82522

Files:
  lldb/source/Core/IOHandlerCursesGUI.cpp


Index: lldb/source/Core/IOHandlerCursesGUI.cpp
===================================================================
--- lldb/source/Core/IOHandlerCursesGUI.cpp
+++ lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -830,6 +830,14 @@
     return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
   }
 
+  int GetTitleDrawWidth() const {
+    const int key_width = m_key_name.empty() ? 1 : m_key_name.size();
+    return m_name.size() + key_width + 2 /* padding */ + 1 /* space */ +
+           2 /* braces */;
+  }
+
+  int GetSubmenuForPosition(int x, int y);
+
   uint64_t GetIdentifier() const { return m_identifier; }
 
   void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
@@ -1010,12 +1018,31 @@
   return true; // Drawing handled...
 }
 
+int Menu::GetSubmenuForPosition(int x, int y) {
+  if (y != 0)
+    return INT32_MAX;
+
+  int begin = 0;
+  int end = 0;
+  int i = 0;
+  for (const MenuSP &menu : m_submenus) {
+    begin = end + 1 /* separator */;
+    end = begin + menu->GetTitleDrawWidth();
+    if (x >= begin && x < end)
+      return i;
+    ++i;
+  }
+
+  return INT32_MAX;
+}
+
 HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
   HandleCharResult result = eKeyNotHandled;
 
   Menus &submenus = GetSubmenus();
   const size_t num_submenus = submenus.size();
   const int selected_idx = GetSelectedSubmenuIndex();
+  MEVENT event;
   Menu::Type menu_type = GetType();
   if (menu_type == Menu::Type::Bar) {
     MenuSP run_menu_sp;
@@ -1052,6 +1079,19 @@
       result = eKeyHandled;
       break;
 
+    case KEY_MOUSE:
+      if (getmouse(&event) == OK) {
+        if (event.bstate & BUTTON1_PRESSED) {
+          int selected = GetSubmenuForPosition(event.x, event.y);
+          if (selected < static_cast<int>(num_submenus)) {
+            m_selected = selected;
+            run_menu_sp = submenus[m_selected];
+          }
+          result = eKeyHandled;
+        }
+      }
+      break;
+
     default:
       for (size_t i = 0; i < num_submenus; ++i) {
         if (submenus[i]->GetKeyValue() == key) {
@@ -1187,6 +1227,11 @@
                                             // of seconds seconds when calling
                                             // Window::GetChar()
 
+    // Enable mouse support.
+    keypad(stdscr, true);
+    mouseinterval(0);
+    mousemask(BUTTON1_PRESSED, NULL);
+
     ListenerSP listener_sp(
         Listener::MakeListener("lldb.IOHandler.curses.Application"));
     ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());


Index: lldb/source/Core/IOHandlerCursesGUI.cpp
===================================================================
--- lldb/source/Core/IOHandlerCursesGUI.cpp
+++ lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -830,6 +830,14 @@
     return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
   }
 
+  int GetTitleDrawWidth() const {
+    const int key_width = m_key_name.empty() ? 1 : m_key_name.size();
+    return m_name.size() + key_width + 2 /* padding */ + 1 /* space */ +
+           2 /* braces */;
+  }
+
+  int GetSubmenuForPosition(int x, int y);
+
   uint64_t GetIdentifier() const { return m_identifier; }
 
   void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
@@ -1010,12 +1018,31 @@
   return true; // Drawing handled...
 }
 
+int Menu::GetSubmenuForPosition(int x, int y) {
+  if (y != 0)
+    return INT32_MAX;
+
+  int begin = 0;
+  int end = 0;
+  int i = 0;
+  for (const MenuSP &menu : m_submenus) {
+    begin = end + 1 /* separator */;
+    end = begin + menu->GetTitleDrawWidth();
+    if (x >= begin && x < end)
+      return i;
+    ++i;
+  }
+
+  return INT32_MAX;
+}
+
 HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
   HandleCharResult result = eKeyNotHandled;
 
   Menus &submenus = GetSubmenus();
   const size_t num_submenus = submenus.size();
   const int selected_idx = GetSelectedSubmenuIndex();
+  MEVENT event;
   Menu::Type menu_type = GetType();
   if (menu_type == Menu::Type::Bar) {
     MenuSP run_menu_sp;
@@ -1052,6 +1079,19 @@
       result = eKeyHandled;
       break;
 
+    case KEY_MOUSE:
+      if (getmouse(&event) == OK) {
+        if (event.bstate & BUTTON1_PRESSED) {
+          int selected = GetSubmenuForPosition(event.x, event.y);
+          if (selected < static_cast<int>(num_submenus)) {
+            m_selected = selected;
+            run_menu_sp = submenus[m_selected];
+          }
+          result = eKeyHandled;
+        }
+      }
+      break;
+
     default:
       for (size_t i = 0; i < num_submenus; ++i) {
         if (submenus[i]->GetKeyValue() == key) {
@@ -1187,6 +1227,11 @@
                                             // of seconds seconds when calling
                                             // Window::GetChar()
 
+    // Enable mouse support.
+    keypad(stdscr, true);
+    mouseinterval(0);
+    mousemask(BUTTON1_PRESSED, NULL);
+
     ListenerSP listener_sp(
         Listener::MakeListener("lldb.IOHandler.curses.Application"));
     ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] ... Jonas Devlieghere via Phabricator via lldb-commits

Reply via email to