X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fevent-Xt.c;h=8c55b2b7002b90129325ab69af77369e65468d9b;hb=aa982acf01b4e35675a624d78c9e5ee109c1203e;hp=ddbb49dbd4b9dca4797a280e1e3c2eb37752d5cd;hpb=98a6e4055a1fa624c592ac06f79287d55196ca37;p=chise%2Fxemacs-chise.git diff --git a/src/event-Xt.c b/src/event-Xt.c index ddbb49d..8c55b2b 100644 --- a/src/event-Xt.c +++ b/src/event-Xt.c @@ -87,11 +87,12 @@ XtAppContext Xt_app_con; int x_allow_sendevents; #ifdef DEBUG_XEMACS -int debug_x_events; +Fixnum debug_x_events; #endif static int process_events_occurred; static int tty_events_occurred; +static Widget widget_with_focus; /* Mask of bits indicating the descriptors that we wait for input on */ extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask; @@ -1350,10 +1351,10 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event) Lisp_Object l_dndlist = Qnil, l_item = Qnil; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - GCPRO4 (l_type, l_data, l_dndlist, l_item); - if (! frame) return 0; /* not for us */ + + GCPRO4 (l_type, l_data, l_dndlist, l_item); XSETFRAME (emacs_event->channel, frame); emacs_event->event_type = misc_user_event; @@ -1536,11 +1537,12 @@ static void handle_focus_event_1 (struct frame *f, int in_p) { #if XtSpecificationRelease > 5 - Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f)); + widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f)); #endif #ifdef HAVE_XIM XIM_focus_event (f, in_p); #endif /* HAVE_XIM */ + /* On focus change, clear all memory of sticky modifiers to avoid non-intuitive behavior. */ clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f))); @@ -1564,13 +1566,19 @@ handle_focus_event_1 (struct frame *f, int in_p) click in the frame. Why is this? */ if (in_p #if XtSpecificationRelease > 5 - && FRAME_X_TEXT_WIDGET (f) != focus_widget + && FRAME_X_TEXT_WIDGET (f) != widget_with_focus #endif ) { lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), FRAME_X_TEXT_WIDGET (f)); } + + /* We have the focus now. See comment in + emacs_Xt_handle_widget_losing_focus (). */ + if (in_p) + widget_with_focus = NULL; + /* do the generic event-stream stuff. */ { Lisp_Object frm; @@ -1587,6 +1595,23 @@ handle_focus_event_1 (struct frame *f, int in_p) } } +/* The idea here is that when a widget glyph gets unmapped we don't + want the focus to stay with it if it has focus - because it may + well just get deleted next andthen we have lost the focus until the + user does something. So handle_focus_event_1 records the widget + with keyboard focus when FocusOut is processed, and then, when a + widget gets unmapped, it calls this function to restore focus if + appropriate. */ +void emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget); +void +emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget) +{ + if (losing_widget == widget_with_focus) + { + handle_focus_event_1 (f, 1); + } +} + /* This is called from the external-widget code */ void emacs_Xt_handle_focus_event (XEvent *event); @@ -1763,6 +1788,41 @@ handle_client_message (struct frame *f, XEvent *event) } } +/* #### I'm struggling to understand how the X event loop really works. + Here is the problem: + + When widgets get mapped / changed etc the actual display updates + are done asynchronously via X events being processed - this + normally happens when XtAppProcessEvent() gets called. However, if + we are executing lisp code or even doing redisplay we won't + necessarily process X events for a very long time. This has the + effect of widgets only getting updated when XEmacs only goes into + idle, or some other event causes processing of the X event queue. + + XtAppProcessEvent can get called from the following places: + + emacs_Xt_next_event () - this is normal event processing, almost + any non-X event will take precedence and this means that we + cannot rely on it to do the right thing at the right time for + widget display. + + drain_X_queue () - this happens when SIGIO gets tripped, + processing the event queue allows C-g to be checked for. It gets + called from emacs_Xt_event_pending_p (). + + In order to solve this I have tried introducing a list primitive - + dispatch-non-command-events - which forces processing of X events + related to display. Unfortunately this has a number of problems, + one is that it is possible for event_stream_event_pending_p to + block for ever if there isn't actually an event. I guess this can + happen if we drop the synthetic event for reason. It also relies on + SIGIO processing which makes things rather fragile. + + People have seen behaviour whereby XEmacs blocks until you move the + mouse. This seems to indicate that dispatch-non-command-events is + blocking. It may be that in a SIGIO world forcing SIGIO processing + does the wrong thing. +*/ static void emacs_Xt_force_event_pending (struct frame* f) { @@ -1778,8 +1838,8 @@ emacs_Xt_force_event_pending (struct frame* f) /* Send the drop message */ XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)), True, NoEventMask, &event); - /* Force event pending to check the X queue. */ - quit_check_signal_tick_count++; + /* We rely on SIGIO and friends to realise we have generated an + event. */ } static void @@ -2949,7 +3009,11 @@ emacs_Xt_event_pending_p (int user_p) /* quit_check_signal_tick_count is volatile so try to avoid race conditions by using a temporary variable */ tick_count_val = quit_check_signal_tick_count; - if (last_quit_check_signal_tick_count != tick_count_val) + if (last_quit_check_signal_tick_count != tick_count_val +#if !defined (SIGIO) || defined (CYGWIN) + || (XtIMXEvent & XtAppPending (Xt_app_con)) +#endif + ) { last_quit_check_signal_tick_count = tick_count_val; @@ -3226,7 +3290,7 @@ vars_of_event_Xt (void) dispatch_event_queue = Qnil; staticpro (&dispatch_event_queue); dispatch_event_queue_tail = Qnil; - pdump_wire (&dispatch_event_queue_tail); + dump_add_root_object (&dispatch_event_queue_tail); DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /* *Non-nil means to allow synthetic events. Nil means they are ignored.