Mercurial > emacs
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 |