comparison src/xterm.c @ 49117:f8288cd7d1cd

*** empty log message ***
author Jan Djärv <jan.h.d@swipnet.se>
date Wed, 08 Jan 2003 20:06:05 +0000
parents 6b6ac8aa78d2
children 2cbb0b823e83
comparison
equal deleted inserted replaced
49116:8c37b25a7f02 49117:f8288cd7d1cd
9932 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)), 9932 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9933 0, 0, 0, 0, True); 9933 0, 0, 0, 0, True);
9934 #endif /* not USE_TOOLKIT_SCROLL_BARS */ 9934 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9935 } 9935 }
9936 9936
9937 /* This processes Expose events from the menu-bar specific X event
9938 loop in xmenu.c. This allows to redisplay the frame if necessary
9939 when handling menu-bar or pop-up items. */
9940
9941 int
9942 process_expose_from_menu (event)
9943 XEvent event;
9944 {
9945 FRAME_PTR f;
9946 struct x_display_info *dpyinfo;
9947 int frame_exposed_p = 0;
9948
9949 BLOCK_INPUT;
9950
9951 dpyinfo = x_display_info_for_display (event.xexpose.display);
9952 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9953 if (f)
9954 {
9955 if (f->async_visible == 0)
9956 {
9957 f->async_visible = 1;
9958 f->async_iconified = 0;
9959 f->output_data.x->has_been_visible = 1;
9960 SET_FRAME_GARBAGED (f);
9961 }
9962 else
9963 {
9964 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9965 event.xexpose.x, event.xexpose.y,
9966 event.xexpose.width, event.xexpose.height);
9967 frame_exposed_p = 1;
9968 }
9969 }
9970 else
9971 {
9972 struct scroll_bar *bar
9973 = x_window_to_scroll_bar (event.xexpose.window);
9974
9975 if (bar)
9976 x_scroll_bar_expose (bar, &event);
9977 }
9978
9979 UNBLOCK_INPUT;
9980 return frame_exposed_p;
9981 }
9982 9937
9983 /* Define a queue to save up SelectionRequest events for later handling. */ 9938 /* Define a queue to save up SelectionRequest events for later handling. */
9984 9939
9985 struct selection_event_queue 9940 struct selection_event_queue
9986 { 9941 {
10105 while (0) 10060 while (0)
10106 10061
10107 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent)) 10062 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10108 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent)) 10063 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10109 10064
10065
10066 enum
10067 {
10068 X_EVENT_NORMAL,
10069 X_EVENT_GOTO_OUT,
10070 X_EVENT_DROP
10071 };
10072
10073 /* Handles the XEvent EVENT on display DPYINFO.
10074
10075 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
10076 *FINISH is zero if caller should continue reading events.
10077 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
10078
10079 Events representing keys are stored in buffer *BUFP_R,
10080 which can hold up to *NUMCHARSP characters.
10081 We return the number of characters stored into the buffer. */
10082
10083 static int
10084 handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
10085 struct x_display_info *dpyinfo;
10086 XEvent *eventp;
10087 /* register */ struct input_event **bufp_r;
10088 /* register */ int *numcharsp;
10089 int *finish;
10090 {
10091 int count = 0;
10092 int nbytes = 0;
10093 struct frame *f;
10094 struct coding_system coding;
10095 struct input_event *bufp = *bufp_r;
10096 int numchars = *numcharsp;
10097 XEvent event = *eventp;
10098
10099 *finish = X_EVENT_NORMAL;
10100
10101 switch (event.type)
10102 {
10103 case ClientMessage:
10104 {
10105 if (event.xclient.message_type
10106 == dpyinfo->Xatom_wm_protocols
10107 && event.xclient.format == 32)
10108 {
10109 if (event.xclient.data.l[0]
10110 == dpyinfo->Xatom_wm_take_focus)
10111 {
10112 /* Use x_any_window_to_frame because this
10113 could be the shell widget window
10114 if the frame has no title bar. */
10115 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10116 #ifdef HAVE_X_I18N
10117 /* Not quite sure this is needed -pd */
10118 if (f && FRAME_XIC (f))
10119 XSetICFocus (FRAME_XIC (f));
10120 #endif
10121 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10122 instructs the WM to set the input focus automatically for
10123 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10124 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10125 it has set the focus. So, XSetInputFocus below is not
10126 needed.
10127
10128 The call to XSetInputFocus below has also caused trouble. In
10129 cases where the XSetInputFocus done by the WM and the one
10130 below are temporally close (on a fast machine), the call
10131 below can generate additional FocusIn events which confuse
10132 Emacs. */
10133
10134 /* Since we set WM_TAKE_FOCUS, we must call
10135 XSetInputFocus explicitly. But not if f is null,
10136 since that might be an event for a deleted frame. */
10137 if (f)
10138 {
10139 Display *d = event.xclient.display;
10140 /* Catch and ignore errors, in case window has been
10141 iconified by a window manager such as GWM. */
10142 int count = x_catch_errors (d);
10143 XSetInputFocus (d, event.xclient.window,
10144 /* The ICCCM says this is
10145 the only valid choice. */
10146 RevertToParent,
10147 event.xclient.data.l[1]);
10148 /* This is needed to detect the error
10149 if there is an error. */
10150 XSync (d, False);
10151 x_uncatch_errors (d, count);
10152 }
10153 /* Not certain about handling scroll bars here */
10154 #endif /* 0 */
10155 }
10156 else if (event.xclient.data.l[0]
10157 == dpyinfo->Xatom_wm_save_yourself)
10158 {
10159 /* Save state modify the WM_COMMAND property to
10160 something which can reinstate us. This notifies
10161 the session manager, who's looking for such a
10162 PropertyNotify. Can restart processing when
10163 a keyboard or mouse event arrives. */
10164 /* If we have a session manager, don't set this.
10165 KDE will then start two Emacsen, one for the
10166 session manager and one for this. */
10167 if (numchars > 0
10168 #ifdef HAVE_X_SM
10169 && ! x_session_have_connection ()
10170 #endif
10171 )
10172 {
10173 f = x_top_window_to_frame (dpyinfo,
10174 event.xclient.window);
10175 /* This is just so we only give real data once
10176 for a single Emacs process. */
10177 if (f == SELECTED_FRAME ())
10178 XSetCommand (FRAME_X_DISPLAY (f),
10179 event.xclient.window,
10180 initial_argv, initial_argc);
10181 else if (f)
10182 XSetCommand (FRAME_X_DISPLAY (f),
10183 event.xclient.window,
10184 0, 0);
10185 }
10186 }
10187 else if (event.xclient.data.l[0]
10188 == dpyinfo->Xatom_wm_delete_window)
10189 {
10190 struct frame *f
10191 = x_any_window_to_frame (dpyinfo,
10192 event.xclient.window);
10193
10194 if (f)
10195 {
10196 if (numchars == 0)
10197 abort ();
10198
10199 bufp->kind = DELETE_WINDOW_EVENT;
10200 XSETFRAME (bufp->frame_or_window, f);
10201 bufp->arg = Qnil;
10202 bufp++;
10203
10204 count += 1;
10205 numchars -= 1;
10206 }
10207 else
10208 goto OTHER; /* May be a dialog that is to be removed */
10209 }
10210 }
10211 else if (event.xclient.message_type
10212 == dpyinfo->Xatom_wm_configure_denied)
10213 {
10214 }
10215 else if (event.xclient.message_type
10216 == dpyinfo->Xatom_wm_window_moved)
10217 {
10218 int new_x, new_y;
10219 struct frame *f
10220 = x_window_to_frame (dpyinfo, event.xclient.window);
10221
10222 new_x = event.xclient.data.s[0];
10223 new_y = event.xclient.data.s[1];
10224
10225 if (f)
10226 {
10227 f->output_data.x->left_pos = new_x;
10228 f->output_data.x->top_pos = new_y;
10229 }
10230 }
10231 #ifdef HACK_EDITRES
10232 else if (event.xclient.message_type
10233 == dpyinfo->Xatom_editres)
10234 {
10235 struct frame *f
10236 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10237 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10238 &event, NULL);
10239 }
10240 #endif /* HACK_EDITRES */
10241 else if ((event.xclient.message_type
10242 == dpyinfo->Xatom_DONE)
10243 || (event.xclient.message_type
10244 == dpyinfo->Xatom_PAGE))
10245 {
10246 /* Ghostview job completed. Kill it. We could
10247 reply with "Next" if we received "Page", but we
10248 currently never do because we are interested in
10249 images, only, which should have 1 page. */
10250 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10251 struct frame *f
10252 = x_window_to_frame (dpyinfo, event.xclient.window);
10253 x_kill_gs_process (pixmap, f);
10254 expose_frame (f, 0, 0, 0, 0);
10255 }
10256 #ifdef USE_TOOLKIT_SCROLL_BARS
10257 /* Scroll bar callbacks send a ClientMessage from which
10258 we construct an input_event. */
10259 else if (event.xclient.message_type
10260 == dpyinfo->Xatom_Scrollbar)
10261 {
10262 x_scroll_bar_to_input_event (&event, bufp);
10263 ++bufp, ++count, --numchars;
10264 goto out;
10265 }
10266 #endif /* USE_TOOLKIT_SCROLL_BARS */
10267 else
10268 goto OTHER;
10269 }
10270 break;
10271
10272 case SelectionNotify:
10273 #ifdef USE_X_TOOLKIT
10274 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10275 goto OTHER;
10276 #endif /* not USE_X_TOOLKIT */
10277 x_handle_selection_notify (&event.xselection);
10278 break;
10279
10280 case SelectionClear: /* Someone has grabbed ownership. */
10281 #ifdef USE_X_TOOLKIT
10282 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10283 goto OTHER;
10284 #endif /* USE_X_TOOLKIT */
10285 {
10286 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10287
10288 if (numchars == 0)
10289 abort ();
10290
10291 bufp->kind = SELECTION_CLEAR_EVENT;
10292 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10293 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10294 SELECTION_EVENT_TIME (bufp) = eventp->time;
10295 bufp->frame_or_window = Qnil;
10296 bufp->arg = Qnil;
10297 bufp++;
10298
10299 count += 1;
10300 numchars -= 1;
10301 }
10302 break;
10303
10304 case SelectionRequest: /* Someone wants our selection. */
10305 #ifdef USE_X_TOOLKIT
10306 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10307 goto OTHER;
10308 #endif /* USE_X_TOOLKIT */
10309 if (x_queue_selection_requests)
10310 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10311 &event);
10312 else
10313 {
10314 XSelectionRequestEvent *eventp
10315 = (XSelectionRequestEvent *) &event;
10316
10317 if (numchars == 0)
10318 abort ();
10319
10320 bufp->kind = SELECTION_REQUEST_EVENT;
10321 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10322 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10323 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10324 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10325 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10326 SELECTION_EVENT_TIME (bufp) = eventp->time;
10327 bufp->frame_or_window = Qnil;
10328 bufp->arg = Qnil;
10329 bufp++;
10330
10331 count += 1;
10332 numchars -= 1;
10333 }
10334 break;
10335
10336 case PropertyNotify:
10337 #if 0 /* This is plain wrong. In the case that we are waiting for a
10338 PropertyNotify used as an ACK in incremental selection
10339 transfer, the property will be on the receiver's window. */
10340 #if defined USE_X_TOOLKIT
10341 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10342 goto OTHER;
10343 #endif
10344 #endif
10345 x_handle_property_notify (&event.xproperty);
10346 goto OTHER;
10347
10348 case ReparentNotify:
10349 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10350 if (f)
10351 {
10352 int x, y;
10353 f->output_data.x->parent_desc = event.xreparent.parent;
10354 x_real_positions (f, &x, &y);
10355 f->output_data.x->left_pos = x;
10356 f->output_data.x->top_pos = y;
10357 goto OTHER;
10358 }
10359 break;
10360
10361 case Expose:
10362 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10363 if (f)
10364 {
10365 x_check_fullscreen (f);
10366
10367 if (f->async_visible == 0)
10368 {
10369 f->async_visible = 1;
10370 f->async_iconified = 0;
10371 f->output_data.x->has_been_visible = 1;
10372 SET_FRAME_GARBAGED (f);
10373 }
10374 else
10375 expose_frame (x_window_to_frame (dpyinfo,
10376 event.xexpose.window),
10377 event.xexpose.x, event.xexpose.y,
10378 event.xexpose.width, event.xexpose.height);
10379 }
10380 else
10381 {
10382 #ifndef USE_TOOLKIT_SCROLL_BARS
10383 struct scroll_bar *bar;
10384 #endif
10385 #if defined USE_LUCID
10386 /* Submenus of the Lucid menu bar aren't widgets
10387 themselves, so there's no way to dispatch events
10388 to them. Recognize this case separately. */
10389 {
10390 Widget widget
10391 = x_window_to_menu_bar (event.xexpose.window);
10392 if (widget)
10393 xlwmenu_redisplay (widget);
10394 }
10395 #endif /* USE_LUCID */
10396
10397 #ifdef USE_TOOLKIT_SCROLL_BARS
10398 /* Dispatch event to the widget. */
10399 goto OTHER;
10400 #else /* not USE_TOOLKIT_SCROLL_BARS */
10401 bar = x_window_to_scroll_bar (event.xexpose.window);
10402
10403 if (bar)
10404 x_scroll_bar_expose (bar, &event);
10405 #ifdef USE_X_TOOLKIT
10406 else
10407 goto OTHER;
10408 #endif /* USE_X_TOOLKIT */
10409 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10410 }
10411 break;
10412
10413 case GraphicsExpose: /* This occurs when an XCopyArea's
10414 source area was obscured or not
10415 available. */
10416 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10417 if (f)
10418 {
10419 expose_frame (f,
10420 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10421 event.xgraphicsexpose.width,
10422 event.xgraphicsexpose.height);
10423 }
10424 #ifdef USE_X_TOOLKIT
10425 else
10426 goto OTHER;
10427 #endif /* USE_X_TOOLKIT */
10428 break;
10429
10430 case NoExpose: /* This occurs when an XCopyArea's
10431 source area was completely
10432 available. */
10433 break;
10434
10435 case UnmapNotify:
10436 /* Redo the mouse-highlight after the tooltip has gone. */
10437 if (event.xmap.window == tip_window)
10438 {
10439 tip_window = 0;
10440 redo_mouse_highlight ();
10441 }
10442
10443 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10444 if (f) /* F may no longer exist if
10445 the frame was deleted. */
10446 {
10447 /* While a frame is unmapped, display generation is
10448 disabled; you don't want to spend time updating a
10449 display that won't ever be seen. */
10450 f->async_visible = 0;
10451 /* We can't distinguish, from the event, whether the window
10452 has become iconified or invisible. So assume, if it
10453 was previously visible, than now it is iconified.
10454 But x_make_frame_invisible clears both
10455 the visible flag and the iconified flag;
10456 and that way, we know the window is not iconified now. */
10457 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10458 {
10459 f->async_iconified = 1;
10460
10461 bufp->kind = ICONIFY_EVENT;
10462 XSETFRAME (bufp->frame_or_window, f);
10463 bufp->arg = Qnil;
10464 bufp++;
10465 count++;
10466 numchars--;
10467 }
10468 }
10469 goto OTHER;
10470
10471 case MapNotify:
10472 if (event.xmap.window == tip_window)
10473 /* The tooltip has been drawn already. Avoid
10474 the SET_FRAME_GARBAGED below. */
10475 goto OTHER;
10476
10477 /* We use x_top_window_to_frame because map events can
10478 come for sub-windows and they don't mean that the
10479 frame is visible. */
10480 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10481 if (f)
10482 {
10483 /* wait_reading_process_input will notice this and update
10484 the frame's display structures.
10485 If we where iconified, we should not set garbaged,
10486 because that stops redrawing on Expose events. This looks
10487 bad if we are called from a recursive event loop
10488 (x_dispatch_event), for example when a dialog is up. */
10489 if (! f->async_iconified)
10490 SET_FRAME_GARBAGED (f);
10491
10492 f->async_visible = 1;
10493 f->async_iconified = 0;
10494 f->output_data.x->has_been_visible = 1;
10495
10496 if (f->iconified)
10497 {
10498 bufp->kind = DEICONIFY_EVENT;
10499 XSETFRAME (bufp->frame_or_window, f);
10500 bufp->arg = Qnil;
10501 bufp++;
10502 count++;
10503 numchars--;
10504 }
10505 else if (! NILP (Vframe_list)
10506 && ! NILP (XCDR (Vframe_list)))
10507 /* Force a redisplay sooner or later
10508 to update the frame titles
10509 in case this is the second frame. */
10510 record_asynch_buffer_change ();
10511 }
10512 goto OTHER;
10513
10514 case KeyPress:
10515
10516 /* Dispatch KeyPress events when in menu. */
10517 if (popup_activated_flag)
10518 goto OTHER;
10519 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10520
10521 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10522 {
10523 dpyinfo->mouse_face_hidden = 1;
10524 clear_mouse_face (dpyinfo);
10525 }
10526
10527 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10528 if (f == 0)
10529 {
10530 /* Scroll bars consume key events, but we want
10531 the keys to go to the scroll bar's frame. */
10532 Widget widget = XtWindowToWidget (dpyinfo->display,
10533 event.xkey.window);
10534 if (widget && XmIsScrollBar (widget))
10535 {
10536 widget = XtParent (widget);
10537 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10538 }
10539 }
10540 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10541
10542 if (f != 0)
10543 {
10544 KeySym keysym, orig_keysym;
10545 /* al%imercury@uunet.uu.net says that making this 81
10546 instead of 80 fixed a bug whereby meta chars made
10547 his Emacs hang.
10548
10549 It seems that some version of XmbLookupString has
10550 a bug of not returning XBufferOverflow in
10551 status_return even if the input is too long to
10552 fit in 81 bytes. So, we must prepare sufficient
10553 bytes for copy_buffer. 513 bytes (256 chars for
10554 two-byte character set) seems to be a fairly good
10555 approximation. -- 2000.8.10 handa@etl.go.jp */
10556 unsigned char copy_buffer[513];
10557 unsigned char *copy_bufptr = copy_buffer;
10558 int copy_bufsiz = sizeof (copy_buffer);
10559 int modifiers;
10560 Lisp_Object coding_system = Qlatin_1;
10561
10562 event.xkey.state
10563 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10564 extra_keyboard_modifiers);
10565 modifiers = event.xkey.state;
10566
10567 /* This will have to go some day... */
10568
10569 /* make_lispy_event turns chars into control chars.
10570 Don't do it here because XLookupString is too eager. */
10571 event.xkey.state &= ~ControlMask;
10572 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10573 | dpyinfo->super_mod_mask
10574 | dpyinfo->hyper_mod_mask
10575 | dpyinfo->alt_mod_mask);
10576
10577 /* In case Meta is ComposeCharacter,
10578 clear its status. According to Markus Ehrnsperger
10579 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10580 this enables ComposeCharacter to work whether or
10581 not it is combined with Meta. */
10582 if (modifiers & dpyinfo->meta_mod_mask)
10583 bzero (&compose_status, sizeof (compose_status));
10584
10585 #ifdef HAVE_X_I18N
10586 if (FRAME_XIC (f))
10587 {
10588 Status status_return;
10589
10590 coding_system = Vlocale_coding_system;
10591 nbytes = XmbLookupString (FRAME_XIC (f),
10592 &event.xkey, copy_bufptr,
10593 copy_bufsiz, &keysym,
10594 &status_return);
10595 if (status_return == XBufferOverflow)
10596 {
10597 copy_bufsiz = nbytes + 1;
10598 copy_bufptr = (char *) alloca (copy_bufsiz);
10599 nbytes = XmbLookupString (FRAME_XIC (f),
10600 &event.xkey, copy_bufptr,
10601 copy_bufsiz, &keysym,
10602 &status_return);
10603 }
10604 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10605 #if 0 && defined X_HAVE_UTF8_STRING
10606 else if (status_return == XLookupKeySym)
10607 { /* Try again but with utf-8. */
10608 coding_system = Qutf_8;
10609 nbytes = Xutf8LookupString (FRAME_XIC (f),
10610 &event.xkey, copy_bufptr,
10611 copy_bufsiz, &keysym,
10612 &status_return);
10613 if (status_return == XBufferOverflow)
10614 {
10615 copy_bufsiz = nbytes + 1;
10616 copy_bufptr = (char *) alloca (copy_bufsiz);
10617 nbytes = Xutf8LookupString (FRAME_XIC (f),
10618 &event.xkey,
10619 copy_bufptr,
10620 copy_bufsiz, &keysym,
10621 &status_return);
10622 }
10623 }
10624 #endif
10625
10626 if (status_return == XLookupNone)
10627 break;
10628 else if (status_return == XLookupChars)
10629 {
10630 keysym = NoSymbol;
10631 modifiers = 0;
10632 }
10633 else if (status_return != XLookupKeySym
10634 && status_return != XLookupBoth)
10635 abort ();
10636 }
10637 else
10638 nbytes = XLookupString (&event.xkey, copy_bufptr,
10639 copy_bufsiz, &keysym,
10640 &compose_status);
10641 #else
10642 nbytes = XLookupString (&event.xkey, copy_bufptr,
10643 copy_bufsiz, &keysym,
10644 &compose_status);
10645 #endif
10646
10647 orig_keysym = keysym;
10648
10649 if (numchars > 1)
10650 {
10651 Lisp_Object c;
10652
10653 /* First deal with keysyms which have defined
10654 translations to characters. */
10655 if (keysym >= 32 && keysym < 128)
10656 /* Avoid explicitly decoding each ASCII character. */
10657 {
10658 bufp->kind = ASCII_KEYSTROKE_EVENT;
10659 bufp->code = keysym;
10660 XSETFRAME (bufp->frame_or_window, f);
10661 bufp->arg = Qnil;
10662 bufp->modifiers
10663 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10664 modifiers);
10665 bufp->timestamp = event.xkey.time;
10666 bufp++;
10667 count++;
10668 numchars--;
10669 }
10670 /* Now non-ASCII. */
10671 else if (HASH_TABLE_P (Vx_keysym_table)
10672 && (NATNUMP (c = Fgethash (make_number (keysym),
10673 Vx_keysym_table,
10674 Qnil))))
10675 {
10676 bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
10677 ? ASCII_KEYSTROKE_EVENT
10678 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10679 bufp->code = XFASTINT (c);
10680 XSETFRAME (bufp->frame_or_window, f);
10681 bufp->arg = Qnil;
10682 bufp->modifiers
10683 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10684 modifiers);
10685 bufp->timestamp = event.xkey.time;
10686 bufp++;
10687 count++;
10688 numchars--;
10689 }
10690 /* Random non-modifier sorts of keysyms. */
10691 else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10692 || keysym == XK_Delete
10693 #ifdef XK_ISO_Left_Tab
10694 || (keysym >= XK_ISO_Left_Tab
10695 && keysym <= XK_ISO_Enter)
10696 #endif
10697 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10698 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10699 #ifdef HPUX
10700 /* This recognizes the "extended function
10701 keys". It seems there's no cleaner way.
10702 Test IsModifierKey to avoid handling
10703 mode_switch incorrectly. */
10704 || ((unsigned) (keysym) >= XK_Select
10705 && (unsigned)(keysym) < XK_KP_Space)
10706 #endif
10707 #ifdef XK_dead_circumflex
10708 || orig_keysym == XK_dead_circumflex
10709 #endif
10710 #ifdef XK_dead_grave
10711 || orig_keysym == XK_dead_grave
10712 #endif
10713 #ifdef XK_dead_tilde
10714 || orig_keysym == XK_dead_tilde
10715 #endif
10716 #ifdef XK_dead_diaeresis
10717 || orig_keysym == XK_dead_diaeresis
10718 #endif
10719 #ifdef XK_dead_macron
10720 || orig_keysym == XK_dead_macron
10721 #endif
10722 #ifdef XK_dead_degree
10723 || orig_keysym == XK_dead_degree
10724 #endif
10725 #ifdef XK_dead_acute
10726 || orig_keysym == XK_dead_acute
10727 #endif
10728 #ifdef XK_dead_cedilla
10729 || orig_keysym == XK_dead_cedilla
10730 #endif
10731 #ifdef XK_dead_breve
10732 || orig_keysym == XK_dead_breve
10733 #endif
10734 #ifdef XK_dead_ogonek
10735 || orig_keysym == XK_dead_ogonek
10736 #endif
10737 #ifdef XK_dead_caron
10738 || orig_keysym == XK_dead_caron
10739 #endif
10740 #ifdef XK_dead_doubleacute
10741 || orig_keysym == XK_dead_doubleacute
10742 #endif
10743 #ifdef XK_dead_abovedot
10744 || orig_keysym == XK_dead_abovedot
10745 #endif
10746 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10747 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10748 /* Any "vendor-specific" key is ok. */
10749 || (orig_keysym & (1 << 28))
10750 || (keysym != NoSymbol && nbytes == 0))
10751 && ! (IsModifierKey (orig_keysym)
10752 #ifndef HAVE_X11R5
10753 #ifdef XK_Mode_switch
10754 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10755 #endif
10756 #ifdef XK_Num_Lock
10757 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10758 #endif
10759 #endif /* not HAVE_X11R5 */
10760 /* The symbols from XK_ISO_Lock
10761 to XK_ISO_Last_Group_Lock
10762 don't have real modifiers but
10763 should be treated similarly to
10764 Mode_switch by Emacs. */
10765 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10766 || ((unsigned)(orig_keysym)
10767 >= XK_ISO_Lock
10768 && (unsigned)(orig_keysym)
10769 <= XK_ISO_Last_Group_Lock)
10770 #endif
10771 ))
10772 {
10773 if (temp_index == sizeof temp_buffer / sizeof (short))
10774 temp_index = 0;
10775 temp_buffer[temp_index++] = keysym;
10776 /* make_lispy_event will convert this to a symbolic
10777 key. */
10778 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10779 bufp->code = keysym;
10780 XSETFRAME (bufp->frame_or_window, f);
10781 bufp->arg = Qnil;
10782 bufp->modifiers
10783 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10784 modifiers);
10785 bufp->timestamp = event.xkey.time;
10786 bufp++;
10787 count++;
10788 numchars--;
10789 }
10790 else if (numchars > nbytes)
10791 { /* Raw bytes, not keysym. */
10792 register int i;
10793 register int c;
10794 int nchars, len;
10795
10796 /* The input should be decoded with `coding_system'
10797 which depends on which X*LookupString function
10798 we used just above and the locale. */
10799 setup_coding_system (coding_system, &coding);
10800 coding.src_multibyte = 0;
10801 coding.dst_multibyte = 1;
10802 /* The input is converted to events, thus we can't
10803 handle composition. Anyway, there's no XIM that
10804 gives us composition information. */
10805 coding.composing = COMPOSITION_DISABLED;
10806
10807 for (i = 0; i < nbytes; i++)
10808 {
10809 if (temp_index == (sizeof temp_buffer
10810 / sizeof (short)))
10811 temp_index = 0;
10812 temp_buffer[temp_index++] = copy_bufptr[i];
10813 }
10814
10815 {
10816 /* Decode the input data. */
10817 int require;
10818 unsigned char *p;
10819
10820 require = decoding_buffer_size (&coding, nbytes);
10821 p = (unsigned char *) alloca (require);
10822 coding.mode |= CODING_MODE_LAST_BLOCK;
10823 /* We explicitely disable composition
10824 handling because key data should
10825 not contain any composition
10826 sequence. */
10827 coding.composing = COMPOSITION_DISABLED;
10828 decode_coding (&coding, copy_bufptr, p,
10829 nbytes, require);
10830 nbytes = coding.produced;
10831 nchars = coding.produced_char;
10832 copy_bufptr = p;
10833 }
10834
10835 /* Convert the input data to a sequence of
10836 character events. */
10837 for (i = 0; i < nbytes; i += len)
10838 {
10839 if (nchars == nbytes)
10840 c = copy_bufptr[i], len = 1;
10841 else
10842 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10843 nbytes - i, len);
10844
10845 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10846 ? ASCII_KEYSTROKE_EVENT
10847 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10848 bufp->code = c;
10849 XSETFRAME (bufp->frame_or_window, f);
10850 bufp->arg = Qnil;
10851 bufp->modifiers
10852 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10853 modifiers);
10854 bufp->timestamp = event.xkey.time;
10855 bufp++;
10856 }
10857
10858 count += nchars;
10859 numchars -= nchars;
10860
10861 if (keysym == NoSymbol)
10862 break;
10863 }
10864 else
10865 abort ();
10866 }
10867 else
10868 abort ();
10869 }
10870 #ifdef HAVE_X_I18N
10871 /* Don't dispatch this event since XtDispatchEvent calls
10872 XFilterEvent, and two calls in a row may freeze the
10873 client. */
10874 break;
10875 #else
10876 goto OTHER;
10877 #endif
10878
10879 case KeyRelease:
10880 #ifdef HAVE_X_I18N
10881 /* Don't dispatch this event since XtDispatchEvent calls
10882 XFilterEvent, and two calls in a row may freeze the
10883 client. */
10884 break;
10885 #else
10886 goto OTHER;
10887 #endif
10888
10889 case EnterNotify:
10890 {
10891 int n;
10892
10893 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10894 if (n > 0)
10895 {
10896 bufp += n, count += n, numchars -= n;
10897 }
10898
10899 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10900
10901 #if 0
10902 if (event.xcrossing.focus)
10903 {
10904 /* Avoid nasty pop/raise loops. */
10905 if (f && (!(f->auto_raise)
10906 || !(f->auto_lower)
10907 || (event.xcrossing.time - enter_timestamp) > 500))
10908 {
10909 x_new_focus_frame (dpyinfo, f);
10910 enter_timestamp = event.xcrossing.time;
10911 }
10912 }
10913 else if (f == dpyinfo->x_focus_frame)
10914 x_new_focus_frame (dpyinfo, 0);
10915 #endif
10916
10917 /* EnterNotify counts as mouse movement,
10918 so update things that depend on mouse position. */
10919 if (f && !f->output_data.x->hourglass_p)
10920 note_mouse_movement (f, &event.xmotion);
10921 goto OTHER;
10922 }
10923
10924 case FocusIn:
10925 {
10926 int n;
10927
10928 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10929 if (n > 0)
10930 {
10931 bufp += n, count += n, numchars -= n;
10932 }
10933 }
10934
10935 goto OTHER;
10936
10937 case LeaveNotify:
10938 {
10939 int n;
10940
10941 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10942 if (n > 0)
10943 {
10944 bufp += n, count += n, numchars -= n;
10945 }
10946 }
10947
10948 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10949 if (f)
10950 {
10951 if (f == dpyinfo->mouse_face_mouse_frame)
10952 {
10953 /* If we move outside the frame, then we're
10954 certainly no longer on any text in the frame. */
10955 clear_mouse_face (dpyinfo);
10956 dpyinfo->mouse_face_mouse_frame = 0;
10957 }
10958
10959 /* Generate a nil HELP_EVENT to cancel a help-echo.
10960 Do it only if there's something to cancel.
10961 Otherwise, the startup message is cleared when
10962 the mouse leaves the frame. */
10963 if (any_help_event_p)
10964 {
10965 Lisp_Object frame;
10966 int n;
10967
10968 XSETFRAME (frame, f);
10969 help_echo = Qnil;
10970 n = gen_help_event (bufp, numchars,
10971 Qnil, frame, Qnil, Qnil, 0);
10972 bufp += n, count += n, numchars -= n;
10973 }
10974
10975 }
10976 goto OTHER;
10977
10978 case FocusOut:
10979 {
10980 int n;
10981
10982 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10983 if (n > 0)
10984 {
10985 bufp += n, count += n, numchars -= n;
10986 }
10987 }
10988
10989 goto OTHER;
10990
10991 case MotionNotify:
10992 {
10993 previous_help_echo = help_echo;
10994 help_echo = help_echo_object = help_echo_window = Qnil;
10995 help_echo_pos = -1;
10996
10997 if (dpyinfo->grabbed && last_mouse_frame
10998 && FRAME_LIVE_P (last_mouse_frame))
10999 f = last_mouse_frame;
11000 else
11001 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11002
11003 if (dpyinfo->mouse_face_hidden)
11004 {
11005 dpyinfo->mouse_face_hidden = 0;
11006 clear_mouse_face (dpyinfo);
11007 }
11008
11009 if (f)
11010 {
11011
11012 /* Generate SELECT_WINDOW_EVENTs when needed. */
11013 if (mouse_autoselect_window)
11014 {
11015 Lisp_Object window;
11016 int area;
11017
11018 window = window_from_coordinates (f,
11019 event.xmotion.x, event.xmotion.y,
11020 &area, 0);
11021
11022 /* Window will be selected only when it is not selected now and
11023 last mouse movement event was not in it. Minibuffer window
11024 will be selected iff it is active. */
11025 if (WINDOWP(window)
11026 && !EQ (window, last_window)
11027 && !EQ (window, selected_window)
11028 && numchars > 0)
11029 {
11030 bufp->kind = SELECT_WINDOW_EVENT;
11031 bufp->frame_or_window = window;
11032 bufp->arg = Qnil;
11033 ++bufp, ++count, --numchars;
11034 }
11035
11036 last_window=window;
11037 }
11038 note_mouse_movement (f, &event.xmotion);
11039 }
11040 else
11041 {
11042 #ifndef USE_TOOLKIT_SCROLL_BARS
11043 struct scroll_bar *bar
11044 = x_window_to_scroll_bar (event.xmotion.window);
11045
11046 if (bar)
11047 x_scroll_bar_note_movement (bar, &event);
11048 #endif /* USE_TOOLKIT_SCROLL_BARS */
11049
11050 /* If we move outside the frame, then we're
11051 certainly no longer on any text in the frame. */
11052 clear_mouse_face (dpyinfo);
11053 }
11054
11055 /* If the contents of the global variable help_echo
11056 has changed, generate a HELP_EVENT. */
11057 if (!NILP (help_echo)
11058 || !NILP (previous_help_echo))
11059 {
11060 Lisp_Object frame;
11061 int n;
11062
11063 if (f)
11064 XSETFRAME (frame, f);
11065 else
11066 frame = Qnil;
11067
11068 any_help_event_p = 1;
11069 n = gen_help_event (bufp, numchars, help_echo, frame,
11070 help_echo_window, help_echo_object,
11071 help_echo_pos);
11072 bufp += n, count += n, numchars -= n;
11073 }
11074
11075 goto OTHER;
11076 }
11077
11078 case ConfigureNotify:
11079 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11080 if (f)
11081 {
11082 #ifndef USE_X_TOOLKIT
11083 /* If there is a pending resize for fullscreen, don't
11084 do this one, the right one will come later.
11085 The toolkit version doesn't seem to need this, but we
11086 need to reset it below. */
11087 int dont_resize =
11088 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11089 && FRAME_NEW_WIDTH (f) != 0);
11090 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11091 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11092 if (dont_resize)
11093 goto OTHER;
11094
11095 /* In the toolkit version, change_frame_size
11096 is called by the code that handles resizing
11097 of the EmacsFrame widget. */
11098
11099 /* Even if the number of character rows and columns has
11100 not changed, the font size may have changed, so we need
11101 to check the pixel dimensions as well. */
11102 if (columns != f->width
11103 || rows != f->height
11104 || event.xconfigure.width != f->output_data.x->pixel_width
11105 || event.xconfigure.height != f->output_data.x->pixel_height)
11106 {
11107 change_frame_size (f, rows, columns, 0, 1, 0);
11108 SET_FRAME_GARBAGED (f);
11109 cancel_mouse_face (f);
11110 }
11111 #endif
11112
11113 f->output_data.x->pixel_width = event.xconfigure.width;
11114 f->output_data.x->pixel_height = event.xconfigure.height;
11115
11116 /* What we have now is the position of Emacs's own window.
11117 Convert that to the position of the window manager window. */
11118 x_real_positions (f, &f->output_data.x->left_pos,
11119 &f->output_data.x->top_pos);
11120
11121 x_check_fullscreen_move(f);
11122 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11123 f->output_data.x->want_fullscreen &=
11124 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11125 #ifdef HAVE_X_I18N
11126 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11127 xic_set_statusarea (f);
11128 #endif
11129
11130 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11131 {
11132 /* Since the WM decorations come below top_pos now,
11133 we must put them below top_pos in the future. */
11134 f->output_data.x->win_gravity = NorthWestGravity;
11135 x_wm_set_size_hint (f, (long) 0, 0);
11136 }
11137 }
11138 goto OTHER;
11139
11140 case ButtonPress:
11141 case ButtonRelease:
11142 {
11143 /* If we decide we want to generate an event to be seen
11144 by the rest of Emacs, we put it here. */
11145 struct input_event emacs_event;
11146 int tool_bar_p = 0;
11147
11148 emacs_event.kind = NO_EVENT;
11149 bzero (&compose_status, sizeof (compose_status));
11150
11151 if (dpyinfo->grabbed
11152 && last_mouse_frame
11153 && FRAME_LIVE_P (last_mouse_frame))
11154 f = last_mouse_frame;
11155 else
11156 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11157
11158 if (f)
11159 {
11160 /* Is this in the tool-bar? */
11161 if (WINDOWP (f->tool_bar_window)
11162 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11163 {
11164 Lisp_Object window;
11165 int p, x, y;
11166
11167 x = event.xbutton.x;
11168 y = event.xbutton.y;
11169
11170 /* Set x and y. */
11171 window = window_from_coordinates (f, x, y, &p, 1);
11172 if (EQ (window, f->tool_bar_window))
11173 {
11174 x_handle_tool_bar_click (f, &event.xbutton);
11175 tool_bar_p = 1;
11176 }
11177 }
11178
11179 if (!tool_bar_p)
11180 if (!dpyinfo->x_focus_frame
11181 || f == dpyinfo->x_focus_frame)
11182 construct_mouse_click (&emacs_event, &event, f);
11183 }
11184 else
11185 {
11186 #ifndef USE_TOOLKIT_SCROLL_BARS
11187 struct scroll_bar *bar
11188 = x_window_to_scroll_bar (event.xbutton.window);
11189
11190 if (bar)
11191 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11192 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11193 }
11194
11195 if (event.type == ButtonPress)
11196 {
11197 dpyinfo->grabbed |= (1 << event.xbutton.button);
11198 last_mouse_frame = f;
11199 /* Ignore any mouse motion that happened
11200 before this event; any subsequent mouse-movement
11201 Emacs events should reflect only motion after
11202 the ButtonPress. */
11203 if (f != 0)
11204 f->mouse_moved = 0;
11205
11206 if (!tool_bar_p)
11207 last_tool_bar_item = -1;
11208 }
11209 else
11210 {
11211 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11212 }
11213
11214 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11215 {
11216 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11217 bufp++;
11218 count++;
11219 numchars--;
11220 }
11221
11222 #ifdef USE_X_TOOLKIT
11223 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11224 /* For a down-event in the menu bar,
11225 don't pass it to Xt right now.
11226 Instead, save it away
11227 and we will pass it to Xt from kbd_buffer_get_event.
11228 That way, we can run some Lisp code first. */
11229 if (f && event.type == ButtonPress
11230 /* Verify the event is really within the menu bar
11231 and not just sent to it due to grabbing. */
11232 && event.xbutton.x >= 0
11233 && event.xbutton.x < f->output_data.x->pixel_width
11234 && event.xbutton.y >= 0
11235 && event.xbutton.y < f->output_data.x->menubar_height
11236 && event.xbutton.same_screen)
11237 {
11238 SET_SAVED_BUTTON_EVENT;
11239 XSETFRAME (last_mouse_press_frame, f);
11240 }
11241 else if (event.type == ButtonPress)
11242 {
11243 last_mouse_press_frame = Qnil;
11244 goto OTHER;
11245 }
11246
11247 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11248 but I am trying to be cautious. */
11249 else if (event.type == ButtonRelease)
11250 {
11251 if (!NILP (last_mouse_press_frame))
11252 {
11253 f = XFRAME (last_mouse_press_frame);
11254 if (f->output_data.x)
11255 SET_SAVED_BUTTON_EVENT;
11256 }
11257 else
11258 goto OTHER;
11259 }
11260 #endif /* USE_MOTIF */
11261 else
11262 goto OTHER;
11263 #endif /* USE_X_TOOLKIT */
11264 }
11265 break;
11266
11267 case CirculateNotify:
11268 goto OTHER;
11269
11270 case CirculateRequest:
11271 goto OTHER;
11272
11273 case VisibilityNotify:
11274 goto OTHER;
11275
11276 case MappingNotify:
11277 /* Someone has changed the keyboard mapping - update the
11278 local cache. */
11279 switch (event.xmapping.request)
11280 {
11281 case MappingModifier:
11282 x_find_modifier_meanings (dpyinfo);
11283 /* This is meant to fall through. */
11284 case MappingKeyboard:
11285 XRefreshKeyboardMapping (&event.xmapping);
11286 }
11287 goto OTHER;
11288
11289 default:
11290 OTHER:
11291 #ifdef USE_X_TOOLKIT
11292 BLOCK_INPUT;
11293 XtDispatchEvent (&event);
11294 UNBLOCK_INPUT;
11295 #endif /* USE_X_TOOLKIT */
11296 break;
11297 }
11298
11299 goto ret;
11300
11301 out:
11302 *finish = X_EVENT_GOTO_OUT;
11303
11304 ret:
11305 *bufp_r = bufp;
11306 *numcharsp = numchars;
11307 *eventp = event;
11308
11309 return count;
11310 }
11311
11312
11313 /* Handles the XEvent EVENT on display DISPLAY.
11314 This is used for event loops outside the normal event handling,
11315 i.e. looping while a popup menu or a dialog is posted. */
11316 void
11317 x_dispatch_event (event, display)
11318 XEvent *event;
11319 Display *display;
11320 {
11321 struct x_display_info *dpyinfo;
11322 struct input_event bufp[10];
11323 struct input_event *bufpp = bufp;
11324 int numchars = 10;
11325 int finish;
11326
11327 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
11328 if (dpyinfo->display == display)
11329 break;
11330
11331 if (dpyinfo)
11332 {
11333 int i, events;
11334 events = handle_one_xevent (dpyinfo,
11335 event,
11336 &bufpp,
11337 &numchars,
11338 &finish);
11339 for (i = 0; i < events; ++i)
11340 kbd_buffer_store_event (&bufp[i]);
11341 }
11342 }
11343
11344
10110 /* Read events coming from the X server. 11345 /* Read events coming from the X server.
10111 This routine is called by the SIGIO handler. 11346 This routine is called by the SIGIO handler.
10112 We return as soon as there are no more events to be read. 11347 We return as soon as there are no more events to be read.
10113 11348
10114 Events representing keys are stored in buffer BUFP, 11349 Events representing keys are stored in buffer BUFP,
10126 int expected; 11361 int expected;
10127 { 11362 {
10128 int count = 0; 11363 int count = 0;
10129 int nbytes = 0; 11364 int nbytes = 0;
10130 XEvent event; 11365 XEvent event;
10131 struct frame *f;
10132 int event_found = 0; 11366 int event_found = 0;
10133 struct x_display_info *dpyinfo; 11367 struct x_display_info *dpyinfo;
10134 struct coding_system coding;
10135 11368
10136 if (interrupt_input_blocked) 11369 if (interrupt_input_blocked)
10137 { 11370 {
10138 interrupt_input_pending = 1; 11371 interrupt_input_pending = 1;
10139 return -1; 11372 return -1;
10194 UNBLOCK_INPUT; 11427 UNBLOCK_INPUT;
10195 #endif 11428 #endif
10196 11429
10197 while (XPending (dpyinfo->display)) 11430 while (XPending (dpyinfo->display))
10198 { 11431 {
11432 int finish;
11433
10199 XNextEvent (dpyinfo->display, &event); 11434 XNextEvent (dpyinfo->display, &event);
10200 11435
10201 #ifdef HAVE_X_I18N 11436 #ifdef HAVE_X_I18N
10202 { 11437 {
10203 /* Filter events for the current X input method. 11438 /* Filter events for the current X input method.
10211 break; 11446 break;
10212 } 11447 }
10213 #endif 11448 #endif
10214 event_found = 1; 11449 event_found = 1;
10215 11450
10216 switch (event.type) 11451 count += handle_one_xevent (dpyinfo,
10217 { 11452 &event,
10218 case ClientMessage: 11453 &bufp,
10219 { 11454 &numchars,
10220 if (event.xclient.message_type 11455 &finish);
10221 == dpyinfo->Xatom_wm_protocols 11456
10222 && event.xclient.format == 32) 11457 if (finish == X_EVENT_GOTO_OUT)
10223 { 11458 goto out;
10224 if (event.xclient.data.l[0] 11459 }
10225 == dpyinfo->Xatom_wm_take_focus)
10226 {
10227 /* Use x_any_window_to_frame because this
10228 could be the shell widget window
10229 if the frame has no title bar. */
10230 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10231 #ifdef HAVE_X_I18N
10232 /* Not quite sure this is needed -pd */
10233 if (f && FRAME_XIC (f))
10234 XSetICFocus (FRAME_XIC (f));
10235 #endif
10236 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10237 instructs the WM to set the input focus automatically for
10238 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10239 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10240 it has set the focus. So, XSetInputFocus below is not
10241 needed.
10242
10243 The call to XSetInputFocus below has also caused trouble. In
10244 cases where the XSetInputFocus done by the WM and the one
10245 below are temporally close (on a fast machine), the call
10246 below can generate additional FocusIn events which confuse
10247 Emacs. */
10248
10249 /* Since we set WM_TAKE_FOCUS, we must call
10250 XSetInputFocus explicitly. But not if f is null,
10251 since that might be an event for a deleted frame. */
10252 if (f)
10253 {
10254 Display *d = event.xclient.display;
10255 /* Catch and ignore errors, in case window has been
10256 iconified by a window manager such as GWM. */
10257 int count = x_catch_errors (d);
10258 XSetInputFocus (d, event.xclient.window,
10259 /* The ICCCM says this is
10260 the only valid choice. */
10261 RevertToParent,
10262 event.xclient.data.l[1]);
10263 /* This is needed to detect the error
10264 if there is an error. */
10265 XSync (d, False);
10266 x_uncatch_errors (d, count);
10267 }
10268 /* Not certain about handling scroll bars here */
10269 #endif /* 0 */
10270 }
10271 else if (event.xclient.data.l[0]
10272 == dpyinfo->Xatom_wm_save_yourself)
10273 {
10274 /* Save state modify the WM_COMMAND property to
10275 something which can reinstate us. This notifies
10276 the session manager, who's looking for such a
10277 PropertyNotify. Can restart processing when
10278 a keyboard or mouse event arrives. */
10279 /* If we have a session manager, don't set this.
10280 KDE will then start two Emacsen, one for the
10281 session manager and one for this. */
10282 if (numchars > 0
10283 #ifdef HAVE_X_SM
10284 && ! x_session_have_connection ()
10285 #endif
10286 )
10287 {
10288 f = x_top_window_to_frame (dpyinfo,
10289 event.xclient.window);
10290 /* This is just so we only give real data once
10291 for a single Emacs process. */
10292 if (f == SELECTED_FRAME ())
10293 XSetCommand (FRAME_X_DISPLAY (f),
10294 event.xclient.window,
10295 initial_argv, initial_argc);
10296 else if (f)
10297 XSetCommand (FRAME_X_DISPLAY (f),
10298 event.xclient.window,
10299 0, 0);
10300 }
10301 }
10302 else if (event.xclient.data.l[0]
10303 == dpyinfo->Xatom_wm_delete_window)
10304 {
10305 struct frame *f
10306 = x_any_window_to_frame (dpyinfo,
10307 event.xclient.window);
10308
10309 if (f)
10310 {
10311 if (numchars == 0)
10312 abort ();
10313
10314 bufp->kind = DELETE_WINDOW_EVENT;
10315 XSETFRAME (bufp->frame_or_window, f);
10316 bufp->arg = Qnil;
10317 bufp++;
10318
10319 count += 1;
10320 numchars -= 1;
10321 }
10322 }
10323 }
10324 else if (event.xclient.message_type
10325 == dpyinfo->Xatom_wm_configure_denied)
10326 {
10327 }
10328 else if (event.xclient.message_type
10329 == dpyinfo->Xatom_wm_window_moved)
10330 {
10331 int new_x, new_y;
10332 struct frame *f
10333 = x_window_to_frame (dpyinfo, event.xclient.window);
10334
10335 new_x = event.xclient.data.s[0];
10336 new_y = event.xclient.data.s[1];
10337
10338 if (f)
10339 {
10340 f->output_data.x->left_pos = new_x;
10341 f->output_data.x->top_pos = new_y;
10342 }
10343 }
10344 #ifdef HACK_EDITRES
10345 else if (event.xclient.message_type
10346 == dpyinfo->Xatom_editres)
10347 {
10348 struct frame *f
10349 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10350 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10351 &event, NULL);
10352 }
10353 #endif /* HACK_EDITRES */
10354 else if ((event.xclient.message_type
10355 == dpyinfo->Xatom_DONE)
10356 || (event.xclient.message_type
10357 == dpyinfo->Xatom_PAGE))
10358 {
10359 /* Ghostview job completed. Kill it. We could
10360 reply with "Next" if we received "Page", but we
10361 currently never do because we are interested in
10362 images, only, which should have 1 page. */
10363 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10364 struct frame *f
10365 = x_window_to_frame (dpyinfo, event.xclient.window);
10366 x_kill_gs_process (pixmap, f);
10367 expose_frame (f, 0, 0, 0, 0);
10368 }
10369 #ifdef USE_TOOLKIT_SCROLL_BARS
10370 /* Scroll bar callbacks send a ClientMessage from which
10371 we construct an input_event. */
10372 else if (event.xclient.message_type
10373 == dpyinfo->Xatom_Scrollbar)
10374 {
10375 x_scroll_bar_to_input_event (&event, bufp);
10376 ++bufp, ++count, --numchars;
10377 goto out;
10378 }
10379 #endif /* USE_TOOLKIT_SCROLL_BARS */
10380 else
10381 goto OTHER;
10382 }
10383 break;
10384
10385 case SelectionNotify:
10386 #ifdef USE_X_TOOLKIT
10387 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10388 goto OTHER;
10389 #endif /* not USE_X_TOOLKIT */
10390 x_handle_selection_notify (&event.xselection);
10391 break;
10392
10393 case SelectionClear: /* Someone has grabbed ownership. */
10394 #ifdef USE_X_TOOLKIT
10395 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10396 goto OTHER;
10397 #endif /* USE_X_TOOLKIT */
10398 {
10399 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10400
10401 if (numchars == 0)
10402 abort ();
10403
10404 bufp->kind = SELECTION_CLEAR_EVENT;
10405 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10406 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10407 SELECTION_EVENT_TIME (bufp) = eventp->time;
10408 bufp->frame_or_window = Qnil;
10409 bufp->arg = Qnil;
10410 bufp++;
10411
10412 count += 1;
10413 numchars -= 1;
10414 }
10415 break;
10416
10417 case SelectionRequest: /* Someone wants our selection. */
10418 #ifdef USE_X_TOOLKIT
10419 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10420 goto OTHER;
10421 #endif /* USE_X_TOOLKIT */
10422 if (x_queue_selection_requests)
10423 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10424 &event);
10425 else
10426 {
10427 XSelectionRequestEvent *eventp
10428 = (XSelectionRequestEvent *) &event;
10429
10430 if (numchars == 0)
10431 abort ();
10432
10433 bufp->kind = SELECTION_REQUEST_EVENT;
10434 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10435 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10436 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10437 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10438 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10439 SELECTION_EVENT_TIME (bufp) = eventp->time;
10440 bufp->frame_or_window = Qnil;
10441 bufp->arg = Qnil;
10442 bufp++;
10443
10444 count += 1;
10445 numchars -= 1;
10446 }
10447 break;
10448
10449 case PropertyNotify:
10450 #if 0 /* This is plain wrong. In the case that we are waiting for a
10451 PropertyNotify used as an ACK in incremental selection
10452 transfer, the property will be on the receiver's window. */
10453 #if defined USE_X_TOOLKIT
10454 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10455 goto OTHER;
10456 #endif
10457 #endif
10458 x_handle_property_notify (&event.xproperty);
10459 goto OTHER;
10460
10461 case ReparentNotify:
10462 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10463 if (f)
10464 {
10465 int x, y;
10466 f->output_data.x->parent_desc = event.xreparent.parent;
10467 x_real_positions (f, &x, &y);
10468 f->output_data.x->left_pos = x;
10469 f->output_data.x->top_pos = y;
10470 goto OTHER;
10471 }
10472 break;
10473
10474 case Expose:
10475 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10476 if (f)
10477 {
10478 x_check_fullscreen (f);
10479
10480 if (f->async_visible == 0)
10481 {
10482 f->async_visible = 1;
10483 f->async_iconified = 0;
10484 f->output_data.x->has_been_visible = 1;
10485 SET_FRAME_GARBAGED (f);
10486 }
10487 else
10488 expose_frame (x_window_to_frame (dpyinfo,
10489 event.xexpose.window),
10490 event.xexpose.x, event.xexpose.y,
10491 event.xexpose.width, event.xexpose.height);
10492 }
10493 else
10494 {
10495 #ifndef USE_TOOLKIT_SCROLL_BARS
10496 struct scroll_bar *bar;
10497 #endif
10498 #if defined USE_LUCID
10499 /* Submenus of the Lucid menu bar aren't widgets
10500 themselves, so there's no way to dispatch events
10501 to them. Recognize this case separately. */
10502 {
10503 Widget widget
10504 = x_window_to_menu_bar (event.xexpose.window);
10505 if (widget)
10506 xlwmenu_redisplay (widget);
10507 }
10508 #endif /* USE_LUCID */
10509
10510 #ifdef USE_TOOLKIT_SCROLL_BARS
10511 /* Dispatch event to the widget. */
10512 goto OTHER;
10513 #else /* not USE_TOOLKIT_SCROLL_BARS */
10514 bar = x_window_to_scroll_bar (event.xexpose.window);
10515
10516 if (bar)
10517 x_scroll_bar_expose (bar, &event);
10518 #ifdef USE_X_TOOLKIT
10519 else
10520 goto OTHER;
10521 #endif /* USE_X_TOOLKIT */
10522 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10523 }
10524 break;
10525
10526 case GraphicsExpose: /* This occurs when an XCopyArea's
10527 source area was obscured or not
10528 available. */
10529 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10530 if (f)
10531 {
10532 expose_frame (f,
10533 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10534 event.xgraphicsexpose.width,
10535 event.xgraphicsexpose.height);
10536 }
10537 #ifdef USE_X_TOOLKIT
10538 else
10539 goto OTHER;
10540 #endif /* USE_X_TOOLKIT */
10541 break;
10542
10543 case NoExpose: /* This occurs when an XCopyArea's
10544 source area was completely
10545 available. */
10546 break;
10547
10548 case UnmapNotify:
10549 /* Redo the mouse-highlight after the tooltip has gone. */
10550 if (event.xmap.window == tip_window)
10551 {
10552 tip_window = 0;
10553 redo_mouse_highlight ();
10554 }
10555
10556 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10557 if (f) /* F may no longer exist if
10558 the frame was deleted. */
10559 {
10560 /* While a frame is unmapped, display generation is
10561 disabled; you don't want to spend time updating a
10562 display that won't ever be seen. */
10563 f->async_visible = 0;
10564 /* We can't distinguish, from the event, whether the window
10565 has become iconified or invisible. So assume, if it
10566 was previously visible, than now it is iconified.
10567 But x_make_frame_invisible clears both
10568 the visible flag and the iconified flag;
10569 and that way, we know the window is not iconified now. */
10570 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10571 {
10572 f->async_iconified = 1;
10573
10574 bufp->kind = ICONIFY_EVENT;
10575 XSETFRAME (bufp->frame_or_window, f);
10576 bufp->arg = Qnil;
10577 bufp++;
10578 count++;
10579 numchars--;
10580 }
10581 }
10582 goto OTHER;
10583
10584 case MapNotify:
10585 if (event.xmap.window == tip_window)
10586 /* The tooltip has been drawn already. Avoid
10587 the SET_FRAME_GARBAGED below. */
10588 goto OTHER;
10589
10590 /* We use x_top_window_to_frame because map events can
10591 come for sub-windows and they don't mean that the
10592 frame is visible. */
10593 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10594 if (f)
10595 {
10596 f->async_visible = 1;
10597 f->async_iconified = 0;
10598 f->output_data.x->has_been_visible = 1;
10599
10600 /* wait_reading_process_input will notice this and update
10601 the frame's display structures. */
10602 SET_FRAME_GARBAGED (f);
10603
10604 if (f->iconified)
10605 {
10606 bufp->kind = DEICONIFY_EVENT;
10607 XSETFRAME (bufp->frame_or_window, f);
10608 bufp->arg = Qnil;
10609 bufp++;
10610 count++;
10611 numchars--;
10612 }
10613 else if (! NILP (Vframe_list)
10614 && ! NILP (XCDR (Vframe_list)))
10615 /* Force a redisplay sooner or later
10616 to update the frame titles
10617 in case this is the second frame. */
10618 record_asynch_buffer_change ();
10619 }
10620 goto OTHER;
10621
10622 case KeyPress:
10623
10624 /* Dispatch KeyPress events when in menu. */
10625 if (popup_activated_flag)
10626 goto OTHER;
10627
10628 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10629
10630 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10631 {
10632 dpyinfo->mouse_face_hidden = 1;
10633 clear_mouse_face (dpyinfo);
10634 }
10635
10636 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10637 if (f == 0)
10638 {
10639 /* Scroll bars consume key events, but we want
10640 the keys to go to the scroll bar's frame. */
10641 Widget widget = XtWindowToWidget (dpyinfo->display,
10642 event.xkey.window);
10643 if (widget && XmIsScrollBar (widget))
10644 {
10645 widget = XtParent (widget);
10646 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10647 }
10648 }
10649 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10650
10651 if (f != 0)
10652 {
10653 KeySym keysym, orig_keysym;
10654 /* al%imercury@uunet.uu.net says that making this 81
10655 instead of 80 fixed a bug whereby meta chars made
10656 his Emacs hang.
10657
10658 It seems that some version of XmbLookupString has
10659 a bug of not returning XBufferOverflow in
10660 status_return even if the input is too long to
10661 fit in 81 bytes. So, we must prepare sufficient
10662 bytes for copy_buffer. 513 bytes (256 chars for
10663 two-byte character set) seems to be a fairly good
10664 approximation. -- 2000.8.10 handa@etl.go.jp */
10665 unsigned char copy_buffer[513];
10666 unsigned char *copy_bufptr = copy_buffer;
10667 int copy_bufsiz = sizeof (copy_buffer);
10668 int modifiers;
10669 Lisp_Object coding_system = Qlatin_1;
10670
10671 event.xkey.state
10672 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10673 extra_keyboard_modifiers);
10674 modifiers = event.xkey.state;
10675
10676 /* This will have to go some day... */
10677
10678 /* make_lispy_event turns chars into control chars.
10679 Don't do it here because XLookupString is too eager. */
10680 event.xkey.state &= ~ControlMask;
10681 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10682 | dpyinfo->super_mod_mask
10683 | dpyinfo->hyper_mod_mask
10684 | dpyinfo->alt_mod_mask);
10685
10686 /* In case Meta is ComposeCharacter,
10687 clear its status. According to Markus Ehrnsperger
10688 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10689 this enables ComposeCharacter to work whether or
10690 not it is combined with Meta. */
10691 if (modifiers & dpyinfo->meta_mod_mask)
10692 bzero (&compose_status, sizeof (compose_status));
10693
10694 #ifdef HAVE_X_I18N
10695 if (FRAME_XIC (f))
10696 {
10697 Status status_return;
10698
10699 coding_system = Vlocale_coding_system;
10700 nbytes = XmbLookupString (FRAME_XIC (f),
10701 &event.xkey, copy_bufptr,
10702 copy_bufsiz, &keysym,
10703 &status_return);
10704 if (status_return == XBufferOverflow)
10705 {
10706 copy_bufsiz = nbytes + 1;
10707 copy_bufptr = (char *) alloca (copy_bufsiz);
10708 nbytes = XmbLookupString (FRAME_XIC (f),
10709 &event.xkey, copy_bufptr,
10710 copy_bufsiz, &keysym,
10711 &status_return);
10712 }
10713 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10714 #if 0 && defined X_HAVE_UTF8_STRING
10715 else if (status_return == XLookupKeySym)
10716 { /* Try again but with utf-8. */
10717 coding_system = Qutf_8;
10718 nbytes = Xutf8LookupString (FRAME_XIC (f),
10719 &event.xkey, copy_bufptr,
10720 copy_bufsiz, &keysym,
10721 &status_return);
10722 if (status_return == XBufferOverflow)
10723 {
10724 copy_bufsiz = nbytes + 1;
10725 copy_bufptr = (char *) alloca (copy_bufsiz);
10726 nbytes = Xutf8LookupString (FRAME_XIC (f),
10727 &event.xkey,
10728 copy_bufptr,
10729 copy_bufsiz, &keysym,
10730 &status_return);
10731 }
10732 }
10733 #endif
10734
10735 if (status_return == XLookupNone)
10736 break;
10737 else if (status_return == XLookupChars)
10738 {
10739 keysym = NoSymbol;
10740 modifiers = 0;
10741 }
10742 else if (status_return != XLookupKeySym
10743 && status_return != XLookupBoth)
10744 abort ();
10745 }
10746 else
10747 nbytes = XLookupString (&event.xkey, copy_bufptr,
10748 copy_bufsiz, &keysym,
10749 &compose_status);
10750 #else
10751 nbytes = XLookupString (&event.xkey, copy_bufptr,
10752 copy_bufsiz, &keysym,
10753 &compose_status);
10754 #endif
10755
10756 orig_keysym = keysym;
10757
10758 if (numchars > 1)
10759 {
10760 Lisp_Object c;
10761
10762 /* First deal with keysyms which have defined
10763 translations to characters. */
10764 if (keysym >= 32 && keysym < 128)
10765 /* Avoid explicitly decoding each ASCII character. */
10766 {
10767 bufp->kind = ASCII_KEYSTROKE_EVENT;
10768 bufp->code = keysym;
10769 XSETFRAME (bufp->frame_or_window, f);
10770 bufp->arg = Qnil;
10771 bufp->modifiers
10772 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10773 modifiers);
10774 bufp->timestamp = event.xkey.time;
10775 bufp++;
10776 count++;
10777 numchars--;
10778 }
10779 /* Now non-ASCII. */
10780 else if (HASH_TABLE_P (Vx_keysym_table)
10781 && (NATNUMP (c = Fgethash (make_number (keysym),
10782 Vx_keysym_table,
10783 Qnil))))
10784 {
10785 bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
10786 ? ASCII_KEYSTROKE_EVENT
10787 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10788 bufp->code = XFASTINT (c);
10789 XSETFRAME (bufp->frame_or_window, f);
10790 bufp->arg = Qnil;
10791 bufp->modifiers
10792 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10793 modifiers);
10794 bufp->timestamp = event.xkey.time;
10795 bufp++;
10796 count++;
10797 numchars--;
10798 }
10799 /* Random non-modifier sorts of keysyms. */
10800 else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10801 || keysym == XK_Delete
10802 #ifdef XK_ISO_Left_Tab
10803 || (keysym >= XK_ISO_Left_Tab
10804 && keysym <= XK_ISO_Enter)
10805 #endif
10806 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10807 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10808 #ifdef HPUX
10809 /* This recognizes the "extended function
10810 keys". It seems there's no cleaner way.
10811 Test IsModifierKey to avoid handling
10812 mode_switch incorrectly. */
10813 || ((unsigned) (keysym) >= XK_Select
10814 && (unsigned)(keysym) < XK_KP_Space)
10815 #endif
10816 #ifdef XK_dead_circumflex
10817 || orig_keysym == XK_dead_circumflex
10818 #endif
10819 #ifdef XK_dead_grave
10820 || orig_keysym == XK_dead_grave
10821 #endif
10822 #ifdef XK_dead_tilde
10823 || orig_keysym == XK_dead_tilde
10824 #endif
10825 #ifdef XK_dead_diaeresis
10826 || orig_keysym == XK_dead_diaeresis
10827 #endif
10828 #ifdef XK_dead_macron
10829 || orig_keysym == XK_dead_macron
10830 #endif
10831 #ifdef XK_dead_degree
10832 || orig_keysym == XK_dead_degree
10833 #endif
10834 #ifdef XK_dead_acute
10835 || orig_keysym == XK_dead_acute
10836 #endif
10837 #ifdef XK_dead_cedilla
10838 || orig_keysym == XK_dead_cedilla
10839 #endif
10840 #ifdef XK_dead_breve
10841 || orig_keysym == XK_dead_breve
10842 #endif
10843 #ifdef XK_dead_ogonek
10844 || orig_keysym == XK_dead_ogonek
10845 #endif
10846 #ifdef XK_dead_caron
10847 || orig_keysym == XK_dead_caron
10848 #endif
10849 #ifdef XK_dead_doubleacute
10850 || orig_keysym == XK_dead_doubleacute
10851 #endif
10852 #ifdef XK_dead_abovedot
10853 || orig_keysym == XK_dead_abovedot
10854 #endif
10855 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10856 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10857 /* Any "vendor-specific" key is ok. */
10858 || (orig_keysym & (1 << 28))
10859 || (keysym != NoSymbol && nbytes == 0))
10860 && ! (IsModifierKey (orig_keysym)
10861 #ifndef HAVE_X11R5
10862 #ifdef XK_Mode_switch
10863 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10864 #endif
10865 #ifdef XK_Num_Lock
10866 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10867 #endif
10868 #endif /* not HAVE_X11R5 */
10869 /* The symbols from XK_ISO_Lock
10870 to XK_ISO_Last_Group_Lock
10871 don't have real modifiers but
10872 should be treated similarly to
10873 Mode_switch by Emacs. */
10874 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10875 || ((unsigned)(orig_keysym)
10876 >= XK_ISO_Lock
10877 && (unsigned)(orig_keysym)
10878 <= XK_ISO_Last_Group_Lock)
10879 #endif
10880 ))
10881 {
10882 if (temp_index == sizeof temp_buffer / sizeof (short))
10883 temp_index = 0;
10884 temp_buffer[temp_index++] = keysym;
10885 /* make_lispy_event will convert this to a symbolic
10886 key. */
10887 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10888 bufp->code = keysym;
10889 XSETFRAME (bufp->frame_or_window, f);
10890 bufp->arg = Qnil;
10891 bufp->modifiers
10892 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10893 modifiers);
10894 bufp->timestamp = event.xkey.time;
10895 bufp++;
10896 count++;
10897 numchars--;
10898 }
10899 else if (numchars > nbytes)
10900 { /* Raw bytes, not keysym. */
10901 register int i;
10902 register int c;
10903 int nchars, len;
10904
10905 /* The input should be decoded with `coding_system'
10906 which depends on which X*LookupString function
10907 we used just above and the locale. */
10908 setup_coding_system (coding_system, &coding);
10909 coding.src_multibyte = 0;
10910 coding.dst_multibyte = 1;
10911 /* The input is converted to events, thus we can't
10912 handle composition. Anyway, there's no XIM that
10913 gives us composition information. */
10914 coding.composing = COMPOSITION_DISABLED;
10915
10916 for (i = 0; i < nbytes; i++)
10917 {
10918 if (temp_index == (sizeof temp_buffer
10919 / sizeof (short)))
10920 temp_index = 0;
10921 temp_buffer[temp_index++] = copy_bufptr[i];
10922 }
10923
10924 {
10925 /* Decode the input data. */
10926 int require;
10927 unsigned char *p;
10928
10929 require = decoding_buffer_size (&coding, nbytes);
10930 p = (unsigned char *) alloca (require);
10931 coding.mode |= CODING_MODE_LAST_BLOCK;
10932 /* We explicitely disable composition
10933 handling because key data should
10934 not contain any composition
10935 sequence. */
10936 coding.composing = COMPOSITION_DISABLED;
10937 decode_coding (&coding, copy_bufptr, p,
10938 nbytes, require);
10939 nbytes = coding.produced;
10940 nchars = coding.produced_char;
10941 copy_bufptr = p;
10942 }
10943
10944 /* Convert the input data to a sequence of
10945 character events. */
10946 for (i = 0; i < nbytes; i += len)
10947 {
10948 if (nchars == nbytes)
10949 c = copy_bufptr[i], len = 1;
10950 else
10951 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10952 nbytes - i, len);
10953
10954 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10955 ? ASCII_KEYSTROKE_EVENT
10956 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10957 bufp->code = c;
10958 XSETFRAME (bufp->frame_or_window, f);
10959 bufp->arg = Qnil;
10960 bufp->modifiers
10961 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10962 modifiers);
10963 bufp->timestamp = event.xkey.time;
10964 bufp++;
10965 }
10966
10967 count += nchars;
10968 numchars -= nchars;
10969
10970 if (keysym == NoSymbol)
10971 break;
10972 }
10973 else
10974 abort ();
10975 }
10976 else
10977 abort ();
10978 }
10979 #ifdef HAVE_X_I18N
10980 /* Don't dispatch this event since XtDispatchEvent calls
10981 XFilterEvent, and two calls in a row may freeze the
10982 client. */
10983 break;
10984 #else
10985 goto OTHER;
10986 #endif
10987
10988 case KeyRelease:
10989 #ifdef HAVE_X_I18N
10990 /* Don't dispatch this event since XtDispatchEvent calls
10991 XFilterEvent, and two calls in a row may freeze the
10992 client. */
10993 break;
10994 #else
10995 goto OTHER;
10996 #endif
10997
10998 case EnterNotify:
10999 {
11000 int n;
11001
11002 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11003 if (n > 0)
11004 {
11005 bufp += n, count += n, numchars -= n;
11006 }
11007
11008 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
11009
11010 #if 0
11011 if (event.xcrossing.focus)
11012 {
11013 /* Avoid nasty pop/raise loops. */
11014 if (f && (!(f->auto_raise)
11015 || !(f->auto_lower)
11016 || (event.xcrossing.time - enter_timestamp) > 500))
11017 {
11018 x_new_focus_frame (dpyinfo, f);
11019 enter_timestamp = event.xcrossing.time;
11020 }
11021 }
11022 else if (f == dpyinfo->x_focus_frame)
11023 x_new_focus_frame (dpyinfo, 0);
11024 #endif
11025
11026 /* EnterNotify counts as mouse movement,
11027 so update things that depend on mouse position. */
11028 if (f && !f->output_data.x->hourglass_p)
11029 note_mouse_movement (f, &event.xmotion);
11030 goto OTHER;
11031 }
11032
11033 case FocusIn:
11034 {
11035 int n;
11036
11037 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11038 if (n > 0)
11039 {
11040 bufp += n, count += n, numchars -= n;
11041 }
11042 }
11043
11044 goto OTHER;
11045
11046 case LeaveNotify:
11047 {
11048 int n;
11049
11050 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11051 if (n > 0)
11052 {
11053 bufp += n, count += n, numchars -= n;
11054 }
11055 }
11056
11057 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
11058 if (f)
11059 {
11060 if (f == dpyinfo->mouse_face_mouse_frame)
11061 {
11062 /* If we move outside the frame, then we're
11063 certainly no longer on any text in the frame. */
11064 clear_mouse_face (dpyinfo);
11065 dpyinfo->mouse_face_mouse_frame = 0;
11066 }
11067
11068 /* Generate a nil HELP_EVENT to cancel a help-echo.
11069 Do it only if there's something to cancel.
11070 Otherwise, the startup message is cleared when
11071 the mouse leaves the frame. */
11072 if (any_help_event_p)
11073 {
11074 Lisp_Object frame;
11075 int n;
11076
11077 XSETFRAME (frame, f);
11078 help_echo = Qnil;
11079 n = gen_help_event (bufp, numchars,
11080 Qnil, frame, Qnil, Qnil, 0);
11081 bufp += n, count += n, numchars -= n;
11082 }
11083
11084 }
11085 goto OTHER;
11086
11087 case FocusOut:
11088 {
11089 int n;
11090
11091 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11092 if (n > 0)
11093 {
11094 bufp += n, count += n, numchars -= n;
11095 }
11096 }
11097
11098 goto OTHER;
11099
11100 case MotionNotify:
11101 {
11102 previous_help_echo = help_echo;
11103 help_echo = help_echo_object = help_echo_window = Qnil;
11104 help_echo_pos = -1;
11105
11106 if (dpyinfo->grabbed && last_mouse_frame
11107 && FRAME_LIVE_P (last_mouse_frame))
11108 f = last_mouse_frame;
11109 else
11110 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11111
11112 if (dpyinfo->mouse_face_hidden)
11113 {
11114 dpyinfo->mouse_face_hidden = 0;
11115 clear_mouse_face (dpyinfo);
11116 }
11117
11118 if (f)
11119 {
11120
11121 /* Generate SELECT_WINDOW_EVENTs when needed. */
11122 if (mouse_autoselect_window)
11123 {
11124 Lisp_Object window;
11125 int area;
11126
11127 window = window_from_coordinates (f,
11128 event.xmotion.x, event.xmotion.y,
11129 &area, 0);
11130
11131 /* Window will be selected only when it is not selected now and
11132 last mouse movement event was not in it. Minibuffer window
11133 will be selected iff it is active. */
11134 if (WINDOWP(window)
11135 && !EQ (window, last_window)
11136 && !EQ (window, selected_window)
11137 && numchars > 0)
11138 {
11139 bufp->kind = SELECT_WINDOW_EVENT;
11140 bufp->frame_or_window = window;
11141 bufp->arg = Qnil;
11142 ++bufp, ++count, --numchars;
11143 }
11144
11145 last_window=window;
11146 }
11147 note_mouse_movement (f, &event.xmotion);
11148 }
11149 else
11150 {
11151 #ifndef USE_TOOLKIT_SCROLL_BARS
11152 struct scroll_bar *bar
11153 = x_window_to_scroll_bar (event.xmotion.window);
11154
11155 if (bar)
11156 x_scroll_bar_note_movement (bar, &event);
11157 #endif /* USE_TOOLKIT_SCROLL_BARS */
11158
11159 /* If we move outside the frame, then we're
11160 certainly no longer on any text in the frame. */
11161 clear_mouse_face (dpyinfo);
11162 }
11163
11164 /* If the contents of the global variable help_echo
11165 has changed, generate a HELP_EVENT. */
11166 if (!NILP (help_echo)
11167 || !NILP (previous_help_echo))
11168 {
11169 Lisp_Object frame;
11170 int n;
11171
11172 if (f)
11173 XSETFRAME (frame, f);
11174 else
11175 frame = Qnil;
11176
11177 any_help_event_p = 1;
11178 n = gen_help_event (bufp, numchars, help_echo, frame,
11179 help_echo_window, help_echo_object,
11180 help_echo_pos);
11181 bufp += n, count += n, numchars -= n;
11182 }
11183
11184 goto OTHER;
11185 }
11186
11187 case ConfigureNotify:
11188 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11189 if (f)
11190 {
11191 #ifndef USE_X_TOOLKIT
11192 /* If there is a pending resize for fullscreen, don't
11193 do this one, the right one will come later.
11194 The toolkit version doesn't seem to need this, but we
11195 need to reset it below. */
11196 int dont_resize =
11197 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11198 && FRAME_NEW_WIDTH (f) != 0);
11199 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11200 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11201 if (dont_resize)
11202 goto OTHER;
11203
11204 /* In the toolkit version, change_frame_size
11205 is called by the code that handles resizing
11206 of the EmacsFrame widget. */
11207
11208 /* Even if the number of character rows and columns has
11209 not changed, the font size may have changed, so we need
11210 to check the pixel dimensions as well. */
11211 if (columns != f->width
11212 || rows != f->height
11213 || event.xconfigure.width != f->output_data.x->pixel_width
11214 || event.xconfigure.height != f->output_data.x->pixel_height)
11215 {
11216 change_frame_size (f, rows, columns, 0, 1, 0);
11217 SET_FRAME_GARBAGED (f);
11218 cancel_mouse_face (f);
11219 }
11220 #endif
11221
11222 f->output_data.x->pixel_width = event.xconfigure.width;
11223 f->output_data.x->pixel_height = event.xconfigure.height;
11224
11225 /* What we have now is the position of Emacs's own window.
11226 Convert that to the position of the window manager window. */
11227 x_real_positions (f, &f->output_data.x->left_pos,
11228 &f->output_data.x->top_pos);
11229
11230 x_check_fullscreen_move(f);
11231 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11232 f->output_data.x->want_fullscreen &=
11233 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11234 #ifdef HAVE_X_I18N
11235 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11236 xic_set_statusarea (f);
11237 #endif
11238
11239 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11240 {
11241 /* Since the WM decorations come below top_pos now,
11242 we must put them below top_pos in the future. */
11243 f->output_data.x->win_gravity = NorthWestGravity;
11244 x_wm_set_size_hint (f, (long) 0, 0);
11245 }
11246 }
11247 goto OTHER;
11248
11249 case ButtonPress:
11250 case ButtonRelease:
11251 {
11252 /* If we decide we want to generate an event to be seen
11253 by the rest of Emacs, we put it here. */
11254 struct input_event emacs_event;
11255 int tool_bar_p = 0;
11256
11257 emacs_event.kind = NO_EVENT;
11258 bzero (&compose_status, sizeof (compose_status));
11259
11260 if (dpyinfo->grabbed
11261 && last_mouse_frame
11262 && FRAME_LIVE_P (last_mouse_frame))
11263 f = last_mouse_frame;
11264 else
11265 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11266
11267 if (f)
11268 {
11269 /* Is this in the tool-bar? */
11270 if (WINDOWP (f->tool_bar_window)
11271 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11272 {
11273 Lisp_Object window;
11274 int p, x, y;
11275
11276 x = event.xbutton.x;
11277 y = event.xbutton.y;
11278
11279 /* Set x and y. */
11280 window = window_from_coordinates (f, x, y, &p, 1);
11281 if (EQ (window, f->tool_bar_window))
11282 {
11283 x_handle_tool_bar_click (f, &event.xbutton);
11284 tool_bar_p = 1;
11285 }
11286 }
11287
11288 if (!tool_bar_p)
11289 if (!dpyinfo->x_focus_frame
11290 || f == dpyinfo->x_focus_frame)
11291 construct_mouse_click (&emacs_event, &event, f);
11292 }
11293 else
11294 {
11295 #ifndef USE_TOOLKIT_SCROLL_BARS
11296 struct scroll_bar *bar
11297 = x_window_to_scroll_bar (event.xbutton.window);
11298
11299 if (bar)
11300 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11301 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11302 }
11303
11304 if (event.type == ButtonPress)
11305 {
11306 dpyinfo->grabbed |= (1 << event.xbutton.button);
11307 last_mouse_frame = f;
11308 /* Ignore any mouse motion that happened
11309 before this event; any subsequent mouse-movement
11310 Emacs events should reflect only motion after
11311 the ButtonPress. */
11312 if (f != 0)
11313 f->mouse_moved = 0;
11314
11315 if (!tool_bar_p)
11316 last_tool_bar_item = -1;
11317 }
11318 else
11319 {
11320 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11321 }
11322
11323 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11324 {
11325 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11326 bufp++;
11327 count++;
11328 numchars--;
11329 }
11330
11331 #ifdef USE_X_TOOLKIT
11332 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11333 /* For a down-event in the menu bar,
11334 don't pass it to Xt right now.
11335 Instead, save it away
11336 and we will pass it to Xt from kbd_buffer_get_event.
11337 That way, we can run some Lisp code first. */
11338 if (f && event.type == ButtonPress
11339 /* Verify the event is really within the menu bar
11340 and not just sent to it due to grabbing. */
11341 && event.xbutton.x >= 0
11342 && event.xbutton.x < f->output_data.x->pixel_width
11343 && event.xbutton.y >= 0
11344 && event.xbutton.y < f->output_data.x->menubar_height
11345 && event.xbutton.same_screen)
11346 {
11347 SET_SAVED_BUTTON_EVENT;
11348 XSETFRAME (last_mouse_press_frame, f);
11349 }
11350 else if (event.type == ButtonPress)
11351 {
11352 last_mouse_press_frame = Qnil;
11353 goto OTHER;
11354 }
11355
11356 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11357 but I am trying to be cautious. */
11358 else if (event.type == ButtonRelease)
11359 {
11360 if (!NILP (last_mouse_press_frame))
11361 {
11362 f = XFRAME (last_mouse_press_frame);
11363 if (f->output_data.x)
11364 SET_SAVED_BUTTON_EVENT;
11365 }
11366 else
11367 goto OTHER;
11368 }
11369 #endif /* USE_MOTIF */
11370 else
11371 goto OTHER;
11372 #endif /* USE_X_TOOLKIT */
11373 }
11374 break;
11375
11376 case CirculateNotify:
11377 goto OTHER;
11378
11379 case CirculateRequest:
11380 goto OTHER;
11381
11382 case VisibilityNotify:
11383 goto OTHER;
11384
11385 case MappingNotify:
11386 /* Someone has changed the keyboard mapping - update the
11387 local cache. */
11388 switch (event.xmapping.request)
11389 {
11390 case MappingModifier:
11391 x_find_modifier_meanings (dpyinfo);
11392 /* This is meant to fall through. */
11393 case MappingKeyboard:
11394 XRefreshKeyboardMapping (&event.xmapping);
11395 }
11396 goto OTHER;
11397
11398 default:
11399 OTHER:
11400 #ifdef USE_X_TOOLKIT
11401 BLOCK_INPUT;
11402 XtDispatchEvent (&event);
11403 UNBLOCK_INPUT;
11404 #endif /* USE_X_TOOLKIT */
11405 break;
11406 }
11407 }
11408 } 11460 }
11409 11461
11410 out:; 11462 out:;
11411 11463
11412 /* On some systems, an X bug causes Emacs to get no more events 11464 /* On some systems, an X bug causes Emacs to get no more events