XEmacs 21.2.18 "Toshima".
[chise/xemacs-chise.git.1] / src / event-Xt.c
index 5052edd..fcc8a92 100644 (file)
@@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include "blocktype.h"
 #include "buffer.h"
-#include "commands.h"
 #include "console.h"
 #include "console-tty.h"
 #include "events.h"
@@ -79,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;
 
@@ -181,7 +181,7 @@ x_reset_key_mapping (struct device *d)
   Display *display = DEVICE_X_DISPLAY (d);
   struct x_device *xd = DEVICE_X_DATA (d);
   KeySym *keysym, *keysym_end;
-  Lisp_Object hashtable;
+  Lisp_Object hash_table;
   int key_code_count, keysyms_per_code;
 
   if (xd->x_keysym_map)
@@ -194,12 +194,12 @@ x_reset_key_mapping (struct device *d)
     XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count,
                         &xd->x_keysym_map_keysyms_per_code);
 
-  hashtable = xd->x_keysym_map_hashtable;
-  if (HASHTABLEP (hashtable))
-    Fclrhash (hashtable);
+  hash_table = xd->x_keysym_map_hash_table;
+  if (HASH_TABLEP (hash_table))
+    Fclrhash (hash_table);
   else
-    xd->x_keysym_map_hashtable = hashtable =
-      make_lisp_hashtable (128, HASHTABLE_NONWEAK, HASHTABLE_EQUAL);
+    xd->x_keysym_map_hash_table = hash_table =
+      make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
 
   for (keysym = xd->x_keysym_map,
         keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
@@ -217,8 +217,8 @@ x_reset_key_mapping (struct device *d)
        Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[0], 0);
        if (name)
          {
-           Fputhash (build_string (name), Qsans_modifiers, hashtable);
-           Fputhash (sym, Qsans_modifiers, hashtable);
+           Fputhash (build_string (name), Qsans_modifiers, hash_table);
+           Fputhash (sym, Qsans_modifiers, hash_table);
          }
       }
 
@@ -229,10 +229,10 @@ x_reset_key_mapping (struct device *d)
            {
              char *name = XKeysymToString (keysym[j]);
              Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[j], 0);
-             if (name && NILP (Fgethash (sym, hashtable, Qnil)))
+             if (name && NILP (Fgethash (sym, hash_table, Qnil)))
                {
-                 Fputhash (build_string (name), Qt, hashtable);
-                 Fputhash (sym, Qt, hashtable);
+                 Fputhash (build_string (name), Qt, hash_table);
+                 Fputhash (sym, Qt, hash_table);
                }
            }
        }
@@ -450,7 +450,7 @@ void
 x_init_modifier_mapping (struct device *d)
 {
   struct x_device *xd = DEVICE_X_DATA (d);
-  xd->x_keysym_map_hashtable = Qnil;
+  xd->x_keysym_map_hash_table = Qnil;
   xd->x_keysym_map = NULL;
   xd->x_modifier_keymap = NULL;
   x_reset_modifier_mapping (d);
@@ -772,7 +772,7 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
      /* simple_p means don't try too hard (ASCII only) */
 {
   KeySym keysym = 0;
-  
+
 #ifdef HAVE_XIM
   int len;
   char buffer[64];
@@ -808,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
@@ -1047,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);
@@ -1059,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;
@@ -1136,7 +1142,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
            emacs_event->timestamp  = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
 
            state=DndDragButtons(x_event);
-           
+
            if (state & ShiftMask)      modifiers |= MOD_SHIFT;
            if (state & ControlMask)    modifiers |= MOD_CONTROL;
            if (state & xd->MetaMask)   modifiers |= MOD_META;
@@ -1183,7 +1189,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                l_type = Qdragdrop_MIME;
                l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
                                            make_string ((Bufbyte *)"8bit", 4),
-                                           make_ext_string ((Extbyte *)data, 
+                                           make_ext_string ((Extbyte *)data,
                                                             strlen((char *)data),
                                                             FORMAT_CTEXT) ) );
                break;
@@ -1205,7 +1211,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
              case DndLink:
              case DndExe:
                {
-                 char *hurl = dnd_url_hexify_string (data, "file:");
+                 char *hurl = dnd_url_hexify_string ((char *) data, "file:");
 
                  l_dndlist = list1 ( make_string ((Bufbyte *)hurl,
                                                   strlen (hurl)) );
@@ -1217,7 +1223,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
              case DndURL:
                /* as it is a real URL it should already be escaped
                   and escaping again will break them (cause % is unsave) */
-               l_dndlist = list1 ( make_ext_string ((Extbyte *)data, 
+               l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
                                                     strlen ((char *)data),
                                                     FORMAT_FILENAME) );
                l_type = Qdragdrop_URL;
@@ -1305,8 +1311,12 @@ 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)
 {
-#ifdef HAVE_XIM
-  XIM_focus_event (f, in_p);
+#if XtSpecificationRelease > 5
+  Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
+#endif
+#if defined(HAVE_XIM) && defined(XIM_XLIB)
+  if (FRAME_X_XIC(f))
+    XIM_focus_event (f, in_p);
 #endif /* HAVE_XIM */
 
   /* On focus change, clear all memory of sticky modifiers
@@ -1320,7 +1330,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 keybpard 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 glick 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;
@@ -1405,7 +1434,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.
@@ -1580,6 +1609,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
@@ -1595,7 +1625,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
       handle_client_message (f, event);
       break;
 
-    case VisibilityNotify: /* window visiblity has changed */
+    case VisibilityNotify: /* window visibility has changed */
       if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f)))
        {
          FRAME_X_TOTALLY_VISIBLE_P (f) =
@@ -1614,8 +1644,9 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
       break;
 
     case ConfigureNotify:
-#ifdef HAVE_XIM
-      XIM_SetGeometry (f);
+#if defined(HAVE_XIM) && defined(XIM_XLIB)
+      if (FRAME_X_XIC(f))
+       XIM_SetGeometry (f);
 #endif
       break;
 
@@ -1694,7 +1725,7 @@ emacs_Xt_remove_timeout (int id)
   struct Xt_timeout *timeout, *t2;
 
   timeout = NULL;
-  
+
   /* Find the timeout on the list of pending ones, if it's still there. */
   if (pending_timeouts)
     {
@@ -1757,6 +1788,8 @@ Xt_timeout_to_emacs_event (struct Lisp_Event *emacs_event)
   /* timeout events have nil as channel */
   emacs_event->timestamp  = 0; /* #### wrong!! */
   emacs_event->event.timeout.interval_id = timeout->id;
+  emacs_event->event.timeout.function = Qnil;
+  emacs_event->event.timeout.object = Qnil;
   Blocktype_free (the_Xt_timeout_blocktype, timeout);
 }
 
@@ -2897,18 +2930,18 @@ vars_of_event_Xt (void)
   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;
-  Xt_event_stream->handle_magic_event_cb= emacs_Xt_handle_magic_event;
-  Xt_event_stream->add_timeout_cb      = emacs_Xt_add_timeout;
-  Xt_event_stream->remove_timeout_cb   = emacs_Xt_remove_timeout;
-  Xt_event_stream->select_console_cb   = emacs_Xt_select_console;
-  Xt_event_stream->unselect_console_cb         = emacs_Xt_unselect_console;
-  Xt_event_stream->select_process_cb   = emacs_Xt_select_process;
-  Xt_event_stream->unselect_process_cb         = emacs_Xt_unselect_process;
-  Xt_event_stream->quit_p_cb           = emacs_Xt_quit_p;
-  Xt_event_stream->create_stream_pair_cb= emacs_Xt_create_stream_pair;
-  Xt_event_stream->delete_stream_pair_cb= emacs_Xt_delete_stream_pair;
+  Xt_event_stream->event_pending_p      = emacs_Xt_event_pending_p;
+  Xt_event_stream->next_event_cb        = emacs_Xt_next_event;
+  Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
+  Xt_event_stream->add_timeout_cb       = emacs_Xt_add_timeout;
+  Xt_event_stream->remove_timeout_cb    = emacs_Xt_remove_timeout;
+  Xt_event_stream->select_console_cb    = emacs_Xt_select_console;
+  Xt_event_stream->unselect_console_cb          = emacs_Xt_unselect_console;
+  Xt_event_stream->select_process_cb    = emacs_Xt_select_process;
+  Xt_event_stream->unselect_process_cb          = emacs_Xt_unselect_process;
+  Xt_event_stream->quit_p_cb            = emacs_Xt_quit_p;
+  Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
+  Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
 
   DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
 *Non-nil makes modifier keys sticky.