XEmacs 21.4.10 "Military Intelligence".
[chise/xemacs-chise.git.1] / src / event-Xt.c
index 4345bb1..eb7fd74 100644 (file)
@@ -67,7 +67,9 @@ Boston, MA 02111-1307, USA.  */
 
 #include "events-mod.h"
 
+void enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p);
 static void handle_focus_event_1 (struct frame *f, int in_p);
+static void handle_focus_event_2 (Window w, struct frame *f, int in_p);
 
 static struct event_stream *Xt_event_stream;
 
@@ -1538,6 +1540,16 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
+  handle_focus_event_2 (XtWindow (FRAME_X_TEXT_WIDGET (f)), f, in_p);
+}
+
+static void
+handle_focus_event_2 (Window win, struct frame *f, int in_p)
+{
+  /* Although this treats focus differently for all widgets (including
+     the frame) it seems to work ok. */
+  Widget needs_it = XtWindowToWidget (FRAME_X_DISPLAY (f), win);
+
 #if XtSpecificationRelease > 5
   widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
 #endif
@@ -1568,14 +1580,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) != widget_with_focus
+      && needs_it != widget_with_focus
 #endif
       )
     {
-      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
-                            FRAME_X_TEXT_WIDGET (f));
+      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), needs_it);
     }
 
+  /* If we are focusing on a native widget then record and exit. */
+  if (needs_it != FRAME_X_TEXT_WIDGET (f)) {
+    widget_with_focus = needs_it;
+    return;
+  }
+
   /* We have the focus now. See comment in
      emacs_Xt_handle_widget_losing_focus (). */
   if (in_p)
@@ -1597,9 +1614,26 @@ handle_focus_event_1 (struct frame *f, int in_p)
   }
 }
 
+/* Create a synthetic X focus event. */
+void
+enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p)
+{
+  Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
+  Lisp_Event *ev          = XEVENT (emacs_event);
+  XEvent *x_event = &ev->event.magic.underlying_x_event;
+
+  x_event->type = in_p ? FocusIn : FocusOut;
+  x_event->xfocus.window = XtWindow (wants_it);
+
+  ev->channel              = frame;
+  ev->event_type           = magic_event;
+
+  enqueue_Xt_dispatch_event (emacs_event);
+}
+
 /* 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
+   well just get deleted next and then 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
@@ -1926,7 +1960,7 @@ emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
       if (FRAME_X_EXTERNAL_WINDOW_P (f))
        break;
 #endif
-      handle_focus_event_1 (f, event->type == FocusIn);
+      handle_focus_event_2 (event->xfocus.window, f, event->type == FocusIn);
       break;
 
     case ClientMessage:
@@ -2905,8 +2939,47 @@ emacs_Xt_quit_p (void)
 static void
 drain_X_queue (void)
 {
+  Lisp_Object devcons, concons;
+  CONSOLE_LOOP (concons)
+  {
+    struct console *con = XCONSOLE (XCAR (concons));
+    if (!con->input_enabled)
+      continue;
+
+    /* sjt sez: Have you tried the loop over devices with XtAppPending(),
+       not XEventsQueued()?
+       Ben Sigelman sez: No.
+       sjt sez: I'm guessing that the reason that your patch "works" is this:
+
+       +      struct device* d;
+       +      Display* display;
+       +      d = XDEVICE (XCAR (devcons));
+       +      if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
+
+       Ie, if the device goes down, XEmacs detects that and deletes it.
+       Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and we don't go
+       into the Xlib-of-no-return.  If you know different, I'd like to hear
+       about it. ;-)
+
+       These ideas haven't been tested; the code below works for Ben.
+    */
+    CONSOLE_DEVICE_LOOP (devcons, con)
+    {
+      struct device* d;
+      Display* display;
+      d = XDEVICE (XCAR (devcons));
+      if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
+        display = DEVICE_X_DISPLAY (d);
+        while (XEventsQueued (display, QueuedAfterReading))
+          XtAppProcessEvent (Xt_app_con, XtIMXEvent);
+      }
+    }
+  }
+  /* This is the old code, before Ben Sigelman's patch. */
+  /*
   while (XtAppPending (Xt_app_con) & XtIMXEvent)
     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
+  */
 }
 
 static int