emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master e8b0808e20 1/5: Fix hangs when clicking on Haiku menu bar to acti


From: Po Lu
Subject: master e8b0808e20 1/5: Fix hangs when clicking on Haiku menu bar to activate frame
Date: Sun, 17 Apr 2022 04:14:30 -0400 (EDT)

branch: master
commit e8b0808e20797f84fb2a720e38f315bfab39bde4
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix hangs when clicking on Haiku menu bar to activate frame
    
    * src/haiku_io.c (haiku_len): Handle new event `MENU_BAR_CLICK'.
    * src/haiku_support.cc (class EmacsWindow): Remove most of the
    menu bar cv stuff.
    (MessageReceived): Handle REPLAY_MENU_BAR message.
    (EmacsWindow_signal_menu_update_complete): Delete function.
    (be_replay_menu_bar_event): New function.
    
    * src/haiku_support.h (enum haiku_event_type): New event type
    `MENU_BAR_CLICK'.
    (struct haiku_menu_bar_click_event): New struct.
    
    * src/haikumenu.c (haiku_activate_menubar): New function.
    * src/haikuterm.c (haiku_read_socket): Save a
    MENU_BAR_ACTIVATE_EVENT and the menu bar click event instead of
    handling the menu bar update synchronously.
    (haiku_create_terminal): Set `activate_menubar_hook'.
    (syms_of_haikuterm): Remove extraneous newline.
    
    * src/haikuterm.h (struct haiku_output): New field
    `saved_menu_event'.
---
 src/haiku_io.c       |  2 ++
 src/haiku_support.cc | 78 +++++++++++++++++++++++++---------------------------
 src/haiku_support.h  | 10 ++++++-
 src/haikumenu.c      | 33 ++++++++++++++++++++++
 src/haikuterm.c      | 28 +++++++++++--------
 src/haikuterm.h      |  4 +++
 6 files changed, 103 insertions(+), 52 deletions(-)

diff --git a/src/haiku_io.c b/src/haiku_io.c
index 89f0877eb6..1830ac01e5 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -79,6 +79,8 @@ haiku_len (enum haiku_event_type type)
       return sizeof (struct haiku_wheel_move_event);
     case MENU_BAR_RESIZE:
       return sizeof (struct haiku_menu_bar_resize_event);
+    case MENU_BAR_CLICK:
+      return sizeof (struct haiku_menu_bar_click_event);
     case MENU_BAR_OPEN:
     case MENU_BAR_CLOSE:
       return sizeof (struct haiku_menu_bar_state_event);
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index e7c157dac8..673ae02ac9 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -91,6 +91,7 @@ enum
     SHOW_MENU_BAR      = 3004,
     BE_MENU_BAR_OPEN   = 3005,
     QUIT_APPLICATION   = 3006,
+    REPLAY_MENU_BAR    = 3007,
   };
 
 /* X11 keysyms that we use.  */
@@ -496,9 +497,6 @@ public:
   window_look pre_override_redirect_look;
   window_feel pre_override_redirect_feel;
   uint32 pre_override_redirect_workspaces;
-  pthread_mutex_t menu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
-  pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER;
-  bool menu_updated_p = false;
   int window_id;
   bool *menus_begun = NULL;
 
@@ -530,9 +528,6 @@ public:
     if (this->parent)
       UnparentAndUnlink ();
     child_frame_lock.Unlock ();
-
-    pthread_cond_destroy (&menu_update_cv);
-    pthread_mutex_destroy (&menu_update_mutex);
   }
 
   BRect
@@ -977,34 +972,13 @@ public:
   }
 
   void
-  MenusBeginning ()
+  MenusBeginning (void)
   {
     struct haiku_menu_bar_state_event rq;
-    int lock_count;
 
     rq.window = this;
-    lock_count = 0;
-
     if (!menus_begun)
-      {
-       haiku_write (MENU_BAR_OPEN, &rq);
-       while (IsLocked ())
-         {
-           ++lock_count;
-           UnlockLooper ();
-         }
-       pthread_mutex_lock (&menu_update_mutex);
-       while (!menu_updated_p)
-         pthread_cond_wait (&menu_update_cv,
-                            &menu_update_mutex);
-       menu_updated_p = false;
-       pthread_mutex_unlock (&menu_update_mutex);
-       for (; lock_count; --lock_count)
-         {
-           if (!LockLooper ())
-             gui_abort ("Failed to lock after cv signal denoting menu update");
-         }
-      }
+      haiku_write (MENU_BAR_OPEN, &rq);
     else
       *menus_begun = true;
 
@@ -1278,6 +1252,8 @@ public:
 
 class EmacsMenuBar : public BMenuBar
 {
+  bool tracking_p;
+
 public:
   EmacsMenuBar () : BMenuBar (BRect (0, 0, 0, 0), NULL)
   {
@@ -1303,6 +1279,22 @@ public:
     BMenuBar::FrameResized (newWidth, newHeight);
   }
 
+  void
+  MouseDown (BPoint point)
+  {
+    struct haiku_menu_bar_click_event rq;
+    EmacsWindow *ew = (EmacsWindow *) Window ();
+
+    rq.window = ew;
+    rq.x = std::lrint (point.x);
+    rq.y = std::lrint (point.y);
+
+    if (!ew->menu_bar_active_p)
+      haiku_write (MENU_BAR_CLICK, &rq);
+    else
+      BMenuBar::MouseDown (point);
+  }
+
   void
   MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
   {
@@ -1351,6 +1343,11 @@ public:
        else
          msg->SendReply (BE_MENU_BAR_OPEN);
       }
+    else if (msg->what == REPLAY_MENU_BAR)
+      {
+       if (msg->FindPoint ("emacs:point", &pt) == B_OK)
+         BMenuBar::MouseDown (pt);
+      }
     else
       BMenuBar::MessageReceived (msg);
   }
@@ -4147,17 +4144,6 @@ be_find_setting (const char *name)
   return value;
 }
 
-void
-EmacsWindow_signal_menu_update_complete (void *window)
-{
-  EmacsWindow *w = (EmacsWindow *) window;
-
-  pthread_mutex_lock (&w->menu_update_mutex);
-  w->menu_updated_p = true;
-  pthread_cond_signal (&w->menu_update_cv);
-  pthread_mutex_unlock (&w->menu_update_mutex);
-}
-
 void
 BMessage_delete (void *message)
 {
@@ -4274,3 +4260,15 @@ be_drag_and_drop_in_progress (void)
 {
   return drag_and_drop_in_progress;
 }
+
+void
+be_replay_menu_bar_event (void *menu_bar,
+                         struct haiku_menu_bar_click_event *event)
+{
+  BMenuBar *m = (BMenuBar *) menu_bar;
+  BMessenger messenger (m);
+  BMessage msg (REPLAY_MENU_BAR);
+
+  msg.AddPoint ("emacs:point", BPoint (event->x, event->y));
+  messenger.SendMessage (&msg);
+}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 9935906f0e..6b285cf3e0 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -80,6 +80,7 @@ enum haiku_event_type
     SCROLL_BAR_DRAG_EVENT,
     WHEEL_MOVE_EVENT,
     MENU_BAR_RESIZE,
+    MENU_BAR_CLICK,
     MENU_BAR_OPEN,
     MENU_BAR_SELECT_EVENT,
     MENU_BAR_CLOSE,
@@ -168,6 +169,12 @@ struct haiku_menu_bar_left_event
   int x, y;
 };
 
+struct haiku_menu_bar_click_event
+{
+  void *window;
+  int x, y;
+};
+
 struct haiku_button_event
 {
   void *window;
@@ -577,7 +584,6 @@ extern void EmacsWindow_unparent (void *);
 extern void EmacsWindow_move_weak_child (void *, void *, int, int);
 extern void EmacsWindow_make_fullscreen (void *, int);
 extern void EmacsWindow_unzoom (void *);
-extern void EmacsWindow_signal_menu_update_complete (void *);
 
 extern void be_get_version_string (char *, int);
 extern int be_get_display_planes (void);
@@ -630,6 +636,8 @@ extern bool be_drag_message (void *, void *, bool, void (*) 
(void),
                             bool (*) (void));
 extern bool be_drag_and_drop_in_progress (void);
 
+extern void be_replay_menu_bar_event (void *, struct 
haiku_menu_bar_click_event *);
+
 #ifdef __cplusplus
 extern void *find_appropriate_view_for_draw (void *);
 }
diff --git a/src/haikumenu.c b/src/haikumenu.c
index 22e9c4ecad..8aced5f9d4 100644
--- a/src/haikumenu.c
+++ b/src/haikumenu.c
@@ -774,6 +774,39 @@ the position of the last non-menu event instead.  */)
   return Qnil;
 }
 
+void
+haiku_activate_menubar (struct frame *f)
+{
+  int rc;
+
+  if (!FRAME_HAIKU_MENU_BAR (f))
+    return;
+
+  set_frame_menubar (f, true);
+
+  if (FRAME_OUTPUT_DATA (f)->saved_menu_event)
+    {
+      block_input ();
+      be_replay_menu_bar_event (FRAME_HAIKU_MENU_BAR (f),
+                               FRAME_OUTPUT_DATA (f)->saved_menu_event);
+      xfree (FRAME_OUTPUT_DATA (f)->saved_menu_event);
+      FRAME_OUTPUT_DATA (f)->saved_menu_event = NULL;
+      unblock_input ();
+    }
+  else
+    {
+      block_input ();
+      rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
+      unblock_input ();
+
+      if (!rc)
+       return;
+
+      FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
+      popup_activated_p += 1;
+    }
+}
+
 void
 syms_of_haikumenu (void)
 {
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 559ec58926..45d22ce22f 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3475,34 +3475,40 @@ haiku_read_socket (struct terminal *terminal, struct 
input_event *hold_quit)
              }
            break;
          }
+       case MENU_BAR_CLICK:
+         {
+           struct haiku_menu_bar_click_event *b = buf;
+           struct frame *f = haiku_window_to_frame (b->window);
+
+           if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
+             continue;
+
+           if (!FRAME_OUTPUT_DATA (f)->saved_menu_event)
+             FRAME_OUTPUT_DATA (f)->saved_menu_event = xmalloc (sizeof *b);
+           *FRAME_OUTPUT_DATA (f)->saved_menu_event = *b;
+           inev.kind = MENU_BAR_ACTIVATE_EVENT;
+           XSETFRAME (inev.frame_or_window, f);
+           break;
+         }
        case MENU_BAR_OPEN:
        case MENU_BAR_CLOSE:
          {
            struct haiku_menu_bar_state_event *b = buf;
            struct frame *f = haiku_window_to_frame (b->window);
-           int was_waiting_for_input_p;
 
            if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
              continue;
 
            if (type == MENU_BAR_OPEN)
              {
-               was_waiting_for_input_p = waiting_for_input;
-               if (waiting_for_input)
-                 waiting_for_input = 0;
-
-               set_frame_menubar (f, 1);
-               waiting_for_input = was_waiting_for_input_p;
-
                FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
                popup_activated_p += 1;
-
-               EmacsWindow_signal_menu_update_complete (b->window);
              }
            else
              {
                if (!popup_activated_p)
                  emacs_abort ();
+
                if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
                  {
                    FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
@@ -3873,6 +3879,7 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo)
   terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
   terminal->fullscreen_hook = haiku_fullscreen;
   terminal->toolkit_position_hook = haiku_toolkit_position;
+  terminal->activate_menubar_hook = haiku_activate_menubar;
 
   return terminal;
 }
@@ -4184,7 +4191,6 @@ This is either one of the symbols `shift', `control', 
`command', and
 Setting it to any other value is equivalent to `shift'.  */);
   Vhaiku_shift_keysym = Qnil;
 
-
   DEFSYM (Qx_use_underline_position_properties,
          "x-use-underline-position-properties");
 
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 7022ea77de..e922743b18 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -176,6 +176,9 @@ struct haiku_output
 
   /* The default cursor foreground color.  */
   uint32_t cursor_fg;
+
+  /* If non-NULL, the last menu bar click event received.  */
+  struct haiku_menu_bar_click_event *saved_menu_event;
 };
 
 struct x_output
@@ -291,6 +294,7 @@ extern void haiku_put_pixel (haiku, int, int, unsigned 
long);
 extern Lisp_Object haiku_menu_show (struct frame *, int, int, int,
                                    Lisp_Object, const char **);
 extern Lisp_Object haiku_popup_dialog (struct frame *, Lisp_Object, 
Lisp_Object);
+extern void haiku_activate_menubar (struct frame *);
 extern void haiku_note_drag_motion (void);
 
 extern void initialize_frame_menubar (struct frame *);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]