]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix hangs when clicking on Haiku menu bar to activate frame
authorPo Lu <luangruo@yahoo.com>
Sun, 17 Apr 2022 07:15:17 +0000 (07:15 +0000)
committerPo Lu <luangruo@yahoo.com>
Sun, 17 Apr 2022 08:14:05 +0000 (08:14 +0000)
* 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
src/haiku_support.cc
src/haiku_support.h
src/haikumenu.c
src/haikuterm.c
src/haikuterm.h

index 89f0877eb673253ec99aea01043c6c0ffc1f68b1..1830ac01e5551e37769b73d1267b14868b907ff7 100644 (file)
@@ -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);
index e7c157dac8401bbac446cf587dfbb3478b33acfd..673ae02ac9cff4e802e1683c809e129b30c2a27e 100644 (file)
@@ -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);
+}
index 9935906f0e3ada5ae720e66c1126716967814cf3..6b285cf3e0acef2ccab32142f492ce54655112d8 100644 (file)
@@ -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 *);
 }
index 22e9c4ecad3ad00115b787ec9c99aefd9b5b47e4..8aced5f9d4369411ed8f64735f8de02c623f205f 100644 (file)
@@ -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)
 {
index 559ec58926c50fc89ed64a8ece60fc8633d590b6..45d22ce22fb786750edff89890a4f8a0b1fb05d9 100644 (file)
@@ -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");
 
index 7022ea77dec0bd47782b9af14a5aaf68bbbd951e..e922743b18c8ff77ee70014efb448679b4277373 100644 (file)
@@ -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 *);