(CHAR_TO_CHARC): New inline function.
[chise/xemacs-chise.git-] / src / event-Xt.c
index cb0115f..78b1c40 100644 (file)
@@ -65,19 +65,8 @@ Boston, MA 02111-1307, USA.  */
 #include "offix.h"
 #endif
 
-#ifdef WINDOWSNT
-/* Hmm, under unix we want X modifiers, under NT we want X modifiers if
-   we are running X and Windows modifiers otherwise.
-   gak. This is a kludge until we support multiple native GUIs!
-*/
-#undef MOD_ALT
-#undef MOD_CONTROL
-#undef MOD_SHIFT
-#endif
-
 #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;
@@ -97,8 +86,6 @@ XtAppContext Xt_app_con;
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
-int modifier_keys_are_sticky;
-
 #ifdef DEBUG_XEMACS
 int x_debug_events;
 #endif
@@ -1124,7 +1111,7 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
     case ButtonPress:
     case ButtonRelease:
       {
-       unsigned int modifiers = 0;
+       int modifiers = 0;
        int shift_p, lock_p;
        Bool key_event_p = (x_event->type == KeyPress);
        unsigned int *state =
@@ -1151,11 +1138,11 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
 
        x_handle_sticky_modifiers (x_event, d);
 
-       if (*state & ControlMask)    modifiers |= MOD_CONTROL;
-       if (*state & xd->MetaMask)   modifiers |= MOD_META;
-       if (*state & xd->SuperMask)  modifiers |= MOD_SUPER;
-       if (*state & xd->HyperMask)  modifiers |= MOD_HYPER;
-       if (*state & xd->AltMask)    modifiers |= MOD_ALT;
+       if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
+       if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
+       if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
+       if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
+       if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
 
        /* Ignore the Caps_Lock key if:
           - any other modifiers are down, so that Caps_Lock doesn't
@@ -1168,7 +1155,7 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
        lock_p  = *state & LockMask;
 
        if (shift_p || lock_p)
-         modifiers |= MOD_SHIFT;
+         modifiers |= XEMACS_MOD_SHIFT;
 
        if (key_event_p)
          {
@@ -1200,7 +1187,7 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
                ! (CHAR_OR_CHAR_INTP (keysym)
                   && keysym_obeys_caps_lock_p
                   ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
-             modifiers &= (~MOD_SHIFT);
+             modifiers &= (~XEMACS_MOD_SHIFT);
 
            /* If this key contains two distinct keysyms, that is,
               "shift" generates a different keysym than the
@@ -1212,13 +1199,13 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
               in the modifiers slot.  Neither the characters "a",
               "A", "2", nor "@" normally have the shift bit set.
               However, "F1" normally does. */
-           if (modifiers & MOD_SHIFT)
+           if (modifiers & XEMACS_MOD_SHIFT)
              {
                int Mode_switch_p = *state & xd->ModeMask;
                KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
                KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
                if (top && bot && top != bot)
-                 modifiers &= ~MOD_SHIFT;
+                 modifiers &= ~XEMACS_MOD_SHIFT;
              }
            emacs_event->event_type          = key_press_event;
            emacs_event->timestamp           = ev->time;
@@ -1255,7 +1242,7 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
       {
         XMotionEvent *ev = &x_event->xmotion;
         struct frame *frame = x_window_to_frame (d, ev->window);
-        unsigned int modifiers = 0;
+        int modifiers = 0;
         XMotionEvent event2;
 
         if (! frame)
@@ -1284,12 +1271,12 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
         emacs_event->timestamp      = ev->time;
         emacs_event->event.motion.x = ev->x;
         emacs_event->event.motion.y = ev->y;
-        if (ev->state & ShiftMask)     modifiers |= MOD_SHIFT;
-        if (ev->state & ControlMask)   modifiers |= MOD_CONTROL;
-        if (ev->state & xd->MetaMask)  modifiers |= MOD_META;
-        if (ev->state & xd->SuperMask) modifiers |= MOD_SUPER;
-        if (ev->state & xd->HyperMask) modifiers |= MOD_HYPER;
-        if (ev->state & xd->AltMask)   modifiers |= MOD_ALT;
+        if (ev->state & ShiftMask)     modifiers |= XEMACS_MOD_SHIFT;
+        if (ev->state & ControlMask)   modifiers |= XEMACS_MOD_CONTROL;
+        if (ev->state & xd->MetaMask)  modifiers |= XEMACS_MOD_META;
+        if (ev->state & xd->SuperMask) modifiers |= XEMACS_MOD_SUPER;
+        if (ev->state & xd->HyperMask) modifiers |= XEMACS_MOD_HYPER;
+        if (ev->state & xd->AltMask)   modifiers |= XEMACS_MOD_ALT;
         /* Currently ignores Shift_Lock but probably shouldn't
            (but it definitely should ignore Caps_Lock). */
         emacs_event->event.motion.modifiers = modifiers;
@@ -1305,7 +1292,9 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
 #ifdef HAVE_OFFIX_DND
        if (DndIsDropMessage(x_event))
          {
-           unsigned int state, modifiers = 0, button=0;
+           unsigned int state;
+           int modifiers = 0;
+           unsigned int button=0;
            struct frame *frame = x_any_window_to_frame (d, ev->window);
            Extbyte *data;
            unsigned long size, dtype;
@@ -1324,12 +1313,12 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
 
            state=DndDragButtons(x_event);
 
-           if (state & ShiftMask)      modifiers |= MOD_SHIFT;
-           if (state & ControlMask)    modifiers |= MOD_CONTROL;
-           if (state & xd->MetaMask)   modifiers |= MOD_META;
-           if (state & xd->SuperMask)  modifiers |= MOD_SUPER;
-           if (state & xd->HyperMask)  modifiers |= MOD_HYPER;
-           if (state & xd->AltMask)    modifiers |= MOD_ALT;
+           if (state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
+           if (state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
+           if (state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
+           if (state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
+           if (state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
+           if (state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
 
            if (state & Button5Mask)    button = Button5;
            if (state & Button4Mask)    button = Button4;
@@ -1463,6 +1452,7 @@ x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
          case FocusIn:
          case FocusOut:         FROB(xfocus, window);            break;
          case VisibilityNotify: FROB(xvisibility, window);       break;
+         case CreateNotify: FROB(xcreatewindow, window);         break;
           default:
            w = x_event->xany.window;
            *x_event_copy = *x_event;
@@ -1498,7 +1488,6 @@ handle_focus_event_1 (struct frame *f, int in_p)
 #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)));
@@ -1722,6 +1711,25 @@ handle_client_message (struct frame *f, XEvent *event)
 }
 
 static void
+emacs_Xt_force_event_pending (struct frame* f)
+{
+  XEvent event;
+
+  Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
+  event.xclient.type           = ClientMessage;
+  event.xclient.display                = dpy;
+  event.xclient.message_type   = XInternAtom (dpy, "BumpQueue", False);
+  event.xclient.format         = 32;
+  event.xclient.window         = 0;
+
+  /* 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++;
+}
+
+static void
 emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
 {
   /* This function can GC */
@@ -1834,6 +1842,9 @@ emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
 #endif
       break;
 
+    case CreateNotify:
+      break;
+
     default:
       break;
     }
@@ -2295,7 +2306,7 @@ describe_event_window (Window window, Display *display)
       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
-                                   strlen (buf), Qterminal);
+                                   strlen (buf), Qterminal, 1);
     }
   stderr_out ("\n");
 }
@@ -2498,7 +2509,7 @@ describe_event (XEvent *event)
 
 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
 
-static void
+void
 enqueue_Xt_dispatch_event (Lisp_Object event)
 {
   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
@@ -3064,6 +3075,42 @@ static void EmacsFreePixel (
 
 \f
 /************************************************************************/
+/*            handle focus changes for native widgets                  */
+/************************************************************************/
+static void
+emacs_Xt_event_widget_focus_in (Widget   w,
+                               XEvent   *event,
+                               String   *params,
+                               Cardinal *num_params)
+{
+  struct frame* f =
+    x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
+
+  XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
+}
+
+static void
+emacs_Xt_event_widget_focus_out (Widget   w,
+                                XEvent   *event,
+                                String   *params,
+                                Cardinal *num_params)
+{
+}
+
+static XtActionsRec widgetActionsList[] =
+{
+  {"widget-focus-in",  emacs_Xt_event_widget_focus_in  },
+  {"widget-focus-out", emacs_Xt_event_widget_focus_out },
+};
+
+static void
+emacs_Xt_event_add_widget_actions (XtAppContext ctx)
+{
+  XtAppAddActions (ctx, widgetActionsList, 2);
+}
+
+\f
+/************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
 
@@ -3080,6 +3127,7 @@ reinit_vars_of_event_Xt (void)
 {
   Xt_event_stream = xnew (struct event_stream);
   Xt_event_stream->event_pending_p      = emacs_Xt_event_pending_p;
+  Xt_event_stream->force_event_pending          = emacs_Xt_force_event_pending;
   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;
@@ -3110,15 +3158,6 @@ vars_of_event_Xt (void)
   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
-the key that you wish to be modified.  Although this is non-standard
-behavior, it is recommended because it reduces the strain on your hand,
-thus reducing the incidence of the dreaded Emacs-pinky syndrome.
-*/ );
-  modifier_keys_are_sticky = 0;
-
   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
 *Non-nil means to allow synthetic events.  Nil means they are ignored.
 Beware: allowing emacs to process SendEvents opens a big security hole.
@@ -3198,6 +3237,8 @@ init_event_Xt_late (void) /* called when already initialized */
                         NULL, 0,
                         XtCacheByDisplay, EmacsFreeXIMStyles);
 #endif /* XIM_XLIB */
+  /* Add extra actions to native widgets to handle focus and friends. */
+  emacs_Xt_event_add_widget_actions (Xt_app_con);
 
   /* insert the visual inheritance patch/hack described above */
   orig_shell_init_proc = shellClassRec.core_class.initialize;