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