[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/src/xterm.c
From: |
Kenichi Handa |
Subject: |
[Emacs-diffs] Changes to emacs/src/xterm.c |
Date: |
Fri, 10 Jan 2003 02:22:04 -0500 |
Index: emacs/src/xterm.c
diff -c emacs/src/xterm.c:1.765 emacs/src/xterm.c:1.766
*** emacs/src/xterm.c:1.765 Sun Jan 5 19:45:31 2003
--- emacs/src/xterm.c Wed Jan 8 15:06:05 2003
***************
*** 9934,9984 ****
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
- /* This processes Expose events from the menu-bar specific X event
- loop in xmenu.c. This allows to redisplay the frame if necessary
- when handling menu-bar or pop-up items. */
-
- int
- process_expose_from_menu (event)
- XEvent event;
- {
- FRAME_PTR f;
- struct x_display_info *dpyinfo;
- int frame_exposed_p = 0;
-
- BLOCK_INPUT;
-
- dpyinfo = x_display_info_for_display (event.xexpose.display);
- f = x_window_to_frame (dpyinfo, event.xexpose.window);
- if (f)
- {
- if (f->async_visible == 0)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
- f->output_data.x->has_been_visible = 1;
- SET_FRAME_GARBAGED (f);
- }
- else
- {
- expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
- frame_exposed_p = 1;
- }
- }
- else
- {
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xexpose.window);
-
- if (bar)
- x_scroll_bar_expose (bar, &event);
- }
-
- UNBLOCK_INPUT;
- return frame_exposed_p;
- }
/* Define a queue to save up SelectionRequest events for later handling. */
--- 9934,9939 ----
***************
*** 10107,10237 ****
#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
- /* Read events coming from the X server.
- This routine is called by the SIGIO handler.
- We return as soon as there are no more events to be read.
! Events representing keys are stored in buffer BUFP,
! which can hold up to NUMCHARS characters.
! We return the number of characters stored into the buffer,
! thus pretending to be `read'.
!
! EXPECTED is nonzero if the caller knows input is available. */
static int
! XTread_socket (sd, bufp, numchars, expected)
! register int sd;
! /* register */ struct input_event *bufp;
! /* register */ int numchars;
! int expected;
{
int count = 0;
int nbytes = 0;
- XEvent event;
struct frame *f;
- int event_found = 0;
- struct x_display_info *dpyinfo;
struct coding_system coding;
! if (interrupt_input_blocked)
! {
! interrupt_input_pending = 1;
! return -1;
! }
! interrupt_input_pending = 0;
! BLOCK_INPUT;
!
! /* So people can tell when we have read the available input. */
! input_signal_count++;
!
! if (numchars <= 0)
! abort (); /* Don't think this happens. */
!
! ++handling_signal;
!
! /* Find the display we are supposed to read input for.
! It's the one communicating on descriptor SD. */
! for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
{
! #if 0 /* This ought to be unnecessary; let's verify it. */
! #ifdef FIOSNBIO
! /* If available, Xlib uses FIOSNBIO to make the socket
! non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
! FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
! a read returns 0, which Xlib interprets as equivalent to EPIPE. */
! fcntl (dpyinfo->connection, F_SETFL, 0);
! #endif /* ! defined (FIOSNBIO) */
! #endif
!
! #if 0 /* This code can't be made to work, with multiple displays,
! and appears not to be used on any system any more.
! Also keyboard.c doesn't turn O_NDELAY on and off
! for X connections. */
! #ifndef SIGIO
! #ifndef HAVE_SELECT
! if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
! {
! extern int read_alarm_should_throw;
! read_alarm_should_throw = 1;
! XPeekEvent (dpyinfo->display, &event);
! read_alarm_should_throw = 0;
! }
! #endif /* HAVE_SELECT */
! #endif /* SIGIO */
! #endif
!
! /* For debugging, this gives a way to fake an I/O error. */
! if (dpyinfo == XTread_socket_fake_io_error)
! {
! XTread_socket_fake_io_error = 0;
! x_io_error_quitter (dpyinfo->display);
! }
!
! #ifdef HAVE_X_SM
! BLOCK_INPUT;
! count += x_session_check_input (bufp, &numchars);
! UNBLOCK_INPUT;
! #endif
!
! while (XPending (dpyinfo->display))
! {
! XNextEvent (dpyinfo->display, &event);
!
! #ifdef HAVE_X_I18N
! {
! /* Filter events for the current X input method.
! XFilterEvent returns non-zero if the input method has
! consumed the event. We pass the frame's X window to
! XFilterEvent because that's the one for which the IC
! was created. */
! struct frame *f1 = x_any_window_to_frame (dpyinfo,
! event.xclient.window);
! if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
! break;
! }
! #endif
! event_found = 1;
!
! switch (event.type)
! {
! case ClientMessage:
! {
! if (event.xclient.message_type
! == dpyinfo->Xatom_wm_protocols
! && event.xclient.format == 32)
! {
! if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_take_focus)
! {
! /* Use x_any_window_to_frame because this
! could be the shell widget window
! if the frame has no title bar. */
! f = x_any_window_to_frame (dpyinfo,
event.xclient.window);
#ifdef HAVE_X_I18N
! /* Not quite sure this is needed -pd */
! if (f && FRAME_XIC (f))
! XSetICFocus (FRAME_XIC (f));
#endif
#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
instructs the WM to set the input focus automatically for
--- 10062,10122 ----
#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
! enum
! {
! X_EVENT_NORMAL,
! X_EVENT_GOTO_OUT,
! X_EVENT_DROP
! };
!
! /* Handles the XEvent EVENT on display DPYINFO.
!
! *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
! *FINISH is zero if caller should continue reading events.
! *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
!
! Events representing keys are stored in buffer *BUFP_R,
! which can hold up to *NUMCHARSP characters.
! We return the number of characters stored into the buffer. */
static int
! handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
! struct x_display_info *dpyinfo;
! XEvent *eventp;
! /* register */ struct input_event **bufp_r;
! /* register */ int *numcharsp;
! int *finish;
{
int count = 0;
int nbytes = 0;
struct frame *f;
struct coding_system coding;
+ struct input_event *bufp = *bufp_r;
+ int numchars = *numcharsp;
+ XEvent event = *eventp;
! *finish = X_EVENT_NORMAL;
! switch (event.type)
{
! case ClientMessage:
! {
! if (event.xclient.message_type
! == dpyinfo->Xatom_wm_protocols
! && event.xclient.format == 32)
! {
! if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_take_focus)
! {
! /* Use x_any_window_to_frame because this
! could be the shell widget window
! if the frame has no title bar. */
! f = x_any_window_to_frame (dpyinfo, event.xclient.window);
#ifdef HAVE_X_I18N
! /* Not quite sure this is needed -pd */
! if (f && FRAME_XIC (f))
! XSetICFocus (FRAME_XIC (f));
#endif
#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
instructs the WM to set the input focus automatically for
***************
*** 10246,11410 ****
below can generate additional FocusIn events which confuse
Emacs. */
! /* Since we set WM_TAKE_FOCUS, we must call
! XSetInputFocus explicitly. But not if f is null,
! since that might be an event for a deleted frame. */
! if (f)
! {
! Display *d = event.xclient.display;
! /* Catch and ignore errors, in case window has been
! iconified by a window manager such as GWM. */
! int count = x_catch_errors (d);
! XSetInputFocus (d, event.xclient.window,
! /* The ICCCM says this is
! the only valid choice. */
! RevertToParent,
! event.xclient.data.l[1]);
! /* This is needed to detect the error
! if there is an error. */
! XSync (d, False);
! x_uncatch_errors (d, count);
! }
! /* Not certain about handling scroll bars here */
#endif /* 0 */
! }
! else if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_save_yourself)
! {
! /* Save state modify the WM_COMMAND property to
! something which can reinstate us. This notifies
! the session manager, who's looking for such a
! PropertyNotify. Can restart processing when
! a keyboard or mouse event arrives. */
! /* If we have a session manager, don't set this.
! KDE will then start two Emacsen, one for the
! session manager and one for this. */
! if (numchars > 0
#ifdef HAVE_X_SM
! && ! x_session_have_connection ()
#endif
! )
! {
! f = x_top_window_to_frame (dpyinfo,
! event.xclient.window);
! /* This is just so we only give real data once
! for a single Emacs process. */
! if (f == SELECTED_FRAME ())
! XSetCommand (FRAME_X_DISPLAY (f),
! event.xclient.window,
! initial_argv, initial_argc);
! else if (f)
! XSetCommand (FRAME_X_DISPLAY (f),
! event.xclient.window,
! 0, 0);
! }
! }
! else if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_delete_window)
! {
! struct frame *f
! = x_any_window_to_frame (dpyinfo,
! event.xclient.window);
!
! if (f)
! {
! if (numchars == 0)
! abort ();
!
! bufp->kind = DELETE_WINDOW_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! }
! }
! else if (event.xclient.message_type
! == dpyinfo->Xatom_wm_configure_denied)
! {
! }
! else if (event.xclient.message_type
! == dpyinfo->Xatom_wm_window_moved)
! {
! int new_x, new_y;
! struct frame *f
! = x_window_to_frame (dpyinfo, event.xclient.window);
!
! new_x = event.xclient.data.s[0];
! new_y = event.xclient.data.s[1];
!
! if (f)
! {
! f->output_data.x->left_pos = new_x;
! f->output_data.x->top_pos = new_y;
! }
! }
#ifdef HACK_EDITRES
! else if (event.xclient.message_type
! == dpyinfo->Xatom_editres)
! {
! struct frame *f
! = x_any_window_to_frame (dpyinfo, event.xclient.window);
! _XEditResCheckMessages (f->output_data.x->widget, NULL,
! &event, NULL);
! }
#endif /* HACK_EDITRES */
! else if ((event.xclient.message_type
! == dpyinfo->Xatom_DONE)
! || (event.xclient.message_type
! == dpyinfo->Xatom_PAGE))
! {
! /* Ghostview job completed. Kill it. We could
! reply with "Next" if we received "Page", but we
! currently never do because we are interested in
! images, only, which should have 1 page. */
! Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
! struct frame *f
! = x_window_to_frame (dpyinfo, event.xclient.window);
! x_kill_gs_process (pixmap, f);
! expose_frame (f, 0, 0, 0, 0);
! }
#ifdef USE_TOOLKIT_SCROLL_BARS
! /* Scroll bar callbacks send a ClientMessage from which
! we construct an input_event. */
! else if (event.xclient.message_type
! == dpyinfo->Xatom_Scrollbar)
! {
! x_scroll_bar_to_input_event (&event, bufp);
! ++bufp, ++count, --numchars;
! goto out;
! }
#endif /* USE_TOOLKIT_SCROLL_BARS */
! else
! goto OTHER;
! }
! break;
! case SelectionNotify:
#ifdef USE_X_TOOLKIT
! if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
! goto OTHER;
#endif /* not USE_X_TOOLKIT */
! x_handle_selection_notify (&event.xselection);
! break;
! case SelectionClear: /* Someone has grabbed ownership. */
#ifdef USE_X_TOOLKIT
! if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! {
! XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
! if (numchars == 0)
! abort ();
! bufp->kind = SELECTION_CLEAR_EVENT;
! SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
! SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
! SELECTION_EVENT_TIME (bufp) = eventp->time;
! bufp->frame_or_window = Qnil;
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! break;
! case SelectionRequest: /* Someone wants our selection. */
#ifdef USE_X_TOOLKIT
! if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! if (x_queue_selection_requests)
! x_queue_event (x_window_to_frame (dpyinfo,
event.xselectionrequest.owner),
! &event);
! else
! {
! XSelectionRequestEvent *eventp
! = (XSelectionRequestEvent *) &event;
!
! if (numchars == 0)
! abort ();
!
! bufp->kind = SELECTION_REQUEST_EVENT;
! SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
! SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
! SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
! SELECTION_EVENT_TARGET (bufp) = eventp->target;
! SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
! SELECTION_EVENT_TIME (bufp) = eventp->time;
! bufp->frame_or_window = Qnil;
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! break;
! case PropertyNotify:
#if 0 /* This is plain wrong. In the case that we are waiting for a
PropertyNotify used as an ACK in incremental selection
transfer, the property will be on the receiver's window. */
#if defined USE_X_TOOLKIT
! if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
! goto OTHER;
#endif
#endif
! x_handle_property_notify (&event.xproperty);
! goto OTHER;
! case ReparentNotify:
! f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
! if (f)
! {
! int x, y;
! f->output_data.x->parent_desc = event.xreparent.parent;
! x_real_positions (f, &x, &y);
! f->output_data.x->left_pos = x;
! f->output_data.x->top_pos = y;
! goto OTHER;
! }
! break;
!
! case Expose:
! f = x_window_to_frame (dpyinfo, event.xexpose.window);
! if (f)
! {
! x_check_fullscreen (f);
!
! if (f->async_visible == 0)
! {
! f->async_visible = 1;
! f->async_iconified = 0;
! f->output_data.x->has_been_visible = 1;
! SET_FRAME_GARBAGED (f);
! }
! else
! expose_frame (x_window_to_frame (dpyinfo,
! event.xexpose.window),
! event.xexpose.x, event.xexpose.y,
! event.xexpose.width, event.xexpose.height);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar;
#endif
#if defined USE_LUCID
! /* Submenus of the Lucid menu bar aren't widgets
! themselves, so there's no way to dispatch events
! to them. Recognize this case separately. */
! {
! Widget widget
! = x_window_to_menu_bar (event.xexpose.window);
! if (widget)
! xlwmenu_redisplay (widget);
! }
#endif /* USE_LUCID */
#ifdef USE_TOOLKIT_SCROLL_BARS
! /* Dispatch event to the widget. */
! goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
! bar = x_window_to_scroll_bar (event.xexpose.window);
! if (bar)
! x_scroll_bar_expose (bar, &event);
#ifdef USE_X_TOOLKIT
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
#endif /* not USE_TOOLKIT_SCROLL_BARS */
! }
! break;
! case GraphicsExpose: /* This occurs when an XCopyArea's
! source area was obscured or not
! available. */
! f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
! if (f)
! {
! expose_frame (f,
! event.xgraphicsexpose.x,
event.xgraphicsexpose.y,
! event.xgraphicsexpose.width,
! event.xgraphicsexpose.height);
! }
#ifdef USE_X_TOOLKIT
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! break;
!
! case NoExpose: /* This occurs when an XCopyArea's
! source area was completely
! available. */
! break;
! case UnmapNotify:
! /* Redo the mouse-highlight after the tooltip has gone. */
! if (event.xmap.window == tip_window)
! {
! tip_window = 0;
! redo_mouse_highlight ();
! }
!
! f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
! if (f) /* F may no longer exist if
! the frame was deleted. */
! {
! /* While a frame is unmapped, display generation is
! disabled; you don't want to spend time updating a
! display that won't ever be seen. */
! f->async_visible = 0;
! /* We can't distinguish, from the event, whether the window
! has become iconified or invisible. So assume, if it
! was previously visible, than now it is iconified.
! But x_make_frame_invisible clears both
! the visible flag and the iconified flag;
! and that way, we know the window is not iconified now. */
! if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
! {
! f->async_iconified = 1;
!
! bufp->kind = ICONIFY_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
! count++;
! numchars--;
! }
! }
! goto OTHER;
!
! case MapNotify:
! if (event.xmap.window == tip_window)
! /* The tooltip has been drawn already. Avoid
! the SET_FRAME_GARBAGED below. */
! goto OTHER;
!
! /* We use x_top_window_to_frame because map events can
! come for sub-windows and they don't mean that the
! frame is visible. */
! f = x_top_window_to_frame (dpyinfo, event.xmap.window);
! if (f)
! {
! f->async_visible = 1;
! f->async_iconified = 0;
! f->output_data.x->has_been_visible = 1;
!
! /* wait_reading_process_input will notice this and update
! the frame's display structures. */
! SET_FRAME_GARBAGED (f);
!
! if (f->iconified)
! {
! bufp->kind = DEICONIFY_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
! count++;
! numchars--;
! }
! else if (! NILP (Vframe_list)
! && ! NILP (XCDR (Vframe_list)))
! /* Force a redisplay sooner or later
! to update the frame titles
! in case this is the second frame. */
! record_asynch_buffer_change ();
! }
! goto OTHER;
!
! case KeyPress:
!
! /* Dispatch KeyPress events when in menu. */
! if (popup_activated_flag)
! goto OTHER;
!
! f = x_any_window_to_frame (dpyinfo, event.xkey.window);
!
! if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
! {
! dpyinfo->mouse_face_hidden = 1;
! clear_mouse_face (dpyinfo);
! }
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
! if (f == 0)
! {
! /* Scroll bars consume key events, but we want
! the keys to go to the scroll bar's frame. */
! Widget widget = XtWindowToWidget (dpyinfo->display,
! event.xkey.window);
! if (widget && XmIsScrollBar (widget))
! {
! widget = XtParent (widget);
! f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
! }
! }
#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
! if (f != 0)
! {
! KeySym keysym, orig_keysym;
! /* address@hidden says that making this 81
! instead of 80 fixed a bug whereby meta chars made
! his Emacs hang.
!
! It seems that some version of XmbLookupString has
! a bug of not returning XBufferOverflow in
! status_return even if the input is too long to
! fit in 81 bytes. So, we must prepare sufficient
! bytes for copy_buffer. 513 bytes (256 chars for
! two-byte character set) seems to be a fairly good
! approximation. -- 2000.8.10 address@hidden */
! unsigned char copy_buffer[513];
! unsigned char *copy_bufptr = copy_buffer;
! int copy_bufsiz = sizeof (copy_buffer);
! int modifiers;
! Lisp_Object coding_system = Qlatin_1;
!
! event.xkey.state
! |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
! extra_keyboard_modifiers);
! modifiers = event.xkey.state;
!
! /* This will have to go some day... */
!
! /* make_lispy_event turns chars into control chars.
! Don't do it here because XLookupString is too eager. */
! event.xkey.state &= ~ControlMask;
! event.xkey.state &= ~(dpyinfo->meta_mod_mask
! | dpyinfo->super_mod_mask
! | dpyinfo->hyper_mod_mask
! | dpyinfo->alt_mod_mask);
!
! /* In case Meta is ComposeCharacter,
! clear its status. According to Markus Ehrnsperger
! address@hidden
! this enables ComposeCharacter to work whether or
! not it is combined with Meta. */
! if (modifiers & dpyinfo->meta_mod_mask)
! bzero (&compose_status, sizeof (compose_status));
#ifdef HAVE_X_I18N
! if (FRAME_XIC (f))
! {
! Status status_return;
!
! coding_system = Vlocale_coding_system;
! nbytes = XmbLookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! if (status_return == XBufferOverflow)
! {
! copy_bufsiz = nbytes + 1;
! copy_bufptr = (char *) alloca (copy_bufsiz);
! nbytes = XmbLookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! }
! /* Xutf8LookupString is a new but already deprecated interface. -stef */
#if 0 && defined X_HAVE_UTF8_STRING
! else if (status_return == XLookupKeySym)
! { /* Try again but with utf-8. */
! coding_system = Qutf_8;
! nbytes = Xutf8LookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! if (status_return == XBufferOverflow)
! {
! copy_bufsiz = nbytes + 1;
! copy_bufptr = (char *) alloca (copy_bufsiz);
! nbytes = Xutf8LookupString (FRAME_XIC (f),
! &event.xkey,
! copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! }
! }
! #endif
!
! if (status_return == XLookupNone)
! break;
! else if (status_return == XLookupChars)
! {
! keysym = NoSymbol;
! modifiers = 0;
! }
! else if (status_return != XLookupKeySym
! && status_return != XLookupBoth)
! abort ();
! }
! else
! nbytes = XLookupString (&event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &compose_status);
#else
! nbytes = XLookupString (&event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &compose_status);
! #endif
!
! orig_keysym = keysym;
!
! if (numchars > 1)
! {
! Lisp_Object c;
!
! /* First deal with keysyms which have defined
! translations to characters. */
! if (keysym >= 32 && keysym < 128)
! /* Avoid explicitly decoding each ASCII character. */
! {
! bufp->kind = ASCII_KEYSTROKE_EVENT;
! bufp->code = keysym;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! /* Now non-ASCII. */
! else if (HASH_TABLE_P (Vx_keysym_table)
! && (NATNUMP (c = Fgethash (make_number (keysym),
! Vx_keysym_table,
! Qnil))))
! {
! bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
! ? ASCII_KEYSTROKE_EVENT
! : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
! bufp->code = XFASTINT (c);
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! /* Random non-modifier sorts of keysyms. */
! else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
! || keysym == XK_Delete
#ifdef XK_ISO_Left_Tab
! || (keysym >= XK_ISO_Left_Tab
! && keysym <= XK_ISO_Enter)
#endif
! || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60
*/
! || IsMiscFunctionKey (keysym) /* 0xff60 <= x <
VARIES */
#ifdef HPUX
! /* This recognizes the "extended function
! keys". It seems there's no cleaner way.
! Test IsModifierKey to avoid handling
! mode_switch incorrectly. */
! || ((unsigned) (keysym) >= XK_Select
! && (unsigned)(keysym) < XK_KP_Space)
#endif
#ifdef XK_dead_circumflex
! || orig_keysym == XK_dead_circumflex
#endif
#ifdef XK_dead_grave
! || orig_keysym == XK_dead_grave
#endif
#ifdef XK_dead_tilde
! || orig_keysym == XK_dead_tilde
#endif
#ifdef XK_dead_diaeresis
! || orig_keysym == XK_dead_diaeresis
#endif
#ifdef XK_dead_macron
! || orig_keysym == XK_dead_macron
#endif
#ifdef XK_dead_degree
! || orig_keysym == XK_dead_degree
#endif
#ifdef XK_dead_acute
! || orig_keysym == XK_dead_acute
#endif
#ifdef XK_dead_cedilla
! || orig_keysym == XK_dead_cedilla
#endif
#ifdef XK_dead_breve
! || orig_keysym == XK_dead_breve
#endif
#ifdef XK_dead_ogonek
! || orig_keysym == XK_dead_ogonek
#endif
#ifdef XK_dead_caron
! || orig_keysym == XK_dead_caron
#endif
#ifdef XK_dead_doubleacute
! || orig_keysym == XK_dead_doubleacute
#endif
#ifdef XK_dead_abovedot
! || orig_keysym == XK_dead_abovedot
#endif
! || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe
*/
! || IsFunctionKey (keysym) /* 0xffbe <= x <
0xffe1 */
! /* Any "vendor-specific" key is ok. */
! || (orig_keysym & (1 << 28))
! || (keysym != NoSymbol && nbytes == 0))
! && ! (IsModifierKey (orig_keysym)
#ifndef HAVE_X11R5
#ifdef XK_Mode_switch
! || ((unsigned)(orig_keysym) ==
XK_Mode_switch)
#endif
#ifdef XK_Num_Lock
! || ((unsigned)(orig_keysym) == XK_Num_Lock)
#endif
#endif /* not HAVE_X11R5 */
! /* The symbols from XK_ISO_Lock
! to XK_ISO_Last_Group_Lock
! don't have real modifiers but
! should be treated similarly to
! Mode_switch by Emacs. */
#if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
! || ((unsigned)(orig_keysym)
! >= XK_ISO_Lock
! && (unsigned)(orig_keysym)
! <= XK_ISO_Last_Group_Lock)
! #endif
! ))
! {
! if (temp_index == sizeof temp_buffer / sizeof (short))
! temp_index = 0;
! temp_buffer[temp_index++] = keysym;
! /* make_lispy_event will convert this to a symbolic
! key. */
! bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
! bufp->code = keysym;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! else if (numchars > nbytes)
! { /* Raw bytes, not keysym. */
! register int i;
! register int c;
! int nchars, len;
!
! /* The input should be decoded with `coding_system'
! which depends on which X*LookupString function
! we used just above and the locale. */
! setup_coding_system (coding_system, &coding);
! coding.src_multibyte = 0;
! coding.dst_multibyte = 1;
! /* The input is converted to events, thus we can't
! handle composition. Anyway, there's no XIM that
! gives us composition information. */
! coding.composing = COMPOSITION_DISABLED;
!
! for (i = 0; i < nbytes; i++)
! {
! if (temp_index == (sizeof temp_buffer
! / sizeof (short)))
! temp_index = 0;
! temp_buffer[temp_index++] = copy_bufptr[i];
! }
!
! {
! /* Decode the input data. */
! int require;
! unsigned char *p;
!
! require = decoding_buffer_size (&coding, nbytes);
! p = (unsigned char *) alloca (require);
! coding.mode |= CODING_MODE_LAST_BLOCK;
! /* We explicitely disable composition
! handling because key data should
! not contain any composition
! sequence. */
! coding.composing = COMPOSITION_DISABLED;
! decode_coding (&coding, copy_bufptr, p,
! nbytes, require);
! nbytes = coding.produced;
! nchars = coding.produced_char;
! copy_bufptr = p;
! }
!
! /* Convert the input data to a sequence of
! character events. */
! for (i = 0; i < nbytes; i += len)
! {
! if (nchars == nbytes)
! c = copy_bufptr[i], len = 1;
! else
! c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
! nbytes - i, len);
!
! bufp->kind = (SINGLE_BYTE_CHAR_P (c)
! ? ASCII_KEYSTROKE_EVENT
! : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
! bufp->code = c;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
(f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! }
!
! count += nchars;
! numchars -= nchars;
!
! if (keysym == NoSymbol)
! break;
! }
! else
! abort ();
! }
! else
! abort ();
! }
#ifdef HAVE_X_I18N
! /* Don't dispatch this event since XtDispatchEvent calls
! XFilterEvent, and two calls in a row may freeze the
! client. */
! break;
#else
! goto OTHER;
#endif
! case KeyRelease:
#ifdef HAVE_X_I18N
! /* Don't dispatch this event since XtDispatchEvent calls
! XFilterEvent, and two calls in a row may freeze the
! client. */
! break;
#else
! goto OTHER;
#endif
! case EnterNotify:
! {
! int n;
! n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
! if (n > 0)
! {
! bufp += n, count += n, numchars -= n;
! }
! f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
#if 0
! if (event.xcrossing.focus)
! {
! /* Avoid nasty pop/raise loops. */
! if (f && (!(f->auto_raise)
! || !(f->auto_lower)
! || (event.xcrossing.time - enter_timestamp) >
500))
! {
! x_new_focus_frame (dpyinfo, f);
! enter_timestamp = event.xcrossing.time;
! }
! }
! else if (f == dpyinfo->x_focus_frame)
! x_new_focus_frame (dpyinfo, 0);
! #endif
!
! /* EnterNotify counts as mouse movement,
! so update things that depend on mouse position. */
! if (f && !f->output_data.x->hourglass_p)
! note_mouse_movement (f, &event.xmotion);
! goto OTHER;
! }
!
! case FocusIn:
{
! int n;
!
! n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
! if (n > 0)
! {
! bufp += n, count += n, numchars -= n;
! }
}
! goto OTHER;
! case LeaveNotify:
{
! int n;
!
! n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
! if (n > 0)
! {
! bufp += n, count += n, numchars -= n;
! }
! }
!
! f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
! if (f)
! {
! if (f == dpyinfo->mouse_face_mouse_frame)
! {
! /* If we move outside the frame, then we're
! certainly no longer on any text in the frame. */
! clear_mouse_face (dpyinfo);
! dpyinfo->mouse_face_mouse_frame = 0;
! }
!
! /* Generate a nil HELP_EVENT to cancel a help-echo.
! Do it only if there's something to cancel.
! Otherwise, the startup message is cleared when
! the mouse leaves the frame. */
! if (any_help_event_p)
! {
! Lisp_Object frame;
! int n;
!
! XSETFRAME (frame, f);
! help_echo = Qnil;
! n = gen_help_event (bufp, numchars,
! Qnil, frame, Qnil, Qnil, 0);
! bufp += n, count += n, numchars -= n;
! }
! }
! goto OTHER;
!
! case FocusOut:
! {
! int n;
! n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
! if (n > 0)
! {
! bufp += n, count += n, numchars -= n;
! }
}
!
! goto OTHER;
!
! case MotionNotify:
! {
! previous_help_echo = help_echo;
! help_echo = help_echo_object = help_echo_window = Qnil;
! help_echo_pos = -1;
!
! if (dpyinfo->grabbed && last_mouse_frame
! && FRAME_LIVE_P (last_mouse_frame))
! f = last_mouse_frame;
! else
! f = x_window_to_frame (dpyinfo, event.xmotion.window);
!
! if (dpyinfo->mouse_face_hidden)
! {
! dpyinfo->mouse_face_hidden = 0;
! clear_mouse_face (dpyinfo);
! }
!
! if (f)
! {
!
! /* Generate SELECT_WINDOW_EVENTs when needed. */
! if (mouse_autoselect_window)
! {
! Lisp_Object window;
! int area;
!
! window = window_from_coordinates (f,
! event.xmotion.x,
event.xmotion.y,
! &area, 0);
!
! /* Window will be selected only when it is not selected
now and
! last mouse movement event was not in it. Minibuffer
window
! will be selected iff it is active. */
! if (WINDOWP(window)
! && !EQ (window, last_window)
! && !EQ (window, selected_window)
! && numchars > 0)
! {
! bufp->kind = SELECT_WINDOW_EVENT;
! bufp->frame_or_window = window;
! bufp->arg = Qnil;
! ++bufp, ++count, --numchars;
! }
!
! last_window=window;
! }
! note_mouse_movement (f, &event.xmotion);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar
! = x_window_to_scroll_bar (event.xmotion.window);
! if (bar)
! x_scroll_bar_note_movement (bar, &event);
#endif /* USE_TOOLKIT_SCROLL_BARS */
! /* If we move outside the frame, then we're
! certainly no longer on any text in the frame. */
! clear_mouse_face (dpyinfo);
! }
!
! /* If the contents of the global variable help_echo
! has changed, generate a HELP_EVENT. */
! if (!NILP (help_echo)
! || !NILP (previous_help_echo))
! {
! Lisp_Object frame;
! int n;
!
! if (f)
! XSETFRAME (frame, f);
! else
! frame = Qnil;
!
! any_help_event_p = 1;
! n = gen_help_event (bufp, numchars, help_echo, frame,
! help_echo_window, help_echo_object,
! help_echo_pos);
! bufp += n, count += n, numchars -= n;
! }
!
! goto OTHER;
! }
!
! case ConfigureNotify:
! f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
! if (f)
! {
#ifndef USE_X_TOOLKIT
! /* If there is a pending resize for fullscreen, don't
! do this one, the right one will come later.
! The toolkit version doesn't seem to need this, but we
! need to reset it below. */
! int dont_resize =
! ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
! && FRAME_NEW_WIDTH (f) != 0);
! int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
! int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
! if (dont_resize)
! goto OTHER;
!
! /* In the toolkit version, change_frame_size
! is called by the code that handles resizing
! of the EmacsFrame widget. */
!
! /* Even if the number of character rows and columns has
! not changed, the font size may have changed, so we need
! to check the pixel dimensions as well. */
! if (columns != f->width
! || rows != f->height
! || event.xconfigure.width != f->output_data.x->pixel_width
! || event.xconfigure.height !=
f->output_data.x->pixel_height)
! {
! change_frame_size (f, rows, columns, 0, 1, 0);
! SET_FRAME_GARBAGED (f);
! cancel_mouse_face (f);
! }
! #endif
!
! f->output_data.x->pixel_width = event.xconfigure.width;
! f->output_data.x->pixel_height = event.xconfigure.height;
!
! /* What we have now is the position of Emacs's own window.
! Convert that to the position of the window manager window.
*/
! x_real_positions (f, &f->output_data.x->left_pos,
! &f->output_data.x->top_pos);
!
! x_check_fullscreen_move(f);
! if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
! f->output_data.x->want_fullscreen &=
! ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
#ifdef HAVE_X_I18N
! if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
! xic_set_statusarea (f);
#endif
! if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO
(f)->root_window)
! {
! /* Since the WM decorations come below top_pos now,
! we must put them below top_pos in the future. */
! f->output_data.x->win_gravity = NorthWestGravity;
! x_wm_set_size_hint (f, (long) 0, 0);
! }
! }
! goto OTHER;
!
! case ButtonPress:
! case ButtonRelease:
! {
! /* If we decide we want to generate an event to be seen
! by the rest of Emacs, we put it here. */
! struct input_event emacs_event;
! int tool_bar_p = 0;
!
! emacs_event.kind = NO_EVENT;
! bzero (&compose_status, sizeof (compose_status));
!
! if (dpyinfo->grabbed
! && last_mouse_frame
! && FRAME_LIVE_P (last_mouse_frame))
! f = last_mouse_frame;
! else
! f = x_window_to_frame (dpyinfo, event.xbutton.window);
!
! if (f)
! {
! /* Is this in the tool-bar? */
! if (WINDOWP (f->tool_bar_window)
! && XFASTINT (XWINDOW (f->tool_bar_window)->height))
! {
! Lisp_Object window;
! int p, x, y;
!
! x = event.xbutton.x;
! y = event.xbutton.y;
!
! /* Set x and y. */
! window = window_from_coordinates (f, x, y, &p, 1);
! if (EQ (window, f->tool_bar_window))
! {
! x_handle_tool_bar_click (f, &event.xbutton);
! tool_bar_p = 1;
! }
! }
!
! if (!tool_bar_p)
! if (!dpyinfo->x_focus_frame
! || f == dpyinfo->x_focus_frame)
! construct_mouse_click (&emacs_event, &event, f);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar
! = x_window_to_scroll_bar (event.xbutton.window);
! if (bar)
! x_scroll_bar_handle_click (bar, &event, &emacs_event);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
! }
! if (event.type == ButtonPress)
! {
! dpyinfo->grabbed |= (1 << event.xbutton.button);
! last_mouse_frame = f;
! /* Ignore any mouse motion that happened
! before this event; any subsequent mouse-movement
! Emacs events should reflect only motion after
! the ButtonPress. */
! if (f != 0)
! f->mouse_moved = 0;
!
! if (!tool_bar_p)
! last_tool_bar_item = -1;
! }
! else
! {
! dpyinfo->grabbed &= ~(1 << event.xbutton.button);
! }
!
! if (numchars >= 1 && emacs_event.kind != NO_EVENT)
! {
! bcopy (&emacs_event, bufp, sizeof (struct input_event));
! bufp++;
! count++;
! numchars--;
! }
#ifdef USE_X_TOOLKIT
! f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
! /* For a down-event in the menu bar,
! don't pass it to Xt right now.
! Instead, save it away
! and we will pass it to Xt from kbd_buffer_get_event.
! That way, we can run some Lisp code first. */
! if (f && event.type == ButtonPress
! /* Verify the event is really within the menu bar
! and not just sent to it due to grabbing. */
! && event.xbutton.x >= 0
! && event.xbutton.x < f->output_data.x->pixel_width
! && event.xbutton.y >= 0
! && event.xbutton.y < f->output_data.x->menubar_height
! && event.xbutton.same_screen)
! {
! SET_SAVED_BUTTON_EVENT;
! XSETFRAME (last_mouse_press_frame, f);
! }
! else if (event.type == ButtonPress)
! {
! last_mouse_press_frame = Qnil;
! goto OTHER;
! }
#ifdef USE_MOTIF /* This should do not harm for Lucid,
but I am trying to be cautious. */
! else if (event.type == ButtonRelease)
! {
! if (!NILP (last_mouse_press_frame))
! {
! f = XFRAME (last_mouse_press_frame);
! if (f->output_data.x)
! SET_SAVED_BUTTON_EVENT;
! }
! else
! goto OTHER;
! }
#endif /* USE_MOTIF */
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! }
! break;
! case CirculateNotify:
! goto OTHER;
! case CirculateRequest:
! goto OTHER;
! case VisibilityNotify:
! goto OTHER;
! case MappingNotify:
! /* Someone has changed the keyboard mapping - update the
! local cache. */
! switch (event.xmapping.request)
! {
! case MappingModifier:
! x_find_modifier_meanings (dpyinfo);
! /* This is meant to fall through. */
! case MappingKeyboard:
! XRefreshKeyboardMapping (&event.xmapping);
! }
! goto OTHER;
!
! default:
! OTHER:
#ifdef USE_X_TOOLKIT
! BLOCK_INPUT;
! XtDispatchEvent (&event);
! UNBLOCK_INPUT;
#endif /* USE_X_TOOLKIT */
! break;
! }
}
}
out:;
--- 10131,11462 ----
below can generate additional FocusIn events which confuse
Emacs. */
! /* Since we set WM_TAKE_FOCUS, we must call
! XSetInputFocus explicitly. But not if f is null,
! since that might be an event for a deleted frame. */
! if (f)
! {
! Display *d = event.xclient.display;
! /* Catch and ignore errors, in case window has been
! iconified by a window manager such as GWM. */
! int count = x_catch_errors (d);
! XSetInputFocus (d, event.xclient.window,
! /* The ICCCM says this is
! the only valid choice. */
! RevertToParent,
! event.xclient.data.l[1]);
! /* This is needed to detect the error
! if there is an error. */
! XSync (d, False);
! x_uncatch_errors (d, count);
! }
! /* Not certain about handling scroll bars here */
#endif /* 0 */
! }
! else if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_save_yourself)
! {
! /* Save state modify the WM_COMMAND property to
! something which can reinstate us. This notifies
! the session manager, who's looking for such a
! PropertyNotify. Can restart processing when
! a keyboard or mouse event arrives. */
! /* If we have a session manager, don't set this.
! KDE will then start two Emacsen, one for the
! session manager and one for this. */
! if (numchars > 0
#ifdef HAVE_X_SM
! && ! x_session_have_connection ()
#endif
! )
! {
! f = x_top_window_to_frame (dpyinfo,
! event.xclient.window);
! /* This is just so we only give real data once
! for a single Emacs process. */
! if (f == SELECTED_FRAME ())
! XSetCommand (FRAME_X_DISPLAY (f),
! event.xclient.window,
! initial_argv, initial_argc);
! else if (f)
! XSetCommand (FRAME_X_DISPLAY (f),
! event.xclient.window,
! 0, 0);
! }
! }
! else if (event.xclient.data.l[0]
! == dpyinfo->Xatom_wm_delete_window)
! {
! struct frame *f
! = x_any_window_to_frame (dpyinfo,
! event.xclient.window);
!
! if (f)
! {
! if (numchars == 0)
! abort ();
!
! bufp->kind = DELETE_WINDOW_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! else
! goto OTHER; /* May be a dialog that is to be removed */
! }
! }
! else if (event.xclient.message_type
! == dpyinfo->Xatom_wm_configure_denied)
! {
! }
! else if (event.xclient.message_type
! == dpyinfo->Xatom_wm_window_moved)
! {
! int new_x, new_y;
! struct frame *f
! = x_window_to_frame (dpyinfo, event.xclient.window);
!
! new_x = event.xclient.data.s[0];
! new_y = event.xclient.data.s[1];
!
! if (f)
! {
! f->output_data.x->left_pos = new_x;
! f->output_data.x->top_pos = new_y;
! }
! }
#ifdef HACK_EDITRES
! else if (event.xclient.message_type
! == dpyinfo->Xatom_editres)
! {
! struct frame *f
! = x_any_window_to_frame (dpyinfo, event.xclient.window);
! _XEditResCheckMessages (f->output_data.x->widget, NULL,
! &event, NULL);
! }
#endif /* HACK_EDITRES */
! else if ((event.xclient.message_type
! == dpyinfo->Xatom_DONE)
! || (event.xclient.message_type
! == dpyinfo->Xatom_PAGE))
! {
! /* Ghostview job completed. Kill it. We could
! reply with "Next" if we received "Page", but we
! currently never do because we are interested in
! images, only, which should have 1 page. */
! Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
! struct frame *f
! = x_window_to_frame (dpyinfo, event.xclient.window);
! x_kill_gs_process (pixmap, f);
! expose_frame (f, 0, 0, 0, 0);
! }
#ifdef USE_TOOLKIT_SCROLL_BARS
! /* Scroll bar callbacks send a ClientMessage from which
! we construct an input_event. */
! else if (event.xclient.message_type
! == dpyinfo->Xatom_Scrollbar)
! {
! x_scroll_bar_to_input_event (&event, bufp);
! ++bufp, ++count, --numchars;
! goto out;
! }
#endif /* USE_TOOLKIT_SCROLL_BARS */
! else
! goto OTHER;
! }
! break;
! case SelectionNotify:
#ifdef USE_X_TOOLKIT
! if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
! goto OTHER;
#endif /* not USE_X_TOOLKIT */
! x_handle_selection_notify (&event.xselection);
! break;
! case SelectionClear: /* Someone has grabbed ownership. */
#ifdef USE_X_TOOLKIT
! if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! {
! XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
! if (numchars == 0)
! abort ();
! bufp->kind = SELECTION_CLEAR_EVENT;
! SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
! SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
! SELECTION_EVENT_TIME (bufp) = eventp->time;
! bufp->frame_or_window = Qnil;
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! break;
! case SelectionRequest: /* Someone wants our selection. */
#ifdef USE_X_TOOLKIT
! if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! if (x_queue_selection_requests)
! x_queue_event (x_window_to_frame (dpyinfo,
event.xselectionrequest.owner),
! &event);
! else
! {
! XSelectionRequestEvent *eventp
! = (XSelectionRequestEvent *) &event;
!
! if (numchars == 0)
! abort ();
!
! bufp->kind = SELECTION_REQUEST_EVENT;
! SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
! SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
! SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
! SELECTION_EVENT_TARGET (bufp) = eventp->target;
! SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
! SELECTION_EVENT_TIME (bufp) = eventp->time;
! bufp->frame_or_window = Qnil;
! bufp->arg = Qnil;
! bufp++;
!
! count += 1;
! numchars -= 1;
! }
! break;
! case PropertyNotify:
#if 0 /* This is plain wrong. In the case that we are waiting for a
PropertyNotify used as an ACK in incremental selection
transfer, the property will be on the receiver's window. */
#if defined USE_X_TOOLKIT
! if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
! goto OTHER;
#endif
#endif
! x_handle_property_notify (&event.xproperty);
! goto OTHER;
! case ReparentNotify:
! f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
! if (f)
! {
! int x, y;
! f->output_data.x->parent_desc = event.xreparent.parent;
! x_real_positions (f, &x, &y);
! f->output_data.x->left_pos = x;
! f->output_data.x->top_pos = y;
! goto OTHER;
! }
! break;
!
! case Expose:
! f = x_window_to_frame (dpyinfo, event.xexpose.window);
! if (f)
! {
! x_check_fullscreen (f);
!
! if (f->async_visible == 0)
! {
! f->async_visible = 1;
! f->async_iconified = 0;
! f->output_data.x->has_been_visible = 1;
! SET_FRAME_GARBAGED (f);
! }
! else
! expose_frame (x_window_to_frame (dpyinfo,
! event.xexpose.window),
! event.xexpose.x, event.xexpose.y,
! event.xexpose.width, event.xexpose.height);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar;
#endif
#if defined USE_LUCID
! /* Submenus of the Lucid menu bar aren't widgets
! themselves, so there's no way to dispatch events
! to them. Recognize this case separately. */
! {
! Widget widget
! = x_window_to_menu_bar (event.xexpose.window);
! if (widget)
! xlwmenu_redisplay (widget);
! }
#endif /* USE_LUCID */
#ifdef USE_TOOLKIT_SCROLL_BARS
! /* Dispatch event to the widget. */
! goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
! bar = x_window_to_scroll_bar (event.xexpose.window);
! if (bar)
! x_scroll_bar_expose (bar, &event);
#ifdef USE_X_TOOLKIT
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
#endif /* not USE_TOOLKIT_SCROLL_BARS */
! }
! break;
! case GraphicsExpose: /* This occurs when an XCopyArea's
! source area was obscured or not
! available. */
! f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
! if (f)
! {
! expose_frame (f,
! event.xgraphicsexpose.x, event.xgraphicsexpose.y,
! event.xgraphicsexpose.width,
! event.xgraphicsexpose.height);
! }
#ifdef USE_X_TOOLKIT
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! break;
! case NoExpose: /* This occurs when an XCopyArea's
! source area was completely
! available. */
! break;
!
! case UnmapNotify:
! /* Redo the mouse-highlight after the tooltip has gone. */
! if (event.xmap.window == tip_window)
! {
! tip_window = 0;
! redo_mouse_highlight ();
! }
!
! f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
! if (f) /* F may no longer exist if
! the frame was deleted. */
! {
! /* While a frame is unmapped, display generation is
! disabled; you don't want to spend time updating a
! display that won't ever be seen. */
! f->async_visible = 0;
! /* We can't distinguish, from the event, whether the window
! has become iconified or invisible. So assume, if it
! was previously visible, than now it is iconified.
! But x_make_frame_invisible clears both
! the visible flag and the iconified flag;
! and that way, we know the window is not iconified now. */
! if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
! {
! f->async_iconified = 1;
!
! bufp->kind = ICONIFY_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
! count++;
! numchars--;
! }
! }
! goto OTHER;
!
! case MapNotify:
! if (event.xmap.window == tip_window)
! /* The tooltip has been drawn already. Avoid
! the SET_FRAME_GARBAGED below. */
! goto OTHER;
!
! /* We use x_top_window_to_frame because map events can
! come for sub-windows and they don't mean that the
! frame is visible. */
! f = x_top_window_to_frame (dpyinfo, event.xmap.window);
! if (f)
! {
! /* wait_reading_process_input will notice this and update
! the frame's display structures.
! If we where iconified, we should not set garbaged,
! because that stops redrawing on Expose events. This looks
! bad if we are called from a recursive event loop
! (x_dispatch_event), for example when a dialog is up. */
! if (! f->async_iconified)
! SET_FRAME_GARBAGED (f);
!
! f->async_visible = 1;
! f->async_iconified = 0;
! f->output_data.x->has_been_visible = 1;
!
! if (f->iconified)
! {
! bufp->kind = DEICONIFY_EVENT;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp++;
! count++;
! numchars--;
! }
! else if (! NILP (Vframe_list)
! && ! NILP (XCDR (Vframe_list)))
! /* Force a redisplay sooner or later
! to update the frame titles
! in case this is the second frame. */
! record_asynch_buffer_change ();
! }
! goto OTHER;
!
! case KeyPress:
!
! /* Dispatch KeyPress events when in menu. */
! if (popup_activated_flag)
! goto OTHER;
! f = x_any_window_to_frame (dpyinfo, event.xkey.window);
!
! if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
! {
! dpyinfo->mouse_face_hidden = 1;
! clear_mouse_face (dpyinfo);
! }
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
! if (f == 0)
! {
! /* Scroll bars consume key events, but we want
! the keys to go to the scroll bar's frame. */
! Widget widget = XtWindowToWidget (dpyinfo->display,
! event.xkey.window);
! if (widget && XmIsScrollBar (widget))
! {
! widget = XtParent (widget);
! f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
! }
! }
#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
! if (f != 0)
! {
! KeySym keysym, orig_keysym;
! /* address@hidden says that making this 81
! instead of 80 fixed a bug whereby meta chars made
! his Emacs hang.
!
! It seems that some version of XmbLookupString has
! a bug of not returning XBufferOverflow in
! status_return even if the input is too long to
! fit in 81 bytes. So, we must prepare sufficient
! bytes for copy_buffer. 513 bytes (256 chars for
! two-byte character set) seems to be a fairly good
! approximation. -- 2000.8.10 address@hidden */
! unsigned char copy_buffer[513];
! unsigned char *copy_bufptr = copy_buffer;
! int copy_bufsiz = sizeof (copy_buffer);
! int modifiers;
! Lisp_Object coding_system = Qlatin_1;
!
! event.xkey.state
! |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
! extra_keyboard_modifiers);
! modifiers = event.xkey.state;
!
! /* This will have to go some day... */
!
! /* make_lispy_event turns chars into control chars.
! Don't do it here because XLookupString is too eager. */
! event.xkey.state &= ~ControlMask;
! event.xkey.state &= ~(dpyinfo->meta_mod_mask
! | dpyinfo->super_mod_mask
! | dpyinfo->hyper_mod_mask
! | dpyinfo->alt_mod_mask);
!
! /* In case Meta is ComposeCharacter,
! clear its status. According to Markus Ehrnsperger
! address@hidden
! this enables ComposeCharacter to work whether or
! not it is combined with Meta. */
! if (modifiers & dpyinfo->meta_mod_mask)
! bzero (&compose_status, sizeof (compose_status));
#ifdef HAVE_X_I18N
! if (FRAME_XIC (f))
! {
! Status status_return;
!
! coding_system = Vlocale_coding_system;
! nbytes = XmbLookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! if (status_return == XBufferOverflow)
! {
! copy_bufsiz = nbytes + 1;
! copy_bufptr = (char *) alloca (copy_bufsiz);
! nbytes = XmbLookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! }
! /* Xutf8LookupString is a new but already deprecated interface.
-stef */
#if 0 && defined X_HAVE_UTF8_STRING
! else if (status_return == XLookupKeySym)
! { /* Try again but with utf-8. */
! coding_system = Qutf_8;
! nbytes = Xutf8LookupString (FRAME_XIC (f),
! &event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! if (status_return == XBufferOverflow)
! {
! copy_bufsiz = nbytes + 1;
! copy_bufptr = (char *) alloca (copy_bufsiz);
! nbytes = Xutf8LookupString (FRAME_XIC (f),
! &event.xkey,
! copy_bufptr,
! copy_bufsiz, &keysym,
! &status_return);
! }
! }
! #endif
!
! if (status_return == XLookupNone)
! break;
! else if (status_return == XLookupChars)
! {
! keysym = NoSymbol;
! modifiers = 0;
! }
! else if (status_return != XLookupKeySym
! && status_return != XLookupBoth)
! abort ();
! }
! else
! nbytes = XLookupString (&event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &compose_status);
#else
! nbytes = XLookupString (&event.xkey, copy_bufptr,
! copy_bufsiz, &keysym,
! &compose_status);
! #endif
!
! orig_keysym = keysym;
!
! if (numchars > 1)
! {
! Lisp_Object c;
!
! /* First deal with keysyms which have defined
! translations to characters. */
! if (keysym >= 32 && keysym < 128)
! /* Avoid explicitly decoding each ASCII character. */
! {
! bufp->kind = ASCII_KEYSTROKE_EVENT;
! bufp->code = keysym;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! /* Now non-ASCII. */
! else if (HASH_TABLE_P (Vx_keysym_table)
! && (NATNUMP (c = Fgethash (make_number (keysym),
! Vx_keysym_table,
! Qnil))))
! {
! bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
! ? ASCII_KEYSTROKE_EVENT
! : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
! bufp->code = XFASTINT (c);
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! /* Random non-modifier sorts of keysyms. */
! else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
! || keysym == XK_Delete
#ifdef XK_ISO_Left_Tab
! || (keysym >= XK_ISO_Left_Tab
! && keysym <= XK_ISO_Enter)
#endif
! || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
! || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES
*/
#ifdef HPUX
! /* This recognizes the "extended function
! keys". It seems there's no cleaner way.
! Test IsModifierKey to avoid handling
! mode_switch incorrectly. */
! || ((unsigned) (keysym) >= XK_Select
! && (unsigned)(keysym) < XK_KP_Space)
#endif
#ifdef XK_dead_circumflex
! || orig_keysym == XK_dead_circumflex
#endif
#ifdef XK_dead_grave
! || orig_keysym == XK_dead_grave
#endif
#ifdef XK_dead_tilde
! || orig_keysym == XK_dead_tilde
#endif
#ifdef XK_dead_diaeresis
! || orig_keysym == XK_dead_diaeresis
#endif
#ifdef XK_dead_macron
! || orig_keysym == XK_dead_macron
#endif
#ifdef XK_dead_degree
! || orig_keysym == XK_dead_degree
#endif
#ifdef XK_dead_acute
! || orig_keysym == XK_dead_acute
#endif
#ifdef XK_dead_cedilla
! || orig_keysym == XK_dead_cedilla
#endif
#ifdef XK_dead_breve
! || orig_keysym == XK_dead_breve
#endif
#ifdef XK_dead_ogonek
! || orig_keysym == XK_dead_ogonek
#endif
#ifdef XK_dead_caron
! || orig_keysym == XK_dead_caron
#endif
#ifdef XK_dead_doubleacute
! || orig_keysym == XK_dead_doubleacute
#endif
#ifdef XK_dead_abovedot
! || orig_keysym == XK_dead_abovedot
#endif
! || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
! || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
! /* Any "vendor-specific" key is ok. */
! || (orig_keysym & (1 << 28))
! || (keysym != NoSymbol && nbytes == 0))
! && ! (IsModifierKey (orig_keysym)
#ifndef HAVE_X11R5
#ifdef XK_Mode_switch
! || ((unsigned)(orig_keysym) == XK_Mode_switch)
#endif
#ifdef XK_Num_Lock
! || ((unsigned)(orig_keysym) == XK_Num_Lock)
#endif
#endif /* not HAVE_X11R5 */
! /* The symbols from XK_ISO_Lock
! to XK_ISO_Last_Group_Lock
! don't have real modifiers but
! should be treated similarly to
! Mode_switch by Emacs. */
#if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
! || ((unsigned)(orig_keysym)
! >= XK_ISO_Lock
! && (unsigned)(orig_keysym)
! <= XK_ISO_Last_Group_Lock)
! #endif
! ))
! {
! if (temp_index == sizeof temp_buffer / sizeof (short))
! temp_index = 0;
! temp_buffer[temp_index++] = keysym;
! /* make_lispy_event will convert this to a symbolic
! key. */
! bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
! bufp->code = keysym;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! count++;
! numchars--;
! }
! else if (numchars > nbytes)
! { /* Raw bytes, not keysym. */
! register int i;
! register int c;
! int nchars, len;
!
! /* The input should be decoded with `coding_system'
! which depends on which X*LookupString function
! we used just above and the locale. */
! setup_coding_system (coding_system, &coding);
! coding.src_multibyte = 0;
! coding.dst_multibyte = 1;
! /* The input is converted to events, thus we can't
! handle composition. Anyway, there's no XIM that
! gives us composition information. */
! coding.composing = COMPOSITION_DISABLED;
!
! for (i = 0; i < nbytes; i++)
! {
! if (temp_index == (sizeof temp_buffer
! / sizeof (short)))
! temp_index = 0;
! temp_buffer[temp_index++] = copy_bufptr[i];
! }
!
! {
! /* Decode the input data. */
! int require;
! unsigned char *p;
!
! require = decoding_buffer_size (&coding, nbytes);
! p = (unsigned char *) alloca (require);
! coding.mode |= CODING_MODE_LAST_BLOCK;
! /* We explicitely disable composition
! handling because key data should
! not contain any composition
! sequence. */
! coding.composing = COMPOSITION_DISABLED;
! decode_coding (&coding, copy_bufptr, p,
! nbytes, require);
! nbytes = coding.produced;
! nchars = coding.produced_char;
! copy_bufptr = p;
! }
!
! /* Convert the input data to a sequence of
! character events. */
! for (i = 0; i < nbytes; i += len)
! {
! if (nchars == nbytes)
! c = copy_bufptr[i], len = 1;
! else
! c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
! nbytes - i, len);
!
! bufp->kind = (SINGLE_BYTE_CHAR_P (c)
! ? ASCII_KEYSTROKE_EVENT
! : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
! bufp->code = c;
! XSETFRAME (bufp->frame_or_window, f);
! bufp->arg = Qnil;
! bufp->modifiers
! = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
! modifiers);
! bufp->timestamp = event.xkey.time;
! bufp++;
! }
!
! count += nchars;
! numchars -= nchars;
!
! if (keysym == NoSymbol)
! break;
! }
! else
! abort ();
! }
! else
! abort ();
! }
#ifdef HAVE_X_I18N
! /* Don't dispatch this event since XtDispatchEvent calls
! XFilterEvent, and two calls in a row may freeze the
! client. */
! break;
#else
! goto OTHER;
#endif
! case KeyRelease:
#ifdef HAVE_X_I18N
! /* Don't dispatch this event since XtDispatchEvent calls
! XFilterEvent, and two calls in a row may freeze the
! client. */
! break;
#else
! goto OTHER;
#endif
! case EnterNotify:
! {
! int n;
! n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
! if (n > 0)
! {
! bufp += n, count += n, numchars -= n;
! }
! f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
#if 0
! if (event.xcrossing.focus)
! {
! /* Avoid nasty pop/raise loops. */
! if (f && (!(f->auto_raise)
! || !(f->auto_lower)
! || (event.xcrossing.time - enter_timestamp) > 500))
{
! x_new_focus_frame (dpyinfo, f);
! enter_timestamp = event.xcrossing.time;
}
+ }
+ else if (f == dpyinfo->x_focus_frame)
+ x_new_focus_frame (dpyinfo, 0);
+ #endif
+
+ /* EnterNotify counts as mouse movement,
+ so update things that depend on mouse position. */
+ if (f && !f->output_data.x->hourglass_p)
+ note_mouse_movement (f, &event.xmotion);
+ goto OTHER;
+ }
+
+ case FocusIn:
+ {
+ int n;
+
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
+
+ goto OTHER;
+
+ case LeaveNotify:
+ {
+ int n;
+
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
+
+ f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
+ if (f)
+ {
+ if (f == dpyinfo->mouse_face_mouse_frame)
+ {
+ /* If we move outside the frame, then we're
+ certainly no longer on any text in the frame. */
+ clear_mouse_face (dpyinfo);
+ dpyinfo->mouse_face_mouse_frame = 0;
+ }
+
+ /* Generate a nil HELP_EVENT to cancel a help-echo.
+ Do it only if there's something to cancel.
+ Otherwise, the startup message is cleared when
+ the mouse leaves the frame. */
+ if (any_help_event_p)
+ {
+ Lisp_Object frame;
+ int n;
+
+ XSETFRAME (frame, f);
+ help_echo = Qnil;
+ n = gen_help_event (bufp, numchars,
+ Qnil, frame, Qnil, Qnil, 0);
+ bufp += n, count += n, numchars -= n;
+ }
+
+ }
+ goto OTHER;
+
+ case FocusOut:
+ {
+ int n;
+
+ n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+ if (n > 0)
+ {
+ bufp += n, count += n, numchars -= n;
+ }
+ }
+
+ goto OTHER;
+
+ case MotionNotify:
+ {
+ previous_help_echo = help_echo;
+ help_echo = help_echo_object = help_echo_window = Qnil;
+ help_echo_pos = -1;
+
+ if (dpyinfo->grabbed && last_mouse_frame
+ && FRAME_LIVE_P (last_mouse_frame))
+ f = last_mouse_frame;
+ else
+ f = x_window_to_frame (dpyinfo, event.xmotion.window);
+
+ if (dpyinfo->mouse_face_hidden)
+ {
+ dpyinfo->mouse_face_hidden = 0;
+ clear_mouse_face (dpyinfo);
+ }
! if (f)
! {
! /* Generate SELECT_WINDOW_EVENTs when needed. */
! if (mouse_autoselect_window)
{
! Lisp_Object window;
! int area;
! window = window_from_coordinates (f,
! event.xmotion.x,
event.xmotion.y,
! &area, 0);
!
! /* Window will be selected only when it is not selected now
and
! last mouse movement event was not in it. Minibuffer window
! will be selected iff it is active. */
! if (WINDOWP(window)
! && !EQ (window, last_window)
! && !EQ (window, selected_window)
! && numchars > 0)
! {
! bufp->kind = SELECT_WINDOW_EVENT;
! bufp->frame_or_window = window;
! bufp->arg = Qnil;
! ++bufp, ++count, --numchars;
! }
! last_window=window;
}
! note_mouse_movement (f, &event.xmotion);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar
! = x_window_to_scroll_bar (event.xmotion.window);
! if (bar)
! x_scroll_bar_note_movement (bar, &event);
#endif /* USE_TOOLKIT_SCROLL_BARS */
! /* If we move outside the frame, then we're
! certainly no longer on any text in the frame. */
! clear_mouse_face (dpyinfo);
! }
!
! /* If the contents of the global variable help_echo
! has changed, generate a HELP_EVENT. */
! if (!NILP (help_echo)
! || !NILP (previous_help_echo))
! {
! Lisp_Object frame;
! int n;
!
! if (f)
! XSETFRAME (frame, f);
! else
! frame = Qnil;
!
! any_help_event_p = 1;
! n = gen_help_event (bufp, numchars, help_echo, frame,
! help_echo_window, help_echo_object,
! help_echo_pos);
! bufp += n, count += n, numchars -= n;
! }
!
! goto OTHER;
! }
!
! case ConfigureNotify:
! f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
! if (f)
! {
#ifndef USE_X_TOOLKIT
! /* If there is a pending resize for fullscreen, don't
! do this one, the right one will come later.
! The toolkit version doesn't seem to need this, but we
! need to reset it below. */
! int dont_resize =
! ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
! && FRAME_NEW_WIDTH (f) != 0);
! int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
! int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
! if (dont_resize)
! goto OTHER;
!
! /* In the toolkit version, change_frame_size
! is called by the code that handles resizing
! of the EmacsFrame widget. */
!
! /* Even if the number of character rows and columns has
! not changed, the font size may have changed, so we need
! to check the pixel dimensions as well. */
! if (columns != f->width
! || rows != f->height
! || event.xconfigure.width != f->output_data.x->pixel_width
! || event.xconfigure.height != f->output_data.x->pixel_height)
! {
! change_frame_size (f, rows, columns, 0, 1, 0);
! SET_FRAME_GARBAGED (f);
! cancel_mouse_face (f);
! }
! #endif
!
! f->output_data.x->pixel_width = event.xconfigure.width;
! f->output_data.x->pixel_height = event.xconfigure.height;
!
! /* What we have now is the position of Emacs's own window.
! Convert that to the position of the window manager window. */
! x_real_positions (f, &f->output_data.x->left_pos,
! &f->output_data.x->top_pos);
!
! x_check_fullscreen_move(f);
! if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
! f->output_data.x->want_fullscreen &=
! ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
#ifdef HAVE_X_I18N
! if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
! xic_set_statusarea (f);
#endif
! if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO
(f)->root_window)
! {
! /* Since the WM decorations come below top_pos now,
! we must put them below top_pos in the future. */
! f->output_data.x->win_gravity = NorthWestGravity;
! x_wm_set_size_hint (f, (long) 0, 0);
! }
! }
! goto OTHER;
!
! case ButtonPress:
! case ButtonRelease:
! {
! /* If we decide we want to generate an event to be seen
! by the rest of Emacs, we put it here. */
! struct input_event emacs_event;
! int tool_bar_p = 0;
!
! emacs_event.kind = NO_EVENT;
! bzero (&compose_status, sizeof (compose_status));
!
! if (dpyinfo->grabbed
! && last_mouse_frame
! && FRAME_LIVE_P (last_mouse_frame))
! f = last_mouse_frame;
! else
! f = x_window_to_frame (dpyinfo, event.xbutton.window);
!
! if (f)
! {
! /* Is this in the tool-bar? */
! if (WINDOWP (f->tool_bar_window)
! && XFASTINT (XWINDOW (f->tool_bar_window)->height))
! {
! Lisp_Object window;
! int p, x, y;
!
! x = event.xbutton.x;
! y = event.xbutton.y;
!
! /* Set x and y. */
! window = window_from_coordinates (f, x, y, &p, 1);
! if (EQ (window, f->tool_bar_window))
! {
! x_handle_tool_bar_click (f, &event.xbutton);
! tool_bar_p = 1;
! }
! }
!
! if (!tool_bar_p)
! if (!dpyinfo->x_focus_frame
! || f == dpyinfo->x_focus_frame)
! construct_mouse_click (&emacs_event, &event, f);
! }
! else
! {
#ifndef USE_TOOLKIT_SCROLL_BARS
! struct scroll_bar *bar
! = x_window_to_scroll_bar (event.xbutton.window);
! if (bar)
! x_scroll_bar_handle_click (bar, &event, &emacs_event);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
! }
! if (event.type == ButtonPress)
! {
! dpyinfo->grabbed |= (1 << event.xbutton.button);
! last_mouse_frame = f;
! /* Ignore any mouse motion that happened
! before this event; any subsequent mouse-movement
! Emacs events should reflect only motion after
! the ButtonPress. */
! if (f != 0)
! f->mouse_moved = 0;
!
! if (!tool_bar_p)
! last_tool_bar_item = -1;
! }
! else
! {
! dpyinfo->grabbed &= ~(1 << event.xbutton.button);
! }
!
! if (numchars >= 1 && emacs_event.kind != NO_EVENT)
! {
! bcopy (&emacs_event, bufp, sizeof (struct input_event));
! bufp++;
! count++;
! numchars--;
! }
#ifdef USE_X_TOOLKIT
! f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
! /* For a down-event in the menu bar,
! don't pass it to Xt right now.
! Instead, save it away
! and we will pass it to Xt from kbd_buffer_get_event.
! That way, we can run some Lisp code first. */
! if (f && event.type == ButtonPress
! /* Verify the event is really within the menu bar
! and not just sent to it due to grabbing. */
! && event.xbutton.x >= 0
! && event.xbutton.x < f->output_data.x->pixel_width
! && event.xbutton.y >= 0
! && event.xbutton.y < f->output_data.x->menubar_height
! && event.xbutton.same_screen)
! {
! SET_SAVED_BUTTON_EVENT;
! XSETFRAME (last_mouse_press_frame, f);
! }
! else if (event.type == ButtonPress)
! {
! last_mouse_press_frame = Qnil;
! goto OTHER;
! }
#ifdef USE_MOTIF /* This should do not harm for Lucid,
but I am trying to be cautious. */
! else if (event.type == ButtonRelease)
! {
! if (!NILP (last_mouse_press_frame))
! {
! f = XFRAME (last_mouse_press_frame);
! if (f->output_data.x)
! SET_SAVED_BUTTON_EVENT;
! }
! else
! goto OTHER;
! }
#endif /* USE_MOTIF */
! else
! goto OTHER;
#endif /* USE_X_TOOLKIT */
! }
! break;
! case CirculateNotify:
! goto OTHER;
! case CirculateRequest:
! goto OTHER;
! case VisibilityNotify:
! goto OTHER;
!
! case MappingNotify:
! /* Someone has changed the keyboard mapping - update the
! local cache. */
! switch (event.xmapping.request)
! {
! case MappingModifier:
! x_find_modifier_meanings (dpyinfo);
! /* This is meant to fall through. */
! case MappingKeyboard:
! XRefreshKeyboardMapping (&event.xmapping);
! }
! goto OTHER;
! default:
! OTHER:
#ifdef USE_X_TOOLKIT
! BLOCK_INPUT;
! XtDispatchEvent (&event);
! UNBLOCK_INPUT;
#endif /* USE_X_TOOLKIT */
! break;
! }
!
! goto ret;
!
! out:
! *finish = X_EVENT_GOTO_OUT;
!
! ret:
! *bufp_r = bufp;
! *numcharsp = numchars;
! *eventp = event;
!
! return count;
! }
!
!
! /* Handles the XEvent EVENT on display DISPLAY.
! This is used for event loops outside the normal event handling,
! i.e. looping while a popup menu or a dialog is posted. */
! void
! x_dispatch_event (event, display)
! XEvent *event;
! Display *display;
! {
! struct x_display_info *dpyinfo;
! struct input_event bufp[10];
! struct input_event *bufpp = bufp;
! int numchars = 10;
! int finish;
!
! for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
! if (dpyinfo->display == display)
! break;
!
! if (dpyinfo)
! {
! int i, events;
! events = handle_one_xevent (dpyinfo,
! event,
! &bufpp,
! &numchars,
! &finish);
! for (i = 0; i < events; ++i)
! kbd_buffer_store_event (&bufp[i]);
! }
! }
!
!
! /* Read events coming from the X server.
! This routine is called by the SIGIO handler.
! We return as soon as there are no more events to be read.
!
! Events representing keys are stored in buffer BUFP,
! which can hold up to NUMCHARS characters.
! We return the number of characters stored into the buffer,
! thus pretending to be `read'.
!
! EXPECTED is nonzero if the caller knows input is available. */
!
! static int
! XTread_socket (sd, bufp, numchars, expected)
! register int sd;
! /* register */ struct input_event *bufp;
! /* register */ int numchars;
! int expected;
! {
! int count = 0;
! int nbytes = 0;
! XEvent event;
! int event_found = 0;
! struct x_display_info *dpyinfo;
!
! if (interrupt_input_blocked)
! {
! interrupt_input_pending = 1;
! return -1;
! }
!
! interrupt_input_pending = 0;
! BLOCK_INPUT;
!
! /* So people can tell when we have read the available input. */
! input_signal_count++;
!
! if (numchars <= 0)
! abort (); /* Don't think this happens. */
!
! ++handling_signal;
!
! /* Find the display we are supposed to read input for.
! It's the one communicating on descriptor SD. */
! for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
! {
! #if 0 /* This ought to be unnecessary; let's verify it. */
! #ifdef FIOSNBIO
! /* If available, Xlib uses FIOSNBIO to make the socket
! non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
! FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
! a read returns 0, which Xlib interprets as equivalent to EPIPE. */
! fcntl (dpyinfo->connection, F_SETFL, 0);
! #endif /* ! defined (FIOSNBIO) */
! #endif
!
! #if 0 /* This code can't be made to work, with multiple displays,
! and appears not to be used on any system any more.
! Also keyboard.c doesn't turn O_NDELAY on and off
! for X connections. */
! #ifndef SIGIO
! #ifndef HAVE_SELECT
! if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
! {
! extern int read_alarm_should_throw;
! read_alarm_should_throw = 1;
! XPeekEvent (dpyinfo->display, &event);
! read_alarm_should_throw = 0;
! }
! #endif /* HAVE_SELECT */
! #endif /* SIGIO */
! #endif
!
! /* For debugging, this gives a way to fake an I/O error. */
! if (dpyinfo == XTread_socket_fake_io_error)
! {
! XTread_socket_fake_io_error = 0;
! x_io_error_quitter (dpyinfo->display);
}
+
+ #ifdef HAVE_X_SM
+ BLOCK_INPUT;
+ count += x_session_check_input (bufp, &numchars);
+ UNBLOCK_INPUT;
+ #endif
+
+ while (XPending (dpyinfo->display))
+ {
+ int finish;
+
+ XNextEvent (dpyinfo->display, &event);
+
+ #ifdef HAVE_X_I18N
+ {
+ /* Filter events for the current X input method.
+ XFilterEvent returns non-zero if the input method has
+ consumed the event. We pass the frame's X window to
+ XFilterEvent because that's the one for which the IC
+ was created. */
+ struct frame *f1 = x_any_window_to_frame (dpyinfo,
+ event.xclient.window);
+ if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
+ break;
+ }
+ #endif
+ event_found = 1;
+
+ count += handle_one_xevent (dpyinfo,
+ &event,
+ &bufp,
+ &numchars,
+ &finish);
+
+ if (finish == X_EVENT_GOTO_OUT)
+ goto out;
+ }
}
out:;