Mercurial > hg > xemacs-beta
comparison src/event-gtk.c @ 462:0784d089fdc9 r21-2-46
Import from CVS: tag r21-2-46
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:44:37 +0200 |
parents | |
children | 5aa1854ad537 |
comparison
equal
deleted
inserted
replaced
461:120ed4009e51 | 462:0784d089fdc9 |
---|---|
1 /* The event_stream interface for X11 with gtk, and/or tty frames. | |
2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
4 Copyright (C) 1996 Ben Wing. | |
5 Copyright (C) 2000 William Perry. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* This file is heavily based upon event-Xt.c */ | |
25 | |
26 /* Synched up with: Not in FSF. */ | |
27 | |
28 #include <config.h> | |
29 #include "lisp.h" | |
30 | |
31 #include "console-gtk.h" | |
32 | |
33 #include "blocktype.h" | |
34 #include "buffer.h" | |
35 #include "commands.h" | |
36 #include "console.h" | |
37 #include "console-tty.h" | |
38 #include "events.h" | |
39 #include "frame.h" | |
40 #include "objects-gtk.h" | |
41 #include "process.h" | |
42 #include "redisplay.h" | |
43 #include "elhash.h" | |
44 | |
45 #include "gtk-xemacs.h" | |
46 | |
47 #include "systime.h" | |
48 #include "sysproc.h" /* for MAXDESC */ | |
49 | |
50 #ifdef FILE_CODING | |
51 #include "lstream.h" | |
52 #include "file-coding.h" | |
53 #endif | |
54 | |
55 #include <gdk/gdkkeysyms.h> | |
56 | |
57 #ifdef HAVE_DRAGNDROP | |
58 #include "dragdrop.h" | |
59 #endif | |
60 | |
61 #if defined (HAVE_OFFIX_DND) | |
62 #include "offix.h" | |
63 #endif | |
64 | |
65 #include "events-mod.h" | |
66 | |
67 #include <gdk/gdkx.h> | |
68 | |
69 static struct event_stream *gtk_event_stream; | |
70 | |
71 /* Do we accept events sent by other clients? */ | |
72 int gtk_allow_sendevents; | |
73 | |
74 static int process_events_occurred; | |
75 static int tty_events_occurred; | |
76 | |
77 /* Mask of bits indicating the descriptors that we wait for input on */ | |
78 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask; | |
79 | |
80 static Lisp_Object gtk_keysym_to_emacs_keysym (); | |
81 void debug_process_finalization (struct Lisp_Process *p); | |
82 gboolean emacs_gtk_event_handler (GtkWidget *wid /* unused */, | |
83 GdkEvent *event, | |
84 gpointer closure /* unused */); | |
85 | |
86 static int last_quit_check_signal_tick_count; | |
87 | |
88 Lisp_Object Qkey_mapping; | |
89 Lisp_Object Qsans_modifiers; | |
90 | |
91 static void enqueue_gtk_dispatch_event (Lisp_Object event); | |
92 | |
93 #define IS_MODIFIER_KEY(keysym) \ | |
94 ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R)) \ | |
95 || ((keysym) == GDK_Mode_switch) \ | |
96 || ((keysym) == GDK_Num_Lock)) | |
97 | |
98 | |
99 | |
100 /************************************************************************/ | |
101 /* magic-event handling */ | |
102 /************************************************************************/ | |
103 static void | |
104 handle_focus_event_1 (struct frame *f, int in_p) | |
105 { | |
106 /* We don't want to handle the focus change now, because we might | |
107 be in an accept-process-output, sleep-for, or sit-for. So | |
108 we enqueue it. | |
109 | |
110 Actually, we half handle it: we handle it as far as changing the | |
111 box cursor for redisplay, but we don't call any hooks or do any | |
112 select-frame stuff until after the sit-for. | |
113 */ | |
114 | |
115 if (in_p) | |
116 { | |
117 GTK_WIDGET_SET_FLAGS (FRAME_GTK_TEXT_WIDGET (f), GTK_HAS_FOCUS); | |
118 } | |
119 else | |
120 { | |
121 GTK_WIDGET_UNSET_FLAGS (FRAME_GTK_TEXT_WIDGET (f), GTK_HAS_FOCUS); | |
122 } | |
123 gtk_widget_grab_focus (FRAME_GTK_TEXT_WIDGET (f)); | |
124 gtk_widget_draw_focus (FRAME_GTK_TEXT_WIDGET (f)); | |
125 | |
126 { | |
127 Lisp_Object frm; | |
128 Lisp_Object conser; | |
129 struct gcpro gcpro1; | |
130 | |
131 XSETFRAME (frm, f); | |
132 conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); | |
133 GCPRO1 (conser); | |
134 | |
135 emacs_handle_focus_change_preliminary (conser); | |
136 enqueue_magic_eval_event (emacs_handle_focus_change_final, | |
137 conser); | |
138 UNGCPRO; | |
139 } | |
140 } | |
141 | |
142 /* both GDK_MAP and GDK_VISIBILITY_NOTIFY can cause this | |
143 JV is_visible has the same semantics as f->visible*/ | |
144 static void | |
145 change_frame_visibility (struct frame *f, int is_visible) | |
146 { | |
147 Lisp_Object frame; | |
148 | |
149 XSETFRAME (frame, f); | |
150 | |
151 if (!FRAME_VISIBLE_P (f) && is_visible) | |
152 { | |
153 FRAME_VISIBLE_P (f) = is_visible; | |
154 /* This improves the double flicker when uniconifying a frame | |
155 some. A lot of it is not showing a buffer which has changed | |
156 while the frame was iconified. To fix it further requires | |
157 the good 'ol double redisplay structure. */ | |
158 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
159 va_run_hook_with_args (Qmap_frame_hook, 1, frame); | |
160 } | |
161 else if (FRAME_VISIBLE_P (f) && !is_visible) | |
162 { | |
163 FRAME_VISIBLE_P (f) = 0; | |
164 va_run_hook_with_args (Qunmap_frame_hook, 1, frame); | |
165 } | |
166 else if (FRAME_VISIBLE_P (f) * is_visible < 0) | |
167 { | |
168 FRAME_VISIBLE_P(f) = - FRAME_VISIBLE_P(f); | |
169 if (FRAME_REPAINT_P (f)) | |
170 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
171 va_run_hook_with_args (Qmap_frame_hook, 1, frame); | |
172 } | |
173 } | |
174 | |
175 static void | |
176 handle_map_event (struct frame *f, GdkEvent *event) | |
177 { | |
178 Lisp_Object frame; | |
179 | |
180 XSETFRAME (frame, f); | |
181 if (event->any.type == GDK_MAP) | |
182 { | |
183 FRAME_GTK_TOTALLY_VISIBLE_P (f) = 1; | |
184 change_frame_visibility (f, 1); | |
185 } | |
186 else | |
187 { | |
188 FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0; | |
189 change_frame_visibility (f, 0); | |
190 /* Calling Fframe_iconified_p is the only way we have to | |
191 correctly update FRAME_ICONIFIED_P */ | |
192 Fframe_iconified_p (frame); | |
193 } | |
194 } | |
195 | |
196 static void | |
197 handle_client_message (struct frame *f, GdkEvent *event) | |
198 { | |
199 Lisp_Object frame; | |
200 | |
201 XSETFRAME (frame, f); | |
202 | |
203 /* The event-Xt code used to handle WM_DELETE_WINDOW here, but we | |
204 handle that directly in frame-gtk.c */ | |
205 | |
206 if (event->client.message_type == gdk_atom_intern ("WM_PROTOCOLS", 0) && | |
207 (GdkAtom) event->client.data.l[0] == gdk_atom_intern ("WM_TAKE_FOCUS", 0)) | |
208 { | |
209 handle_focus_event_1 (f, 1); | |
210 } | |
211 } | |
212 | |
213 static void | |
214 emacs_gtk_handle_magic_event (struct Lisp_Event *emacs_event) | |
215 { | |
216 /* This function can GC */ | |
217 GdkEvent *event = &emacs_event->event.magic.underlying_gdk_event; | |
218 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event)); | |
219 | |
220 if (!FRAME_LIVE_P (f)) | |
221 return; | |
222 | |
223 switch (event->any.type) | |
224 { | |
225 case GDK_CLIENT_EVENT: | |
226 handle_client_message (f, event); | |
227 break; | |
228 | |
229 case GDK_FOCUS_CHANGE: | |
230 handle_focus_event_1 (f, event->focus_change.in); | |
231 break; | |
232 | |
233 case GDK_MAP: | |
234 case GDK_UNMAP: | |
235 handle_map_event (f, event); | |
236 break; | |
237 | |
238 case GDK_ENTER_NOTIFY: | |
239 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) | |
240 { | |
241 Lisp_Object frame; | |
242 | |
243 XSETFRAME (frame, f); | |
244 /* FRAME_X_MOUSE_P (f) = 1; */ | |
245 va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame); | |
246 } | |
247 break; | |
248 | |
249 case GDK_LEAVE_NOTIFY: | |
250 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) | |
251 { | |
252 Lisp_Object frame; | |
253 | |
254 XSETFRAME (frame, f); | |
255 /* FRAME_X_MOUSE_P (f) = 0; */ | |
256 va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame); | |
257 } | |
258 break; | |
259 | |
260 case GDK_VISIBILITY_NOTIFY: /* window visiblity has changed */ | |
261 if (event->visibility.window == GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))) | |
262 { | |
263 FRAME_GTK_TOTALLY_VISIBLE_P (f) = | |
264 (event->visibility.state == GDK_VISIBILITY_UNOBSCURED); | |
265 /* Note that the fvwm pager only sends VisibilityNotify when | |
266 changing pages. Is this all we need to do ? JV */ | |
267 /* Nope. We must at least trigger a redisplay here. | |
268 Since this case seems similar to MapNotify, I've | |
269 factored out some code to change_frame_visibility(). | |
270 This triggers the necessary redisplay and runs | |
271 (un)map-frame-hook. - dkindred@cs.cmu.edu */ | |
272 /* Changed it again to support the tristate visibility flag */ | |
273 change_frame_visibility (f, (event->visibility.state | |
274 != GDK_VISIBILITY_FULLY_OBSCURED) ? 1 : -1); | |
275 } | |
276 break; | |
277 | |
278 default: | |
279 break; | |
280 } | |
281 } | |
282 | |
283 /************************************************************************/ | |
284 /* Gtk to Emacs event conversion */ | |
285 /************************************************************************/ | |
286 | |
287 static int | |
288 keysym_obeys_caps_lock_p (guint sym, struct device *d) | |
289 { | |
290 struct gtk_device *gd = DEVICE_GTK_DATA (d); | |
291 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't alphabetic | |
292 characters, where "alphabetic" means something more than simply A-Z. | |
293 That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC. | |
294 But if shift-lock is down, then it does. */ | |
295 if (gd->lock_interpretation == GDK_Shift_Lock) | |
296 return 1; | |
297 | |
298 return | |
299 ((sym >= GDK_A) && (sym <= GDK_Z)) || | |
300 ((sym >= GDK_a) && (sym <= GDK_z)) || | |
301 ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis)) || | |
302 ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis)) || | |
303 ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn)) || | |
304 ((sym >= GDK_oslash) && (sym <= GDK_thorn)); | |
305 } | |
306 | |
307 static void | |
308 set_last_server_timestamp (struct device *d, GdkEvent *gdk_event) | |
309 { | |
310 guint32 t; | |
311 switch (gdk_event->type) | |
312 { | |
313 case GDK_KEY_PRESS: | |
314 case GDK_KEY_RELEASE: t = gdk_event->key.time; break; | |
315 case GDK_BUTTON_PRESS: | |
316 case GDK_2BUTTON_PRESS: | |
317 case GDK_3BUTTON_PRESS: | |
318 case GDK_BUTTON_RELEASE: t = gdk_event->button.time; break; | |
319 case GDK_ENTER_NOTIFY: | |
320 case GDK_LEAVE_NOTIFY: t = gdk_event->crossing.time; break; | |
321 case GDK_MOTION_NOTIFY: t = gdk_event->motion.time; break; | |
322 case GDK_PROPERTY_NOTIFY: t = gdk_event->property.time; break; | |
323 case GDK_SELECTION_CLEAR: | |
324 case GDK_SELECTION_REQUEST: | |
325 case GDK_SELECTION_NOTIFY: t = gdk_event->selection.time; break; | |
326 default: return; | |
327 } | |
328 DEVICE_GTK_LAST_SERVER_TIMESTAMP (d) = t; | |
329 } | |
330 | |
331 static Lisp_Object | |
332 gtk_keysym_to_emacs_keysym (guint keysym, int simple_p) | |
333 { | |
334 char *name; | |
335 if (keysym >= GDK_exclam && keysym <= GDK_asciitilde) | |
336 /* We must assume that the X keysym numbers for the ASCII graphic | |
337 characters are the same as their ASCII codes. */ | |
338 return make_char (keysym); | |
339 | |
340 switch (keysym) | |
341 { | |
342 /* These would be handled correctly by the default case, but by | |
343 special-casing them here we don't garbage a string or call | |
344 intern(). */ | |
345 case GDK_BackSpace: return QKbackspace; | |
346 case GDK_Tab: return QKtab; | |
347 case GDK_Linefeed: return QKlinefeed; | |
348 case GDK_Return: return QKreturn; | |
349 case GDK_Escape: return QKescape; | |
350 case GDK_space: return QKspace; | |
351 case GDK_Delete: return QKdelete; | |
352 case 0: return Qnil; | |
353 default: | |
354 if (simple_p) return Qnil; | |
355 /* !!#### not Mule-ized */ | |
356 name = gdk_keyval_name (keysym); | |
357 if (!name || !name[0]) | |
358 /* This happens if there is a mismatch between the Xlib of | |
359 XEmacs and the Xlib of the X server... | |
360 | |
361 Let's hard-code in some knowledge of common keysyms introduced | |
362 in recent X11 releases. Snarfed from X11/keysymdef.h | |
363 | |
364 Probably we should add some stuff here for X11R6. */ | |
365 switch (keysym) | |
366 { | |
367 case 0xFF95: return KEYSYM ("kp-home"); | |
368 case 0xFF96: return KEYSYM ("kp-left"); | |
369 case 0xFF97: return KEYSYM ("kp-up"); | |
370 case 0xFF98: return KEYSYM ("kp-right"); | |
371 case 0xFF99: return KEYSYM ("kp-down"); | |
372 case 0xFF9A: return KEYSYM ("kp-prior"); | |
373 case 0xFF9B: return KEYSYM ("kp-next"); | |
374 case 0xFF9C: return KEYSYM ("kp-end"); | |
375 case 0xFF9D: return KEYSYM ("kp-begin"); | |
376 case 0xFF9E: return KEYSYM ("kp-insert"); | |
377 case 0xFF9F: return KEYSYM ("kp-delete"); | |
378 | |
379 case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */ | |
380 case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */ | |
381 default: | |
382 { | |
383 char buf [64]; | |
384 sprintf (buf, "unknown-keysym-0x%X", (int) keysym); | |
385 return KEYSYM (buf); | |
386 } | |
387 } | |
388 /* If it's got a one-character name, that's good enough. */ | |
389 if (!name[1]) | |
390 return make_char (name[0]); | |
391 | |
392 /* If it's in the "Keyboard" character set, downcase it. | |
393 The case of those keysyms is too totally random for us to | |
394 force anyone to remember them. | |
395 The case of the other character sets is significant, however. | |
396 */ | |
397 if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00)) | |
398 { | |
399 char buf [255]; | |
400 char *s1, *s2; | |
401 for (s1 = name, s2 = buf; *s1; s1++, s2++) { | |
402 if (*s1 == '_') { | |
403 *s2 = '-'; | |
404 } else { | |
405 *s2 = tolower (* (unsigned char *) s1); | |
406 } | |
407 } | |
408 *s2 = 0; | |
409 return KEYSYM (buf); | |
410 } | |
411 return KEYSYM (name); | |
412 } | |
413 } | |
414 | |
415 static Lisp_Object | |
416 gtk_to_emacs_keysym (struct device *d, GdkEventKey *event, int simple_p) | |
417 /* simple_p means don't try too hard (ASCII only) */ | |
418 { | |
419 if (event->length != 1) | |
420 { | |
421 #ifdef FILE_CODING | |
422 /* Generate multiple emacs events */ | |
423 Emchar ch; | |
424 Lisp_Object instream, fb_instream; | |
425 Lstream *istr; | |
426 struct gcpro gcpro1, gcpro2; | |
427 | |
428 fb_instream = | |
429 make_fixed_buffer_input_stream ((unsigned char *) event->string, event->length); | |
430 | |
431 /* ### Use Fget_coding_system (Vcomposed_input_coding_system) */ | |
432 instream = | |
433 make_decoding_input_stream (XLSTREAM (fb_instream), | |
434 Fget_coding_system (Qundecided)); | |
435 | |
436 istr = XLSTREAM (instream); | |
437 | |
438 GCPRO2 (instream, fb_instream); | |
439 while ((ch = Lstream_get_emchar (istr)) != EOF) | |
440 { | |
441 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | |
442 struct Lisp_Event *ev = XEVENT (emacs_event); | |
443 ev->channel = DEVICE_CONSOLE (d); | |
444 ev->event_type = key_press_event; | |
445 ev->timestamp = event->time; | |
446 ev->event.key.modifiers = 0; | |
447 ev->event.key.keysym = make_char (ch); | |
448 enqueue_gtk_dispatch_event (emacs_event); | |
449 } | |
450 Lstream_close (istr); | |
451 UNGCPRO; | |
452 Lstream_delete (istr); | |
453 Lstream_delete (XLSTREAM (fb_instream)); | |
454 #else | |
455 int i; | |
456 for (i = 0; i < event->length; i++) | |
457 { | |
458 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | |
459 struct Lisp_Event *ev = XEVENT (emacs_event); | |
460 ev->channel = DEVICE_CONSOLE (d); | |
461 ev->event_type = key_press_event; | |
462 ev->timestamp = event->time; | |
463 ev->event.key.modifiers = 0; | |
464 ev->event.key.keysym = make_char (event->string[i]); | |
465 enqueue_gtk_dispatch_event (emacs_event); | |
466 } | |
467 #endif | |
468 if (IS_MODIFIER_KEY (event->keyval) || (event->keyval == GDK_Mode_switch)) | |
469 return (Qnil); | |
470 return (gtk_keysym_to_emacs_keysym (event->keyval, simple_p)); | |
471 } | |
472 else | |
473 { | |
474 if (IS_MODIFIER_KEY (event->keyval) || (event->keyval == GDK_Mode_switch)) | |
475 return (Qnil); | |
476 return (gtk_keysym_to_emacs_keysym (event->keyval, simple_p)); | |
477 } | |
478 } | |
479 | |
480 | |
481 /************************************************************************/ | |
482 /* timeout events */ | |
483 /************************************************************************/ | |
484 | |
485 static int timeout_id_tick; | |
486 | |
487 struct GTK_timeout { | |
488 int id; | |
489 guint timeout_id; | |
490 struct GTK_timeout *next; | |
491 } *pending_timeouts, *completed_timeouts; | |
492 | |
493 struct GTK_timeout_blocktype | |
494 { | |
495 Blocktype_declare (struct GTK_timeout); | |
496 } *the_GTK_timeout_blocktype; | |
497 | |
498 /* called by the gtk main loop */ | |
499 static gint | |
500 gtk_timeout_callback (gpointer closure) | |
501 { | |
502 struct GTK_timeout *timeout = (struct GTK_timeout *) closure; | |
503 struct GTK_timeout *t2 = pending_timeouts; | |
504 | |
505 /* Remove this one from the list of pending timeouts */ | |
506 if (t2 == timeout) | |
507 pending_timeouts = pending_timeouts->next; | |
508 else | |
509 { | |
510 while (t2->next && t2->next != timeout) t2 = t2->next; | |
511 assert (t2->next); | |
512 t2->next = t2->next->next; | |
513 } | |
514 /* Add this one to the list of completed timeouts */ | |
515 timeout->next = completed_timeouts; | |
516 completed_timeouts = timeout; | |
517 return(FALSE); | |
518 } | |
519 | |
520 static int | |
521 emacs_gtk_add_timeout (EMACS_TIME thyme) | |
522 { | |
523 struct GTK_timeout *timeout = Blocktype_alloc (the_GTK_timeout_blocktype); | |
524 EMACS_TIME current_time; | |
525 int milliseconds; | |
526 | |
527 timeout->id = timeout_id_tick++; | |
528 timeout->next = pending_timeouts; | |
529 pending_timeouts = timeout; | |
530 EMACS_GET_TIME (current_time); | |
531 EMACS_SUB_TIME (thyme, thyme, current_time); | |
532 milliseconds = EMACS_SECS (thyme) * 1000 + | |
533 EMACS_USECS (thyme) / 1000; | |
534 if (milliseconds < 1) | |
535 milliseconds = 1; | |
536 timeout->timeout_id = gtk_timeout_add (milliseconds, | |
537 gtk_timeout_callback, | |
538 (gpointer) timeout); | |
539 return timeout->id; | |
540 } | |
541 | |
542 static void | |
543 emacs_gtk_remove_timeout (int id) | |
544 { | |
545 struct GTK_timeout *timeout, *t2; | |
546 | |
547 timeout = NULL; | |
548 | |
549 /* Find the timeout on the list of pending ones, if it's still there. */ | |
550 if (pending_timeouts) | |
551 { | |
552 if (id == pending_timeouts->id) | |
553 { | |
554 timeout = pending_timeouts; | |
555 pending_timeouts = pending_timeouts->next; | |
556 } | |
557 else | |
558 { | |
559 t2 = pending_timeouts; | |
560 while (t2->next && t2->next->id != id) t2 = t2->next; | |
561 if ( t2->next) /*found it */ | |
562 { | |
563 timeout = t2->next; | |
564 t2->next = t2->next->next; | |
565 } | |
566 } | |
567 /* if it was pending, we have removed it from the list */ | |
568 if (timeout) | |
569 gtk_timeout_remove (timeout->timeout_id); | |
570 } | |
571 | |
572 /* It could be that the call back was already called but we didn't convert | |
573 into an Emacs event yet */ | |
574 if (!timeout && completed_timeouts) | |
575 { | |
576 /* Code duplication! */ | |
577 if (id == completed_timeouts->id) | |
578 { | |
579 timeout = completed_timeouts; | |
580 completed_timeouts = completed_timeouts->next; | |
581 } | |
582 else | |
583 { | |
584 t2 = completed_timeouts; | |
585 while (t2->next && t2->next->id != id) t2 = t2->next; | |
586 if ( t2->next) /*found it */ | |
587 { | |
588 timeout = t2->next; | |
589 t2->next = t2->next->next; | |
590 } | |
591 } | |
592 } | |
593 | |
594 /* If we found the thing on the lists of timeouts, | |
595 and removed it, deallocate | |
596 */ | |
597 if (timeout) | |
598 Blocktype_free (the_GTK_timeout_blocktype, timeout); | |
599 } | |
600 | |
601 static void | |
602 gtk_timeout_to_emacs_event (struct Lisp_Event *emacs_event) | |
603 { | |
604 struct GTK_timeout *timeout = completed_timeouts; | |
605 assert (timeout); | |
606 completed_timeouts = completed_timeouts->next; | |
607 emacs_event->event_type = timeout_event; | |
608 /* timeout events have nil as channel */ | |
609 emacs_event->timestamp = 0; /* #### wrong!! */ | |
610 emacs_event->event.timeout.interval_id = timeout->id; | |
611 Blocktype_free (the_GTK_timeout_blocktype, timeout); | |
612 } | |
613 | |
614 | |
615 /************************************************************************/ | |
616 /* process and tty events */ | |
617 /************************************************************************/ | |
618 | |
619 struct what_is_ready_closure | |
620 { | |
621 int fd; | |
622 Lisp_Object what; | |
623 gint id; | |
624 }; | |
625 | |
626 static Lisp_Object *filedesc_with_input; | |
627 static struct what_is_ready_closure **filedesc_to_what_closure; | |
628 | |
629 static void | |
630 init_what_input_once (void) | |
631 { | |
632 int i; | |
633 | |
634 filedesc_with_input = xnew_array (Lisp_Object, MAXDESC); | |
635 filedesc_to_what_closure = | |
636 xnew_array (struct what_is_ready_closure *, MAXDESC); | |
637 | |
638 for (i = 0; i < MAXDESC; i++) | |
639 { | |
640 filedesc_to_what_closure[i] = 0; | |
641 filedesc_with_input[i] = Qnil; | |
642 } | |
643 | |
644 process_events_occurred = 0; | |
645 tty_events_occurred = 0; | |
646 } | |
647 | |
648 static void | |
649 mark_what_as_being_ready (struct what_is_ready_closure *closure) | |
650 { | |
651 if (NILP (filedesc_with_input[closure->fd])) | |
652 { | |
653 SELECT_TYPE temp_mask; | |
654 FD_ZERO (&temp_mask); | |
655 FD_SET (closure->fd, &temp_mask); | |
656 /* Check to make sure there's *really* input available. | |
657 Sometimes things seem to get confused and this gets called | |
658 for the tty fd when there's really only input available | |
659 on some process's fd. (It will subsequently get called | |
660 for that process's fd, so returning without setting any | |
661 flags will take care of it.) To see the problem, uncomment | |
662 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS | |
663 down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log' | |
664 and press return repeatedly. (Seen under AIX & Linux.) | |
665 -dkindred@cs.cmu.edu */ | |
666 if (!poll_fds_for_input (temp_mask)) | |
667 { | |
668 #if 0 | |
669 stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n", | |
670 closure->fd); | |
671 #endif | |
672 return; | |
673 } | |
674 filedesc_with_input[closure->fd] = closure->what; | |
675 if (PROCESSP (closure->what)) | |
676 { | |
677 /* Don't increment this if the current process is already marked | |
678 * as having input. */ | |
679 process_events_occurred++; | |
680 } | |
681 else | |
682 { | |
683 tty_events_occurred++; | |
684 } | |
685 } | |
686 } | |
687 | |
688 static void | |
689 gtk_what_callback (gpointer closure, gint source, GdkInputCondition why) | |
690 { | |
691 /* If closure is 0, then we got a fake event from a signal handler. | |
692 The only purpose of this is to make XtAppProcessEvent() stop | |
693 blocking. */ | |
694 if (closure) | |
695 mark_what_as_being_ready ((struct what_is_ready_closure *) closure); | |
696 else | |
697 { | |
698 fake_event_occurred++; | |
699 drain_signal_event_pipe (); | |
700 } | |
701 } | |
702 | |
703 static void | |
704 select_filedesc (int fd, Lisp_Object what) | |
705 { | |
706 struct what_is_ready_closure *closure; | |
707 | |
708 /* If somebody is trying to select something that's already selected | |
709 for, then something went wrong. The generic routines ought to | |
710 detect this and error before here. */ | |
711 assert (!filedesc_to_what_closure[fd]); | |
712 | |
713 closure = xnew (struct what_is_ready_closure); | |
714 closure->fd = fd; | |
715 closure->what = what; | |
716 closure->id = gdk_input_add (fd, GDK_INPUT_READ, | |
717 (GdkInputFunction) gtk_what_callback, closure); | |
718 filedesc_to_what_closure[fd] = closure; | |
719 } | |
720 | |
721 static void | |
722 unselect_filedesc (int fd) | |
723 { | |
724 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd]; | |
725 | |
726 assert (closure); | |
727 if (!NILP (filedesc_with_input[fd])) | |
728 { | |
729 /* We are unselecting this process before we have drained the rest of | |
730 the input from it, probably from status_notify() in the command loop. | |
731 This can happen like so: | |
732 | |
733 - We are waiting in XtAppNextEvent() | |
734 - Process generates output | |
735 - Process is marked as being ready | |
736 - Process dies, SIGCHLD gets generated before we return (!?) | |
737 It could happen I guess. | |
738 - sigchld_handler() marks process as dead | |
739 - Somehow we end up getting a new KeyPress event on the queue | |
740 at the same time (I'm really so sure how that happens but I'm | |
741 not sure it can't either so let's assume it can...). | |
742 - Key events have priority so we return that instead of the proc. | |
743 - Before dispatching the lisp key event we call status_notify() | |
744 - Which deselects the process that SIGCHLD marked as dead. | |
745 | |
746 Thus we never remove it from _with_input and turn it into a lisp | |
747 event, so we need to do it here. But this does not mean that we're | |
748 throwing away the last block of output - status_notify() has already | |
749 taken care of running the proc filter or whatever. | |
750 */ | |
751 filedesc_with_input[fd] = Qnil; | |
752 if (PROCESSP (closure->what)) | |
753 { | |
754 assert (process_events_occurred > 0); | |
755 process_events_occurred--; | |
756 } | |
757 else | |
758 { | |
759 assert (tty_events_occurred > 0); | |
760 tty_events_occurred--; | |
761 } | |
762 } | |
763 gdk_input_remove (closure->id); | |
764 xfree (closure); | |
765 filedesc_to_what_closure[fd] = 0; | |
766 } | |
767 | |
768 static void | |
769 emacs_gtk_select_process (struct Lisp_Process *p) | |
770 { | |
771 Lisp_Object process; | |
772 int infd = event_stream_unixoid_select_process (p); | |
773 | |
774 XSETPROCESS (process, p); | |
775 select_filedesc (infd, process); | |
776 } | |
777 | |
778 static void | |
779 emacs_gtk_unselect_process (struct Lisp_Process *p) | |
780 { | |
781 int infd = event_stream_unixoid_unselect_process (p); | |
782 | |
783 unselect_filedesc (infd); | |
784 } | |
785 | |
786 static USID | |
787 emacs_gtk_create_stream_pair (void* inhandle, void* outhandle, | |
788 Lisp_Object* instream, Lisp_Object* outstream, int flags) | |
789 { | |
790 USID u = event_stream_unixoid_create_stream_pair | |
791 (inhandle, outhandle, instream, outstream, flags); | |
792 if (u != USID_ERROR) | |
793 u = USID_DONTHASH; | |
794 return u; | |
795 } | |
796 | |
797 static USID | |
798 emacs_gtk_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream) | |
799 { | |
800 event_stream_unixoid_delete_stream_pair (instream, outstream); | |
801 return USID_DONTHASH; | |
802 } | |
803 | |
804 /* This is called from GC when a process object is about to be freed. | |
805 If we've still got pointers to it in this file, we're gonna lose hard. | |
806 */ | |
807 void | |
808 debug_process_finalization (struct Lisp_Process *p) | |
809 { | |
810 #if 0 /* #### */ | |
811 int i; | |
812 Lisp_Object instr, outstr; | |
813 | |
814 get_process_streams (p, &instr, &outstr); | |
815 /* if it still has fds, then it hasn't been killed yet. */ | |
816 assert (NILP(instr)); | |
817 assert (NILP(outstr)); | |
818 /* Better not still be in the "with input" table; we know it's got no fds. */ | |
819 for (i = 0; i < MAXDESC; i++) | |
820 { | |
821 Lisp_Object process = filedesc_fds_with_input [i]; | |
822 assert (!PROCESSP (process) || XPROCESS (process) != p); | |
823 } | |
824 #endif | |
825 } | |
826 | |
827 static void | |
828 gtk_process_to_emacs_event (struct Lisp_Event *emacs_event) | |
829 { | |
830 int i; | |
831 Lisp_Object process; | |
832 | |
833 assert (process_events_occurred > 0); | |
834 for (i = 0; i < MAXDESC; i++) | |
835 { | |
836 process = filedesc_with_input[i]; | |
837 if (PROCESSP (process)) | |
838 break; | |
839 } | |
840 assert (i < MAXDESC); | |
841 filedesc_with_input[i] = Qnil; | |
842 process_events_occurred--; | |
843 /* process events have nil as channel */ | |
844 emacs_event->event_type = process_event; | |
845 emacs_event->timestamp = 0; /* #### */ | |
846 emacs_event->event.process.process = process; | |
847 } | |
848 | |
849 static void | |
850 emacs_gtk_select_console (struct console *con) | |
851 { | |
852 Lisp_Object console; | |
853 int infd; | |
854 | |
855 if (CONSOLE_GTK_P (con)) | |
856 return; /* Gtk consoles are automatically selected for when we initialize them */ | |
857 infd = event_stream_unixoid_select_console (con); | |
858 XSETCONSOLE (console, con); | |
859 select_filedesc (infd, console); | |
860 } | |
861 | |
862 static void | |
863 emacs_gtk_unselect_console (struct console *con) | |
864 { | |
865 Lisp_Object console; | |
866 int infd; | |
867 | |
868 if (CONSOLE_GTK_P (con)) | |
869 return; /* X consoles are automatically selected for when we initialize them */ | |
870 infd = event_stream_unixoid_unselect_console (con); | |
871 XSETCONSOLE (console, con); | |
872 unselect_filedesc (infd); | |
873 } | |
874 | |
875 /* read an event from a tty, if one is available. Returns non-zero | |
876 if an event was available. Note that when this function is | |
877 called, there should always be a tty marked as ready for input. | |
878 However, the input condition might actually be EOF, so there | |
879 may not really be any input available. (In this case, | |
880 read_event_from_tty_or_stream_desc() will arrange for the TTY device | |
881 to be deleted.) */ | |
882 | |
883 static int | |
884 gtk_tty_to_emacs_event (struct Lisp_Event *emacs_event) | |
885 { | |
886 int i; | |
887 | |
888 assert (tty_events_occurred > 0); | |
889 for (i = 0; i < MAXDESC; i++) | |
890 { | |
891 Lisp_Object console = filedesc_with_input[i]; | |
892 if (CONSOLEP (console)) | |
893 { | |
894 assert (tty_events_occurred > 0); | |
895 tty_events_occurred--; | |
896 filedesc_with_input[i] = Qnil; | |
897 if (read_event_from_tty_or_stream_desc | |
898 (emacs_event, XCONSOLE (console), i)) | |
899 return 1; | |
900 } | |
901 } | |
902 | |
903 return 0; | |
904 } | |
905 | |
906 | |
907 /************************************************************************/ | |
908 /* Drag 'n Drop handling */ | |
909 /************************************************************************/ | |
910 #ifdef HAVE_DRAGNDROP | |
911 #define TARGET_URI_LIST 0x00 | |
912 #define TARGET_TEXT_PLAIN 0x01 | |
913 #define TARGET_FILE_NAME 0x02 | |
914 #define TARGET_NETSCAPE 0x03 | |
915 | |
916 static GdkAtom preferred_targets[10]; | |
917 | |
918 void | |
919 dragndrop_data_received (GtkWidget *widget, | |
920 GdkDragContext *context, | |
921 gint x, | |
922 gint y, | |
923 GtkSelectionData *data, | |
924 guint info, | |
925 guint time) | |
926 { | |
927 Lisp_Object event = Fmake_event (Qnil, Qnil); | |
928 struct device *d = gtk_any_window_to_device (widget->window); | |
929 struct frame *f = gtk_any_widget_or_parent_to_frame (d, widget); | |
930 struct Lisp_Event *ev = XEVENT (event); | |
931 Lisp_Object l_type = Qnil, l_data = Qnil; | |
932 Lisp_Object l_dndlist = Qnil, l_item = Qnil; | |
933 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
934 | |
935 GCPRO4 (l_type, l_data, l_dndlist, l_item); | |
936 | |
937 ev->event_type = misc_user_event; | |
938 ev->timestamp = time; | |
939 | |
940 XSETFRAME (ev->channel, f); | |
941 | |
942 ev->event.misc.x = x; | |
943 ev->event.misc.y = y; | |
944 | |
945 if (data->type == preferred_targets[TARGET_URI_LIST]) | |
946 { | |
947 /* newline-separated list of URLs */ | |
948 int start, end; | |
949 const char *string_data = (char *) data->data; | |
950 | |
951 l_type = Qdragdrop_URL; | |
952 | |
953 for (start = 0, end = 0; string_data && string_data[end]; end++) | |
954 { | |
955 if ((string_data[end] == '\r') && (string_data[end+1] == '\n')) | |
956 { | |
957 l_item = make_string (&string_data[start], end - start); | |
958 l_dndlist = Fcons (l_item, l_dndlist); | |
959 ++end; | |
960 start = ++end; | |
961 } | |
962 } | |
963 } | |
964 else if (data->type == preferred_targets[TARGET_TEXT_PLAIN]) | |
965 { | |
966 /* Arbitrary string */ | |
967 l_type = Qdragdrop_MIME; | |
968 l_dndlist = list1 (list3 (list1 (build_string ("text/plain")), | |
969 build_string ("8_bit"), | |
970 make_ext_string (data->data, | |
971 strlen ((char *)data->data), | |
972 Qctext))); | |
973 } | |
974 else if (data->type == preferred_targets[TARGET_FILE_NAME]) | |
975 { | |
976 /* Random filename */ | |
977 char *hurl = dnd_url_hexify_string (data->data, "file:"); | |
978 | |
979 l_dndlist = list1 (make_string ((Bufbyte *)hurl, strlen (hurl))); | |
980 l_type = Qdragdrop_URL; | |
981 | |
982 xfree (hurl); | |
983 } | |
984 else if (data->type == preferred_targets[TARGET_NETSCAPE]) | |
985 { | |
986 /* Single URL */ | |
987 l_dndlist = list1 (make_string ((Extbyte *)data->data, | |
988 strlen ((char *)data->data))); | |
989 l_type = Qdragdrop_URL; | |
990 } | |
991 else | |
992 { | |
993 /* Unknown type - what to do? | |
994 We just pass it up to lisp - we already have a mime type. | |
995 */ | |
996 l_type = Qdragdrop_MIME; | |
997 l_dndlist = list1 (list3 (list1 (build_string (gdk_atom_name (data->type))), | |
998 build_string ("8bit"), | |
999 make_ext_string ((Extbyte *) data->data, | |
1000 data->length, Qbinary))); | |
1001 } | |
1002 | |
1003 ev->event.misc.function = Qdragdrop_drop_dispatch; | |
1004 ev->event.misc.object = Fcons (l_type, l_dndlist); | |
1005 | |
1006 UNGCPRO; | |
1007 | |
1008 gtk_drag_finish (context, TRUE, FALSE, time); | |
1009 enqueue_gtk_dispatch_event (event); | |
1010 } | |
1011 | |
1012 gboolean | |
1013 dragndrop_dropped (GtkWidget *widget, | |
1014 GdkDragContext *drag_context, | |
1015 gint x, | |
1016 gint y, | |
1017 guint time, | |
1018 gpointer user_data) | |
1019 { | |
1020 /* Netscape drops things like: | |
1021 STRING | |
1022 _SGI_ICON | |
1023 _SGI_ICON_TYPE | |
1024 SGI_FILE | |
1025 FILE_NAME | |
1026 _NETSCAPE_URL | |
1027 | |
1028 gmc drops things like | |
1029 application/x-mc-desktop-icon | |
1030 text/uri-list | |
1031 text/plain | |
1032 _NETSCAPE_URL | |
1033 | |
1034 We prefer: | |
1035 text/uri-list | |
1036 text/plain | |
1037 FILE_NAME | |
1038 _NETSCAPE_URL | |
1039 first one | |
1040 */ | |
1041 GdkAtom found = 0; | |
1042 GList *list = drag_context->targets; | |
1043 | |
1044 int i; | |
1045 | |
1046 if (!preferred_targets[0]) | |
1047 { | |
1048 preferred_targets[TARGET_URI_LIST] = gdk_atom_intern ("text/uri-list", FALSE); | |
1049 preferred_targets[TARGET_TEXT_PLAIN] = gdk_atom_intern ("text/plain", FALSE); | |
1050 preferred_targets[TARGET_FILE_NAME] = gdk_atom_intern ("FILE_NAME", FALSE); | |
1051 preferred_targets[TARGET_NETSCAPE] = gdk_atom_intern ("_NETSCAPE_URL", FALSE); | |
1052 } | |
1053 | |
1054 #if 0 | |
1055 stderr_out ("Drop info available in the following formats: \n"); | |
1056 while (list) | |
1057 { | |
1058 stderr_out ("\t%s\n", gdk_atom_name ((GdkAtom)list->data)); | |
1059 list = list->next; | |
1060 } | |
1061 list = drag_context->targets; | |
1062 #endif | |
1063 | |
1064 while (list && !found) | |
1065 { | |
1066 for (i = 0; preferred_targets[i] && !found; i++) | |
1067 { | |
1068 if ((GdkAtom) list->data == preferred_targets[i]) | |
1069 { | |
1070 found = (GdkAtom) list->data; | |
1071 } | |
1072 } | |
1073 list = list->next; | |
1074 } | |
1075 | |
1076 if (!found) | |
1077 { | |
1078 found = (GdkAtom) drag_context->targets->data; | |
1079 } | |
1080 | |
1081 gtk_drag_get_data (GTK_WIDGET (user_data), drag_context, found, time); | |
1082 return (TRUE); | |
1083 } | |
1084 #endif /* HAVE_DRAGNDROP */ | |
1085 | |
1086 | |
1087 /************************************************************************/ | |
1088 /* get the next event from gtk */ | |
1089 /************************************************************************/ | |
1090 | |
1091 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail; | |
1092 | |
1093 static void | |
1094 enqueue_gtk_dispatch_event (Lisp_Object event) | |
1095 { | |
1096 enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail); | |
1097 } | |
1098 | |
1099 static Lisp_Object | |
1100 dequeue_gtk_dispatch_event (void) | |
1101 { | |
1102 return dequeue_event (&dispatch_event_queue, &dispatch_event_queue_tail); | |
1103 } | |
1104 | |
1105 /* This business exists because menu events "happen" when | |
1106 menubar_selection_callback() is called from somewhere deep | |
1107 within XtAppProcessEvent in emacs_Xt_next_event(). The | |
1108 callback needs to terminate the modal loop in that function | |
1109 or else it will continue waiting until another event is | |
1110 received. | |
1111 | |
1112 Same business applies to scrollbar events. */ | |
1113 | |
1114 void | |
1115 signal_special_gtk_user_event (Lisp_Object channel, Lisp_Object function, | |
1116 Lisp_Object object) | |
1117 { | |
1118 Lisp_Object event = Fmake_event (Qnil, Qnil); | |
1119 | |
1120 XEVENT (event)->event_type = misc_user_event; | |
1121 XEVENT (event)->channel = channel; | |
1122 XEVENT (event)->event.eval.function = function; | |
1123 XEVENT (event)->event.eval.object = object; | |
1124 | |
1125 enqueue_gtk_dispatch_event (event); | |
1126 } | |
1127 | |
1128 static void | |
1129 emacs_gtk_next_event (struct Lisp_Event *emacs_event) | |
1130 { | |
1131 we_didnt_get_an_event: | |
1132 | |
1133 while (NILP (dispatch_event_queue) && | |
1134 !completed_timeouts && | |
1135 !fake_event_occurred && | |
1136 !process_events_occurred && | |
1137 !tty_events_occurred) | |
1138 { | |
1139 gtk_main_iteration(); | |
1140 } | |
1141 | |
1142 if (!NILP (dispatch_event_queue)) | |
1143 { | |
1144 Lisp_Object event, event2; | |
1145 XSETEVENT (event2, emacs_event); | |
1146 event = dequeue_gtk_dispatch_event (); | |
1147 Fcopy_event (event, event2); | |
1148 Fdeallocate_event (event); | |
1149 } | |
1150 else if (tty_events_occurred) | |
1151 { | |
1152 if (!gtk_tty_to_emacs_event (emacs_event)) | |
1153 goto we_didnt_get_an_event; | |
1154 } | |
1155 else if (completed_timeouts) | |
1156 gtk_timeout_to_emacs_event (emacs_event); | |
1157 else if (fake_event_occurred) | |
1158 { | |
1159 /* A dummy event, so that a cycle of the command loop will occur. */ | |
1160 fake_event_occurred = 0; | |
1161 /* eval events have nil as channel */ | |
1162 emacs_event->event_type = eval_event; | |
1163 emacs_event->event.eval.function = Qidentity; | |
1164 emacs_event->event.eval.object = Qnil; | |
1165 } | |
1166 else /* if (process_events_occurred) */ | |
1167 gtk_process_to_emacs_event (emacs_event); | |
1168 } | |
1169 | |
1170 int | |
1171 gtk_event_to_emacs_event (struct frame *frame, GdkEvent *gdk_event, struct Lisp_Event *emacs_event) | |
1172 { | |
1173 struct device *d = NULL; | |
1174 struct gtk_device *gd = NULL; | |
1175 gboolean accept_any_window = FALSE; | |
1176 | |
1177 if (!frame) | |
1178 { | |
1179 frame = XFRAME (Fselected_frame (Vdefault_gtk_device)); | |
1180 accept_any_window = TRUE; | |
1181 } | |
1182 | |
1183 d = XDEVICE (FRAME_DEVICE (frame)); | |
1184 gd = DEVICE_GTK_DATA (d); | |
1185 | |
1186 set_last_server_timestamp (d, gdk_event); | |
1187 | |
1188 switch (gdk_event->type) | |
1189 { | |
1190 /* XEmacs handles double and triple clicking on its own, and if | |
1191 we capture these events, it royally confuses the code in | |
1192 ../lisp/mouse.el */ | |
1193 case GDK_2BUTTON_PRESS: | |
1194 case GDK_3BUTTON_PRESS: | |
1195 return (0); | |
1196 | |
1197 case GDK_BUTTON_PRESS: | |
1198 case GDK_BUTTON_RELEASE: | |
1199 /* We need to ignore button events outside our main window or | |
1200 things get ugly. The standard scrollbars in Gtk try to be | |
1201 nice and pass the button press events up to the parent | |
1202 widget. This causes us no end of grief though. Effects | |
1203 range from setting point to the wrong place to selecting | |
1204 new windows. */ | |
1205 { | |
1206 GdkWindow *w = gdk_window_at_pointer (NULL, NULL); | |
1207 | |
1208 /* If you press mouse button and drag it around, and release | |
1209 it outside the window, you will get a NULL GdkWindow at | |
1210 pointer. We need to forward these events on to XEmacs so | |
1211 that the mouse selection voodoo works. | |
1212 */ | |
1213 if (w && (w != gdk_window_lookup (GDK_ROOT_WINDOW ()))) | |
1214 { | |
1215 GdkEvent ev; | |
1216 GtkWidget *wid = NULL; | |
1217 | |
1218 ev.any.window = w; | |
1219 wid = gtk_get_event_widget (&ev); | |
1220 | |
1221 if (!GTK_IS_XEMACS (wid) && !accept_any_window) | |
1222 { | |
1223 return (0); | |
1224 } | |
1225 } | |
1226 if (!accept_any_window) | |
1227 gtk_widget_grab_focus (FRAME_GTK_TEXT_WIDGET (frame)); | |
1228 } | |
1229 /* Fall through */ | |
1230 case GDK_KEY_PRESS: | |
1231 { | |
1232 unsigned int modifiers = 0; | |
1233 int shift_p, lock_p; | |
1234 gboolean key_event_p = (gdk_event->type == GDK_KEY_PRESS); | |
1235 unsigned int *state = | |
1236 key_event_p ? &gdk_event->key.state : &gdk_event->button.state; | |
1237 | |
1238 /* If this is a synthetic KeyPress or Button event, and the user | |
1239 has expressed a disinterest in this security hole, then drop | |
1240 it on the floor. */ | |
1241 /* #### BILL!!! Should this be a generic check for ANY synthetic | |
1242 event? */ | |
1243 if ((gdk_event->any.send_event) && !gtk_allow_sendevents) | |
1244 return 0; | |
1245 | |
1246 DEVICE_GTK_MOUSE_TIMESTAMP (d) = | |
1247 DEVICE_GTK_GLOBAL_MOUSE_TIMESTAMP (d) = | |
1248 key_event_p ? gdk_event->key.time : gdk_event->button.time; | |
1249 | |
1250 if (*state & GDK_CONTROL_MASK) modifiers |= XEMACS_MOD_CONTROL; | |
1251 if (*state & gd->MetaMask) modifiers |= XEMACS_MOD_META; | |
1252 if (*state & gd->SuperMask) modifiers |= XEMACS_MOD_SUPER; | |
1253 if (*state & gd->HyperMask) modifiers |= XEMACS_MOD_HYPER; | |
1254 if (*state & gd->AltMask) modifiers |= XEMACS_MOD_ALT; | |
1255 | |
1256 /* Ignore the Caps_Lock key if: | |
1257 - any other modifiers are down, so that Caps_Lock doesn't | |
1258 turn C-x into C-X, which would suck. | |
1259 - the event was a mouse event. */ | |
1260 if (modifiers || ! key_event_p) | |
1261 *state &= (~GDK_LOCK_MASK); | |
1262 | |
1263 shift_p = *state & GDK_SHIFT_MASK; | |
1264 lock_p = *state & GDK_LOCK_MASK; | |
1265 | |
1266 if (shift_p || lock_p) | |
1267 modifiers |= XEMACS_MOD_SHIFT; | |
1268 | |
1269 if (key_event_p) | |
1270 { | |
1271 GdkEventKey *key_event = &gdk_event->key; | |
1272 Lisp_Object keysym; | |
1273 | |
1274 /* This used to compute the frame from the given X window and | |
1275 store it here, but we really don't care about the frame. */ | |
1276 emacs_event->channel = DEVICE_CONSOLE (d); | |
1277 | |
1278 /* Keysym mucking has already been done inside the | |
1279 GdkEventKey parsing */ | |
1280 keysym = gtk_to_emacs_keysym (d, key_event, 0); | |
1281 | |
1282 /* If the emacs keysym is nil, then that means that the X | |
1283 keysym was either a Modifier or NoSymbol, which | |
1284 probably means that we're in the midst of reading a | |
1285 Multi_key sequence, or a "dead" key prefix, or XIM | |
1286 input. Ignore it. */ | |
1287 if (NILP (keysym)) | |
1288 return 0; | |
1289 | |
1290 /* More Caps_Lock garbage: Caps_Lock should *only* add the | |
1291 shift modifier to two-case keys (that is, A-Z and | |
1292 related characters). So at this point (after looking up | |
1293 the keysym) if the keysym isn't a dual-case alphabetic, | |
1294 and if the caps lock key was down but the shift key | |
1295 wasn't, then turn off the shift modifier. Gag barf */ | |
1296 /* #### type lossage: assuming equivalence of emacs and | |
1297 X keysyms */ | |
1298 /* !!#### maybe fix for Mule */ | |
1299 if (lock_p && !shift_p && | |
1300 ! (CHAR_OR_CHAR_INTP (keysym) | |
1301 && keysym_obeys_caps_lock_p | |
1302 ((guint) XCHAR_OR_CHAR_INT (keysym), d))) | |
1303 modifiers &= (~XEMACS_MOD_SHIFT); | |
1304 | |
1305 /* If this key contains two distinct keysyms, that is, | |
1306 "shift" generates a different keysym than the | |
1307 non-shifted key, then don't apply the shift modifier | |
1308 bit: it's implicit. Otherwise, if there would be no | |
1309 other way to tell the difference between the shifted | |
1310 and unshifted version of this key, apply the shift bit. | |
1311 Non-graphics, like Backspace and F1 get the shift bit | |
1312 in the modifiers slot. Neither the characters "a", | |
1313 "A", "2", nor "@" normally have the shift bit set. | |
1314 However, "F1" normally does. */ | |
1315 if (modifiers & XEMACS_MOD_SHIFT) | |
1316 { | |
1317 if (CHAR_OR_CHAR_INTP (keysym)) | |
1318 { | |
1319 modifiers &= ~XEMACS_MOD_SHIFT; | |
1320 } | |
1321 } | |
1322 | |
1323 emacs_event->event_type = key_press_event; | |
1324 emacs_event->timestamp = key_event->time; | |
1325 emacs_event->event.key.modifiers = modifiers; | |
1326 emacs_event->event.key.keysym = keysym; | |
1327 } | |
1328 else /* Mouse press/release event */ | |
1329 { | |
1330 GdkEventButton *button_event = &gdk_event->button; | |
1331 XSETFRAME (emacs_event->channel, frame); | |
1332 | |
1333 emacs_event->event_type = (button_event->type == GDK_BUTTON_RELEASE) ? | |
1334 button_release_event : button_press_event; | |
1335 | |
1336 emacs_event->event.button.modifiers = modifiers; | |
1337 emacs_event->timestamp = button_event->time; | |
1338 emacs_event->event.button.button = button_event->button; | |
1339 emacs_event->event.button.x = button_event->x; | |
1340 emacs_event->event.button.y = button_event->y; | |
1341 } | |
1342 } | |
1343 break; | |
1344 case GDK_KEY_RELEASE: | |
1345 return 0; | |
1346 break; | |
1347 case GDK_MOTION_NOTIFY: | |
1348 { | |
1349 GdkEventMotion *ev = &gdk_event->motion; | |
1350 unsigned int modifiers = 0; | |
1351 gint x,y; | |
1352 GdkModifierType mask; | |
1353 | |
1354 /* We use MOTION_HINT_MASK, so we will get only one motion | |
1355 event until the next time we call gdk_window_get_pointer or | |
1356 the user clicks the mouse. So call gdk_window_get_pointer | |
1357 now (meaning that the event will be in sync with the server | |
1358 just before Fnext_event() returns). If the mouse is still | |
1359 in motion, then the server will immediately generate | |
1360 exactly one more motion event, which will be on the queue | |
1361 waiting for us next time around. */ | |
1362 gdk_window_get_pointer (ev->window, &x, &y, &mask); | |
1363 | |
1364 DEVICE_GTK_MOUSE_TIMESTAMP (d) = ev->time; | |
1365 | |
1366 XSETFRAME (emacs_event->channel, frame); | |
1367 emacs_event->event_type = pointer_motion_event; | |
1368 emacs_event->timestamp = ev->time; | |
1369 emacs_event->event.motion.x = x; | |
1370 emacs_event->event.motion.y = y; | |
1371 if (mask & GDK_SHIFT_MASK) modifiers |= XEMACS_MOD_SHIFT; | |
1372 if (mask & GDK_CONTROL_MASK) modifiers |= XEMACS_MOD_CONTROL; | |
1373 if (mask & gd->MetaMask) modifiers |= XEMACS_MOD_META; | |
1374 if (mask & gd->SuperMask) modifiers |= XEMACS_MOD_SUPER; | |
1375 if (mask & gd->HyperMask) modifiers |= XEMACS_MOD_HYPER; | |
1376 if (mask & gd->AltMask) modifiers |= XEMACS_MOD_ALT; | |
1377 /* Currently ignores Shift_Lock but probably shouldn't | |
1378 (but it definitely should ignore Caps_Lock). */ | |
1379 emacs_event->event.motion.modifiers = modifiers; | |
1380 } | |
1381 break; | |
1382 | |
1383 default: /* it's a magic event */ | |
1384 return (0); | |
1385 break; | |
1386 } | |
1387 return 1; | |
1388 } | |
1389 | |
1390 static const char *event_name (GdkEvent *); | |
1391 | |
1392 static gboolean | |
1393 generic_event_handler (GtkWidget *widget, GdkEvent *event) | |
1394 { | |
1395 Lisp_Object emacs_event = Qnil; | |
1396 if (!GTK_IS_XEMACS (widget)) | |
1397 { | |
1398 stderr_out ("Got a %s event for a non-XEmacs widget\n",event_name (event)); | |
1399 return (FALSE); | |
1400 } | |
1401 | |
1402 emacs_event = Fmake_event (Qnil, Qnil); | |
1403 | |
1404 if (gtk_event_to_emacs_event (GTK_XEMACS_FRAME (widget), event, XEVENT (emacs_event))) | |
1405 { | |
1406 enqueue_gtk_dispatch_event (emacs_event); | |
1407 return (TRUE); | |
1408 } | |
1409 else | |
1410 { | |
1411 Fdeallocate_event (emacs_event); | |
1412 } | |
1413 return (FALSE); | |
1414 } | |
1415 | |
1416 gint emacs_gtk_key_event_handler(GtkWidget *widget, GdkEventKey *event) | |
1417 { | |
1418 return (generic_event_handler (widget, (GdkEvent *) event)); | |
1419 } | |
1420 | |
1421 gint emacs_gtk_button_event_handler(GtkWidget *widget, GdkEventButton *event) | |
1422 { | |
1423 return (generic_event_handler (widget, (GdkEvent *) event)); | |
1424 } | |
1425 | |
1426 gint emacs_gtk_motion_event_handler (GtkWidget *widget, GdkEventMotion *event) | |
1427 { | |
1428 return (generic_event_handler (widget, (GdkEvent *) event)); | |
1429 } | |
1430 | |
1431 gboolean | |
1432 emacs_shell_event_handler (GtkWidget *wid /* unused */, | |
1433 GdkEvent *event, | |
1434 gpointer closure) | |
1435 { | |
1436 struct frame *frame = (struct frame *) closure; | |
1437 Lisp_Object lisp_event = Fmake_event (Qnil, Qnil); | |
1438 struct Lisp_Event *emacs_event = XEVENT (lisp_event); | |
1439 GdkEvent *gdk_event_copy = &emacs_event->event.magic.underlying_gdk_event; | |
1440 struct device *d = XDEVICE (FRAME_DEVICE (frame)); | |
1441 gboolean ignore_p = FALSE; | |
1442 | |
1443 set_last_server_timestamp (d, event); | |
1444 | |
1445 #define FROB(event_member) gdk_event_copy->event_member = event->event_member | |
1446 | |
1447 switch (event->type) | |
1448 { | |
1449 case GDK_SELECTION_REQUEST: | |
1450 case GDK_SELECTION_CLEAR: | |
1451 case GDK_SELECTION_NOTIFY: FROB(selection); break; | |
1452 case GDK_PROPERTY_NOTIFY: FROB(property); break; | |
1453 case GDK_CLIENT_EVENT: FROB(client); break; | |
1454 case GDK_MAP: | |
1455 case GDK_UNMAP: FROB(any); break; | |
1456 case GDK_CONFIGURE: FROB(configure); break; | |
1457 case GDK_ENTER_NOTIFY: | |
1458 case GDK_LEAVE_NOTIFY: FROB(crossing); break; | |
1459 case GDK_FOCUS_CHANGE: FROB(focus_change); break; | |
1460 case GDK_VISIBILITY_NOTIFY: FROB(visibility); break; | |
1461 default: | |
1462 ignore_p = TRUE; | |
1463 /* Hrmm... do we really want to swallow all the other events as magic? */ | |
1464 *gdk_event_copy = *event; | |
1465 break; | |
1466 } | |
1467 #undef FROB | |
1468 | |
1469 emacs_event->event_type = magic_event; | |
1470 XSETFRAME (emacs_event->channel, frame); | |
1471 | |
1472 if (ignore_p) | |
1473 { | |
1474 stderr_out ("Ignoring event... (%s)\n", event_name (event)); | |
1475 Fdeallocate_event (lisp_event); | |
1476 return (FALSE); | |
1477 } | |
1478 else | |
1479 { | |
1480 enqueue_gtk_dispatch_event (lisp_event); | |
1481 return (TRUE); | |
1482 } | |
1483 } | |
1484 | |
1485 | |
1486 /************************************************************************/ | |
1487 /* input pending / C-g checking */ | |
1488 /************************************************************************/ | |
1489 static void | |
1490 gtk_check_for_quit_char (struct device *d); | |
1491 | |
1492 static void | |
1493 check_for_tty_quit_char (struct device *d) | |
1494 { | |
1495 SELECT_TYPE temp_mask; | |
1496 int infd = DEVICE_INFD (d); | |
1497 struct console *con = XCONSOLE (DEVICE_CONSOLE (d)); | |
1498 Emchar quit_char = CONSOLE_QUIT_CHAR (con); | |
1499 | |
1500 FD_ZERO (&temp_mask); | |
1501 FD_SET (infd, &temp_mask); | |
1502 | |
1503 while (1) | |
1504 { | |
1505 Lisp_Object event; | |
1506 Emchar the_char; | |
1507 | |
1508 if (!poll_fds_for_input (temp_mask)) | |
1509 return; | |
1510 | |
1511 event = Fmake_event (Qnil, Qnil); | |
1512 if (!read_event_from_tty_or_stream_desc (XEVENT (event), con, infd)) | |
1513 /* EOF, or something ... */ | |
1514 return; | |
1515 /* #### bogus. quit-char should be allowed to be any sort | |
1516 of event. */ | |
1517 the_char = event_to_character (XEVENT (event), 1, 0, 0); | |
1518 if (the_char >= 0 && the_char == quit_char) | |
1519 { | |
1520 Vquit_flag = Qt; | |
1521 /* do not queue the C-g. See above. */ | |
1522 return; | |
1523 } | |
1524 | |
1525 /* queue the read event to be read for real later. */ | |
1526 enqueue_gtk_dispatch_event (event); | |
1527 } | |
1528 } | |
1529 | |
1530 static void | |
1531 emacs_gtk_quit_p (void) | |
1532 { | |
1533 Lisp_Object devcons, concons; | |
1534 | |
1535 CONSOLE_LOOP (concons) | |
1536 { | |
1537 struct console *con = XCONSOLE (XCAR (concons)); | |
1538 if (!con->input_enabled) | |
1539 continue; | |
1540 | |
1541 CONSOLE_DEVICE_LOOP (devcons, con) | |
1542 { | |
1543 struct device *d; | |
1544 d = XDEVICE (XCAR (devcons)); | |
1545 | |
1546 if (DEVICE_GTK_P (d)) | |
1547 /* emacs may be exiting */ | |
1548 gtk_check_for_quit_char (d); | |
1549 else if (DEVICE_TTY_P (d)) | |
1550 check_for_tty_quit_char (d); | |
1551 } | |
1552 } | |
1553 } | |
1554 | |
1555 #include <gdk/gdkx.h> | |
1556 | |
1557 static void | |
1558 drain_gtk_queue (void) | |
1559 | |
1560 { | |
1561 /* We can't just spin through here and wait for GTKs idea of the | |
1562 event queue to get empty, or the queue never gets drained. The | |
1563 situation is as follows. A process event gets signalled, we put | |
1564 it on the queue, then we go into Fnext_event(), which calls | |
1565 drain_gtk_queue(). But gtk_events_pending() will always return | |
1566 TRUE if there are file-descriptor (aka our process) events | |
1567 pending. Using GDK_events_pending() only shows us windowing | |
1568 system events. | |
1569 */ | |
1570 if (GDK_DISPLAY ()) | |
1571 while (gdk_events_pending ()) | |
1572 gtk_main_iteration (); | |
1573 } | |
1574 | |
1575 static int | |
1576 emacs_gtk_event_pending_p (int user_p) | |
1577 { | |
1578 Lisp_Object event; | |
1579 int tick_count_val; | |
1580 | |
1581 /* If `user_p' is false, then this function returns whether there are any | |
1582 X, timeout, or fd events pending (that is, whether emacs_gtk_next_event() | |
1583 would return immediately without blocking). | |
1584 | |
1585 if `user_p' is true, then this function returns whether there are any | |
1586 *user generated* events available (that is, whether there are keyboard | |
1587 or mouse-click events ready to be read). This also implies that | |
1588 emacs_Xt_next_event() would not block. | |
1589 | |
1590 In a non-SIGIO world, this also checks whether the user has typed ^G, | |
1591 since this is a convenient place to do so. We don't need to do this | |
1592 in a SIGIO world, since input causes an interrupt. | |
1593 */ | |
1594 | |
1595 /* This function used to simply check whether there were any X | |
1596 events (or if user_p was 1, it iterated over all the pending | |
1597 X events using XCheckIfEvent(), looking for keystrokes and | |
1598 button events). That worked in the old cheesoid event loop, | |
1599 which didn't go through XtAppDispatchEvent(), but it doesn't | |
1600 work any more -- X events may not result in anything. For | |
1601 example, a button press in a blank part of the menubar appears | |
1602 as an X event but will not result in any Emacs events (a | |
1603 button press that activates the menubar results in an Emacs | |
1604 event through the stop_next_event mechanism). | |
1605 | |
1606 The only accurate way of determining whether these X events | |
1607 translate into Emacs events is to go ahead and dispatch them | |
1608 until there's something on the dispatch queue. */ | |
1609 | |
1610 /* See if there are any user events already on the queue. */ | |
1611 EVENT_CHAIN_LOOP (event, dispatch_event_queue) | |
1612 if (!user_p || command_event_p (event)) | |
1613 return 1; | |
1614 | |
1615 /* See if there's any TTY input available. | |
1616 */ | |
1617 if (poll_fds_for_input (tty_only_mask)) | |
1618 return 1; | |
1619 | |
1620 if (!user_p) | |
1621 { | |
1622 /* If not user_p and there are any timer or file-desc events | |
1623 pending, we know there will be an event so we're through. */ | |
1624 /* XtInputMask pending_value; */ | |
1625 | |
1626 /* Note that formerly we just checked the value of XtAppPending() | |
1627 to determine if there was file-desc input. This doesn't | |
1628 work any more with the signal_event_pipe; XtAppPending() | |
1629 will says "yes" in this case but there isn't really any | |
1630 input. Another way of fixing this problem is for the | |
1631 signal_event_pipe to generate actual input in the form | |
1632 of an identity eval event or something. (#### maybe this | |
1633 actually happens?) */ | |
1634 | |
1635 if (poll_fds_for_input (process_only_mask)) | |
1636 return 1; | |
1637 | |
1638 /* #### Is there any way to do this in Gtk? I don't think there | |
1639 is a 'peek' for events */ | |
1640 #if 0 | |
1641 pending_value = XtAppPending (Xt_app_con); | |
1642 | |
1643 if (pending_value & XtIMTimer) | |
1644 return 1; | |
1645 #endif | |
1646 } | |
1647 | |
1648 /* XtAppPending() can be super-slow, esp. over a network connection. | |
1649 Quantify results have indicated that in some cases the | |
1650 call to detect_input_pending() completely dominates the | |
1651 running time of redisplay(). Fortunately, in a SIGIO world | |
1652 we can more quickly determine whether there are any X events: | |
1653 if an event has happened since the last time we checked, then | |
1654 a SIGIO will have happened. On a machine with broken SIGIO, | |
1655 we'll still be in an OK state -- the sigio_happened flag | |
1656 will get set at least once a second, so we'll be no more than | |
1657 one second behind reality. (In general it's OK if we | |
1658 erroneously report no input pending when input is actually | |
1659 pending() -- preemption is just a bit less efficient, that's | |
1660 all. It's bad bad bad if you err the other way -- you've | |
1661 promised that `next-event' won't block but it actually will, | |
1662 and some action might get delayed until the next time you | |
1663 hit a key.) | |
1664 */ | |
1665 | |
1666 /* quit_check_signal_tick_count is volatile so try to avoid race conditions | |
1667 by using a temporary variable */ | |
1668 tick_count_val = quit_check_signal_tick_count; | |
1669 if (last_quit_check_signal_tick_count != tick_count_val) | |
1670 { | |
1671 last_quit_check_signal_tick_count = tick_count_val; | |
1672 | |
1673 /* We need to drain the entire queue now -- if we only | |
1674 drain part of it, we may later on end up with events | |
1675 actually pending but detect_input_pending() returning | |
1676 false because there wasn't another SIGIO. */ | |
1677 | |
1678 drain_gtk_queue (); | |
1679 | |
1680 EVENT_CHAIN_LOOP (event, dispatch_event_queue) | |
1681 if (!user_p || command_event_p (event)) | |
1682 return 1; | |
1683 } | |
1684 | |
1685 return 0; | |
1686 } | |
1687 | |
1688 | |
1689 /************************************************************************/ | |
1690 /* initialization */ | |
1691 /************************************************************************/ | |
1692 | |
1693 void | |
1694 syms_of_event_gtk (void) | |
1695 { | |
1696 defsymbol (&Qkey_mapping, "key-mapping"); | |
1697 defsymbol (&Qsans_modifiers, "sans-modifiers"); | |
1698 } | |
1699 | |
1700 void reinit_vars_of_event_gtk (void) | |
1701 { | |
1702 gtk_event_stream = xnew (struct event_stream); | |
1703 gtk_event_stream->event_pending_p = emacs_gtk_event_pending_p; | |
1704 gtk_event_stream->next_event_cb = emacs_gtk_next_event; | |
1705 gtk_event_stream->handle_magic_event_cb= emacs_gtk_handle_magic_event; | |
1706 gtk_event_stream->add_timeout_cb = emacs_gtk_add_timeout; | |
1707 gtk_event_stream->remove_timeout_cb = emacs_gtk_remove_timeout; | |
1708 gtk_event_stream->select_console_cb = emacs_gtk_select_console; | |
1709 gtk_event_stream->unselect_console_cb = emacs_gtk_unselect_console; | |
1710 gtk_event_stream->select_process_cb = emacs_gtk_select_process; | |
1711 gtk_event_stream->unselect_process_cb = emacs_gtk_unselect_process; | |
1712 gtk_event_stream->quit_p_cb = emacs_gtk_quit_p; | |
1713 gtk_event_stream->create_stream_pair_cb= emacs_gtk_create_stream_pair; | |
1714 gtk_event_stream->delete_stream_pair_cb= emacs_gtk_delete_stream_pair; | |
1715 | |
1716 the_GTK_timeout_blocktype = Blocktype_new (struct GTK_timeout_blocktype); | |
1717 | |
1718 /* this function only makes safe calls */ | |
1719 init_what_input_once (); | |
1720 } | |
1721 | |
1722 void | |
1723 vars_of_event_gtk (void) | |
1724 { | |
1725 reinit_vars_of_event_gtk (); | |
1726 | |
1727 dispatch_event_queue = Qnil; | |
1728 staticpro (&dispatch_event_queue); | |
1729 dispatch_event_queue_tail = Qnil; | |
1730 | |
1731 DEFVAR_BOOL ("gtk-allow-sendevents", >k_allow_sendevents /* | |
1732 *Non-nil means to allow synthetic events. Nil means they are ignored. | |
1733 Beware: allowing emacs to process SendEvents opens a big security hole. | |
1734 */ ); | |
1735 gtk_allow_sendevents = 0; | |
1736 | |
1737 last_quit_check_signal_tick_count = 0; | |
1738 } | |
1739 | |
1740 void | |
1741 init_event_gtk_late (void) /* called when already initialized */ | |
1742 { | |
1743 timeout_id_tick = 1; | |
1744 pending_timeouts = 0; | |
1745 completed_timeouts = 0; | |
1746 | |
1747 event_stream = gtk_event_stream; | |
1748 | |
1749 #if 0 | |
1750 /* Shut GDK the hell up */ | |
1751 gdk_error_trap_push (); | |
1752 #endif | |
1753 | |
1754 gdk_input_add (signal_event_pipe[0], GDK_INPUT_READ, | |
1755 (GdkInputFunction) gtk_what_callback, NULL); | |
1756 } | |
1757 | |
1758 /* Bogus utility routines */ | |
1759 static const char *event_name (GdkEvent *ev) | |
1760 { | |
1761 return (gtk_event_name (ev->any.type)); | |
1762 } | |
1763 | |
1764 /* This is down at the bottom of the file so I can avoid polluting the | |
1765 generic code with this X specific CRAP! */ | |
1766 | |
1767 #include <gdk/gdkx.h> | |
1768 #include <X11/keysym.h> | |
1769 /* #### BILL!!! Fix this please! */ | |
1770 | |
1771 | |
1772 /************************************************************************/ | |
1773 /* keymap handling */ | |
1774 /************************************************************************/ | |
1775 | |
1776 /* X bogusly doesn't define the interpretations of any bits besides | |
1777 ModControl, ModShift, and ModLock; so the Interclient Communication | |
1778 Conventions Manual says that we have to bend over backwards to figure | |
1779 out what the other modifier bits mean. According to ICCCM: | |
1780 | |
1781 - Any keycode which is assigned ModControl is a "control" key. | |
1782 | |
1783 - Any modifier bit which is assigned to a keycode which generates Meta_L | |
1784 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper, | |
1785 etc. | |
1786 | |
1787 - Any keypress event which contains ModControl in its state should be | |
1788 interpreted as a "control" character. | |
1789 | |
1790 - Any keypress event which contains a modifier bit in its state which is | |
1791 generated by a keycode whose corresponding keysym is Meta_L or Meta_R | |
1792 should be interpreted as a "meta" character. Likewise for Super, Hyper, | |
1793 etc. | |
1794 | |
1795 - It is illegal for a keysym to be associated with more than one modifier | |
1796 bit. | |
1797 | |
1798 This means that the only thing that emacs can reasonably interpret as a | |
1799 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates | |
1800 one of the modifier bits Mod1-Mod5. | |
1801 | |
1802 Unfortunately, many keyboards don't have Meta keys in their default | |
1803 configuration. So, if there are no Meta keys, but there are "Alt" keys, | |
1804 emacs will interpret Alt as Meta. If there are both Meta and Alt keys, | |
1805 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to | |
1806 mean "Symbol," but that just confused the hell out of way too many people). | |
1807 | |
1808 This works with the default configurations of the 19 keyboard-types I've | |
1809 checked. | |
1810 | |
1811 Emacs detects keyboard configurations which violate the above rules, and | |
1812 prints an error message on the standard-error-output. (Perhaps it should | |
1813 use a pop-up-window instead.) | |
1814 */ | |
1815 | |
1816 static void | |
1817 gtk_reset_key_mapping (struct device *d) | |
1818 { | |
1819 Display *display = GDK_DISPLAY (); | |
1820 struct gtk_device *xd = DEVICE_GTK_DATA (d); | |
1821 XModifierKeymap *map = (XModifierKeymap *) xd->x_keysym_map; | |
1822 KeySym *keysym, *keysym_end; | |
1823 Lisp_Object hashtable; | |
1824 int key_code_count, keysyms_per_code; | |
1825 | |
1826 if (map) | |
1827 XFree ((char *) map); | |
1828 XDisplayKeycodes (display, | |
1829 &xd->x_keysym_map_min_code, | |
1830 &xd->x_keysym_map_max_code); | |
1831 key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1; | |
1832 map = (XModifierKeymap *) | |
1833 XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count, | |
1834 &xd->x_keysym_map_keysyms_per_code); | |
1835 | |
1836 xd->x_keysym_map = (void *)map; | |
1837 hashtable = xd->x_keysym_map_hashtable; | |
1838 if (HASH_TABLEP (hashtable)) | |
1839 { | |
1840 Fclrhash (hashtable); | |
1841 } | |
1842 else | |
1843 { | |
1844 xd->x_keysym_map_hashtable = hashtable = | |
1845 make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); | |
1846 } | |
1847 | |
1848 for (keysym = (KeySym *) map, | |
1849 keysyms_per_code = xd->x_keysym_map_keysyms_per_code, | |
1850 keysym_end = keysym + (key_code_count * keysyms_per_code); | |
1851 keysym < keysym_end; | |
1852 keysym += keysyms_per_code) | |
1853 { | |
1854 int j; | |
1855 | |
1856 if (keysym[0] == NoSymbol) | |
1857 continue; | |
1858 | |
1859 { | |
1860 char *name = XKeysymToString (keysym[0]); | |
1861 Lisp_Object sym = gtk_keysym_to_emacs_keysym (keysym[0], 0); | |
1862 if (name) | |
1863 { | |
1864 Fputhash (build_string (name), Qsans_modifiers, hashtable); | |
1865 Fputhash (sym, Qsans_modifiers, hashtable); | |
1866 } | |
1867 } | |
1868 | |
1869 for (j = 1; j < keysyms_per_code; j++) | |
1870 { | |
1871 if (keysym[j] != keysym[0] && | |
1872 keysym[j] != NoSymbol) | |
1873 { | |
1874 char *name = XKeysymToString (keysym[j]); | |
1875 Lisp_Object sym = gtk_keysym_to_emacs_keysym (keysym[j], 0); | |
1876 if (name && NILP (Fgethash (sym, hashtable, Qnil))) | |
1877 { | |
1878 Fputhash (build_string (name), Qt, hashtable); | |
1879 Fputhash (sym, Qt, hashtable); | |
1880 } | |
1881 } | |
1882 } | |
1883 } | |
1884 } | |
1885 | |
1886 static const char * | |
1887 index_to_name (int indice) | |
1888 { | |
1889 switch (indice) | |
1890 { | |
1891 case ShiftMapIndex: return "ModShift"; | |
1892 case LockMapIndex: return "ModLock"; | |
1893 case ControlMapIndex: return "ModControl"; | |
1894 case Mod1MapIndex: return "Mod1"; | |
1895 case Mod2MapIndex: return "Mod2"; | |
1896 case Mod3MapIndex: return "Mod3"; | |
1897 case Mod4MapIndex: return "Mod4"; | |
1898 case Mod5MapIndex: return "Mod5"; | |
1899 default: return "???"; | |
1900 } | |
1901 } | |
1902 | |
1903 /* Boy, I really wish C had local functions... */ | |
1904 struct c_doesnt_have_closures /* #### not yet used */ | |
1905 { | |
1906 int warned_about_overlapping_modifiers; | |
1907 int warned_about_predefined_modifiers; | |
1908 int warned_about_duplicate_modifiers; | |
1909 int meta_bit; | |
1910 int hyper_bit; | |
1911 int super_bit; | |
1912 int alt_bit; | |
1913 int mode_bit; | |
1914 }; | |
1915 | |
1916 static void | |
1917 gtk_reset_modifier_mapping (struct device *d) | |
1918 { | |
1919 Display *display = GDK_DISPLAY (); | |
1920 struct gtk_device *xd = DEVICE_GTK_DATA (d); | |
1921 int modifier_index, modifier_key, column, mkpm; | |
1922 int warned_about_overlapping_modifiers = 0; | |
1923 /* int warned_about_predefined_modifiers = 0; */ | |
1924 /* int warned_about_duplicate_modifiers = 0; */ | |
1925 int meta_bit = 0; | |
1926 int hyper_bit = 0; | |
1927 int super_bit = 0; | |
1928 int alt_bit = 0; | |
1929 int mode_bit = 0; | |
1930 XModifierKeymap *map = (XModifierKeymap *) xd->x_modifier_keymap; | |
1931 | |
1932 xd->lock_interpretation = 0; | |
1933 | |
1934 if (map) | |
1935 XFreeModifiermap (map); | |
1936 | |
1937 gtk_reset_key_mapping (d); | |
1938 | |
1939 xd->x_modifier_keymap = map = XGetModifierMapping (display); | |
1940 | |
1941 /* Boy, I really wish C had local functions... | |
1942 */ | |
1943 | |
1944 /* The call to warn_when_safe must be on the same line as the string or | |
1945 make-msgfile won't pick it up properly (the newline doesn't confuse | |
1946 it, but the backslash does). */ | |
1947 | |
1948 #define store_modifier(name,old) \ | |
1949 old = modifier_index; | |
1950 | |
1951 mkpm = map->max_keypermod; | |
1952 for (modifier_index = 0; modifier_index < 8; modifier_index++) | |
1953 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { | |
1954 KeySym last_sym = 0; | |
1955 for (column = 0; column < 4; column += 2) { | |
1956 KeyCode code = map->modifiermap[modifier_index * mkpm | |
1957 + modifier_key]; | |
1958 KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0); | |
1959 if (sym == last_sym) continue; | |
1960 last_sym = sym; | |
1961 switch (sym) { | |
1962 case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break; | |
1963 case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break; | |
1964 case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break; | |
1965 case XK_Super_L: store_modifier ("Super_L", super_bit); break; | |
1966 case XK_Super_R: store_modifier ("Super_R", super_bit); break; | |
1967 case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break; | |
1968 case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break; | |
1969 case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break; | |
1970 case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break; | |
1971 #if 0 | |
1972 case XK_Control_L: check_modifier ("Control_L", ControlMask); break; | |
1973 case XK_Control_R: check_modifier ("Control_R", ControlMask); break; | |
1974 case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break; | |
1975 case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break; | |
1976 #endif | |
1977 case XK_Shift_Lock: /* check_modifier ("Shift_Lock", LockMask); */ | |
1978 xd->lock_interpretation = XK_Shift_Lock; break; | |
1979 case XK_Caps_Lock: /* check_modifier ("Caps_Lock", LockMask); */ | |
1980 xd->lock_interpretation = XK_Caps_Lock; break; | |
1981 | |
1982 /* It probably doesn't make any sense for a modifier bit to be | |
1983 assigned to a key that is not one of the above, but OpenWindows | |
1984 assigns modifier bits to a couple of random function keys for | |
1985 no reason that I can discern, so printing a warning here would | |
1986 be annoying. */ | |
1987 } | |
1988 } | |
1989 } | |
1990 #undef store_modifier | |
1991 #undef check_modifier | |
1992 #undef modwarn | |
1993 #undef modbarf | |
1994 | |
1995 /* If there was no Meta key, then try using the Alt key instead. | |
1996 If there is both a Meta key and an Alt key, then the Alt key | |
1997 is not disturbed and remains an Alt key. */ | |
1998 if (! meta_bit && alt_bit) | |
1999 meta_bit = alt_bit, alt_bit = 0; | |
2000 | |
2001 /* mode_bit overrides everything, since it's processed down inside of | |
2002 XLookupString() instead of by us. If Meta and Mode_switch both | |
2003 generate the same modifier bit (which is an error), then we don't | |
2004 interpret that bit as Meta, because we can't make XLookupString() | |
2005 not interpret it as Mode_switch; and interpreting it as both would | |
2006 be totally wrong. */ | |
2007 if (mode_bit) | |
2008 { | |
2009 const char *warn = 0; | |
2010 if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0; | |
2011 else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0; | |
2012 else if (mode_bit == super_bit) warn = "Super", super_bit = 0; | |
2013 else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0; | |
2014 if (warn) | |
2015 { | |
2016 warn_when_safe | |
2017 (Qkey_mapping, Qwarning, | |
2018 "XEmacs: %s is being used for both Mode_switch and %s.", | |
2019 index_to_name (mode_bit), warn), | |
2020 warned_about_overlapping_modifiers = 1; | |
2021 } | |
2022 } | |
2023 #undef index_to_name | |
2024 | |
2025 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0); | |
2026 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0); | |
2027 xd->SuperMask = (super_bit ? (1 << super_bit) : 0); | |
2028 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0); | |
2029 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */ | |
2030 | |
2031 } | |
2032 | |
2033 void | |
2034 gtk_init_modifier_mapping (struct device *d) | |
2035 { | |
2036 struct gtk_device *gd = DEVICE_GTK_DATA (d); | |
2037 gd->x_keysym_map_hashtable = Qnil; | |
2038 gd->x_keysym_map = NULL; | |
2039 gd->x_modifier_keymap = NULL; | |
2040 gtk_reset_modifier_mapping (d); | |
2041 } | |
2042 | |
2043 #if 0 | |
2044 static int | |
2045 gtk_key_is_modifier_p (KeyCode keycode, struct device *d) | |
2046 { | |
2047 struct gtk_device *xd = DEVICE_GTK_DATA (d); | |
2048 KeySym *syms; | |
2049 KeySym *map = (KeySym *) xd->x_keysym_map; | |
2050 int i; | |
2051 | |
2052 if (keycode < xd->x_keysym_map_min_code || | |
2053 keycode > xd->x_keysym_map_max_code) | |
2054 return 0; | |
2055 | |
2056 syms = &map [(keycode - xd->x_keysym_map_min_code) * | |
2057 xd->x_keysym_map_keysyms_per_code]; | |
2058 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) | |
2059 if (IsModifierKey (syms [i]) || | |
2060 syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */ | |
2061 return 1; | |
2062 return 0; | |
2063 } | |
2064 #endif | |
2065 | |
2066 struct _quit_predicate_closure { | |
2067 struct device *device; | |
2068 Bool *critical; | |
2069 }; | |
2070 | |
2071 static Bool | |
2072 quit_char_predicate (Display *display, XEvent *event, XPointer data) | |
2073 { | |
2074 struct _quit_predicate_closure *cl = (struct _quit_predicate_closure *) data; | |
2075 struct device *d = cl->device; | |
2076 struct frame *f = NULL; | |
2077 struct gtk_device *gd = DEVICE_GTK_DATA (d); | |
2078 char c, quit_char; | |
2079 Bool *critical = cl->critical; | |
2080 Lisp_Object keysym; | |
2081 GdkWindow *window = gdk_window_lookup (event->xany.window); | |
2082 guint32 keycode = 0; | |
2083 GdkEventKey gdk_event; | |
2084 | |
2085 if (window) | |
2086 f = gtk_any_window_to_frame (d, window); | |
2087 | |
2088 if (critical) | |
2089 *critical = False; | |
2090 | |
2091 if ((event->type != KeyPress) || | |
2092 (! window) || | |
2093 (! f) || | |
2094 (event->xkey.state | |
2095 & (gd->MetaMask | gd->HyperMask | gd->SuperMask | gd->AltMask))) | |
2096 { | |
2097 return 0; | |
2098 } | |
2099 | |
2100 { | |
2101 char dummy[256]; | |
2102 XLookupString (&(event->xkey), dummy, 200, (KeySym *)&keycode, 0); | |
2103 } | |
2104 | |
2105 memset (&gdk_event, 0, sizeof (gdk_event)); | |
2106 gdk_event.type = GDK_KEY_PRESS; | |
2107 gdk_event.window = window; | |
2108 gdk_event.keyval = keycode; | |
2109 gdk_event.state = event->xkey.state; | |
2110 | |
2111 /* This duplicates some code that exists elsewhere, but it's relatively | |
2112 fast and doesn't cons. */ | |
2113 keysym = gtk_to_emacs_keysym (d, &gdk_event, 1); | |
2114 if (NILP (keysym)) return 0; | |
2115 if (CHAR_OR_CHAR_INTP (keysym)) | |
2116 c = XCHAR_OR_CHAR_INT (keysym); | |
2117 /* Highly doubtful that these are the quit character, but... */ | |
2118 else if (EQ (keysym, QKbackspace)) c = '\b'; | |
2119 else if (EQ (keysym, QKtab)) c = '\t'; | |
2120 else if (EQ (keysym, QKlinefeed)) c = '\n'; | |
2121 else if (EQ (keysym, QKreturn)) c = '\r'; | |
2122 else if (EQ (keysym, QKescape)) c = 27; | |
2123 else if (EQ (keysym, QKspace)) c = ' '; | |
2124 else if (EQ (keysym, QKdelete)) c = 127; | |
2125 else return 0; | |
2126 | |
2127 if (event->xkey.state & gd->MetaMask) c |= 0x80; | |
2128 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z')) | |
2129 c &= 0x1F; /* unshifted control characters */ | |
2130 quit_char = CONSOLE_QUIT_CHAR (XCONSOLE (DEVICE_CONSOLE (d))); | |
2131 | |
2132 if (c == quit_char) | |
2133 return True; | |
2134 /* If we've got Control-Shift-G instead of Control-G, that means | |
2135 we have a critical_quit. Caps_Lock is its own modifier, so it | |
2136 won't cause ^G to act differently than before. */ | |
2137 if (event->xkey.state & ControlMask) c &= 0x1F; | |
2138 if (c == quit_char) | |
2139 { | |
2140 if (critical) *critical = True; | |
2141 return True; | |
2142 } | |
2143 return False; | |
2144 } | |
2145 | |
2146 static void | |
2147 gtk_check_for_quit_char (struct device *d) | |
2148 { | |
2149 XEvent event; | |
2150 int queued; | |
2151 Bool critical_quit = False; | |
2152 struct _quit_predicate_closure closure; | |
2153 | |
2154 XEventsQueued (GDK_DISPLAY (), QueuedAfterReading); | |
2155 | |
2156 closure.device = d; | |
2157 closure.critical = &critical_quit; | |
2158 | |
2159 queued = XCheckIfEvent (GDK_DISPLAY (), &event, quit_char_predicate, (char *) &closure); | |
2160 | |
2161 if (queued) | |
2162 { | |
2163 Vquit_flag = (critical_quit ? Qcritical : Qt); | |
2164 } | |
2165 } |