int x_allow_sendevents;
#ifdef DEBUG_XEMACS
-int x_debug_events;
+int debug_x_events;
#endif
static int process_events_occurred;
static int tty_events_occurred;
+static Widget widget_with_focus;
/* Mask of bits indicating the descriptors that we wait for input on */
extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
{ /* Not a modifier key */
Bool key_event_p = (type == KeyPress || type == KeyRelease);
- if (type == KeyPress && !xd->last_downkey)
- xd->last_downkey = keycode;
- else if (type == ButtonPress ||
- (type == KeyPress && xd->last_downkey &&
- (keycode != xd->last_downkey ||
- ev->xkey.time != xd->release_time)))
+ if (type == ButtonPress
+ || (type == KeyPress
+ && ((xd->last_downkey
+ && ((keycode != xd->last_downkey
+ || ev->xkey.time != xd->release_time)))
+ || (INTP (Vmodifier_keys_sticky_time)
+ && ev->xkey.time
+ > (xd->modifier_release_time
+ + XINT (Vmodifier_keys_sticky_time))))))
{
xd->need_to_add_mask = 0;
xd->last_downkey = 0;
}
+ else if (type == KeyPress && !xd->last_downkey)
+ xd->last_downkey = keycode;
+
if (type == KeyPress)
xd->release_time = 0;
if (type == KeyPress || type == ButtonPress)
- xd->down_mask = 0;
+ {
+ xd->down_mask = 0;
+ xd->modifier_release_time = 0;
+ }
if (key_event_p)
ev->xkey.state |= xd->need_to_add_mask;
So we assume that if the release and the next press
occur at the same time, the key was actually auto-
repeated. Under Open-Windows, at least, this works. */
- xd->release_time = key_event_p ? ev->xkey.time : ev->xbutton.time;
+ xd->modifier_release_time = xd->release_time
+ = key_event_p ? ev->xkey.time : ev->xbutton.time;
}
else /* Modifier key pressed */
{
xd->need_to_add_mask = 0;
}
+ if (xd->modifier_release_time
+ && INTP (Vmodifier_keys_sticky_time)
+ && (ev->xkey.time
+ > xd->modifier_release_time + XINT (Vmodifier_keys_sticky_time)))
+ {
+ xd->need_to_add_mask = 0;
+ xd->down_mask = 0;
+ }
+
#define FROB(mask) \
do { \
if (type == KeyPress) \
xd->need_to_add_mask |= mask; \
} \
} \
+ xd->modifier_release_time = ev->xkey.time; \
} while (0)
for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
#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;
#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)
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
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;
Lisp_Object l_dndlist = Qnil, l_item = Qnil;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- GCPRO4 (l_type, l_data, l_dndlist, l_item);
-
if (! frame)
return 0; /* not for us */
+
+ GCPRO4 (l_type, l_data, l_dndlist, l_item);
XSETFRAME (emacs_event->channel, frame);
emacs_event->event_type = misc_user_event;
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;
handle_focus_event_1 (struct frame *f, int in_p)
{
#if XtSpecificationRelease > 5
- Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
+ widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
#endif
#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)));
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
- && FRAME_X_TEXT_WIDGET (f) != focus_widget
+ && FRAME_X_TEXT_WIDGET (f) != widget_with_focus
#endif
)
{
lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
FRAME_X_TEXT_WIDGET (f));
}
+
+ /* We have the focus now. See comment in
+ emacs_Xt_handle_widget_losing_focus (). */
+ if (in_p)
+ widget_with_focus = NULL;
+
/* do the generic event-stream stuff. */
{
Lisp_Object frm;
}
}
+/* 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
+ 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
+ appropriate. */
+void emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget);
+void
+emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget)
+{
+ if (losing_widget == widget_with_focus)
+ {
+ handle_focus_event_1 (f, 1);
+ }
+}
+
/* This is called from the external-widget code */
void emacs_Xt_handle_focus_event (XEvent *event);
}
}
+/* #### I'm struggling to understand how the X event loop really works.
+ Here is the problem:
+
+ When widgets get mapped / changed etc the actual display updates
+ are done asynchronously via X events being processed - this
+ normally happens when XtAppProcessEvent() gets called. However, if
+ we are executing lisp code or even doing redisplay we won't
+ necessarily process X events for a very long time. This has the
+ effect of widgets only getting updated when XEmacs only goes into
+ idle, or some other event causes processing of the X event queue.
+
+ XtAppProcessEvent can get called from the following places:
+
+ emacs_Xt_next_event () - this is normal event processing, almost
+ any non-X event will take precedence and this means that we
+ cannot rely on it to do the right thing at the right time for
+ widget display.
+
+ drain_X_queue () - this happens when SIGIO gets tripped,
+ processing the event queue allows C-g to be checked for. It gets
+ called from emacs_Xt_event_pending_p ().
+
+ In order to solve this I have tried introducing a list primitive -
+ dispatch-non-command-events - which forces processing of X events
+ related to display. Unfortunately this has a number of problems,
+ one is that it is possible for event_stream_event_pending_p to
+ block for ever if there isn't actually an event. I guess this can
+ happen if we drop the synthetic event for reason. It also relies on
+ SIGIO processing which makes things rather fragile.
+
+ People have seen behaviour whereby XEmacs blocks until you move the
+ mouse. This seems to indicate that dispatch-non-command-events is
+ blocking. It may be that in a SIGIO world forcing SIGIO processing
+ does the wrong thing.
+*/
static void
emacs_Xt_force_event_pending (struct frame* f)
{
/* 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++;
+ /* We rely on SIGIO and friends to realise we have generated an
+ event. */
}
static void
break;
case Expose:
- if (x_debug_events > 1)
+ if (debug_x_events > 1)
{
XExposeEvent *ev = &event->xexpose;
describe_event_window (ev->window, ev->display);
break;
case GraphicsExpose:
- if (x_debug_events > 1)
+ if (debug_x_events > 1)
{
XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
describe_event_window (ev->drawable, ev->display);
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);
break;
case ConfigureNotify:
- if (x_debug_events > 1)
+ if (debug_x_events > 1)
{
XConfigureEvent *ev = &event->xconfigure;
describe_event_window (ev->window, ev->display);
break;
case VisibilityNotify:
- if (x_debug_events > 1)
+ if (debug_x_events > 1)
{
XVisibilityEvent *ev = &event->xvisibility;
describe_event_window (ev->window, ev->display);
Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
#ifdef DEBUG_XEMACS
- if (x_debug_events > 0)
+ if (debug_x_events > 0)
{
describe_event (event);
}
/* quit_check_signal_tick_count is volatile so try to avoid race conditions
by using a temporary variable */
tick_count_val = quit_check_signal_tick_count;
- if (last_quit_check_signal_tick_count != tick_count_val)
+ if (last_quit_check_signal_tick_count != tick_count_val
+#if !defined (SIGIO) || defined (CYGWIN)
+ || (XtIMXEvent & XtAppPending (Xt_app_con))
+#endif
+ )
{
last_quit_check_signal_tick_count = tick_count_val;
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);
+ }
+}
+
\f
/************************************************************************/
/* replacement for standard string-to-pixel converter */
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 {
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);
dispatch_event_queue = Qnil;
staticpro (&dispatch_event_queue);
dispatch_event_queue_tail = Qnil;
- pdump_wire (&dispatch_event_queue_tail);
+ dump_add_root_object (&dispatch_event_queue_tail);
DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
*Non-nil means to allow synthetic events. Nil means they are ignored.
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
}
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);