1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-09 21:20:45 -08:00

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'.
This commit is contained in:
Po Lu 2022-04-17 07:15:17 +00:00
parent 3dc73569b4
commit e8b0808e20
6 changed files with 103 additions and 52 deletions

View 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);

View 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);
}

View 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 *);
}

View 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)
{

View 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");

View 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 *);