From f8eb15727ae6a5c629e27ab9755e638766b27822 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 16 Sep 2013 11:27:51 +0400 Subject: [PATCH] Fix X event waiting to handle multiple frames. * frame.h (struct frame) [HAVE_X_WINDOWS]: New member wait_event_type. * xterm.c (pending_event_wait): Remove. Adjust users. (x_detect_focus_change): Pass frame arg. (handle_one_xevent): Find related frame early and clear per-frame wait_event_type only if this is an event for the relevant frame. (x_wait_for_event): Use per-frame wait_event_type. --- src/ChangeLog | 10 ++++++++ src/frame.h | 5 ++++ src/xterm.c | 67 +++++++++++++++++++++------------------------------ 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 0050d949dd2..10349aea412 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2013-09-16 Dmitry Antipov + + Fix X event waiting to handle multiple frames. + * frame.h (struct frame) [HAVE_X_WINDOWS]: New member wait_event_type. + * xterm.c (pending_event_wait): Remove. Adjust users. + (x_detect_focus_change): Pass frame arg. + (handle_one_xevent): Find related frame early and clear per-frame + wait_event_type only if this is an event for the relevant frame. + (x_wait_for_event): Use per-frame wait_event_type. + 2013-09-15 Jan Djärv * nsfns.m (Fx_create_frame): Fix font driver registration for diff --git a/src/frame.h b/src/frame.h index d8a6d380090..c5ad71628ab 100644 --- a/src/frame.h +++ b/src/frame.h @@ -328,6 +328,11 @@ struct frame unsigned int external_menu_bar : 1; #endif +#if defined (HAVE_X_WINDOWS) + /* Used by x_wait_for_event when watching for an X event on this frame. */ + int wait_event_type; +#endif + /* Next two bitfields are mutually exclusive. They might both be zero if the frame has been made invisible without an icon. */ diff --git a/src/xterm.c b/src/xterm.c index 4086d913c8a..ea75df11048 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -159,13 +159,6 @@ Lisp_Object x_display_name_list; static struct frame *pending_autoraise_frame; -/* This is a frame waiting for an event matching mask, within XTread_socket. */ - -static struct { - struct frame *f; - int eventtype; -} pending_event_wait; - #ifdef USE_X_TOOLKIT /* The application context for Xt use. */ XtAppContext Xt_app_con; @@ -293,8 +286,6 @@ static void frame_unhighlight (struct frame *); static void x_new_focus_frame (struct x_display_info *, struct frame *); static void x_focus_changed (int, int, struct x_display_info *, struct frame *, struct input_event *); -static void x_detect_focus_change (struct x_display_info *, - XEvent *, struct input_event *); static void XTframe_rehighlight (struct frame *); static void x_frame_rehighlight (struct x_display_info *); static void x_draw_hollow_cursor (struct window *, struct glyph_row *); @@ -3549,12 +3540,10 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc) Returns FOCUS_IN_EVENT event in *BUFP. */ static void -x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp) +x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, + XEvent *event, struct input_event *bufp) { - struct frame *frame; - - frame = x_any_window_to_frame (dpyinfo, event->xany.window); - if (! frame) + if (!frame) return; switch (event->type) @@ -5883,7 +5872,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, int count = 0; int do_help = 0; ptrdiff_t nbytes = 0; - struct frame *f = NULL; + struct frame *any, *f = NULL; struct coding_system coding; XEvent event = *eventptr; Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; @@ -5901,8 +5890,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (pending_event_wait.eventtype == event.type) - pending_event_wait.eventtype = 0; /* Indicates we got it. */ + any = x_any_window_to_frame (dpyinfo, event.xany.window); + + if (any && any->wait_event_type == event.type) + any->wait_event_type = 0; /* Indicates we got it. */ switch (event.type) { @@ -5915,10 +5906,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (event.xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus) { - /* Use x_any_window_to_frame because this - could be the shell widget window - if the frame has no title bar. */ - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + /* Use the value returned by x_any_window_to_frame + because this could be the shell widget window + if the frame has no title bar. */ + f = any; #ifdef HAVE_X_I18N /* Not quite sure this is needed -pd */ if (f && FRAME_XIC (f)) @@ -5995,8 +5986,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (event.xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window) { - f = x_any_window_to_frame (dpyinfo, - event.xclient.window); + f = any; if (!f) goto OTHER; /* May be a dialog that is to be removed */ @@ -6035,7 +6025,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (event.xclient.message_type == dpyinfo->Xatom_editres) { - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + f = any; if (f) _XEditResCheckMessages (f->output_data.x->widget, NULL, &event, NULL); @@ -6079,7 +6069,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, { enum xembed_message msg = event.xclient.data.l[1]; if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT) - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, &event, &inev.ie); *finish = X_EVENT_GOTO_OUT; goto done; @@ -6087,7 +6077,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, xft_settings_event (dpyinfo, &event); - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + f = any; if (!f) goto OTHER; if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie)) @@ -6349,7 +6339,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto OTHER; #endif - f = x_any_window_to_frame (dpyinfo, event.xkey.window); + f = any; #if ! defined (USE_GTK) /* If mouse-highlight is an integer, input clears out @@ -6683,9 +6673,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, case EnterNotify: dpyinfo->last_user_time = event.xcrossing.time; - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, &event, &inev.ie); - f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); + f = any; if (f && x_mouse_click_focus_ignore_position) ignore_next_mouse_click_timeout = event.xmotion.time + 200; @@ -6703,12 +6693,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto OTHER; case FocusIn: - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, &event, &inev.ie); goto OTHER; case LeaveNotify: dpyinfo->last_user_time = event.xcrossing.time; - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, &event, &inev.ie); f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); if (f) @@ -6736,7 +6726,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto OTHER; case FocusOut: - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, &event, &inev.ie); goto OTHER; case MotionNotify: @@ -6822,7 +6812,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, f = x_top_window_to_frame (dpyinfo, event.xconfigure.window); #ifdef USE_GTK if (!f - && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window)) + && (f = any) && event.xconfigure.window == FRAME_X_WINDOW (f)) { xg_frame_resized (f, event.xconfigure.width, @@ -8733,15 +8723,14 @@ x_wait_for_event (struct frame *f, int eventtype) struct timespec tmo, tmo_at, time_now; int fd = ConnectionNumber (FRAME_X_DISPLAY (f)); - pending_event_wait.f = f; - pending_event_wait.eventtype = eventtype; + f->wait_event_type = eventtype; /* Set timeout to 0.1 second. Hopefully not noticeable. Maybe it should be configurable. */ tmo = make_timespec (0, 100 * 1000 * 1000); tmo_at = timespec_add (current_timespec (), tmo); - while (pending_event_wait.eventtype) + while (f->wait_event_type) { pending_signals = 1; totally_unblock_input (); @@ -8760,8 +8749,8 @@ x_wait_for_event (struct frame *f, int eventtype) if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0) break; /* Timeout */ } - pending_event_wait.f = 0; - pending_event_wait.eventtype = 0; + + f->wait_event_type = 0; } @@ -10684,8 +10673,6 @@ x_initialize (void) #endif pending_autoraise_frame = 0; - pending_event_wait.f = 0; - pending_event_wait.eventtype = 0; /* Note that there is no real way portable across R3/R4 to get the original error handler. */ -- 2.39.2