diff src/event-Xt.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
line wrap: on
line diff
--- a/src/event-Xt.c	Mon Aug 13 11:33:40 2007 +0200
+++ b/src/event-Xt.c	Mon Aug 13 11:35:02 2007 +0200
@@ -65,19 +65,8 @@
 #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,10 +86,8 @@
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
-int modifier_keys_are_sticky;
-
 #ifdef DEBUG_XEMACS
-int x_debug_events;
+int debug_x_events;
 #endif
 
 static int process_events_occurred;
@@ -109,7 +96,7 @@
 /* Mask of bits indicating the descriptors that we wait for input on */
 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
 
-static CONST String x_fallback_resources[] =
+static const String x_fallback_resources[] =
 {
   /* This file is automatically generated from the app-defaults file
      in ../etc/Emacs.ad.  These resources are consulted only if no
@@ -336,11 +323,17 @@
 
   if (keysym < 0x80) /* Optimize for ASCII keysyms */
     return;
-  /* If you do:  xmodmap -e 'keysym NN = scaron'
+
+  /* If you execute:
+     xmodmap -e 'keysym NN = scaron'
      and then press (Shift scaron), X11 will return the different
-     keysym Scaron, but  xmodmap -pke  might not even mention Scaron.
-     So we `register' both scaron and Scaron. */
+     keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
+     So we "register" both `scaron' and `Scaron'. */
+#ifdef HAVE_XCONVERTCASE
   XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
+#else
+  upper_lower[0] = upper_lower[1] = keysym;
+#endif
 
   for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
     {
@@ -415,7 +408,7 @@
     }
 }
 
-static CONST char *
+static const char *
 index_to_name (int indice)
 {
   switch (indice)
@@ -570,7 +563,7 @@
      be totally wrong. */
   if (mode_bit)
     {
-      CONST char *warn = 0;
+      const char *warn = 0;
       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
@@ -951,7 +944,11 @@
 
 #ifdef HAVE_XIM
   int len;
-  char buffer[64];
+  /* Some implementations of XmbLookupString don't return
+     XBufferOverflow correctly, so increase the size of the xim input
+     buffer from 64 to the more reasonable size 513, as Emacs has done.
+     From Kenichi Handa. */
+  char buffer[513];
   char *bufptr = buffer;
   int   bufsiz = sizeof (buffer);
   Status status;
@@ -989,7 +986,7 @@
 #endif /* HAVE_XIM */
 
 #ifdef DEBUG_XEMACS
-  if (x_debug_events > 0)
+  if (debug_x_events > 0)
     {
       stderr_out ("   status=");
 #define print_status_when(S) if (status == S) stderr_out (#S)
@@ -1118,7 +1115,7 @@
     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 =
@@ -1145,11 +1142,30 @@
 
 	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;
+	{
+	  int numero_de_botao = -1;
+
+	  if (!key_event_p)
+	    numero_de_botao = x_event->xbutton.button;
+
+	  /* the button gets noted either in the button or the modifiers
+	     field, but not both. */
+	  if (numero_de_botao != 1 && (*state & Button1Mask))
+	    modifiers |= XEMACS_MOD_BUTTON1;
+	  if (numero_de_botao != 2 && (*state & Button2Mask))
+	    modifiers |= XEMACS_MOD_BUTTON2;
+	  if (numero_de_botao != 3 && (*state & Button3Mask))
+	    modifiers |= XEMACS_MOD_BUTTON3;
+	  if (numero_de_botao != 4 && (*state & Button4Mask))
+	    modifiers |= XEMACS_MOD_BUTTON4;
+	  if (numero_de_botao != 5 && (*state & Button5Mask))
+	    modifiers |= XEMACS_MOD_BUTTON5;
+	}
 
 	/* Ignore the Caps_Lock key if:
 	   - any other modifiers are down, so that Caps_Lock doesn't
@@ -1162,7 +1178,7 @@
 	lock_p  = *state & LockMask;
 
 	if (shift_p || lock_p)
-	  modifiers |= MOD_SHIFT;
+	  modifiers |= XEMACS_MOD_SHIFT;
 
 	if (key_event_p)
 	  {
@@ -1194,7 +1210,7 @@
 		! (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
@@ -1206,13 +1222,13 @@
 	       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;
@@ -1249,7 +1265,7 @@
       {
         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)
@@ -1278,12 +1294,17 @@
         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;
+        if (ev->state & Button1Mask)	modifiers |= XEMACS_MOD_BUTTON1;
+        if (ev->state & Button2Mask)	modifiers |= XEMACS_MOD_BUTTON2;
+        if (ev->state & Button3Mask)	modifiers |= XEMACS_MOD_BUTTON3;
+        if (ev->state & Button4Mask)	modifiers |= XEMACS_MOD_BUTTON4;
+        if (ev->state & Button5Mask)	modifiers |= XEMACS_MOD_BUTTON5;
         /* Currently ignores Shift_Lock but probably shouldn't
            (but it definitely should ignore Caps_Lock). */
         emacs_event->event.motion.modifiers = modifiers;
@@ -1299,7 +1320,9 @@
 #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;
@@ -1318,12 +1341,17 @@
 
 	    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 & Button1Mask)	modifiers |= XEMACS_MOD_BUTTON1;
+	    if (state & Button2Mask)	modifiers |= XEMACS_MOD_BUTTON2;
+	    if (state & Button3Mask)	modifiers |= XEMACS_MOD_BUTTON3;
+	    if (state & Button4Mask)	modifiers |= XEMACS_MOD_BUTTON4;
+	    if (state & Button5Mask)	modifiers |= XEMACS_MOD_BUTTON5;
 
 	    if (state & Button5Mask)    button = Button5;
 	    if (state & Button4Mask)    button = Button4;
@@ -1457,6 +1485,7 @@
 	  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;
@@ -1492,7 +1521,6 @@
 #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)));
@@ -1512,7 +1540,7 @@
      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
+     a widget-glyph but you don't get a corresponding FocusIn when you
      click in the frame. Why is this?  */
   if (in_p
 #if XtSpecificationRelease > 5
@@ -1716,6 +1744,25 @@
 }
 
 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 */
@@ -1828,6 +1875,9 @@
 #endif
       break;
 
+    case CreateNotify:
+      break;
+
     default:
       break;
     }
@@ -2289,12 +2339,12 @@
       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");
 }
 
-static CONST char *
+static const char *
 XEvent_mode_to_string (int mode)
 {
   switch (mode)
@@ -2307,7 +2357,7 @@
   }
 }
 
-static CONST char *
+static const char *
 XEvent_detail_to_string (int detail)
 {
   switch (detail)
@@ -2323,7 +2373,7 @@
   }
 }
 
-static CONST char *
+static const char *
 XEvent_visibility_to_string (int state)
 {
   switch (state)
@@ -2385,7 +2435,7 @@
     break;
 
     case Expose:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
 	{
 	  XExposeEvent *ev = &event->xexpose;
 	  describe_event_window (ev->window, ev->display);
@@ -2398,7 +2448,7 @@
       break;
 
     case GraphicsExpose:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
 	{
 	  XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
 	  describe_event_window (ev->drawable, ev->display);
@@ -2415,7 +2465,7 @@
 
     case EnterNotify:
     case LeaveNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
 	{
 	  XCrossingEvent *ev = &event->xcrossing;
 	  describe_event_window (ev->window, ev->display);
@@ -2436,7 +2486,7 @@
       break;
 
     case ConfigureNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
 	{
 	  XConfigureEvent *ev = &event->xconfigure;
 	  describe_event_window (ev->window, ev->display);
@@ -2450,7 +2500,7 @@
       break;
 
     case VisibilityNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
 	{
 	  XVisibilityEvent *ev = &event->xvisibility;
 	  describe_event_window (ev->window, ev->display);
@@ -2492,7 +2542,7 @@
 
 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);
@@ -2613,7 +2663,7 @@
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
 
 #ifdef DEBUG_XEMACS
-  if (x_debug_events > 0)
+  if (debug_x_events > 0)
     {
       describe_event (event);
     }
@@ -2897,6 +2947,21 @@
   return 0;
 }
 
+static int
+emacs_Xt_current_event_timestamp (struct console *c)
+{
+  /* semi-yuck. */
+  Lisp_Object devs = CONSOLE_DEVICE_LIST (c);
+
+  if (NILP (devs))
+    return 0;
+  else
+    {
+      struct device *d = XDEVICE (XCAR (devs));
+      return DEVICE_X_LAST_SERVER_TIMESTAMP (d);
+    }
+}
+
 
 /************************************************************************/
 /*            replacement for standard string-to-pixel converter        */
@@ -2994,9 +3059,9 @@
   if ((d = get_device_from_display_1(dpy))) {
     visual = DEVICE_X_VISUAL(d);
     if (colormap != DEVICE_X_COLORMAP(d)) {
-      XtAppWarningMsg(the_app_con, "wierdColormap", "cvtStringToPixel",
+      XtAppWarningMsg(the_app_con, "weirdColormap", "cvtStringToPixel",
 		      "XtToolkitWarning",
-		      "The colormap passed to cvtStringToPixel doesn't match the one registerd to the device.\n",
+		      "The colormap passed to cvtStringToPixel doesn't match the one registered to the device.\n",
 		      NULL, 0);
       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
     } else {
@@ -3058,6 +3123,42 @@
 
 
 /************************************************************************/
+/*            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);
+}
+
+
+/************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
 
@@ -3074,6 +3175,7 @@
 {
   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;
@@ -3085,6 +3187,8 @@
   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->current_event_timestamp_cb =
+    emacs_Xt_current_event_timestamp;
 
   the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
 
@@ -3104,15 +3208,6 @@
   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.
@@ -3120,14 +3215,14 @@
   x_allow_sendevents = 0;
 
 #ifdef DEBUG_XEMACS
-  DEFVAR_INT ("x-debug-events", &x_debug_events /*
+  DEFVAR_INT ("debug-x-events", &debug_x_events /*
 If non-zero, display debug information about X events that XEmacs sees.
 Information is displayed on stderr.  Currently defined values are:
 
 1 == non-verbose output
 2 == verbose output
 */ );
-  x_debug_events = 0;
+  debug_x_events = 0;
 #endif
 }
 
@@ -3170,12 +3265,12 @@
   Xt_app_con = XtCreateApplicationContext ();
   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
 
-  /* In xselect.c */
+  /* In select-x.c */
   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_IO_error_handler);
 
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
 		 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
 		 Xt_what_callback, 0);
@@ -3192,6 +3287,8 @@
 			 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;