XEmacs 21.2.20 "Yoko".
[chise/xemacs-chise.git-] / src / event-Xt.c
index b729cfa..3417197 100644 (file)
@@ -78,6 +78,7 @@ Boston, MA 02111-1307, USA.  */
 #include "events-mod.h"
 
 static void enqueue_Xt_dispatch_event (Lisp_Object event);
+static void handle_focus_event_1 (struct frame *f, int in_p);
 
 static struct event_stream *Xt_event_stream;
 
@@ -807,7 +808,8 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
                            event, bufptr, bufsiz, &keysym, &status);
 #else /* XIM_XLIB */
-  len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
+  if (xic)
+    len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
 #endif /* HAVE_XIM */
 
 #ifdef DEBUG_XEMACS
@@ -1046,6 +1048,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
          {
            XButtonEvent *ev = &x_event->xbutton;
            struct frame *frame = x_window_to_frame (d, ev->window);
+
            if (! frame)
              return 0; /* not for us */
            XSETFRAME (emacs_event->channel, frame);
@@ -1058,7 +1061,11 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
            emacs_event->event.button.button    = ev->button;
            emacs_event->event.button.x         = ev->x;
            emacs_event->event.button.y         = ev->y;
-
+           /* because we don't seem to get a FocusIn event for button clicks
+              when a widget-glyph is selected we will assume that we want the
+              focus if a button gets pressed. */
+           if (x_event->type == ButtonPress)
+             handle_focus_event_1 (frame, 1);
          }
       }
     break;
@@ -1304,6 +1311,9 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
+#if XtSpecificationRelease > 5
+  Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
+#endif
 #ifdef HAVE_XIM
   XIM_focus_event (f, in_p);
 #endif /* HAVE_XIM */
@@ -1319,7 +1329,26 @@ handle_focus_event_1 (struct frame *f, int in_p)
      Actually, we half handle it: we handle it as far as changing the
      box cursor for redisplay, but we don't call any hooks or do any
      select-frame stuff until after the sit-for.
-   */
+
+     Unfortunately native widgets break the model because they grab
+     the keyboard focus and nothing sets it back again. I cannot find
+     any reasonable way to do this elsewhere so we assert here that
+     the keyboard focus is on the emacs text widget. Menus and dialogs
+     do this in their selection callback, but we don't want that since
+     a button having focus is legitimate. An edit field having focus
+     is mandatory. Weirdly you get a FocusOut event when you click in
+     a widget-glyph but you don't get a correspondng FocusIn when you
+     click in the frame. Why is this?  */
+  if (in_p 
+#if XtSpecificationRelease > 5      
+      && FRAME_X_TEXT_WIDGET (f) != focus_widget
+#endif
+      )
+    {
+      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
+                            FRAME_X_TEXT_WIDGET (f));
+    }
+  /* do the generic event-stream stuff. */
   {
     Lisp_Object frm;
     Lisp_Object conser;
@@ -1404,7 +1433,7 @@ handle_map_event (struct frame *f, XEvent *event)
 
       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
         send synthetic MapNotify events when a window is first
-        created, EVENT IF IT'S CREATED ICONIFIED OR INVISIBLE.
+        created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
         Or something like that.  We initially tried a different
         solution below, but that ran into a different window-
         manager bug.
@@ -1540,8 +1569,13 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
       break;
 
     case Expose:
-      x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
-                            event->xexpose.width, event->xexpose.height);
+      if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
+                                    event->xexpose.width, event->xexpose.height)
+         &&
+         !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
+         event->xexpose.width, event->xexpose.height))
+       x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
+                              event->xexpose.width, event->xexpose.height);
       break;
 
     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
@@ -1579,6 +1613,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
 
     case FocusIn:
     case FocusOut:
+
 #ifdef EXTERNAL_WIDGET
       /* External widget lossage: Ben said:
         YUCK.  The only way to make focus changes work properly is to
@@ -1633,14 +1668,14 @@ static int timeout_id_tick;
 /* Xt interval id's might not fit into an int (they're pointers, as it
    happens), so we need to provide a conversion list. */
 
-struct Xt_timeout
+static struct Xt_timeout
 {
   int id;
   XtIntervalId interval_id;
   struct Xt_timeout *next;
 } *pending_timeouts, *completed_timeouts;
 
-struct Xt_timeout_blocktype
+static struct Xt_timeout_blocktype
 {
   Blocktype_declare (struct Xt_timeout);
 } *the_Xt_timeout_blocktype;
@@ -2888,15 +2923,8 @@ syms_of_event_Xt (void)
 }
 
 void
-vars_of_event_Xt (void)
+reinit_vars_of_event_Xt (void)
 {
-  dispatch_event_queue = Qnil;
-  staticpro (&dispatch_event_queue);
-  dispatch_event_queue_tail = Qnil;
-
-  /* this function only makes safe calls */
-  init_what_input_once ();
-
   Xt_event_stream = xnew (struct event_stream);
   Xt_event_stream->event_pending_p      = emacs_Xt_event_pending_p;
   Xt_event_stream->next_event_cb        = emacs_Xt_next_event;
@@ -2911,6 +2939,24 @@ vars_of_event_Xt (void)
   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
 
+  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
+
+  last_quit_check_signal_tick_count = 0;
+
+  /* this function only makes safe calls */
+  init_what_input_once ();
+}
+
+void
+vars_of_event_Xt (void)
+{
+  reinit_vars_of_event_Xt ();
+
+  dispatch_event_queue = Qnil;
+  staticpro (&dispatch_event_queue);
+  dispatch_event_queue_tail = Qnil;
+  pdump_wire (&dispatch_event_queue_tail);
+
   DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
 *Non-nil makes modifier keys sticky.
 This means that you can release the modifier key before pressing down
@@ -2936,10 +2982,6 @@ Information is displayed on stderr.  Currently defined values are:
 */ );
   x_debug_events = 0;
 #endif
-
-  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
-
-  last_quit_check_signal_tick_count = 0;
 }
 
 /* This mess is a hack that patches the shell widget to treat visual inheritance