Mercurial > hg > xemacs-beta
annotate src/event-Xt.c @ 4539:061e030e3270
Fix some bugs in load-history construction, built-in symbol file names.
lib-src/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* make-docfile.c (main): Allow more than one -d argument, followed
by a directory to change to.
(put_filename): Don't strip directory information; with previous
change, allows retrieval of Lisp function and variable origin
files from #'built-in-symbol-file relative to lisp-directory.
(scan_lisp_file): Don't add an extraneous newline after the file
name, put_filename has added the newline already.
lisp/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* loadup.el (load-history):
Add the contents of current-load-list to load-history before
clearing it. Move the variable declarations earlier in the file to
a format understood by make-docfile.c.
* custom.el (custom-declare-variable): Add the variable's symbol
to the current file's load history entry correctly, don't use a
cons. Eliminate a comment that we don't need to worry about, we
don't need to check the `initialized' C variable in Lisp.
* bytecomp.el (byte-compile-output-file-form):
Merge Andreas Schwab's pre-GPLv3 GNU change of 19970831 here;
treat #'custom-declare-variable correctly, generating the
docstrings in a format understood by make-docfile.c.
* loadhist.el (symbol-file): Correct behaviour for checking
autoloaded macros and functions when supplied with a TYPE
argument. Accept fully-qualified paths from
#'built-in-symbol-file; if a path is not fully-qualified, return
it relative to lisp-directory if the filename corresponds to a
Lisp file, and relative to (concat source-directory "/src/")
otherwise.
* make-docfile.el (preloaded-file-list):
Rationalise some let bindings a little. Use the "-d" argument to
make-docfile.c to supply Lisp paths relative to lisp-directory,
not absolutely. Add in loadup.el explicitly to the list of files
to be processed by make-docfile.c--it doesn't make sense to add it
to preloaded-file-list, since that is used for purposes of
byte-compilation too.
src/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* doc.c (Fbuilt_in_symbol_file):
Return a subr's filename immediately if we've found it. Check for
compiled function and compiled macro docstrings in DOC too, and
return them if they exist.
The branch of the if statement focused on functions may have
executed, but we may still want to check variable bindings; an
else clause isn't appropriate.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 27 Dec 2008 14:05:50 +0000 |
parents | 726060ee587c |
children | 2fd201d73a92 |
rev | line source |
---|---|
428 | 1 /* The event_stream interface for X11 with Xt, and/or tty frames. |
2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
1268 | 4 Copyright (C) 1996, 2001, 2002, 2003 Ben Wing. |
428 | 5 |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 #include <config.h> | |
26 #include "lisp.h" | |
27 | |
28 #include "blocktype.h" | |
771 | 29 #include "charset.h" |
428 | 30 #include "console.h" |
872 | 31 #include "device-impl.h" |
800 | 32 #include "elhash.h" |
428 | 33 #include "events.h" |
800 | 34 #include "file-coding.h" |
872 | 35 #include "frame-impl.h" |
800 | 36 #include "glyphs.h" |
37 #include "lstream.h" | |
428 | 38 #include "process.h" |
39 #include "redisplay.h" | |
800 | 40 #include "window.h" |
41 | |
42 #include "console-tty.h" | |
43 | |
872 | 44 #include "console-x-impl.h" |
800 | 45 #include "objects-x.h" |
46 #include "../lwlib/lwlib.h" | |
47 #include "EmacsFrame.h" | |
48 | |
49 #include "sysproc.h" /* for MAXDESC */ | |
428 | 50 #include "systime.h" |
51 | |
52 #include "xintrinsicp.h" /* CoreP.h needs this */ | |
53 #include <X11/CoreP.h> /* Numerous places access the fields of | |
54 a core widget directly. We could | |
55 use XtGetValues(), but ... */ | |
56 #include <X11/ShellP.h> | |
57 | |
800 | 58 #if defined (HAVE_XIM) && defined (XIM_MOTIF) |
1315 | 59 #include "xmotif.h" |
428 | 60 #endif |
61 | |
62 #ifdef HAVE_DRAGNDROP | |
63 #include "dragdrop.h" | |
64 #endif | |
65 | |
66 #if defined (HAVE_OFFIX_DND) | |
67 #include "offix.h" | |
68 #endif | |
69 | |
1292 | 70 #ifdef WIN32_ANY |
71 extern int mswindows_is_blocking; | |
72 #endif | |
73 | |
2828 | 74 /* For Russian C-x processing. */ |
3171 | 75 Lisp_Object Vx_us_keymap_description; |
76 Fixnum Vx_us_keymap_first_keycode; | |
2699 | 77 |
1094 | 78 /* used in glyphs-x.c */ |
79 void enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p); | |
428 | 80 static void handle_focus_event_1 (struct frame *f, int in_p); |
863 | 81 static void handle_focus_event_2 (Window w, struct frame *f, int in_p); |
428 | 82 |
83 static struct event_stream *Xt_event_stream; | |
84 | |
85 /* With the new event model, all events go through XtDispatchEvent() | |
86 and are picked up by an event handler that is added to each frame | |
87 widget. (This is how it's supposed to be.) In the old method, | |
88 Emacs sucks out events directly from XtNextEvent() and only | |
89 dispatches the events that it doesn't need to deal with. This | |
90 old way has lots of corresponding junk that is no longer | |
91 necessary: lwlib extensions, synthetic XAnyEvents, unnecessary | |
92 magic events, etc. */ | |
93 | |
94 /* The one and only one application context that Emacs uses. */ | |
95 XtAppContext Xt_app_con; | |
96 | |
97 /* Do we accept events sent by other clients? */ | |
98 int x_allow_sendevents; | |
99 | |
100 #ifdef DEBUG_XEMACS | |
458 | 101 Fixnum debug_x_events; |
428 | 102 #endif |
103 | |
104 static int process_events_occurred; | |
105 static int tty_events_occurred; | |
450 | 106 static Widget widget_with_focus; |
428 | 107 |
108 /* Mask of bits indicating the descriptors that we wait for input on */ | |
1268 | 109 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask; |
110 extern SELECT_TYPE process_only_mask, tty_only_mask; | |
428 | 111 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
112 /* #### This should be String, but G++ 4.3 doesn't apply the const |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
113 specifier the same way for String (typedef'd to char*) and char*. */ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
114 static const char * x_fallback_resources[] = |
428 | 115 { |
116 /* This file is automatically generated from the app-defaults file | |
117 in ../etc/Emacs.ad. These resources are consulted only if no | |
118 app-defaults file is found at all. | |
119 */ | |
120 #include <Emacs.ad.h> | |
121 0 | |
122 }; | |
123 | |
124 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p); | |
125 void emacs_Xt_mapping_action (Widget w, XEvent *event); | |
440 | 126 void debug_process_finalization (Lisp_Process *p); |
428 | 127 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event, |
128 Boolean *continue_to_dispatch); | |
129 | |
130 static int last_quit_check_signal_tick_count; | |
131 | |
132 Lisp_Object Qsans_modifiers; | |
133 | |
1268 | 134 #define THIS_IS_X |
135 #include "event-xlike-inc.c" | |
136 | |
428 | 137 |
138 /************************************************************************/ | |
139 /* keymap handling */ | |
140 /************************************************************************/ | |
141 | |
2828 | 142 /* See comment near character_to_event(). */ |
440 | 143 static void |
2828 | 144 maybe_define_x_key_as_self_inserting_character (KeySym keysym, |
145 Lisp_Object symbol) | |
440 | 146 { |
147 Lisp_Object character = x_keysym_to_character (keysym); | |
148 | |
149 if (CHARP (character)) | |
150 { | |
151 extern Lisp_Object Vcurrent_global_map; | |
2828 | 152 extern Lisp_Object Qcharacter_of_keysym; |
971 | 153 if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil))) |
154 { | |
2828 | 155 Fput (symbol, Qcharacter_of_keysym, character); |
971 | 156 Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command); |
157 } | |
440 | 158 } |
159 } | |
160 | |
2828 | 161 void |
440 | 162 x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers) |
163 { | |
164 KeySym upper_lower[2]; | |
165 int j; | |
166 | |
167 if (keysym < 0x80) /* Optimize for ASCII keysyms */ | |
168 return; | |
442 | 169 |
170 /* If you execute: | |
171 xmodmap -e 'keysym NN = scaron' | |
440 | 172 and then press (Shift scaron), X11 will return the different |
442 | 173 keysym `Scaron', but `xmodmap -pke' might not even mention `Scaron'. |
174 So we "register" both `scaron' and `Scaron'. */ | |
175 #ifdef HAVE_XCONVERTCASE | |
440 | 176 XConvertCase (keysym, &upper_lower[0], &upper_lower[1]); |
442 | 177 #else |
178 upper_lower[0] = upper_lower[1] = keysym; | |
179 #endif | |
440 | 180 |
181 for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) | |
182 { | |
2828 | 183 Extbyte *name; |
440 | 184 keysym = upper_lower[j]; |
185 | |
186 name = XKeysymToString (keysym); | |
187 if (name) | |
188 { | |
189 /* X guarantees NAME to be in the Host Portable Character Encoding */ | |
190 Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0); | |
191 Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers; | |
192 Lisp_Object old_value = Fgethash (sym, hash_table, Qnil); | |
193 | |
194 if (! EQ (old_value, new_value) | |
195 && ! (EQ (old_value, Qsans_modifiers) && | |
196 EQ (new_value, Qt))) | |
197 { | |
198 maybe_define_x_key_as_self_inserting_character (keysym, sym); | |
2828 | 199 Fputhash (build_ext_string (name, Qbinary), new_value, |
200 hash_table); | |
440 | 201 Fputhash (sym, new_value, hash_table); |
202 } | |
203 } | |
204 } | |
205 } | |
206 | |
428 | 207 static void |
208 x_reset_key_mapping (struct device *d) | |
209 { | |
210 Display *display = DEVICE_X_DISPLAY (d); | |
211 struct x_device *xd = DEVICE_X_DATA (d); | |
212 KeySym *keysym, *keysym_end; | |
213 Lisp_Object hash_table; | |
214 int key_code_count, keysyms_per_code; | |
215 | |
216 if (xd->x_keysym_map) | |
217 XFree ((char *) xd->x_keysym_map); | |
218 XDisplayKeycodes (display, | |
219 &xd->x_keysym_map_min_code, | |
220 &xd->x_keysym_map_max_code); | |
221 key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1; | |
222 xd->x_keysym_map = | |
223 XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count, | |
224 &xd->x_keysym_map_keysyms_per_code); | |
225 | |
226 hash_table = xd->x_keysym_map_hash_table; | |
227 if (HASH_TABLEP (hash_table)) | |
228 Fclrhash (hash_table); | |
229 else | |
230 xd->x_keysym_map_hash_table = hash_table = | |
231 make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); | |
232 | |
233 for (keysym = xd->x_keysym_map, | |
234 keysyms_per_code = xd->x_keysym_map_keysyms_per_code, | |
235 keysym_end = keysym + (key_code_count * keysyms_per_code); | |
236 keysym < keysym_end; | |
237 keysym += keysyms_per_code) | |
238 { | |
239 int j; | |
240 | |
241 if (keysym[0] == NoSymbol) | |
242 continue; | |
243 | |
440 | 244 x_has_keysym (keysym[0], hash_table, 0); |
428 | 245 |
246 for (j = 1; j < keysyms_per_code; j++) | |
247 { | |
248 if (keysym[j] != keysym[0] && | |
249 keysym[j] != NoSymbol) | |
440 | 250 x_has_keysym (keysym[j], hash_table, 1); |
428 | 251 } |
252 } | |
253 } | |
254 | |
2828 | 255 static const Ascbyte * |
428 | 256 index_to_name (int indice) |
257 { | |
258 switch (indice) | |
259 { | |
260 case ShiftMapIndex: return "ModShift"; | |
261 case LockMapIndex: return "ModLock"; | |
262 case ControlMapIndex: return "ModControl"; | |
263 case Mod1MapIndex: return "Mod1"; | |
264 case Mod2MapIndex: return "Mod2"; | |
265 case Mod3MapIndex: return "Mod3"; | |
266 case Mod4MapIndex: return "Mod4"; | |
267 case Mod5MapIndex: return "Mod5"; | |
268 default: return "???"; | |
269 } | |
270 } | |
271 | |
2828 | 272 /* X bogusly doesn't define the interpretations of any bits besides |
273 ModControl, ModShift, and ModLock; so the Interclient Communication | |
274 Conventions Manual says that we have to bend over backwards to figure | |
275 out what the other modifier bits mean. According to ICCCM: | |
276 | |
277 - Any keycode which is assigned ModControl is a "control" key. | |
278 | |
279 - Any modifier bit which is assigned to a keycode which generates Meta_L | |
280 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper, | |
281 etc. | |
282 | |
283 - Any keypress event which contains ModControl in its state should be | |
284 interpreted as a "control" character. | |
285 | |
286 - Any keypress event which contains a modifier bit in its state which is | |
287 generated by a keycode whose corresponding keysym is Meta_L or Meta_R | |
288 should be interpreted as a "meta" character. Likewise for Super, Hyper, | |
289 etc. | |
290 | |
291 - It is illegal for a keysym to be associated with more than one modifier | |
292 bit. | |
293 | |
294 This means that the only thing that emacs can reasonably interpret as a | |
295 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates | |
296 one of the modifier bits Mod1-Mod5. | |
297 | |
298 Unfortunately, many keyboards don't have Meta keys in their default | |
299 configuration. So, if there are no Meta keys, but there are "Alt" keys, | |
300 emacs will interpret Alt as Meta. If there are both Meta and Alt keys, | |
301 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to | |
302 mean "Symbol," but that just confused the hell out of way too many people). | |
303 | |
304 This works with the default configurations of the 19 keyboard-types I've | |
305 checked. | |
306 | |
307 Emacs detects keyboard configurations which violate the above rules, and | |
308 gives a warning. */ | |
428 | 309 |
310 static void | |
311 x_reset_modifier_mapping (struct device *d) | |
312 { | |
313 Display *display = DEVICE_X_DISPLAY (d); | |
314 struct x_device *xd = DEVICE_X_DATA (d); | |
315 int modifier_index, modifier_key, column, mkpm; | |
316 int warned_about_overlapping_modifiers = 0; | |
317 int warned_about_predefined_modifiers = 0; | |
318 int warned_about_duplicate_modifiers = 0; | |
319 int meta_bit = 0; | |
320 int hyper_bit = 0; | |
321 int super_bit = 0; | |
322 int alt_bit = 0; | |
323 int mode_bit = 0; | |
324 | |
325 xd->lock_interpretation = 0; | |
326 | |
327 if (xd->x_modifier_keymap) | |
3949 | 328 { |
329 XFreeModifiermap (xd->x_modifier_keymap); | |
330 /* Set it to NULL in case we receive two MappingModifier events in a | |
331 row, and the second is processed during some CHECK_QUITs within | |
332 x_reset_key_mapping. If that happens, XFreeModifierMap will be | |
333 called twice on the same map, and we crash. */ | |
334 xd->x_modifier_keymap = NULL; | |
335 } | |
428 | 336 |
337 x_reset_key_mapping (d); | |
338 | |
339 xd->x_modifier_keymap = XGetModifierMapping (display); | |
340 | |
341 /* Boy, I really wish C had local functions... | |
342 */ | |
343 | |
344 /* The call to warn_when_safe must be on the same line as the string or | |
345 make-msgfile won't pick it up properly (the newline doesn't confuse | |
346 it, but the backslash does). */ | |
347 | |
348 #define modwarn(name,old,other) \ | |
349 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is generated by %s.", \ | |
350 name, code, index_to_name (old), other), \ | |
351 warned_about_overlapping_modifiers = 1 | |
352 | |
353 #define modbarf(name,other) \ | |
354 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \ | |
355 name, code, other), \ | |
356 warned_about_predefined_modifiers = 1 | |
357 | |
358 #define check_modifier(name,mask) \ | |
359 if ((1<<modifier_index) != mask) \ | |
360 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \ | |
361 name, code, index_to_name (modifier_index)), \ | |
362 warned_about_predefined_modifiers = 1 | |
363 | |
364 #define store_modifier(name,old) \ | |
365 if (old && old != modifier_index) \ | |
366 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates both %s and %s, which is nonsensical.",\ | |
367 name, code, index_to_name (old), \ | |
368 index_to_name (modifier_index)), \ | |
369 warned_about_duplicate_modifiers = 1; \ | |
370 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \ | |
371 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \ | |
372 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \ | |
373 else if (sym == XK_Mode_switch) \ | |
374 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \ | |
375 else if (modifier_index == meta_bit && old != meta_bit) \ | |
376 modwarn (name, meta_bit, "Meta"); \ | |
377 else if (modifier_index == super_bit && old != super_bit) \ | |
378 modwarn (name, super_bit, "Super"); \ | |
379 else if (modifier_index == hyper_bit && old != hyper_bit) \ | |
380 modwarn (name, hyper_bit, "Hyper"); \ | |
381 else if (modifier_index == alt_bit && old != alt_bit) \ | |
382 modwarn (name, alt_bit, "Alt"); \ | |
383 else \ | |
384 old = modifier_index; | |
385 | |
386 mkpm = xd->x_modifier_keymap->max_keypermod; | |
387 for (modifier_index = 0; modifier_index < 8; modifier_index++) | |
388 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { | |
389 KeySym last_sym = 0; | |
390 for (column = 0; column < 4; column += 2) { | |
391 KeyCode code = xd->x_modifier_keymap->modifiermap[modifier_index * mkpm | |
392 + modifier_key]; | |
393 KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0); | |
394 if (sym == last_sym) continue; | |
395 last_sym = sym; | |
396 switch (sym) { | |
397 case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break; | |
398 case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break; | |
399 case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break; | |
400 case XK_Super_L: store_modifier ("Super_L", super_bit); break; | |
401 case XK_Super_R: store_modifier ("Super_R", super_bit); break; | |
402 case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break; | |
403 case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break; | |
404 case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break; | |
405 case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break; | |
406 case XK_Control_L: check_modifier ("Control_L", ControlMask); break; | |
407 case XK_Control_R: check_modifier ("Control_R", ControlMask); break; | |
408 case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break; | |
409 case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break; | |
410 case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask); | |
411 xd->lock_interpretation = XK_Shift_Lock; break; | |
412 case XK_Caps_Lock: check_modifier ("Caps_Lock", LockMask); | |
413 xd->lock_interpretation = XK_Caps_Lock; break; | |
414 | |
415 /* It probably doesn't make any sense for a modifier bit to be | |
416 assigned to a key that is not one of the above, but OpenWindows | |
417 assigns modifier bits to a couple of random function keys for | |
418 no reason that I can discern, so printing a warning here would | |
419 be annoying. */ | |
420 } | |
421 } | |
422 } | |
423 #undef store_modifier | |
424 #undef check_modifier | |
425 #undef modwarn | |
426 #undef modbarf | |
427 | |
428 /* If there was no Meta key, then try using the Alt key instead. | |
429 If there is both a Meta key and an Alt key, then the Alt key | |
430 is not disturbed and remains an Alt key. */ | |
431 if (! meta_bit && alt_bit) | |
432 meta_bit = alt_bit, alt_bit = 0; | |
433 | |
434 /* mode_bit overrides everything, since it's processed down inside of | |
435 XLookupString() instead of by us. If Meta and Mode_switch both | |
436 generate the same modifier bit (which is an error), then we don't | |
437 interpret that bit as Meta, because we can't make XLookupString() | |
438 not interpret it as Mode_switch; and interpreting it as both would | |
439 be totally wrong. */ | |
440 if (mode_bit) | |
441 { | |
2828 | 442 const Ascbyte *warn = 0; |
428 | 443 if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0; |
444 else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0; | |
445 else if (mode_bit == super_bit) warn = "Super", super_bit = 0; | |
446 else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0; | |
447 if (warn) | |
448 { | |
449 warn_when_safe | |
450 (Qkey_mapping, Qwarning, | |
451 "XEmacs: %s is being used for both Mode_switch and %s.", | |
452 index_to_name (mode_bit), warn), | |
453 warned_about_overlapping_modifiers = 1; | |
454 } | |
455 } | |
456 #undef index_to_name | |
457 | |
458 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0); | |
459 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0); | |
460 xd->SuperMask = (super_bit ? (1 << super_bit) : 0); | |
461 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0); | |
462 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */ | |
463 | |
464 | |
465 if (warned_about_overlapping_modifiers) | |
466 warn_when_safe (Qkey_mapping, Qwarning, "\n" | |
467 " Two distinct modifier keys (such as Meta and Hyper) cannot generate\n" | |
468 " the same modifier bit, because Emacs won't be able to tell which\n" | |
469 " modifier was actually held down when some other key is pressed. It\n" | |
470 " won't be able to tell Meta-x and Hyper-x apart, for example. Change\n" | |
471 " one of these keys to use some other modifier bit. If you intend for\n" | |
472 " these keys to have the same behavior, then change them to have the\n" | |
473 " same keysym as well as the same modifier bit."); | |
474 | |
475 if (warned_about_predefined_modifiers) | |
476 warn_when_safe (Qkey_mapping, Qwarning, "\n" | |
477 " The semantics of the modifier bits ModShift, ModLock, and ModControl\n" | |
478 " are predefined. It does not make sense to assign ModControl to any\n" | |
479 " keysym other than Control_L or Control_R, or to assign any modifier\n" | |
480 " bits to the \"control\" keysyms other than ModControl. You can't\n" | |
481 " turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n" | |
482 " assigning the key a different modifier bit. You must also make that\n" | |
483 " key generate an appropriate keysym (Control_L, Meta_L, etc)."); | |
484 | |
485 /* No need to say anything more for warned_about_duplicate_modifiers. */ | |
486 | |
487 if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers) | |
488 warn_when_safe (Qkey_mapping, Qwarning, "\n" | |
489 " The meanings of the modifier bits Mod1 through Mod5 are determined\n" | |
490 " by the keysyms used to control those bits. Mod1 does NOT always\n" | |
491 " mean Meta, although some non-ICCCM-compliant programs assume that."); | |
492 } | |
493 | |
494 void | |
495 x_init_modifier_mapping (struct device *d) | |
496 { | |
497 struct x_device *xd = DEVICE_X_DATA (d); | |
498 xd->x_keysym_map_hash_table = Qnil; | |
499 xd->x_keysym_map = NULL; | |
500 xd->x_modifier_keymap = NULL; | |
501 x_reset_modifier_mapping (d); | |
502 } | |
503 | |
504 static int | |
505 x_key_is_modifier_p (KeyCode keycode, struct device *d) | |
506 { | |
507 struct x_device *xd = DEVICE_X_DATA (d); | |
508 KeySym *syms; | |
509 int i; | |
510 | |
511 if (keycode < xd->x_keysym_map_min_code || | |
512 keycode > xd->x_keysym_map_max_code) | |
513 return 0; | |
514 | |
515 syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) * | |
516 xd->x_keysym_map_keysyms_per_code]; | |
517 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) | |
518 if (IsModifierKey (syms [i]) || | |
519 syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */ | |
520 return 1; | |
521 return 0; | |
522 } | |
523 | |
524 /* key-handling code is always ugly. It just ends up working out | |
525 that way. | |
526 | |
527 Here are some pointers: | |
528 | |
529 -- DOWN_MASK indicates which modifiers should be treated as "down" | |
530 when the corresponding upstroke happens. It gets reset for | |
531 a particular modifier when that modifier goes up, and reset | |
532 for all modifiers when a non-modifier key is pressed. Example: | |
533 | |
534 I press Control-A-Shift and then release Control-A-Shift. | |
535 I want the Shift key to be sticky but not the Control key. | |
536 | |
537 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of | |
538 auto-repeat -- see below. | |
539 | |
540 -- If a modifier key is sticky, I can unstick it by pressing | |
541 the modifier key again. */ | |
542 | |
543 static void | |
544 x_handle_sticky_modifiers (XEvent *ev, struct device *d) | |
545 { | |
546 struct x_device *xd; | |
547 KeyCode keycode; | |
548 int type; | |
549 | |
550 if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */ | |
551 return; | |
552 | |
553 xd = DEVICE_X_DATA (d); | |
554 keycode = ev->xkey.keycode; | |
555 type = ev->type; | |
556 | |
557 if (keycode < xd->x_keysym_map_min_code || | |
558 keycode > xd->x_keysym_map_max_code) | |
559 return; | |
560 | |
561 if (! ((type == KeyPress || type == KeyRelease) && | |
562 x_key_is_modifier_p (keycode, d))) | |
563 { /* Not a modifier key */ | |
564 Bool key_event_p = (type == KeyPress || type == KeyRelease); | |
565 | |
444 | 566 if (type == ButtonPress |
567 || (type == KeyPress | |
568 && ((xd->last_downkey | |
569 && ((keycode != xd->last_downkey | |
570 || ev->xkey.time != xd->release_time))) | |
571 || (INTP (Vmodifier_keys_sticky_time) | |
572 && ev->xkey.time | |
573 > (xd->modifier_release_time | |
574 + XINT (Vmodifier_keys_sticky_time)))))) | |
428 | 575 { |
576 xd->need_to_add_mask = 0; | |
577 xd->last_downkey = 0; | |
578 } | |
444 | 579 else if (type == KeyPress && !xd->last_downkey) |
580 xd->last_downkey = keycode; | |
581 | |
428 | 582 if (type == KeyPress) |
583 xd->release_time = 0; | |
584 if (type == KeyPress || type == ButtonPress) | |
444 | 585 { |
586 xd->down_mask = 0; | |
587 xd->modifier_release_time = 0; | |
588 } | |
428 | 589 |
590 if (key_event_p) | |
591 ev->xkey.state |= xd->need_to_add_mask; | |
592 else | |
593 ev->xbutton.state |= xd->need_to_add_mask; | |
594 | |
595 if (type == KeyRelease && keycode == xd->last_downkey) | |
596 /* If I hold press-and-release the Control key and then press | |
597 and hold down the right arrow, I want it to auto-repeat | |
598 Control-Right. On the other hand, if I do the same but | |
599 manually press the Right arrow a bunch of times, I want | |
600 to see one Control-Right and then a bunch of Rights. | |
601 This means that we need to distinguish between an | |
602 auto-repeated key and a key pressed and released a bunch | |
603 of times. | |
604 | |
605 Naturally, the designers of the X spec didn't see fit | |
606 to provide an obvious way to distinguish these cases. | |
607 So we assume that if the release and the next press | |
608 occur at the same time, the key was actually auto- | |
609 repeated. Under Open-Windows, at least, this works. */ | |
444 | 610 xd->modifier_release_time = xd->release_time |
611 = key_event_p ? ev->xkey.time : ev->xbutton.time; | |
428 | 612 } |
613 else /* Modifier key pressed */ | |
614 { | |
615 int i; | |
616 KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) * | |
617 xd->x_keysym_map_keysyms_per_code]; | |
618 | |
619 /* If a non-modifier key was pressed in the middle of a bunch | |
620 of modifiers, then it unsticks all the modifiers that were | |
621 previously pressed. We cannot unstick the modifiers until | |
622 now because we want to check for auto-repeat of the | |
623 non-modifier key. */ | |
624 | |
625 if (xd->last_downkey) | |
626 { | |
627 xd->last_downkey = 0; | |
628 xd->need_to_add_mask = 0; | |
629 } | |
630 | |
444 | 631 if (xd->modifier_release_time |
632 && INTP (Vmodifier_keys_sticky_time) | |
633 && (ev->xkey.time | |
634 > xd->modifier_release_time + XINT (Vmodifier_keys_sticky_time))) | |
635 { | |
636 xd->need_to_add_mask = 0; | |
637 xd->down_mask = 0; | |
638 } | |
639 | |
428 | 640 #define FROB(mask) \ |
641 do { \ | |
642 if (type == KeyPress) \ | |
643 { \ | |
644 /* If modifier key is already sticky, \ | |
645 then unstick it. Note that we do \ | |
646 not test down_mask to deal with the \ | |
647 unlikely but possible case that the \ | |
648 modifier key auto-repeats. */ \ | |
649 if (xd->need_to_add_mask & mask) \ | |
650 { \ | |
651 xd->need_to_add_mask &= ~mask; \ | |
652 xd->down_mask &= ~mask; \ | |
653 } \ | |
654 else \ | |
655 xd->down_mask |= mask; \ | |
656 } \ | |
657 else \ | |
658 { \ | |
659 if (xd->down_mask & mask) \ | |
660 { \ | |
661 xd->down_mask &= ~mask; \ | |
662 xd->need_to_add_mask |= mask; \ | |
663 } \ | |
664 } \ | |
444 | 665 xd->modifier_release_time = ev->xkey.time; \ |
428 | 666 } while (0) |
667 | |
668 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) | |
669 switch (syms[i]) | |
670 { | |
671 case XK_Control_L: case XK_Control_R: FROB (ControlMask); break; | |
672 case XK_Shift_L: case XK_Shift_R: FROB (ShiftMask); break; | |
673 case XK_Meta_L: case XK_Meta_R: FROB (xd->MetaMask); break; | |
674 case XK_Super_L: case XK_Super_R: FROB (xd->SuperMask); break; | |
675 case XK_Hyper_L: case XK_Hyper_R: FROB (xd->HyperMask); break; | |
676 case XK_Alt_L: case XK_Alt_R: FROB (xd->AltMask); break; | |
677 } | |
678 } | |
679 #undef FROB | |
680 } | |
681 | |
682 static void | |
683 clear_sticky_modifiers (struct device *d) | |
684 { | |
685 struct x_device *xd = DEVICE_X_DATA (d); | |
686 | |
687 xd->need_to_add_mask = 0; | |
688 xd->last_downkey = 0; | |
689 xd->release_time = 0; | |
690 xd->down_mask = 0; | |
691 } | |
692 | |
693 static int | |
694 keysym_obeys_caps_lock_p (KeySym sym, struct device *d) | |
695 { | |
696 struct x_device *xd = DEVICE_X_DATA (d); | |
697 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't alphabetic | |
698 characters, where "alphabetic" means something more than simply A-Z. | |
699 That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC. | |
700 But if shift-lock is down, then it does. */ | |
701 if (xd->lock_interpretation == XK_Shift_Lock) | |
702 return 1; | |
703 | |
704 return | |
705 ((sym >= XK_A) && (sym <= XK_Z)) || | |
706 ((sym >= XK_a) && (sym <= XK_z)) || | |
707 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) || | |
708 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) || | |
709 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) || | |
710 ((sym >= XK_oslash) && (sym <= XK_thorn)); | |
711 } | |
712 | |
713 /* called from EmacsFrame.c (actually from Xt itself) when a | |
714 MappingNotify event is received. In its infinite wisdom, Xt | |
715 decided that Xt event handlers never get MappingNotify events. | |
716 O'Reilly Xt Programming Manual 9.1.2 says: | |
717 | |
718 MappingNotify is automatically handled by Xt, so it isn't passed | |
719 to event handlers and you don't need to worry about it. | |
720 | |
721 Of course, we DO worry about it, so we need a special translation. */ | |
722 void | |
2286 | 723 emacs_Xt_mapping_action (Widget UNUSED (w), XEvent *event) |
428 | 724 { |
725 struct device *d = get_device_from_display (event->xany.display); | |
726 | |
727 if (DEVICE_X_BEING_DELETED (d)) | |
728 return; | |
729 #if 0 | |
730 /* nyet. Now this is handled by Xt. */ | |
731 XRefreshKeyboardMapping (&event->xmapping); | |
732 #endif | |
733 /* xmodmap generates about a billion MappingKeyboard events, followed | |
734 by a single MappingModifier event, so it might be worthwhile to | |
735 take extra MappingKeyboard events out of the queue before requesting | |
736 the current keymap from the server. */ | |
737 switch (event->xmapping.request) | |
738 { | |
739 case MappingKeyboard: x_reset_key_mapping (d); break; | |
740 case MappingModifier: x_reset_modifier_mapping (d); break; | |
741 case MappingPointer: /* Do something here? */ break; | |
2500 | 742 default: ABORT(); |
428 | 743 } |
744 } | |
745 | |
746 | |
747 /************************************************************************/ | |
748 /* X to Emacs event conversion */ | |
749 /************************************************************************/ | |
750 | |
751 static Lisp_Object | |
752 x_keysym_to_emacs_keysym (KeySym keysym, int simple_p) | |
753 { | |
2828 | 754 Extbyte *name; |
755 DECLARE_EISTRING(einame); | |
756 | |
428 | 757 if (keysym >= XK_exclam && keysym <= XK_asciitilde) |
758 /* We must assume that the X keysym numbers for the ASCII graphic | |
759 characters are the same as their ASCII codes. */ | |
760 return make_char (keysym); | |
761 | |
762 switch (keysym) | |
763 { | |
764 /* These would be handled correctly by the default case, but by | |
765 special-casing them here we don't garbage a string or call | |
766 intern(). */ | |
767 case XK_BackSpace: return QKbackspace; | |
768 case XK_Tab: return QKtab; | |
769 case XK_Linefeed: return QKlinefeed; | |
770 case XK_Return: return QKreturn; | |
771 case XK_Escape: return QKescape; | |
772 case XK_space: return QKspace; | |
773 case XK_Delete: return QKdelete; | |
774 case 0: return Qnil; | |
775 default: | |
776 if (simple_p) return Qnil; | |
777 name = XKeysymToString (keysym); | |
778 if (!name || !name[0]) | |
779 /* This happens if there is a mismatch between the Xlib of | |
780 XEmacs and the Xlib of the X server... | |
781 | |
782 Let's hard-code in some knowledge of common keysyms introduced | |
783 in recent X11 releases. Snarfed from X11/keysymdef.h | |
784 | |
785 Probably we should add some stuff here for X11R6. */ | |
786 switch (keysym) | |
787 { | |
788 case 0xFF95: return KEYSYM ("kp-home"); | |
789 case 0xFF96: return KEYSYM ("kp-left"); | |
790 case 0xFF97: return KEYSYM ("kp-up"); | |
791 case 0xFF98: return KEYSYM ("kp-right"); | |
792 case 0xFF99: return KEYSYM ("kp-down"); | |
793 case 0xFF9A: return KEYSYM ("kp-prior"); | |
794 case 0xFF9B: return KEYSYM ("kp-next"); | |
795 case 0xFF9C: return KEYSYM ("kp-end"); | |
796 case 0xFF9D: return KEYSYM ("kp-begin"); | |
797 case 0xFF9E: return KEYSYM ("kp-insert"); | |
798 case 0xFF9F: return KEYSYM ("kp-delete"); | |
799 | |
800 case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */ | |
801 case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */ | |
802 default: | |
803 { | |
2828 | 804 Ascbyte buf [64]; |
428 | 805 sprintf (buf, "unknown-keysym-0x%X", (int) keysym); |
806 return KEYSYM (buf); | |
807 } | |
808 } | |
2828 | 809 |
428 | 810 /* If it's got a one-character name, that's good enough. */ |
811 if (!name[1]) | |
2828 | 812 return make_char ((Ichar)name[0]); |
813 | |
814 /* In theory the Host Portable Character Set is just ASCII, but | |
815 trusting X11 implementors to get that right is likely to lead to | |
816 tears. */ | |
817 eicpy_ext(einame, name, Qbinary); | |
428 | 818 |
819 /* If it's in the "Keyboard" character set, downcase it. | |
820 The case of those keysyms is too totally random for us to | |
821 force anyone to remember them. | |
2828 | 822 The case of the other character sets is significant, however. */ |
428 | 823 if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00)) |
824 { | |
2828 | 825 Ibyte *iname; |
826 eilwr(einame); | |
827 | |
828 for (iname = eidata(einame); *iname != '\0';) | |
829 { | |
830 if (*iname == '_') | |
831 { | |
832 *iname = '-'; | |
833 } | |
834 INC_IBYTEPTR(iname); | |
428 | 835 } |
836 } | |
2837 | 837 return KEYSYM ((const CIbyte *) eidata (einame)); |
428 | 838 } |
839 } | |
840 | |
841 static Lisp_Object | |
842 x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p) | |
843 /* simple_p means don't try too hard (ASCII only) */ | |
844 { | |
845 KeySym keysym = 0; | |
846 | |
847 #ifdef HAVE_XIM | |
3072 | 848 int len = 0; |
442 | 849 /* Some implementations of XmbLookupString don't return |
850 XBufferOverflow correctly, so increase the size of the xim input | |
851 buffer from 64 to the more reasonable size 513, as Emacs has done. | |
852 From Kenichi Handa. */ | |
853 char buffer[513]; | |
428 | 854 char *bufptr = buffer; |
855 int bufsiz = sizeof (buffer); | |
856 Status status; | |
857 #ifdef XIM_XLIB | |
858 XIC xic = FRAME_X_XIC (x_any_window_to_frame | |
859 (get_device_from_display (event->display), | |
860 event->window)); | |
861 #endif /* XIM_XLIB */ | |
862 #endif /* HAVE_XIM */ | |
863 | |
864 /* We use XLookupString if we're not using XIM, or are using | |
865 XIM_XLIB but input context creation failed. */ | |
866 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF)) | |
867 #if defined (HAVE_XIM) && defined (XIM_XLIB) | |
868 if (!xic) | |
869 #endif /* XIM_XLIB */ | |
870 { | |
871 /* Apparently it's necessary to specify a dummy here (rather | |
872 than passing in 0) to avoid crashes on German IRIX */ | |
873 char dummy[256]; | |
874 XLookupString (event, dummy, 200, &keysym, 0); | |
875 return (IsModifierKey (keysym) || keysym == XK_Mode_switch ) | |
876 ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p); | |
877 } | |
878 #endif /* ! XIM_MOTIF */ | |
879 | |
880 #ifdef HAVE_XIM | |
881 Lookup_String: /* Come-From XBufferOverflow */ | |
882 #ifdef XIM_MOTIF | |
883 len = XmImMbLookupString (XtWindowToWidget (event->display, event->window), | |
884 event, bufptr, bufsiz, &keysym, &status); | |
885 #else /* XIM_XLIB */ | |
886 if (xic) | |
887 len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status); | |
1494 | 888 #endif /* XIM_MOTIF */ |
428 | 889 |
890 #ifdef DEBUG_XEMACS | |
442 | 891 if (debug_x_events > 0) |
428 | 892 { |
893 stderr_out (" status="); | |
894 #define print_status_when(S) if (status == S) stderr_out (#S) | |
895 print_status_when (XLookupKeySym); | |
896 print_status_when (XLookupBoth); | |
897 print_status_when (XLookupChars); | |
898 print_status_when (XLookupNone); | |
899 print_status_when (XBufferOverflow); | |
900 | |
901 if (status == XLookupKeySym || status == XLookupBoth) | |
902 stderr_out (" keysym=%s", XKeysymToString (keysym)); | |
903 if (status == XLookupChars || status == XLookupBoth) | |
904 { | |
3072 | 905 if (len > 1) |
428 | 906 { |
907 int j; | |
908 stderr_out (" chars=\""); | |
909 for (j=0; j<len; j++) | |
3142 | 910 { |
911 if (040 <= bufptr[j] && bufptr[j] >= 0177) | |
912 { | |
913 stderr_out ("%c", bufptr[j]); | |
914 } | |
915 else | |
916 { | |
917 stderr_out ("\\%o", (unsigned)(bufptr[j])); | |
918 } | |
919 } | |
428 | 920 stderr_out ("\""); |
921 } | |
922 else if (bufptr[0] <= 32 || bufptr[0] >= 127) | |
923 stderr_out (" char=0x%x", bufptr[0]); | |
924 else | |
925 stderr_out (" char=%c", bufptr[0]); | |
926 } | |
927 stderr_out ("\n"); | |
928 } | |
929 #endif /* DEBUG_XEMACS */ | |
930 | |
931 switch (status) | |
932 { | |
933 case XLookupKeySym: | |
934 case XLookupBoth: | |
935 return (IsModifierKey (keysym) || keysym == XK_Mode_switch ) | |
936 ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p); | |
937 | |
938 case XLookupChars: | |
939 { | |
940 /* Generate multiple emacs events */ | |
941 struct device *d = get_device_from_display (event->display); | |
867 | 942 Ichar ch; |
428 | 943 Lisp_Object instream, fb_instream; |
944 Lstream *istr; | |
945 struct gcpro gcpro1, gcpro2; | |
946 | |
440 | 947 fb_instream = make_fixed_buffer_input_stream (bufptr, len); |
948 | |
3142 | 949 /* [[ Use get_coding_system_for_text_file |
950 (Vcomposed_input_coding_system, 0) ]] | |
951 | |
952 Nope. If it is possible for the X libraries to have multiple IM | |
953 connections on different DISPLAYs active at once, this should be | |
954 a console-specific variable (like a TTY's coding system) but I've | |
955 seen no evidence that that is possible. Aidan Kehoe, | |
956 2005-12-17. */ | |
957 | |
428 | 958 instream = |
771 | 959 make_coding_input_stream |
3142 | 960 (XLSTREAM (fb_instream), Qkeyboard, CODING_DECODE, 0); |
428 | 961 |
962 istr = XLSTREAM (instream); | |
963 | |
964 GCPRO2 (instream, fb_instream); | |
867 | 965 while ((ch = Lstream_get_ichar (istr)) != EOF) |
428 | 966 { |
967 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | |
440 | 968 Lisp_Event *ev = XEVENT (emacs_event); |
428 | 969 ev->channel = DEVICE_CONSOLE (d); |
960 | 970 ev->timestamp = event->time; |
971 XSET_EVENT_TYPE (emacs_event, key_press_event); | |
1204 | 972 XSET_EVENT_KEY_MODIFIERS (emacs_event, 0); |
973 XSET_EVENT_KEY_KEYSYM (emacs_event, make_char (ch)); | |
974 enqueue_dispatch_event (emacs_event); | |
428 | 975 } |
976 Lstream_close (istr); | |
977 UNGCPRO; | |
978 Lstream_delete (istr); | |
979 Lstream_delete (XLSTREAM (fb_instream)); | |
980 return Qnil; | |
981 } | |
982 case XLookupNone: return Qnil; | |
983 case XBufferOverflow: | |
2367 | 984 /* !!#### needs work */ |
851 | 985 bufptr = (char *) ALLOCA (len+1); |
428 | 986 bufsiz = len+1; |
987 goto Lookup_String; | |
988 } | |
801 | 989 return Qnil; /* not (usually) reached */ |
428 | 990 #endif /* HAVE_XIM */ |
991 } | |
992 | |
993 static void | |
994 set_last_server_timestamp (struct device *d, XEvent *x_event) | |
995 { | |
996 Time t; | |
997 switch (x_event->type) | |
998 { | |
999 case KeyPress: | |
1000 case KeyRelease: t = x_event->xkey.time; break; | |
1001 case ButtonPress: | |
1002 case ButtonRelease: t = x_event->xbutton.time; break; | |
1003 case EnterNotify: | |
1004 case LeaveNotify: t = x_event->xcrossing.time; break; | |
1005 case MotionNotify: t = x_event->xmotion.time; break; | |
1006 case PropertyNotify: t = x_event->xproperty.time; break; | |
1007 case SelectionClear: t = x_event->xselectionclear.time; break; | |
1008 case SelectionRequest: t = x_event->xselectionrequest.time; break; | |
1009 case SelectionNotify: t = x_event->xselection.time; break; | |
1010 default: return; | |
1011 } | |
1012 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = t; | |
1013 } | |
1014 | |
1015 static int | |
440 | 1016 x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event) |
428 | 1017 { |
1018 Display *display = x_event->xany.display; | |
1019 struct device *d = get_device_from_display (display); | |
1020 struct x_device *xd = DEVICE_X_DATA (d); | |
1021 | |
1022 if (DEVICE_X_BEING_DELETED (d)) | |
2828 | 1023 { |
1024 /* [[ Uh, is this 0 correct? ]] | |
1025 | |
1026 Yup--it means emacs_Xt_event_handler, the only place that calls | |
1027 this, doesn't queue the emacs_event dispatch, instead immediately | |
1028 deallocating it. */ | |
1029 return 0; | |
1030 } | |
428 | 1031 |
1032 set_last_server_timestamp (d, x_event); | |
1033 | |
1034 switch (x_event->type) | |
1035 { | |
1036 case KeyRelease: | |
934 | 1037 { |
1038 x_handle_sticky_modifiers (x_event, d); | |
1039 return 0; | |
1040 } | |
428 | 1041 case KeyPress: |
1042 case ButtonPress: | |
1043 case ButtonRelease: | |
1044 { | |
442 | 1045 int modifiers = 0; |
428 | 1046 int shift_p, lock_p; |
1047 Bool key_event_p = (x_event->type == KeyPress); | |
1048 unsigned int *state = | |
1049 key_event_p ? &x_event->xkey.state : &x_event->xbutton.state; | |
1050 | |
1051 /* If this is a synthetic KeyPress or Button event, and the user | |
1052 has expressed a disinterest in this security hole, then drop | |
1053 it on the floor. */ | |
1054 if ((key_event_p | |
1055 ? x_event->xkey.send_event | |
1056 : x_event->xbutton.send_event) | |
1057 #ifdef EXTERNAL_WIDGET | |
1058 /* ben: events get sent to an ExternalShell using XSendEvent. | |
1059 This is not a perfect solution. */ | |
1060 && !FRAME_X_EXTERNAL_WINDOW_P | |
1061 (x_any_window_to_frame (d, x_event->xany.window)) | |
1062 #endif | |
1063 && !x_allow_sendevents) | |
1064 return 0; | |
1065 | |
1066 DEVICE_X_MOUSE_TIMESTAMP (d) = | |
1067 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) = | |
1068 key_event_p ? x_event->xkey.time : x_event->xbutton.time; | |
1069 | |
1070 x_handle_sticky_modifiers (x_event, d); | |
1071 | |
442 | 1072 if (*state & ControlMask) modifiers |= XEMACS_MOD_CONTROL; |
1073 if (*state & xd->MetaMask) modifiers |= XEMACS_MOD_META; | |
1074 if (*state & xd->SuperMask) modifiers |= XEMACS_MOD_SUPER; | |
1075 if (*state & xd->HyperMask) modifiers |= XEMACS_MOD_HYPER; | |
1076 if (*state & xd->AltMask) modifiers |= XEMACS_MOD_ALT; | |
1077 { | |
1078 int numero_de_botao = -1; | |
1079 | |
1080 if (!key_event_p) | |
1081 numero_de_botao = x_event->xbutton.button; | |
1082 | |
1083 /* the button gets noted either in the button or the modifiers | |
1084 field, but not both. */ | |
1085 if (numero_de_botao != 1 && (*state & Button1Mask)) | |
1086 modifiers |= XEMACS_MOD_BUTTON1; | |
1087 if (numero_de_botao != 2 && (*state & Button2Mask)) | |
1088 modifiers |= XEMACS_MOD_BUTTON2; | |
1089 if (numero_de_botao != 3 && (*state & Button3Mask)) | |
1090 modifiers |= XEMACS_MOD_BUTTON3; | |
1091 if (numero_de_botao != 4 && (*state & Button4Mask)) | |
1092 modifiers |= XEMACS_MOD_BUTTON4; | |
1093 if (numero_de_botao != 5 && (*state & Button5Mask)) | |
1094 modifiers |= XEMACS_MOD_BUTTON5; | |
1095 } | |
428 | 1096 |
1097 /* Ignore the Caps_Lock key if: | |
1098 - any other modifiers are down, so that Caps_Lock doesn't | |
1099 turn C-x into C-X, which would suck. | |
1100 - the event was a mouse event. */ | |
1101 if (modifiers || ! key_event_p) | |
1102 *state &= (~LockMask); | |
1103 | |
1104 shift_p = *state & ShiftMask; | |
1105 lock_p = *state & LockMask; | |
1106 | |
1107 if (shift_p || lock_p) | |
442 | 1108 modifiers |= XEMACS_MOD_SHIFT; |
428 | 1109 |
1110 if (key_event_p) | |
1111 { | |
1112 Lisp_Object keysym; | |
1113 XKeyEvent *ev = &x_event->xkey; | |
1114 /* This used to compute the frame from the given X window and | |
1115 store it here, but we really don't care about the frame. */ | |
934 | 1116 SET_EVENT_CHANNEL (emacs_event, DEVICE_CONSOLE (d)); |
428 | 1117 keysym = x_to_emacs_keysym (&x_event->xkey, 0); |
1118 | |
1119 /* If the emacs keysym is nil, then that means that the X | |
1120 keysym was either a Modifier or NoSymbol, which | |
1121 probably means that we're in the midst of reading a | |
1122 Multi_key sequence, or a "dead" key prefix, or XIM | |
1123 input. Ignore it. */ | |
1124 if (NILP (keysym)) | |
1125 return 0; | |
1126 | |
3171 | 1127 /* If we have the map from keycodes to the US layout for our |
1128 keyboard available, store the US layout interpretation of | |
1129 that key in the event structure, in case a binding lookup | |
1130 fails and we want to fall back to the US layout binding. | |
1131 | |
1132 This _might_ be possible within an XKB framework, changing | |
1133 the keyboard to a US XKB layout for a moment at startup, | |
1134 storing the correspondance, and changing it back. But that | |
1135 won't work on non-XKB servers, it makes our already slow | |
1136 startup slower, and it's not clear that it's really any | |
1137 easier or more maintainable than storing a correspondence in | |
1138 Lisp. */ | |
1139 | |
1140 if (!NILP(Vx_us_keymap_description) && | |
1141 VECTORP(Vx_us_keymap_description) && | |
1142 ev->keycode >= (unsigned)Vx_us_keymap_first_keycode && | |
1143 ev->keycode | |
1144 < (unsigned)XVECTOR_LENGTH(Vx_us_keymap_description)) | |
1145 { | |
1146 Lisp_Object entr = XVECTOR_DATA(Vx_us_keymap_description) | |
1147 [ev->keycode - Vx_us_keymap_first_keycode]; | |
1148 Ichar alternate = '\0'; | |
1149 | |
1150 if (!NILP (entr)) | |
1151 { | |
1152 if (CHARP(entr)) | |
1153 { | |
1154 alternate = XCHAR(entr); | |
1155 } | |
1156 else if (VECTORP(entr)) | |
1157 { | |
1158 if (modifiers & XEMACS_MOD_SHIFT | |
1159 && XVECTOR_LENGTH(Vx_us_keymap_description) > 1) | |
1160 { | |
1161 entr = XVECTOR_DATA(entr)[1]; | |
1162 if (CHARP(entr)) | |
1163 { | |
1164 alternate = XCHAR(entr); | |
1165 } | |
1166 } | |
1167 else if (XVECTOR_LENGTH(Vx_us_keymap_description) | |
1168 > 0) | |
1169 { | |
1170 entr = XVECTOR_DATA(entr)[0]; | |
1171 if (CHARP(entr)) | |
1172 { | |
1173 alternate = XCHAR(entr); | |
1174 } | |
1175 } | |
1176 } | |
1177 if ('\0' != alternate) | |
1178 { | |
1179 SET_EVENT_KEY_ALT_KEYCHARS(emacs_event, KEYCHAR_QWERTY, | |
1180 alternate); | |
1181 } | |
1182 } | |
1183 } | |
1184 | |
428 | 1185 /* More Caps_Lock garbage: Caps_Lock should *only* add the |
1186 shift modifier to two-case keys (that is, A-Z and | |
1187 related characters). So at this point (after looking up | |
1188 the keysym) if the keysym isn't a dual-case alphabetic, | |
1189 and if the caps lock key was down but the shift key | |
1190 wasn't, then turn off the shift modifier. Gag barf */ | |
2828 | 1191 |
428 | 1192 /* #### type lossage: assuming equivalence of emacs and |
2828 | 1193 X keysyms |
1194 | |
1195 The right thing to do here is to have pass a third, pointer, | |
1196 argument to x_to_emacs_keysym, where it should store the | |
1197 intermediate KeySym it used to calculate the string XEmacs | |
1198 keysym. Then we can call keysym_obeys_caps_lock_p with | |
1199 exactly the right argument. */ | |
3171 | 1200 |
2828 | 1201 /* !!#### maybe fix for Mule |
1202 | |
1203 Hard, in the absence of a full case infrastructure for | |
1204 Mule characters. When | |
1205 (downcase (make-char 'cyrillic-iso8859-5 73)) | |
1206 works, we should revisit it. */ | |
1207 | |
428 | 1208 if (lock_p && !shift_p && |
1209 ! (CHAR_OR_CHAR_INTP (keysym) | |
1210 && keysym_obeys_caps_lock_p | |
1211 ((KeySym) XCHAR_OR_CHAR_INT (keysym), d))) | |
442 | 1212 modifiers &= (~XEMACS_MOD_SHIFT); |
428 | 1213 |
1214 /* If this key contains two distinct keysyms, that is, | |
1215 "shift" generates a different keysym than the | |
1216 non-shifted key, then don't apply the shift modifier | |
1217 bit: it's implicit. Otherwise, if there would be no | |
1218 other way to tell the difference between the shifted | |
1219 and unshifted version of this key, apply the shift bit. | |
1220 Non-graphics, like Backspace and F1 get the shift bit | |
1221 in the modifiers slot. Neither the characters "a", | |
1222 "A", "2", nor "@" normally have the shift bit set. | |
1223 However, "F1" normally does. */ | |
3171 | 1224 |
442 | 1225 if (modifiers & XEMACS_MOD_SHIFT) |
428 | 1226 { |
1227 int Mode_switch_p = *state & xd->ModeMask; | |
1228 KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0); | |
1229 KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1); | |
1230 if (top && bot && top != bot) | |
442 | 1231 modifiers &= ~XEMACS_MOD_SHIFT; |
428 | 1232 } |
934 | 1233 set_event_type (emacs_event, key_press_event); |
1234 SET_EVENT_TIMESTAMP (emacs_event, ev->time); | |
1204 | 1235 SET_EVENT_KEY_MODIFIERS (emacs_event, modifiers); |
1236 SET_EVENT_KEY_KEYSYM (emacs_event, keysym); | |
428 | 1237 } |
1238 else /* Mouse press/release event */ | |
1239 { | |
1240 XButtonEvent *ev = &x_event->xbutton; | |
1241 struct frame *frame = x_window_to_frame (d, ev->window); | |
1242 | |
1243 if (! frame) | |
1244 return 0; /* not for us */ | |
934 | 1245 set_event_type (emacs_event, (x_event->type == ButtonPress) ? |
1246 button_press_event : button_release_event); | |
1204 | 1247 SET_EVENT_CHANNEL (emacs_event, wrap_frame (frame)); |
1248 | |
1249 SET_EVENT_BUTTON_MODIFIERS (emacs_event, modifiers); | |
934 | 1250 SET_EVENT_TIMESTAMP (emacs_event, ev->time); |
1204 | 1251 SET_EVENT_BUTTON_BUTTON (emacs_event, ev->button); |
1252 SET_EVENT_BUTTON_X (emacs_event, ev->x); | |
1253 SET_EVENT_BUTTON_Y (emacs_event, ev->y); | |
428 | 1254 /* because we don't seem to get a FocusIn event for button clicks |
1255 when a widget-glyph is selected we will assume that we want the | |
1256 focus if a button gets pressed. */ | |
1257 if (x_event->type == ButtonPress) | |
1258 handle_focus_event_1 (frame, 1); | |
1259 } | |
1260 } | |
1261 break; | |
1262 | |
1263 case MotionNotify: | |
1264 { | |
1265 XMotionEvent *ev = &x_event->xmotion; | |
1266 struct frame *frame = x_window_to_frame (d, ev->window); | |
442 | 1267 int modifiers = 0; |
428 | 1268 XMotionEvent event2; |
1269 | |
1270 if (! frame) | |
1271 return 0; /* not for us */ | |
1272 | |
1273 /* We use MotionHintMask, so we will get only one motion event | |
1274 until the next time we call XQueryPointer or the user | |
1275 clicks the mouse. So call XQueryPointer now (meaning that | |
1276 the event will be in sync with the server just before | |
1277 Fnext_event() returns). If the mouse is still in motion, | |
1278 then the server will immediately generate exactly one more | |
1279 motion event, which will be on the queue waiting for us | |
1280 next time around. */ | |
1281 event2 = *ev; | |
1282 if (XQueryPointer (event2.display, event2.window, | |
1283 &event2.root, &event2.subwindow, | |
1284 &event2.x_root, &event2.y_root, | |
1285 &event2.x, &event2.y, | |
1286 &event2.state)) | |
1287 ev = &event2; /* only one structure copy */ | |
1288 | |
1289 DEVICE_X_MOUSE_TIMESTAMP (d) = ev->time; | |
1204 | 1290 SET_EVENT_CHANNEL (emacs_event, wrap_frame (frame)); |
934 | 1291 set_event_type (emacs_event, pointer_motion_event); |
1292 SET_EVENT_TIMESTAMP (emacs_event, ev->time); | |
1204 | 1293 SET_EVENT_MOTION_X (emacs_event, ev->x); |
1294 SET_EVENT_MOTION_Y (emacs_event, ev->y); | |
442 | 1295 if (ev->state & ShiftMask) modifiers |= XEMACS_MOD_SHIFT; |
1296 if (ev->state & ControlMask) modifiers |= XEMACS_MOD_CONTROL; | |
1297 if (ev->state & xd->MetaMask) modifiers |= XEMACS_MOD_META; | |
1298 if (ev->state & xd->SuperMask) modifiers |= XEMACS_MOD_SUPER; | |
1299 if (ev->state & xd->HyperMask) modifiers |= XEMACS_MOD_HYPER; | |
1300 if (ev->state & xd->AltMask) modifiers |= XEMACS_MOD_ALT; | |
1301 if (ev->state & Button1Mask) modifiers |= XEMACS_MOD_BUTTON1; | |
1302 if (ev->state & Button2Mask) modifiers |= XEMACS_MOD_BUTTON2; | |
1303 if (ev->state & Button3Mask) modifiers |= XEMACS_MOD_BUTTON3; | |
1304 if (ev->state & Button4Mask) modifiers |= XEMACS_MOD_BUTTON4; | |
1305 if (ev->state & Button5Mask) modifiers |= XEMACS_MOD_BUTTON5; | |
428 | 1306 /* Currently ignores Shift_Lock but probably shouldn't |
1307 (but it definitely should ignore Caps_Lock). */ | |
1204 | 1308 SET_EVENT_MOTION_MODIFIERS (emacs_event, modifiers); |
428 | 1309 } |
1310 break; | |
1311 | |
1312 case ClientMessage: | |
1313 { | |
1314 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is | |
1315 passed as the timestamp of the TAKE_FOCUS, which the ICCCM | |
1316 explicitly prohibits. */ | |
1317 XClientMessageEvent *ev = &x_event->xclient; | |
1318 #ifdef HAVE_OFFIX_DND | |
2367 | 1319 if (DndIsDropMessage (x_event)) |
428 | 1320 { |
442 | 1321 unsigned int state; |
1322 int modifiers = 0; | |
647 | 1323 int button = 0; |
428 | 1324 struct frame *frame = x_any_window_to_frame (d, ev->window); |
1325 Extbyte *data; | |
1326 unsigned long size, dtype; | |
1327 Lisp_Object l_type = Qnil, l_data = Qnil; | |
1328 Lisp_Object l_dndlist = Qnil, l_item = Qnil; | |
1329 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
1330 | |
1331 if (! frame) | |
1332 return 0; /* not for us */ | |
446 | 1333 |
1334 GCPRO4 (l_type, l_data, l_dndlist, l_item); | |
934 | 1335 set_event_type (emacs_event, misc_user_event); |
1204 | 1336 SET_EVENT_CHANNEL (emacs_event, wrap_frame (frame)); |
2367 | 1337 SET_EVENT_TIMESTAMP (emacs_event, |
1338 DEVICE_X_LAST_SERVER_TIMESTAMP (d)); | |
1204 | 1339 state=DndDragButtons (x_event); |
428 | 1340 |
442 | 1341 if (state & ShiftMask) modifiers |= XEMACS_MOD_SHIFT; |
1342 if (state & ControlMask) modifiers |= XEMACS_MOD_CONTROL; | |
1343 if (state & xd->MetaMask) modifiers |= XEMACS_MOD_META; | |
1344 if (state & xd->SuperMask) modifiers |= XEMACS_MOD_SUPER; | |
1345 if (state & xd->HyperMask) modifiers |= XEMACS_MOD_HYPER; | |
1346 if (state & xd->AltMask) modifiers |= XEMACS_MOD_ALT; | |
1347 if (state & Button1Mask) modifiers |= XEMACS_MOD_BUTTON1; | |
1348 if (state & Button2Mask) modifiers |= XEMACS_MOD_BUTTON2; | |
1349 if (state & Button3Mask) modifiers |= XEMACS_MOD_BUTTON3; | |
1350 if (state & Button4Mask) modifiers |= XEMACS_MOD_BUTTON4; | |
1351 if (state & Button5Mask) modifiers |= XEMACS_MOD_BUTTON5; | |
428 | 1352 |
1353 if (state & Button5Mask) button = Button5; | |
1354 if (state & Button4Mask) button = Button4; | |
1355 if (state & Button3Mask) button = Button3; | |
1356 if (state & Button2Mask) button = Button2; | |
1357 if (state & Button1Mask) button = Button1; | |
1358 | |
1204 | 1359 SET_EVENT_MISC_USER_MODIFIERS (emacs_event, modifiers); |
1360 SET_EVENT_MISC_USER_BUTTON (emacs_event, button); | |
1361 | |
1362 DndDropCoordinates (FRAME_X_TEXT_WIDGET (frame), x_event, | |
1363 &(EVENT_MISC_USER_X (emacs_event)), | |
1364 &(EVENT_MISC_USER_Y (emacs_event))); | |
2367 | 1365 DndGetData (x_event, &data, &size); |
1366 | |
1367 dtype = DndDataType (x_event); | |
428 | 1368 switch (dtype) |
1369 { | |
1370 case DndFiles: /* null terminated strings, end null */ | |
1371 { | |
1372 int len; | |
2367 | 1373 Ibyte *hurl = NULL; |
428 | 1374 |
1375 while (*data) | |
1376 { | |
2367 | 1377 Ibyte *dataint; |
1378 len = strlen (data); | |
1379 EXTERNAL_TO_C_STRING (data, dataint, Qfile_name); | |
2956 | 1380 hurl = dnd_url_hexify_string (dataint, |
1381 (const Ibyte *) "file:"); | |
2367 | 1382 l_item = build_intstring (hurl); |
428 | 1383 l_dndlist = Fcons (l_item, l_dndlist); |
1384 data += len + 1; | |
2367 | 1385 xfree (hurl, Ibyte *); |
428 | 1386 } |
1387 l_type = Qdragdrop_URL; | |
1388 } | |
1389 break; | |
1390 case DndText: | |
1391 l_type = Qdragdrop_MIME; | |
2367 | 1392 l_dndlist = list1 (list3 (list1 (build_string ("text/plain")), |
1393 build_string ("8bit"), | |
1394 build_ext_string (data, | |
1395 Qctext))); | |
428 | 1396 break; |
1397 case DndMIME: | |
1398 /* we have to parse this in some way to extract | |
1399 content-type and params (in the tm way) and | |
1400 content encoding. | |
1401 OR: if data is string, let tm do the job | |
1402 if data is list[2], give the first two | |
1403 to tm... | |
1404 */ | |
1405 l_type = Qdragdrop_MIME; | |
2367 | 1406 l_dndlist = list1 (build_ext_string (data, Qbinary)); |
428 | 1407 break; |
1408 case DndFile: | |
1409 case DndDir: | |
1410 case DndLink: | |
1411 case DndExe: | |
1412 { | |
2367 | 1413 Ibyte *dataint, *hurl; |
1414 EXTERNAL_TO_C_STRING (data, dataint, Qfile_name); | |
1415 hurl = dnd_url_hexify_string (dataint, "file:"); | |
1416 l_dndlist = list1 (build_intstring (hurl)); | |
1417 xfree (hurl, Ibyte *); | |
428 | 1418 } |
1419 break; | |
1420 case DndURL: | |
1421 /* as it is a real URL it should already be escaped | |
1422 and escaping again will break them (cause % is unsave) */ | |
2367 | 1423 l_dndlist = list1 (build_ext_string (data, |
1424 Qfile_name)); | |
428 | 1425 l_type = Qdragdrop_URL; |
1426 break; | |
1427 default: /* Unknown, RawData and any other type */ | |
2367 | 1428 l_dndlist = list1 (list3 (list1 (build_string |
1429 ("application/octet-stream")), | |
1430 build_string ("8bit"), | |
1431 make_ext_string (data, size, | |
1432 Qbinary))); | |
428 | 1433 l_type = Qdragdrop_MIME; |
1434 break; | |
1435 } | |
1436 | |
2367 | 1437 SET_EVENT_MISC_USER_FUNCTION (emacs_event, |
1438 Qdragdrop_drop_dispatch); | |
1439 SET_EVENT_MISC_USER_OBJECT (emacs_event, | |
1440 Fcons (l_type, l_dndlist)); | |
428 | 1441 |
1442 UNGCPRO; | |
1443 | |
1444 break; | |
1445 } | |
1446 #endif /* HAVE_OFFIX_DND */ | |
1447 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS (d) | |
1448 && (Atom) (ev->data.l[0]) == DEVICE_XATOM_WM_TAKE_FOCUS (d) | |
1449 && (Atom) (ev->data.l[1]) == 0) | |
1450 { | |
1451 ev->data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d); | |
1452 } | |
1453 } | |
1454 /* fall through */ | |
1455 | |
1456 default: /* it's a magic event */ | |
1457 { | |
1458 struct frame *frame; | |
1459 Window w; | |
934 | 1460 XEvent *x_event_copy; |
1461 SET_EVENT_TYPE (emacs_event, magic_event); | |
1204 | 1462 x_event_copy = &EVENT_MAGIC_X_EVENT (emacs_event); |
428 | 1463 |
1464 #define FROB(event_member, window_member) \ | |
1465 x_event_copy->event_member = x_event->event_member; \ | |
1466 w = x_event->event_member.window_member | |
1467 | |
1468 switch (x_event->type) | |
1469 { | |
1470 case SelectionRequest: FROB(xselectionrequest, owner); break; | |
1471 case SelectionClear: FROB(xselectionclear, window); break; | |
1472 case SelectionNotify: FROB(xselection, requestor); break; | |
1473 case PropertyNotify: FROB(xproperty, window); break; | |
1474 case ClientMessage: FROB(xclient, window); break; | |
1475 case ConfigureNotify: FROB(xconfigure, window); break; | |
1476 case Expose: | |
1477 case GraphicsExpose: FROB(xexpose, window); break; | |
1478 case MapNotify: | |
1479 case UnmapNotify: FROB(xmap, window); break; | |
1480 case EnterNotify: | |
1481 case LeaveNotify: FROB(xcrossing, window); break; | |
1482 case FocusIn: | |
1483 case FocusOut: FROB(xfocus, window); break; | |
1484 case VisibilityNotify: FROB(xvisibility, window); break; | |
442 | 1485 case CreateNotify: FROB(xcreatewindow, window); break; |
428 | 1486 default: |
1487 w = x_event->xany.window; | |
1488 *x_event_copy = *x_event; | |
1489 break; | |
1490 } | |
1491 #undef FROB | |
1492 frame = x_any_window_to_frame (d, w); | |
1493 | |
1494 if (!frame) | |
1495 return 0; | |
1496 | |
1204 | 1497 SET_EVENT_CHANNEL (emacs_event, wrap_frame (frame)); |
428 | 1498 break; |
1499 } | |
1500 } | |
1501 return 1; | |
1502 } | |
1503 | |
1504 | |
1505 | |
1506 /************************************************************************/ | |
1507 /* magic-event handling */ | |
1508 /************************************************************************/ | |
1509 | |
1510 static void | |
1511 handle_focus_event_1 (struct frame *f, int in_p) | |
1512 { | |
863 | 1513 handle_focus_event_2 (XtWindow (FRAME_X_TEXT_WIDGET (f)), f, in_p); |
1514 } | |
1515 | |
1516 static void | |
1517 handle_focus_event_2 (Window win, struct frame *f, int in_p) | |
1518 { | |
1519 /* Although this treats focus differently for all widgets (including | |
1520 the frame) it seems to work ok. */ | |
1521 Widget needs_it = XtWindowToWidget (FRAME_X_DISPLAY (f), win); | |
1522 | |
428 | 1523 #if XtSpecificationRelease > 5 |
450 | 1524 widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f)); |
428 | 1525 #endif |
1526 #ifdef HAVE_XIM | |
1527 XIM_focus_event (f, in_p); | |
1528 #endif /* HAVE_XIM */ | |
450 | 1529 |
428 | 1530 /* On focus change, clear all memory of sticky modifiers |
1531 to avoid non-intuitive behavior. */ | |
1532 clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f))); | |
1533 | |
1534 /* We don't want to handle the focus change now, because we might | |
1535 be in an accept-process-output, sleep-for, or sit-for. So | |
1536 we enqueue it. | |
1537 | |
1538 Actually, we half handle it: we handle it as far as changing the | |
1539 box cursor for redisplay, but we don't call any hooks or do any | |
1540 select-frame stuff until after the sit-for. | |
1541 | |
1542 Unfortunately native widgets break the model because they grab | |
1543 the keyboard focus and nothing sets it back again. I cannot find | |
1544 any reasonable way to do this elsewhere so we assert here that | |
1545 the keyboard focus is on the emacs text widget. Menus and dialogs | |
1546 do this in their selection callback, but we don't want that since | |
1547 a button having focus is legitimate. An edit field having focus | |
1548 is mandatory. Weirdly you get a FocusOut event when you click in | |
442 | 1549 a widget-glyph but you don't get a corresponding FocusIn when you |
428 | 1550 click in the frame. Why is this? */ |
438 | 1551 if (in_p |
1552 #if XtSpecificationRelease > 5 | |
863 | 1553 && needs_it != widget_with_focus |
428 | 1554 #endif |
1555 ) | |
1556 { | |
863 | 1557 lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), needs_it); |
428 | 1558 } |
450 | 1559 |
863 | 1560 /* If we are focusing on a native widget then record and exit. */ |
1561 if (needs_it != FRAME_X_TEXT_WIDGET (f)) { | |
1562 widget_with_focus = needs_it; | |
1563 return; | |
1564 } | |
1565 | |
450 | 1566 /* We have the focus now. See comment in |
1567 emacs_Xt_handle_widget_losing_focus (). */ | |
1568 if (in_p) | |
1569 widget_with_focus = NULL; | |
1570 | |
428 | 1571 /* do the generic event-stream stuff. */ |
1572 { | |
1573 Lisp_Object frm; | |
1574 Lisp_Object conser; | |
1575 struct gcpro gcpro1; | |
1576 | |
793 | 1577 frm = wrap_frame (f); |
428 | 1578 conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); |
1579 GCPRO1 (conser); | |
1580 emacs_handle_focus_change_preliminary (conser); | |
1581 enqueue_magic_eval_event (emacs_handle_focus_change_final, | |
1582 conser); | |
1583 UNGCPRO; | |
1584 } | |
1585 } | |
1586 | |
863 | 1587 /* Create a synthetic X focus event. */ |
1111 | 1588 void emacs_Xt_enqueue_focus_event (Widget wants_it, Lisp_Object frame, |
1589 int in_p); | |
863 | 1590 void |
1111 | 1591 emacs_Xt_enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p) |
863 | 1592 { |
1593 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | |
1594 Lisp_Event *ev = XEVENT (emacs_event); | |
960 | 1595 XEvent *x_event; |
1596 | |
1597 XSET_EVENT_TYPE (emacs_event, magic_event); | |
1204 | 1598 x_event = &EVENT_MAGIC_X_EVENT (ev); |
863 | 1599 |
1600 x_event->type = in_p ? FocusIn : FocusOut; | |
1601 x_event->xfocus.window = XtWindow (wants_it); | |
1602 | |
960 | 1603 SET_EVENT_CHANNEL (ev, frame); |
1204 | 1604 |
1605 enqueue_dispatch_event (emacs_event); | |
863 | 1606 } |
1607 | |
450 | 1608 /* The idea here is that when a widget glyph gets unmapped we don't |
1609 want the focus to stay with it if it has focus - because it may | |
863 | 1610 well just get deleted next and then we have lost the focus until the |
450 | 1611 user does something. So handle_focus_event_1 records the widget |
1612 with keyboard focus when FocusOut is processed, and then, when a | |
1613 widget gets unmapped, it calls this function to restore focus if | |
1614 appropriate. */ | |
853 | 1615 void emacs_Xt_handle_widget_losing_focus (struct frame *f, Widget losing_widget); |
450 | 1616 void |
853 | 1617 emacs_Xt_handle_widget_losing_focus (struct frame *f, Widget losing_widget) |
450 | 1618 { |
1619 if (losing_widget == widget_with_focus) | |
1620 { | |
1621 handle_focus_event_1 (f, 1); | |
1622 } | |
1623 } | |
1624 | |
428 | 1625 /* This is called from the external-widget code */ |
1626 | |
1627 void emacs_Xt_handle_focus_event (XEvent *event); | |
1628 void | |
1629 emacs_Xt_handle_focus_event (XEvent *event) | |
1630 { | |
1631 struct device *d = get_device_from_display (event->xany.display); | |
1632 struct frame *f; | |
1633 | |
1634 if (DEVICE_X_BEING_DELETED (d)) | |
1635 return; | |
1636 | |
1637 /* | |
1638 * It's curious that we're using x_any_window_to_frame() instead | |
1639 * of x_window_to_frame(). I don't know what the impact of this is. | |
1640 */ | |
1641 f = x_any_window_to_frame (d, event->xfocus.window); | |
1642 if (!f) | |
1643 /* focus events are sometimes generated just before | |
1644 a frame is destroyed. */ | |
1645 return; | |
1646 handle_focus_event_1 (f, event->type == FocusIn); | |
1647 } | |
1648 | |
1649 /* both MapNotify and VisibilityNotify can cause this | |
1650 JV is_visible has the same semantics as f->visible*/ | |
1651 static void | |
1652 change_frame_visibility (struct frame *f, int is_visible) | |
1653 { | |
793 | 1654 Lisp_Object frame = wrap_frame (f); |
1655 | |
428 | 1656 |
1657 if (!FRAME_VISIBLE_P (f) && is_visible) | |
1658 { | |
1659 FRAME_VISIBLE_P (f) = is_visible; | |
872 | 1660 /* [[ This improves the double flicker when uniconifying a frame |
428 | 1661 some. A lot of it is not showing a buffer which has changed |
1662 while the frame was iconified. To fix it further requires | |
872 | 1663 the good 'ol double redisplay structure. ]] -- comment is |
1664 invalid, obviously predates 19.12, when the double redisplay | |
1665 structure (i.e. current + desired) was put back in. --ben */ | |
428 | 1666 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); |
1667 va_run_hook_with_args (Qmap_frame_hook, 1, frame); | |
1668 } | |
1669 else if (FRAME_VISIBLE_P (f) && !is_visible) | |
1670 { | |
1671 FRAME_VISIBLE_P (f) = 0; | |
1672 va_run_hook_with_args (Qunmap_frame_hook, 1, frame); | |
1673 } | |
1674 else if (FRAME_VISIBLE_P (f) * is_visible < 0) | |
1675 { | |
1676 FRAME_VISIBLE_P(f) = - FRAME_VISIBLE_P(f); | |
1677 if (FRAME_REPAINT_P(f)) | |
1678 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
1679 va_run_hook_with_args (Qmap_frame_hook, 1, frame); | |
1680 } | |
1681 } | |
1682 | |
1683 static void | |
593 | 1684 update_frame_iconify_status (struct frame *f) |
1685 { | |
1686 f->iconified = (x_frame_window_state (f) == IconicState); | |
1687 } | |
1688 | |
1689 static void | |
428 | 1690 handle_map_event (struct frame *f, XEvent *event) |
1691 { | |
593 | 1692 |
1693 /* It seems that, given the multiplicity of window managers and X | |
1694 implementations, plus the fact that X was designed without | |
1695 window managers or icons in mind and this was then grafted on | |
1696 with about the skill of a drunk freshman med student attempting | |
1697 surgery with a rusty razor blade, we cannot treat any off | |
1698 MapNotify/UnmapNotify/VisibilityNotify as more than vague hints | |
1699 as to the actual situation. | |
1700 | |
1701 So we should just query the actual status. Unfortunately, things | |
1702 are worse because (a) there aren't obvious ways to query some | |
1703 of these values (e.g. "totally visible"), and (b) there may be | |
1704 race conditions (see below). | |
1705 | |
638 | 1706 However, according to the ICCCM, there's a specific way to |
593 | 1707 ask the window manager whether the state is (a) visible, |
1708 (b) iconic, (c) withdrawn. It must be one of these three. | |
1709 We already use this call to check for the iconified state. | |
1710 I'd suggest we do the same for visible (i.e. NormalState), | |
1711 and scrap most of the nasty code below. | |
1712 | |
1713 --ben | |
1714 */ | |
1715 | |
1716 update_frame_iconify_status (f); | |
1717 | |
1718 /* #### Ben suggests rewriting the code below using | |
1719 x_frame_window_state (f). */ | |
1720 | |
428 | 1721 if (event->type == MapNotify) |
1722 { | |
1723 XWindowAttributes xwa; | |
1724 | |
1725 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM) | |
1726 send synthetic MapNotify events when a window is first | |
1727 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE. | |
1728 Or something like that. We initially tried a different | |
1729 solution below, but that ran into a different window- | |
1730 manager bug. | |
1731 | |
1732 It seems that the only reliable way is to treat a | |
1733 MapNotify event as a "hint" that the window might or | |
1734 might not be visible, and check explicitly. */ | |
1735 | |
1736 XGetWindowAttributes (event->xany.display, event->xmap.window, | |
1737 &xwa); | |
1738 if (xwa.map_state != IsViewable) | |
593 | 1739 return; |
428 | 1740 |
1741 FRAME_X_TOTALLY_VISIBLE_P (f) = 1; | |
1742 #if 0 | |
1743 /* Bleagh again!!!! We initially tried the following hack | |
1744 around the MWM problem, but it turns out that TWM | |
1745 has a race condition when you un-iconify, where it maps | |
1746 the window and then tells the server that the window | |
1747 is un-iconified. Usually, XEmacs wakes up between | |
1748 those two occurrences, and thus thinks that un-iconified | |
1749 windows are still iconified. | |
1750 | |
1751 Ah, the joys of X. */ | |
1752 | |
1753 /* By Emacs definition, a frame that is iconified is not | |
1754 visible. Marking a frame as visible will automatically cause | |
1755 frame-iconified-p to return nil, regardless of whether the | |
1756 frame is actually iconified. Therefore, we have to ignore | |
1757 MapNotify events on iconified frames. (It's not obvious | |
1758 to me why these are being sent, but it happens at startup | |
1759 with frames that are initially iconified; perhaps they are | |
1760 synthetic MapNotify events coming from the window manager.) | |
1761 Note that `frame-iconified-p' queries the server | |
1762 to determine whether the frame is currently iconified, | |
1763 rather than consulting some internal (and likely | |
1764 inaccurate) state flag. Therefore, ignoring the MapNotify | |
1765 is correct. */ | |
793 | 1766 if (!FRAME_VISIBLE_P (f) && NILP (Fframe_iconified_p (wrap_frame (f)))) |
428 | 1767 #endif /* 0 */ |
1768 change_frame_visibility (f, 1); | |
1769 } | |
1770 else | |
1771 { | |
1772 FRAME_X_TOTALLY_VISIBLE_P (f) = 0; | |
1773 change_frame_visibility (f, 0); | |
1774 } | |
1775 } | |
1776 | |
1777 static void | |
1778 handle_client_message (struct frame *f, XEvent *event) | |
1779 { | |
1780 struct device *d = XDEVICE (FRAME_DEVICE (f)); | |
793 | 1781 Lisp_Object frame = wrap_frame (f); |
428 | 1782 |
1783 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) && | |
1784 (Atom) (event->xclient.data.l[0]) == DEVICE_XATOM_WM_DELETE_WINDOW (d)) | |
1785 { | |
1786 /* WM_DELETE_WINDOW is a misc-user event, but other ClientMessages, | |
1787 such as WM_TAKE_FOCUS, are eval events. That's because delete-window | |
1788 was probably executed with a mouse click, while the others could | |
1789 have been sent as a result of mouse motion or some other implicit | |
1790 action. (Call this a "heuristic"...) The reason for caring about | |
1791 this is so that clicking on the close-box will make emacs prompt | |
1792 using a dialog box instead of the minibuffer if there are unsaved | |
1793 buffers. | |
1794 */ | |
1795 enqueue_misc_user_event (frame, Qeval, | |
1796 list3 (Qdelete_frame, frame, Qt)); | |
1797 } | |
1798 else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) && | |
1799 (Atom) event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d)) | |
1800 { | |
1801 handle_focus_event_1 (f, 1); | |
1802 #if 0 | |
1803 /* If there is a dialog box up, focus on it. | |
1804 | |
1805 #### Actually, we're raising it too, which is wrong. We should | |
1806 #### just focus on it, but lwlib doesn't currently give us an | |
1807 #### easy way to do that. This should be fixed. | |
1808 */ | |
1809 unsigned long take_focus_timestamp = event->xclient.data.l[1]; | |
1810 Widget widget = lw_raise_all_pop_up_widgets (); | |
1811 if (widget) | |
1812 { | |
1813 /* kludge: raise_all returns bottommost widget, but we really | |
1814 want the topmost. So just raise it for now. */ | |
1815 XMapRaised (XtDisplay (widget), XtWindow (widget)); | |
1816 /* Grab the focus with the timestamp of the TAKE_FOCUS. */ | |
1817 XSetInputFocus (XtDisplay (widget), XtWindow (widget), | |
1818 RevertToParent, take_focus_timestamp); | |
1819 } | |
1820 #endif | |
1821 } | |
1822 } | |
1823 | |
448 | 1824 /* #### I'm struggling to understand how the X event loop really works. |
1825 Here is the problem: | |
1826 | |
1827 When widgets get mapped / changed etc the actual display updates | |
1828 are done asynchronously via X events being processed - this | |
1829 normally happens when XtAppProcessEvent() gets called. However, if | |
1830 we are executing lisp code or even doing redisplay we won't | |
1831 necessarily process X events for a very long time. This has the | |
1832 effect of widgets only getting updated when XEmacs only goes into | |
1833 idle, or some other event causes processing of the X event queue. | |
1834 | |
1835 XtAppProcessEvent can get called from the following places: | |
1836 | |
1837 emacs_Xt_next_event () - this is normal event processing, almost | |
1838 any non-X event will take precedence and this means that we | |
1839 cannot rely on it to do the right thing at the right time for | |
1840 widget display. | |
1841 | |
1204 | 1842 emacs_Xt_drain_queue () - this happens when SIGIO gets tripped, |
1843 processing the event queue allows C-g to be checked for. It gets | |
1844 called from emacs_Xt_event_pending_p (). #### Update this comment. | |
448 | 1845 |
1846 In order to solve this I have tried introducing a list primitive - | |
1847 dispatch-non-command-events - which forces processing of X events | |
1848 related to display. Unfortunately this has a number of problems, | |
1849 one is that it is possible for event_stream_event_pending_p to | |
1850 block for ever if there isn't actually an event. I guess this can | |
1851 happen if we drop the synthetic event for reason. It also relies on | |
1852 SIGIO processing which makes things rather fragile. | |
1853 | |
1854 People have seen behaviour whereby XEmacs blocks until you move the | |
1855 mouse. This seems to indicate that dispatch-non-command-events is | |
1856 blocking. It may be that in a SIGIO world forcing SIGIO processing | |
1857 does the wrong thing. | |
1858 */ | |
428 | 1859 static void |
853 | 1860 emacs_Xt_force_event_pending (struct frame *f) |
442 | 1861 { |
1862 XEvent event; | |
1863 | |
853 | 1864 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE (f))); |
442 | 1865 event.xclient.type = ClientMessage; |
1866 event.xclient.display = dpy; | |
1867 event.xclient.message_type = XInternAtom (dpy, "BumpQueue", False); | |
1868 event.xclient.format = 32; | |
1869 event.xclient.window = 0; | |
1870 | |
1871 /* Send the drop message */ | |
1872 XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)), | |
1873 True, NoEventMask, &event); | |
448 | 1874 /* We rely on SIGIO and friends to realise we have generated an |
1875 event. */ | |
442 | 1876 } |
1877 | |
1878 static void | |
788 | 1879 emacs_Xt_format_magic_event (Lisp_Event *event, Lisp_Object pstream) |
1880 { | |
1881 Lisp_Object console = CDFW_CONSOLE (EVENT_CHANNEL (event)); | |
1882 if (CONSOLE_X_P (XCONSOLE (console))) | |
826 | 1883 write_c_string |
1204 | 1884 (pstream, x_event_name ((EVENT_MAGIC_X_EVENT (event)).type)); |
788 | 1885 } |
1886 | |
1887 static int | |
1888 emacs_Xt_compare_magic_event (Lisp_Event *e1, Lisp_Event *e2) | |
1889 { | |
1890 if (CONSOLE_X_P (XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e1)))) && | |
1891 CONSOLE_X_P (XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e2))))) | |
1204 | 1892 return ((EVENT_MAGIC_X_EVENT (e1)).xany.serial == |
1893 (EVENT_MAGIC_X_EVENT (e2)).xany.serial); | |
788 | 1894 if (CONSOLE_X_P (XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e1)))) || |
1895 CONSOLE_X_P (XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e2))))) | |
1896 return 0; | |
1897 return 1; | |
1898 } | |
1899 | |
1900 static Hashcode | |
1901 emacs_Xt_hash_magic_event (Lisp_Event *e) | |
1902 { | |
1903 Lisp_Object console = CDFW_CONSOLE (EVENT_CHANNEL (e)); | |
1904 if (CONSOLE_X_P (XCONSOLE (console))) | |
1204 | 1905 return (EVENT_MAGIC_X_EVENT (e)).xany.serial; |
788 | 1906 return 0; |
1907 } | |
1908 | |
1909 static void | |
440 | 1910 emacs_Xt_handle_magic_event (Lisp_Event *emacs_event) |
428 | 1911 { |
1912 /* This function can GC */ | |
1204 | 1913 XEvent *event = &EVENT_MAGIC_X_EVENT (emacs_event); |
428 | 1914 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event)); |
1915 | |
1916 if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f)))) | |
1917 return; | |
1918 | |
1919 switch (event->type) | |
1920 { | |
1921 case SelectionRequest: | |
1922 x_handle_selection_request (&event->xselectionrequest); | |
1923 break; | |
934 | 1924 |
428 | 1925 case SelectionClear: |
1926 x_handle_selection_clear (&event->xselectionclear); | |
1927 break; | |
934 | 1928 |
428 | 1929 case SelectionNotify: |
1930 x_handle_selection_notify (&event->xselection); | |
1931 break; | |
934 | 1932 |
428 | 1933 case PropertyNotify: |
1934 x_handle_property_notify (&event->xproperty); | |
1935 break; | |
934 | 1936 |
428 | 1937 case Expose: |
1938 if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y, | |
1318 | 1939 event->xexpose.width, |
1940 event->xexpose.height) | |
428 | 1941 && |
1942 !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y, | |
1943 event->xexpose.width, event->xexpose.height)) | |
1318 | 1944 redisplay_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y, |
1945 event->xexpose.width, | |
1946 event->xexpose.height); | |
428 | 1947 break; |
1948 | |
1949 case GraphicsExpose: /* This occurs when an XCopyArea's source area was | |
1950 obscured or not available. */ | |
1318 | 1951 redisplay_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y, |
1952 event->xexpose.width, | |
1953 event->xexpose.height); | |
428 | 1954 break; |
1955 | |
1956 case MapNotify: | |
1957 case UnmapNotify: | |
1958 handle_map_event (f, event); | |
1959 break; | |
1960 | |
1961 case EnterNotify: | |
1962 if (event->xcrossing.detail != NotifyInferior) | |
1963 { | |
793 | 1964 Lisp_Object frame = wrap_frame (f); |
1965 | |
428 | 1966 /* FRAME_X_MOUSE_P (f) = 1; */ |
1967 va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame); | |
1968 } | |
1969 break; | |
1970 | |
1971 case LeaveNotify: | |
1972 if (event->xcrossing.detail != NotifyInferior) | |
1973 { | |
793 | 1974 Lisp_Object frame = wrap_frame (f); |
1975 | |
428 | 1976 /* FRAME_X_MOUSE_P (f) = 0; */ |
1977 va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame); | |
1978 } | |
1979 break; | |
1980 | |
1981 case FocusIn: | |
1982 case FocusOut: | |
1983 | |
1984 #ifdef EXTERNAL_WIDGET | |
1985 /* External widget lossage: Ben said: | |
1986 YUCK. The only way to make focus changes work properly is to | |
1987 completely ignore all FocusIn/FocusOut events and depend only | |
1988 on notifications from the ExternalClient widget. */ | |
1989 if (FRAME_X_EXTERNAL_WINDOW_P (f)) | |
1990 break; | |
1991 #endif | |
863 | 1992 handle_focus_event_2 (event->xfocus.window, f, event->type == FocusIn); |
428 | 1993 break; |
1994 | |
1995 case ClientMessage: | |
1996 handle_client_message (f, event); | |
1997 break; | |
1998 | |
1999 case VisibilityNotify: /* window visibility has changed */ | |
2000 if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f))) | |
2001 { | |
593 | 2002 /* See comment in handle_map_event */ |
2003 update_frame_iconify_status (f); | |
2004 | |
2005 /* #### Ben suggests rewriting the code below using | |
2006 x_frame_window_state (f). */ | |
428 | 2007 FRAME_X_TOTALLY_VISIBLE_P (f) = |
2008 (event->xvisibility.state == VisibilityUnobscured); | |
2009 /* Note that the fvwm pager only sends VisibilityNotify when | |
2010 changing pages. Is this all we need to do ? JV */ | |
2011 /* Nope. We must at least trigger a redisplay here. | |
2012 Since this case seems similar to MapNotify, I've | |
2013 factored out some code to change_frame_visibility(). | |
2014 This triggers the necessary redisplay and runs | |
2015 (un)map-frame-hook. - dkindred@cs.cmu.edu */ | |
2016 /* Changed it again to support the tristate visibility flag */ | |
2017 change_frame_visibility (f, (event->xvisibility.state | |
2018 != VisibilityFullyObscured) ? 1 : -1); | |
2019 } | |
2020 break; | |
2021 | |
2022 case ConfigureNotify: | |
2023 #ifdef HAVE_XIM | |
2024 XIM_SetGeometry (f); | |
2025 #endif | |
2026 break; | |
2027 | |
442 | 2028 case CreateNotify: |
2029 break; | |
2030 | |
428 | 2031 default: |
2032 break; | |
2033 } | |
2034 } | |
2035 | |
2036 | |
2037 /************************************************************************/ | |
2038 /* timeout events */ | |
2039 /************************************************************************/ | |
2040 | |
2041 static int timeout_id_tick; | |
2042 | |
2043 /* Xt interval id's might not fit into an int (they're pointers, as it | |
2044 happens), so we need to provide a conversion list. */ | |
2045 | |
2046 static struct Xt_timeout | |
2047 { | |
2048 int id; | |
2049 XtIntervalId interval_id; | |
2050 struct Xt_timeout *next; | |
2051 } *pending_timeouts, *completed_timeouts; | |
2052 | |
2053 static struct Xt_timeout_blocktype | |
2054 { | |
2055 Blocktype_declare (struct Xt_timeout); | |
2056 } *the_Xt_timeout_blocktype; | |
2057 | |
2058 /* called by XtAppNextEvent() */ | |
2059 static void | |
2286 | 2060 Xt_timeout_callback (XtPointer closure, XtIntervalId *UNUSED (id)) |
428 | 2061 { |
2062 struct Xt_timeout *timeout = (struct Xt_timeout *) closure; | |
2063 struct Xt_timeout *t2 = pending_timeouts; | |
2064 /* Remove this one from the list of pending timeouts */ | |
2065 if (t2 == timeout) | |
2066 pending_timeouts = pending_timeouts->next; | |
2067 else | |
2068 { | |
2069 while (t2->next && t2->next != timeout) t2 = t2->next; | |
2070 assert (t2->next); | |
2071 t2->next = t2->next->next; | |
2072 } | |
2073 /* Add this one to the list of completed timeouts */ | |
2074 timeout->next = completed_timeouts; | |
2075 completed_timeouts = timeout; | |
2076 } | |
2077 | |
2078 static int | |
2079 emacs_Xt_add_timeout (EMACS_TIME thyme) | |
2080 { | |
2081 struct Xt_timeout *timeout = Blocktype_alloc (the_Xt_timeout_blocktype); | |
2082 EMACS_TIME current_time; | |
2083 int milliseconds; | |
2084 | |
2085 timeout->id = timeout_id_tick++; | |
2086 timeout->next = pending_timeouts; | |
2087 pending_timeouts = timeout; | |
2088 EMACS_GET_TIME (current_time); | |
2089 EMACS_SUB_TIME (thyme, thyme, current_time); | |
2090 milliseconds = EMACS_SECS (thyme) * 1000 + | |
2091 EMACS_USECS (thyme) / 1000; | |
2092 if (milliseconds < 1) | |
2093 milliseconds = 1; | |
2094 timeout->interval_id = XtAppAddTimeOut (Xt_app_con, milliseconds, | |
2095 Xt_timeout_callback, | |
2096 (XtPointer) timeout); | |
2097 return timeout->id; | |
2098 } | |
2099 | |
2100 static void | |
2101 emacs_Xt_remove_timeout (int id) | |
2102 { | |
2103 struct Xt_timeout *timeout, *t2; | |
2104 | |
2105 timeout = NULL; | |
2106 | |
2107 /* Find the timeout on the list of pending ones, if it's still there. */ | |
2108 if (pending_timeouts) | |
2109 { | |
2110 if (id == pending_timeouts->id) | |
2111 { | |
2112 timeout = pending_timeouts; | |
2113 pending_timeouts = pending_timeouts->next; | |
2114 } | |
2115 else | |
2116 { | |
2117 t2 = pending_timeouts; | |
2118 while (t2->next && t2->next->id != id) t2 = t2->next; | |
2119 if ( t2->next) /*found it */ | |
2120 { | |
2121 timeout = t2->next; | |
2122 t2->next = t2->next->next; | |
2123 } | |
2124 } | |
2125 /* if it was pending, we have removed it from the list */ | |
2126 if (timeout) | |
2127 XtRemoveTimeOut (timeout->interval_id); | |
2128 } | |
2129 | |
2130 /* It could be that the Xt call back was already called but we didn't convert | |
2131 into an Emacs event yet */ | |
2132 if (!timeout && completed_timeouts) | |
2133 { | |
2134 /* Code duplication! */ | |
2135 if (id == completed_timeouts->id) | |
2136 { | |
2137 timeout = completed_timeouts; | |
2138 completed_timeouts = completed_timeouts->next; | |
2139 } | |
2140 else | |
2141 { | |
2142 t2 = completed_timeouts; | |
2143 while (t2->next && t2->next->id != id) t2 = t2->next; | |
2144 if ( t2->next) /*found it */ | |
2145 { | |
2146 timeout = t2->next; | |
2147 t2->next = t2->next->next; | |
2148 } | |
2149 } | |
2150 } | |
2151 | |
2152 /* If we found the thing on the lists of timeouts, | |
2153 and removed it, deallocate | |
2154 */ | |
2155 if (timeout) | |
2156 Blocktype_free (the_Xt_timeout_blocktype, timeout); | |
2157 } | |
2158 | |
2159 static void | |
440 | 2160 Xt_timeout_to_emacs_event (Lisp_Event *emacs_event) |
428 | 2161 { |
2162 struct Xt_timeout *timeout = completed_timeouts; | |
2163 assert (timeout); | |
2164 completed_timeouts = completed_timeouts->next; | |
934 | 2165 /* timeout events have nil as channel */ |
1204 | 2166 set_event_type (emacs_event, timeout_event); |
934 | 2167 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### wrong!! */ |
1204 | 2168 SET_EVENT_TIMEOUT_INTERVAL_ID (emacs_event, timeout->id); |
2169 SET_EVENT_TIMEOUT_FUNCTION (emacs_event, Qnil); | |
2170 SET_EVENT_TIMEOUT_OBJECT (emacs_event, Qnil); | |
428 | 2171 Blocktype_free (the_Xt_timeout_blocktype, timeout); |
2172 } | |
2173 | |
2174 | |
2175 /************************************************************************/ | |
2176 /* process and tty events */ | |
2177 /************************************************************************/ | |
2178 | |
2179 struct what_is_ready_closure | |
2180 { | |
2181 int fd; | |
2182 Lisp_Object what; | |
2183 XtInputId id; | |
2184 }; | |
2185 | |
2186 static Lisp_Object *filedesc_with_input; | |
2187 static struct what_is_ready_closure **filedesc_to_what_closure; | |
2188 | |
2189 static void | |
2190 init_what_input_once (void) | |
2191 { | |
2192 int i; | |
2193 | |
2194 filedesc_with_input = xnew_array (Lisp_Object, MAXDESC); | |
2195 filedesc_to_what_closure = | |
2196 xnew_array (struct what_is_ready_closure *, MAXDESC); | |
2197 | |
2198 for (i = 0; i < MAXDESC; i++) | |
2199 { | |
2200 filedesc_to_what_closure[i] = 0; | |
2201 filedesc_with_input[i] = Qnil; | |
2202 } | |
2203 | |
2204 process_events_occurred = 0; | |
2205 tty_events_occurred = 0; | |
2206 } | |
2207 | |
2208 static void | |
2209 mark_what_as_being_ready (struct what_is_ready_closure *closure) | |
2210 { | |
2211 if (NILP (filedesc_with_input[closure->fd])) | |
2212 { | |
2213 SELECT_TYPE temp_mask; | |
2214 FD_ZERO (&temp_mask); | |
2215 FD_SET (closure->fd, &temp_mask); | |
2216 /* Check to make sure there's *really* input available. | |
2217 Sometimes things seem to get confused and this gets called | |
2218 for the tty fd when there's really only input available | |
2219 on some process's fd. (It will subsequently get called | |
2220 for that process's fd, so returning without setting any | |
2221 flags will take care of it.) To see the problem, uncomment | |
2222 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS | |
2223 down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log' | |
2224 and press return repeatedly. (Seen under AIX & Linux.) | |
2225 -dkindred@cs.cmu.edu */ | |
2226 if (!poll_fds_for_input (temp_mask)) | |
2227 { | |
2228 #if 0 | |
2229 stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n", | |
2230 closure->fd); | |
2231 #endif | |
2232 return; | |
2233 } | |
2234 filedesc_with_input[closure->fd] = closure->what; | |
2235 if (PROCESSP (closure->what)) | |
2236 /* Don't increment this if the current process is already marked | |
2237 * as having input. */ | |
2238 process_events_occurred++; | |
2239 else | |
2240 tty_events_occurred++; | |
2241 } | |
2242 } | |
2243 | |
2244 static void | |
2286 | 2245 Xt_what_callback (void *closure, int *UNUSED (source), XtInputId *UNUSED (id)) |
428 | 2246 { |
2247 /* If closure is 0, then we got a fake event from a signal handler. | |
2248 The only purpose of this is to make XtAppProcessEvent() stop | |
2249 blocking. */ | |
2250 if (closure) | |
2251 mark_what_as_being_ready ((struct what_is_ready_closure *) closure); | |
2252 else | |
2253 { | |
2254 fake_event_occurred++; | |
2255 drain_signal_event_pipe (); | |
2256 } | |
2257 } | |
2258 | |
2259 static void | |
2260 select_filedesc (int fd, Lisp_Object what) | |
2261 { | |
2262 struct what_is_ready_closure *closure; | |
2263 | |
2264 /* If somebody is trying to select something that's already selected | |
2265 for, then something went wrong. The generic routines ought to | |
2266 detect this and error before here. */ | |
2267 assert (!filedesc_to_what_closure[fd]); | |
2268 | |
2269 closure = xnew (struct what_is_ready_closure); | |
2270 closure->fd = fd; | |
2271 closure->what = what; | |
2272 closure->id = | |
2273 XtAppAddInput (Xt_app_con, fd, | |
2274 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */), | |
2275 Xt_what_callback, closure); | |
2276 filedesc_to_what_closure[fd] = closure; | |
2277 } | |
2278 | |
2279 static void | |
2280 unselect_filedesc (int fd) | |
2281 { | |
2282 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd]; | |
2283 | |
2284 assert (closure); | |
2285 if (!NILP (filedesc_with_input[fd])) | |
2286 { | |
2287 /* We are unselecting this process before we have drained the rest of | |
2288 the input from it, probably from status_notify() in the command loop. | |
2289 This can happen like so: | |
2290 | |
2291 - We are waiting in XtAppNextEvent() | |
2292 - Process generates output | |
2293 - Process is marked as being ready | |
2294 - Process dies, SIGCHLD gets generated before we return (!?) | |
2295 It could happen I guess. | |
2296 - sigchld_handler() marks process as dead | |
2297 - Somehow we end up getting a new KeyPress event on the queue | |
2298 at the same time (I'm really so sure how that happens but I'm | |
2299 not sure it can't either so let's assume it can...). | |
2300 - Key events have priority so we return that instead of the proc. | |
2301 - Before dispatching the lisp key event we call status_notify() | |
2302 - Which deselects the process that SIGCHLD marked as dead. | |
2303 | |
2304 Thus we never remove it from _with_input and turn it into a lisp | |
2305 event, so we need to do it here. But this does not mean that we're | |
2306 throwing away the last block of output - status_notify() has already | |
2307 taken care of running the proc filter or whatever. | |
2308 */ | |
2309 filedesc_with_input[fd] = Qnil; | |
2310 if (PROCESSP (closure->what)) | |
2311 { | |
2312 assert (process_events_occurred > 0); | |
2313 process_events_occurred--; | |
2314 } | |
2315 else | |
2316 { | |
2317 assert (tty_events_occurred > 0); | |
2318 tty_events_occurred--; | |
2319 } | |
2320 } | |
2321 XtRemoveInput (closure->id); | |
1726 | 2322 xfree (closure, struct what_is_ready_closure *); |
428 | 2323 filedesc_to_what_closure[fd] = 0; |
2324 } | |
2325 | |
2326 static void | |
853 | 2327 emacs_Xt_select_process (Lisp_Process *process, int doin, int doerr) |
428 | 2328 { |
853 | 2329 Lisp_Object proc; |
2330 int infd, errfd; | |
2331 | |
2332 event_stream_unixoid_select_process (process, doin, doerr, &infd, &errfd); | |
2333 | |
2334 proc = wrap_process (process); | |
2335 if (doin) | |
2336 select_filedesc (infd, proc); | |
2337 if (doerr) | |
2338 select_filedesc (errfd, proc); | |
2339 } | |
2340 | |
2341 static void | |
2342 emacs_Xt_unselect_process (Lisp_Process *process, int doin, int doerr) | |
2343 { | |
2344 int infd, errfd; | |
2345 | |
2346 event_stream_unixoid_unselect_process (process, doin, doerr, &infd, &errfd); | |
2347 | |
2348 if (doin) | |
2349 unselect_filedesc (infd); | |
2350 if (doerr) | |
2351 unselect_filedesc (errfd); | |
428 | 2352 } |
2353 | |
2354 static void | |
853 | 2355 emacs_Xt_create_io_streams (void *inhandle, void *outhandle, |
2356 void *errhandle, Lisp_Object *instream, | |
2357 Lisp_Object *outstream, | |
2358 Lisp_Object *errstream, | |
2359 USID *in_usid, | |
2360 USID *err_usid, | |
2361 int flags) | |
428 | 2362 { |
853 | 2363 event_stream_unixoid_create_io_streams |
2364 (inhandle, outhandle, errhandle, instream, outstream, | |
2365 errstream, in_usid, err_usid, flags); | |
2366 if (*in_usid != USID_ERROR) | |
2367 *in_usid = USID_DONTHASH; | |
2368 if (*err_usid != USID_ERROR) | |
2369 *err_usid = USID_DONTHASH; | |
428 | 2370 } |
2371 | |
853 | 2372 static void |
2373 emacs_Xt_delete_io_streams (Lisp_Object instream, | |
2374 Lisp_Object outstream, | |
2375 Lisp_Object errstream, | |
2376 USID *in_usid, | |
2377 USID *err_usid) | |
428 | 2378 { |
853 | 2379 event_stream_unixoid_delete_io_streams |
2380 (instream, outstream, errstream, in_usid, err_usid); | |
2381 *in_usid = USID_DONTHASH; | |
2382 *err_usid = USID_DONTHASH; | |
428 | 2383 } |
2384 | |
2385 /* This is called from GC when a process object is about to be freed. | |
2386 If we've still got pointers to it in this file, we're gonna lose hard. | |
2387 */ | |
2388 void | |
2286 | 2389 debug_process_finalization (Lisp_Process *UNUSED (p)) |
428 | 2390 { |
2391 #if 0 /* #### */ | |
2392 int i; | |
853 | 2393 Lisp_Object instr, outstr, errstr; |
2394 | |
2395 get_process_streams (p, &instr, &outstr, &errstr); | |
428 | 2396 /* if it still has fds, then it hasn't been killed yet. */ |
2397 assert (NILP(instr)); | |
2398 assert (NILP(outstr)); | |
853 | 2399 assert (NILP(errstr)); |
428 | 2400 /* Better not still be in the "with input" table; we know it's got no fds. */ |
2401 for (i = 0; i < MAXDESC; i++) | |
2402 { | |
2403 Lisp_Object process = filedesc_fds_with_input [i]; | |
2404 assert (!PROCESSP (process) || XPROCESS (process) != p); | |
2405 } | |
2406 #endif | |
2407 } | |
2408 | |
2409 static void | |
440 | 2410 Xt_process_to_emacs_event (Lisp_Event *emacs_event) |
428 | 2411 { |
2412 int i; | |
2413 | |
2414 assert (process_events_occurred > 0); | |
438 | 2415 |
428 | 2416 for (i = 0; i < MAXDESC; i++) |
2417 { | |
438 | 2418 Lisp_Object process = filedesc_with_input[i]; |
428 | 2419 if (PROCESSP (process)) |
438 | 2420 { |
2421 filedesc_with_input[i] = Qnil; | |
2422 process_events_occurred--; | |
2423 /* process events have nil as channel */ | |
934 | 2424 set_event_type (emacs_event, process_event); |
2425 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */ | |
1204 | 2426 SET_EVENT_PROCESS_PROCESS (emacs_event, process); |
438 | 2427 return; |
2428 } | |
428 | 2429 } |
2500 | 2430 ABORT (); |
428 | 2431 } |
2432 | |
2433 static void | |
2434 emacs_Xt_select_console (struct console *con) | |
2435 { | |
2436 Lisp_Object console; | |
2437 int infd; | |
2438 | |
2439 if (CONSOLE_X_P (con)) | |
2440 return; /* X consoles are automatically selected for when we | |
2441 initialize them in Xt */ | |
2442 infd = event_stream_unixoid_select_console (con); | |
793 | 2443 console = wrap_console (con); |
428 | 2444 select_filedesc (infd, console); |
2445 } | |
2446 | |
2447 static void | |
2448 emacs_Xt_unselect_console (struct console *con) | |
2449 { | |
2450 int infd; | |
2451 | |
2452 if (CONSOLE_X_P (con)) | |
2453 return; /* X consoles are automatically selected for when we | |
2454 initialize them in Xt */ | |
2455 infd = event_stream_unixoid_unselect_console (con); | |
2456 unselect_filedesc (infd); | |
2457 } | |
2458 | |
2459 /* read an event from a tty, if one is available. Returns non-zero | |
2460 if an event was available. Note that when this function is | |
2461 called, there should always be a tty marked as ready for input. | |
2462 However, the input condition might actually be EOF, so there | |
2463 may not really be any input available. (In this case, | |
2464 read_event_from_tty_or_stream_desc() will arrange for the TTY device | |
2465 to be deleted.) */ | |
2466 | |
2467 static int | |
440 | 2468 Xt_tty_to_emacs_event (Lisp_Event *emacs_event) |
428 | 2469 { |
2470 int i; | |
2471 | |
2472 assert (tty_events_occurred > 0); | |
2473 for (i = 0; i < MAXDESC; i++) | |
2474 { | |
2475 Lisp_Object console = filedesc_with_input[i]; | |
2476 if (CONSOLEP (console)) | |
2477 { | |
2478 assert (tty_events_occurred > 0); | |
2479 tty_events_occurred--; | |
2480 filedesc_with_input[i] = Qnil; | |
771 | 2481 if (read_event_from_tty_or_stream_desc (emacs_event, |
2482 XCONSOLE (console))) | |
428 | 2483 return 1; |
2484 } | |
2485 } | |
2486 | |
2487 return 0; | |
2488 } | |
2489 | |
2490 | |
2491 /************************************************************************/ | |
2492 /* debugging functions to decipher an event */ | |
2493 /************************************************************************/ | |
2494 | |
2495 #ifdef DEBUG_XEMACS | |
2496 #include "xintrinsicp.h" /* only describe_event() needs this */ | |
2497 #include <X11/Xproto.h> /* only describe_event() needs this */ | |
2498 | |
2499 static void | |
788 | 2500 describe_event_window (Window window, Display *display, Lisp_Object pstream) |
428 | 2501 { |
2502 struct frame *f; | |
2503 Widget w; | |
788 | 2504 write_fmt_string (pstream, " window: 0x%lx", (unsigned long) window); |
428 | 2505 w = XtWindowToWidget (display, window); |
2506 if (w) | |
788 | 2507 write_fmt_string (pstream, " %s", |
2508 w->core.widget_class->core_class.class_name); | |
428 | 2509 f = x_any_window_to_frame (get_device_from_display (display), window); |
2510 if (f) | |
788 | 2511 write_fmt_string_lisp (pstream, " \"%s\"", 1, f->name); |
2512 write_fmt_string (pstream, "\n"); | |
428 | 2513 } |
2514 | |
442 | 2515 static const char * |
428 | 2516 XEvent_mode_to_string (int mode) |
2517 { | |
2518 switch (mode) | |
2519 { | |
2520 case NotifyNormal: return "Normal"; | |
2521 case NotifyGrab: return "Grab"; | |
2522 case NotifyUngrab: return "Ungrab"; | |
2523 case NotifyWhileGrabbed: return "WhileGrabbed"; | |
2524 default: return "???"; | |
2525 } | |
2526 } | |
2527 | |
442 | 2528 static const char * |
428 | 2529 XEvent_detail_to_string (int detail) |
2530 { | |
2531 switch (detail) | |
2532 { | |
2533 case NotifyAncestor: return "Ancestor"; | |
2534 case NotifyInferior: return "Inferior"; | |
2535 case NotifyNonlinear: return "Nonlinear"; | |
2536 case NotifyNonlinearVirtual: return "NonlinearVirtual"; | |
2537 case NotifyPointer: return "Pointer"; | |
2538 case NotifyPointerRoot: return "PointerRoot"; | |
2539 case NotifyDetailNone: return "DetailNone"; | |
2540 default: return "???"; | |
2541 } | |
2542 } | |
2543 | |
442 | 2544 static const char * |
428 | 2545 XEvent_visibility_to_string (int state) |
2546 { | |
2547 switch (state) | |
2548 { | |
2549 case VisibilityFullyObscured: return "FullyObscured"; | |
2550 case VisibilityPartiallyObscured: return "PartiallyObscured"; | |
2551 case VisibilityUnobscured: return "Unobscured"; | |
2552 default: return "???"; | |
2553 } | |
2554 } | |
2555 | |
2556 static void | |
788 | 2557 describe_event (XEvent *event, Lisp_Object pstream) |
428 | 2558 { |
2559 char buf[100]; | |
2560 struct device *d = get_device_from_display (event->xany.display); | |
2561 | |
2562 sprintf (buf, "%s%s", x_event_name (event->type), | |
2563 event->xany.send_event ? " (send)" : ""); | |
788 | 2564 write_fmt_string (pstream, "%-30s", buf); |
428 | 2565 switch (event->type) |
2566 { | |
2567 case FocusIn: | |
2568 case FocusOut: | |
2569 { | |
2570 XFocusChangeEvent *ev = &event->xfocus; | |
788 | 2571 describe_event_window (ev->window, ev->display, pstream); |
2572 write_fmt_string (pstream, " mode: %s\n", | |
2573 XEvent_mode_to_string (ev->mode)); | |
2574 write_fmt_string (pstream, " detail: %s\n", | |
2575 XEvent_detail_to_string (ev->detail)); | |
428 | 2576 break; |
2577 } | |
2578 | |
2579 case KeyPress: | |
2580 { | |
2581 XKeyEvent *ev = &event->xkey; | |
2582 unsigned int state = ev->state; | |
2583 | |
788 | 2584 describe_event_window (ev->window, ev->display, pstream); |
2585 write_fmt_string (pstream, " subwindow: %ld\n", ev->subwindow); | |
2586 write_fmt_string (pstream, " state: "); | |
428 | 2587 /* Complete list of modifier key masks */ |
788 | 2588 if (state & ShiftMask) write_fmt_string (pstream, "Shift "); |
2589 if (state & LockMask) write_fmt_string (pstream, "Lock "); | |
2590 if (state & ControlMask) write_fmt_string (pstream, "Control "); | |
2591 if (state & Mod1Mask) write_fmt_string (pstream, "Mod1 "); | |
2592 if (state & Mod2Mask) write_fmt_string (pstream, "Mod2 "); | |
2593 if (state & Mod3Mask) write_fmt_string (pstream, "Mod3 "); | |
2594 if (state & Mod4Mask) write_fmt_string (pstream, "Mod4 "); | |
2595 if (state & Mod5Mask) write_fmt_string (pstream, "Mod5 "); | |
428 | 2596 |
2597 if (! state) | |
788 | 2598 write_fmt_string (pstream, "vanilla\n"); |
428 | 2599 else |
788 | 2600 write_fmt_string (pstream, "\n"); |
428 | 2601 if (x_key_is_modifier_p (ev->keycode, d)) |
788 | 2602 write_fmt_string (pstream, " Modifier key"); |
2603 write_fmt_string (pstream, " keycode: 0x%x\n", ev->keycode); | |
428 | 2604 } |
2605 break; | |
2606 | |
2607 case Expose: | |
442 | 2608 if (debug_x_events > 1) |
428 | 2609 { |
2610 XExposeEvent *ev = &event->xexpose; | |
788 | 2611 describe_event_window (ev->window, ev->display, pstream); |
2612 write_fmt_string (pstream, | |
2613 " region: x=%d y=%d width=%d height=%d\n", | |
428 | 2614 ev->x, ev->y, ev->width, ev->height); |
788 | 2615 write_fmt_string (pstream, " count: %d\n", ev->count); |
428 | 2616 } |
2617 else | |
788 | 2618 write_fmt_string (pstream, "\n"); |
428 | 2619 break; |
2620 | |
2621 case GraphicsExpose: | |
442 | 2622 if (debug_x_events > 1) |
428 | 2623 { |
2624 XGraphicsExposeEvent *ev = &event->xgraphicsexpose; | |
788 | 2625 describe_event_window (ev->drawable, ev->display, pstream); |
2626 write_fmt_string (pstream, " major: %s\n", | |
428 | 2627 (ev ->major_code == X_CopyArea ? "CopyArea" : |
2628 (ev->major_code == X_CopyPlane ? "CopyPlane" : "?"))); | |
788 | 2629 write_fmt_string (pstream, |
2630 " region: x=%d y=%d width=%d height=%d\n", | |
428 | 2631 ev->x, ev->y, ev->width, ev->height); |
788 | 2632 write_fmt_string (pstream, " count: %d\n", ev->count); |
428 | 2633 } |
2634 else | |
788 | 2635 write_fmt_string (pstream, "\n"); |
428 | 2636 break; |
2637 | |
2638 case EnterNotify: | |
2639 case LeaveNotify: | |
442 | 2640 if (debug_x_events > 1) |
428 | 2641 { |
2642 XCrossingEvent *ev = &event->xcrossing; | |
788 | 2643 describe_event_window (ev->window, ev->display, pstream); |
428 | 2644 #if 0 |
788 | 2645 write_fmt_string (pstream, " subwindow: 0x%x\n", ev->subwindow); |
2646 write_fmt_string (pstream, " pos: %d %d\n", ev->x, ev->y); | |
2647 write_fmt_string (pstream, " root pos: %d %d\n", ev->x_root, | |
2648 ev->y_root); | |
428 | 2649 #endif |
788 | 2650 write_fmt_string (pstream, " mode: %s\n", |
2651 XEvent_mode_to_string(ev->mode)); | |
2652 write_fmt_string (pstream, " detail: %s\n", | |
2653 XEvent_detail_to_string(ev->detail)); | |
2654 write_fmt_string (pstream, " focus: %d\n", ev->focus); | |
428 | 2655 #if 0 |
788 | 2656 write_fmt_string (pstream, " state: 0x%x\n", ev->state); |
428 | 2657 #endif |
2658 } | |
2659 else | |
788 | 2660 write_fmt_string (pstream, "\n"); |
428 | 2661 break; |
2662 | |
2663 case ConfigureNotify: | |
442 | 2664 if (debug_x_events > 1) |
428 | 2665 { |
2666 XConfigureEvent *ev = &event->xconfigure; | |
788 | 2667 describe_event_window (ev->window, ev->display, pstream); |
2668 write_fmt_string (pstream, " above: 0x%lx\n", ev->above); | |
2669 write_fmt_string (pstream, " size: %d %d %d %d\n", ev->x, ev->y, | |
428 | 2670 ev->width, ev->height); |
788 | 2671 write_fmt_string (pstream, " redirect: %d\n", |
2672 ev->override_redirect); | |
428 | 2673 } |
2674 else | |
788 | 2675 write_fmt_string (pstream, "\n"); |
428 | 2676 break; |
2677 | |
2678 case VisibilityNotify: | |
442 | 2679 if (debug_x_events > 1) |
428 | 2680 { |
2681 XVisibilityEvent *ev = &event->xvisibility; | |
788 | 2682 describe_event_window (ev->window, ev->display, pstream); |
2683 write_fmt_string (pstream, " state: %s\n", | |
2684 XEvent_visibility_to_string (ev->state)); | |
428 | 2685 } |
2686 else | |
788 | 2687 write_fmt_string (pstream, "\n"); |
428 | 2688 break; |
2689 | |
2690 case ClientMessage: | |
2691 { | |
2692 XClientMessageEvent *ev = &event->xclient; | |
2693 char *name = XGetAtomName (ev->display, ev->message_type); | |
788 | 2694 write_fmt_string (pstream, "%s", name); |
2695 if (!strcmp (name, "WM_PROTOCOLS")) | |
2696 { | |
2697 char *protname = XGetAtomName (ev->display, ev->data.l[0]); | |
2698 write_fmt_string (pstream, "(%s)", protname); | |
2699 XFree (protname); | |
2700 } | |
428 | 2701 XFree (name); |
788 | 2702 write_fmt_string (pstream, "\n"); |
428 | 2703 break; |
2704 } | |
2705 | |
2706 default: | |
788 | 2707 write_fmt_string (pstream, "\n"); |
428 | 2708 break; |
2709 } | |
2710 | |
2711 fflush (stdout); | |
2712 } | |
2713 | |
2714 #endif /* include describe_event definition */ | |
2715 | |
2716 | |
2717 /************************************************************************/ | |
2718 /* get the next event from Xt */ | |
2719 /************************************************************************/ | |
2720 | |
2721 /* This business exists because menu events "happen" when | |
2722 menubar_selection_callback() is called from somewhere deep | |
2723 within XtAppProcessEvent in emacs_Xt_next_event(). The | |
2724 callback needs to terminate the modal loop in that function | |
2725 or else it will continue waiting until another event is | |
2726 received. | |
2727 | |
2728 Same business applies to scrollbar events. */ | |
2729 | |
2730 void | |
2731 signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function, | |
2732 Lisp_Object object) | |
2733 { | |
2734 Lisp_Object event = Fmake_event (Qnil, Qnil); | |
2735 | |
934 | 2736 XSET_EVENT_TYPE (event, misc_user_event); |
2737 XSET_EVENT_CHANNEL (event, channel); | |
1204 | 2738 XSET_EVENT_MISC_USER_FUNCTION (event, function); |
2739 XSET_EVENT_MISC_USER_OBJECT (event, object); | |
2740 enqueue_dispatch_event (event); | |
428 | 2741 } |
2742 | |
2743 static void | |
440 | 2744 emacs_Xt_next_event (Lisp_Event *emacs_event) |
428 | 2745 { |
2746 we_didnt_get_an_event: | |
2747 | |
2748 while (NILP (dispatch_event_queue) && | |
2749 !completed_timeouts && | |
2750 !fake_event_occurred && | |
2751 !process_events_occurred && | |
2752 !tty_events_occurred) | |
2753 { | |
1268 | 2754 if (in_modal_loop) |
2755 { | |
2756 /* in_modal_loop gets set when we are in the process of | |
2757 dispatching an event (more specifically, when we are inside of | |
2758 a menu callback -- if we get here, it means we called a filter | |
2759 and the filter did something that tried to fetch an event, | |
2760 e.g. sit-for). In such a case, we cannot safely dispatch any | |
2761 more events. This is because those dispatching those events | |
2762 could cause lwlib to be entered reentranty, specifically if | |
2763 they are menu events. lwlib is not designed for this and will | |
2764 crash. We used to see this crash constantly as a result of | |
2765 QUIT checking, but QUIT will not now function in a modal loop. | |
2766 However, we can't just not process any events at all, because | |
2767 that will make sit-for etc. hang. So we go ahead and process | |
2768 the non-X kinds of events. */ | |
1292 | 2769 #ifdef WIN32_ANY |
2770 mswindows_is_blocking = 1; | |
2771 #endif | |
2772 XtAppProcessEvent (Xt_app_con, XtIMTimer | XtIMAlternateInput); | |
2773 #ifdef WIN32_ANY | |
2774 mswindows_is_blocking = 0; | |
2775 #endif | |
1268 | 2776 } |
428 | 2777 else |
2778 { | |
1268 | 2779 /* Stupid logic in XtAppProcessEvent() dictates that, if process |
2780 events and X events are both available, the process event gets | |
2781 taken first. This will cause an infinite loop if we're being | |
2782 called from Fdiscard_input(). | |
2783 */ | |
2784 | |
2785 if (XtAppPending (Xt_app_con) & XtIMXEvent) | |
2786 XtAppProcessEvent (Xt_app_con, XtIMXEvent); | |
2787 else | |
428 | 2788 { |
1268 | 2789 Lisp_Object devcons, concons; |
2790 | |
2791 /* We're about to block. Xt has a bug in it (big surprise, | |
2792 there) in that it blocks using select() and doesn't | |
2793 flush the Xlib output buffers (XNextEvent() does this | |
2794 automatically before blocking). So it's necessary | |
2795 for us to do this ourselves. If we don't do it, then | |
2796 display output may not be seen until the next time | |
2797 an X event is received. (This happens esp. with | |
2798 subprocess output that gets sent to a visible buffer.) | |
2799 | |
2800 #### The above comment may not have any validity. */ | |
2801 | |
2802 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
2803 { | |
2804 struct device *d; | |
2805 d = XDEVICE (XCAR (devcons)); | |
2806 | |
2807 if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) | |
2808 /* emacs may be exiting */ | |
2809 XFlush (DEVICE_X_DISPLAY (d)); | |
2810 } | |
1292 | 2811 #ifdef WIN32_ANY |
2812 mswindows_is_blocking = 1; | |
2813 #endif | |
1268 | 2814 XtAppProcessEvent (Xt_app_con, XtIMAll); |
1292 | 2815 #ifdef WIN32_ANY |
2816 mswindows_is_blocking = 0; | |
2817 #endif | |
428 | 2818 } |
2819 } | |
2820 } | |
2821 | |
2822 if (!NILP (dispatch_event_queue)) | |
2823 { | |
2824 Lisp_Object event, event2; | |
793 | 2825 event2 = wrap_event (emacs_event); |
1204 | 2826 event = dequeue_dispatch_event (); |
428 | 2827 Fcopy_event (event, event2); |
2828 Fdeallocate_event (event); | |
2829 } | |
2830 else if (tty_events_occurred) | |
2831 { | |
2832 if (!Xt_tty_to_emacs_event (emacs_event)) | |
2833 goto we_didnt_get_an_event; | |
2834 } | |
2835 else if (completed_timeouts) | |
2836 Xt_timeout_to_emacs_event (emacs_event); | |
2837 else if (fake_event_occurred) | |
2838 { | |
2839 /* A dummy event, so that a cycle of the command loop will occur. */ | |
2840 fake_event_occurred = 0; | |
2841 /* eval events have nil as channel */ | |
934 | 2842 set_event_type (emacs_event, eval_event); |
1204 | 2843 SET_EVENT_EVAL_FUNCTION (emacs_event, Qidentity); |
2844 SET_EVENT_EVAL_OBJECT (emacs_event, Qnil); | |
428 | 2845 } |
2846 else /* if (process_events_occurred) */ | |
2847 Xt_process_to_emacs_event (emacs_event); | |
2848 | |
2849 /* No need to call XFilterEvent; Xt does it for us */ | |
2850 } | |
2851 | |
2852 void | |
2286 | 2853 emacs_Xt_event_handler (Widget UNUSED (wid), |
2854 XtPointer UNUSED (closure), | |
428 | 2855 XEvent *event, |
2286 | 2856 Boolean *UNUSED (continue_to_dispatch)) |
428 | 2857 { |
2858 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | |
2859 | |
2860 #ifdef DEBUG_XEMACS | |
442 | 2861 if (debug_x_events > 0) |
788 | 2862 describe_event (event, Qexternal_debugging_output); |
428 | 2863 #endif /* DEBUG_XEMACS */ |
2864 if (x_event_to_emacs_event (event, XEVENT (emacs_event))) | |
1204 | 2865 enqueue_dispatch_event (emacs_event); |
428 | 2866 else |
2867 Fdeallocate_event (emacs_event); | |
2868 } | |
2869 | |
2870 | |
2871 /************************************************************************/ | |
1204 | 2872 /* input pending */ |
428 | 2873 /************************************************************************/ |
2874 | |
2875 static void | |
1204 | 2876 emacs_Xt_drain_queue (void) |
428 | 2877 { |
2878 Lisp_Object devcons, concons; | |
1268 | 2879 if (!in_modal_loop) |
428 | 2880 { |
1268 | 2881 CONSOLE_LOOP (concons) |
428 | 2882 { |
1268 | 2883 struct console *con = XCONSOLE (XCAR (concons)); |
2884 if (!con->input_enabled) | |
2885 continue; | |
2886 | |
2887 CONSOLE_DEVICE_LOOP (devcons, con) | |
1204 | 2888 { |
1268 | 2889 struct device *d; |
2890 Display *display; | |
2891 d = XDEVICE (XCAR (devcons)); | |
2892 if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) | |
2893 { | |
2894 display = DEVICE_X_DISPLAY (d); | |
2895 while (XEventsQueued (display, QueuedAfterReading)) | |
2896 XtAppProcessEvent (Xt_app_con, XtIMXEvent); | |
2897 } | |
1204 | 2898 } |
428 | 2899 } |
1268 | 2900 /* |
2901 while (XtAppPending (Xt_app_con) & XtIMXEvent) | |
2902 XtAppProcessEvent (Xt_app_con, XtIMXEvent); | |
2903 */ | |
428 | 2904 } |
1268 | 2905 |
2906 #ifdef HAVE_TTY | |
1204 | 2907 drain_tty_devices (); |
428 | 2908 #endif |
2909 } | |
2910 | |
1204 | 2911 int |
2912 check_if_pending_expose_event (struct device *dev) | |
2913 { | |
2914 Display *d = DEVICE_X_DISPLAY (dev); | |
2915 Lisp_Object event; | |
2916 | |
2917 emacs_Xt_drain_queue (); | |
2918 | |
2919 EVENT_CHAIN_LOOP (event, dispatch_event_queue) | |
2920 if (XEVENT_TYPE (event) == magic_event) | |
2921 { | |
2922 XEvent *xev = &XEVENT_MAGIC_X_EVENT (event); | |
2923 if (xev->type == Expose && | |
2924 xev->xexpose.display == d) | |
2925 return 1; | |
2926 } | |
2927 | |
2928 return 0; | |
2929 } | |
2930 | |
442 | 2931 static int |
2932 emacs_Xt_current_event_timestamp (struct console *c) | |
2933 { | |
2934 /* semi-yuck. */ | |
2935 Lisp_Object devs = CONSOLE_DEVICE_LIST (c); | |
2936 | |
2937 if (NILP (devs)) | |
2938 return 0; | |
2939 else | |
2940 { | |
2941 struct device *d = XDEVICE (XCAR (devs)); | |
2942 return DEVICE_X_LAST_SERVER_TIMESTAMP (d); | |
2943 } | |
2944 } | |
2945 | |
428 | 2946 |
2947 /************************************************************************/ | |
2948 /* replacement for standard string-to-pixel converter */ | |
2949 /************************************************************************/ | |
2950 | |
2951 /* This was constructed by ripping off the standard string-to-pixel | |
2952 converter from Converters.c in the Xt source code and modifying | |
2953 appropriately. */ | |
2954 | |
2955 #if 0 | |
2956 | |
2957 /* This is exported by the Xt library (at least by mine). If this | |
2958 isn't the case somewhere, rename this appropriately and remove | |
2959 the '#if 0'. Note, however, that I got "unknown structure" | |
2960 errors when I tried this. */ | |
2961 XtConvertArgRec Const colorConvertArgs[] = { | |
440 | 2962 { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), |
2963 sizeof (Screen *) }, | |
2964 { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), | |
2965 sizeof (Colormap) } | |
428 | 2966 }; |
2967 | |
2968 #endif | |
2969 | |
2970 #define done(type, value) \ | |
2971 if (toVal->addr != NULL) { \ | |
2972 if (toVal->size < sizeof(type)) { \ | |
2973 toVal->size = sizeof(type); \ | |
2974 return False; \ | |
2975 } \ | |
2976 *(type*)(toVal->addr) = (value); \ | |
2977 } else { \ | |
2978 static type static_val; \ | |
2979 static_val = (value); \ | |
2980 toVal->addr = (XPointer)&static_val; \ | |
2981 } \ | |
2982 toVal->size = sizeof(type); \ | |
2983 return True /* Caller supplies `;' */ | |
2984 | |
2985 /* JH: We use this because I think there's a possibility this | |
2986 is called before the device is properly set up, in which case | |
2987 I don't want to abort. */ | |
2988 extern struct device *get_device_from_display_1 (Display *dpy); | |
2989 | |
2990 static | |
2991 Boolean EmacsXtCvtStringToPixel ( | |
2992 Display *dpy, | |
2993 XrmValuePtr args, | |
2994 Cardinal *num_args, | |
2995 XrmValuePtr fromVal, | |
2996 XrmValuePtr toVal, | |
2997 XtPointer *closure_ret) | |
2998 { | |
2999 String str = (String)fromVal->addr; | |
3000 XColor screenColor; | |
3001 XColor exactColor; | |
3002 Screen *screen; | |
3003 Colormap colormap; | |
3004 Visual *visual; | |
3005 struct device *d; | |
3006 Status status; | |
3007 String params[1]; | |
3008 Cardinal num_params = 1; | |
3009 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy); | |
3010 | |
3011 if (*num_args != 2) { | |
3012 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToPixel", | |
3013 "XtToolkitError", | |
3014 "String to pixel conversion needs screen and colormap arguments", | |
3015 (String *)NULL, (Cardinal *)NULL); | |
3016 return False; | |
3017 } | |
3018 | |
3019 screen = *((Screen **) args[0].addr); | |
3020 colormap = *((Colormap *) args[1].addr); | |
3021 | |
3022 /* The original uses the private function CompareISOLatin1(). | |
3023 Use XmuCompareISOLatin1() if you want, but I don't think it | |
3024 makes any difference here. */ | |
3025 if (strcmp(str, XtDefaultBackground) == 0) { | |
3026 *closure_ret = False; | |
3027 /* This refers to the display's "*reverseVideo" resource. | |
3028 These display resources aren't documented anywhere that | |
3029 I can find, so I'm going to ignore this. */ | |
3030 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */ | |
3031 done(Pixel, WhitePixelOfScreen(screen)); | |
3032 } | |
3033 if (strcmp(str, XtDefaultForeground) == 0) { | |
3034 *closure_ret = False; | |
3035 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */ | |
3036 done(Pixel, BlackPixelOfScreen(screen)); | |
3037 } | |
3038 | |
3039 /* Originally called XAllocNamedColor() here. */ | |
3040 if ((d = get_device_from_display_1(dpy))) { | |
3041 visual = DEVICE_X_VISUAL(d); | |
3042 if (colormap != DEVICE_X_COLORMAP(d)) { | |
442 | 3043 XtAppWarningMsg(the_app_con, "weirdColormap", "cvtStringToPixel", |
428 | 3044 "XtToolkitWarning", |
442 | 3045 "The colormap passed to cvtStringToPixel doesn't match the one registered to the device.\n", |
428 | 3046 NULL, 0); |
3047 status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor); | |
3048 } else { | |
3049 status = XParseColor (dpy, colormap, (char*)str, &screenColor); | |
3050 if (status) { | |
3094 | 3051 status = x_allocate_nearest_color (dpy, colormap, visual, &screenColor); |
428 | 3052 } |
3053 } | |
3054 } else { | |
3055 /* We haven't set up this device totally yet, so just punt */ | |
3056 status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor); | |
3057 } | |
3058 if (status == 0) { | |
3059 params[0] = str; | |
3060 /* Server returns a specific error code but Xlib discards it. Ugh */ | |
3061 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*) str, | |
3062 &exactColor, &screenColor)) { | |
3063 XtAppWarningMsg(the_app_con, "noColormap", "cvtStringToPixel", | |
3064 "XtToolkitError", | |
3065 "Cannot allocate colormap entry for \"%s\"", | |
3066 params, &num_params); | |
3067 | |
3068 } else { | |
3069 XtAppWarningMsg(the_app_con, "badValue", "cvtStringToPixel", | |
3070 "XtToolkitError", | |
3071 "Color name \"%s\" is not defined", params, &num_params); | |
3072 } | |
3073 | |
3074 *closure_ret = False; | |
3075 return False; | |
3076 } else { | |
3077 *closure_ret = (char*)True; | |
3078 done(Pixel, screenColor.pixel); | |
3079 } | |
3080 } | |
3081 | |
3082 /* ARGSUSED */ | |
3083 static void EmacsFreePixel ( | |
3084 XtAppContext app, | |
3085 XrmValuePtr toVal, | |
3086 XtPointer closure, | |
3087 XrmValuePtr args, | |
3088 Cardinal *num_args) | |
3089 { | |
3090 if (*num_args != 2) { | |
3091 XtAppWarningMsg(app, "wrongParameters","freePixel","XtToolkitError", | |
3092 "Freeing a pixel requires screen and colormap arguments", | |
3093 (String *)NULL, (Cardinal *)NULL); | |
3094 return; | |
3095 } | |
3096 | |
3097 if (closure) { | |
3098 Screen *screen = *((Screen **) args[0].addr); | |
3099 Colormap colormap = *((Colormap *) args[1].addr); | |
3100 XFreeColors(DisplayOfScreen(screen), colormap, | |
3101 (unsigned long*)toVal->addr, 1, (unsigned long)0); | |
3102 } | |
3103 } | |
3104 | |
3105 | |
3106 /************************************************************************/ | |
442 | 3107 /* handle focus changes for native widgets */ |
3108 /************************************************************************/ | |
3109 static void | |
3110 emacs_Xt_event_widget_focus_in (Widget w, | |
3111 XEvent *event, | |
2286 | 3112 String *UNUSED (params), |
3113 Cardinal *UNUSED (num_params)) | |
442 | 3114 { |
853 | 3115 struct frame *f = |
442 | 3116 x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w); |
3117 | |
3118 XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w); | |
3119 } | |
3120 | |
3121 static void | |
2286 | 3122 emacs_Xt_event_widget_focus_out (Widget UNUSED (w), |
3123 XEvent *UNUSED (event), | |
3124 String *UNUSED (params), | |
3125 Cardinal *UNUSED (num_params)) | |
442 | 3126 { |
3127 } | |
3128 | |
3129 static XtActionsRec widgetActionsList[] = | |
3130 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
3131 { (String) "widget-focus-in", emacs_Xt_event_widget_focus_in }, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
3132 { (String) "widget-focus-out", emacs_Xt_event_widget_focus_out }, |
442 | 3133 }; |
3134 | |
3135 static void | |
3136 emacs_Xt_event_add_widget_actions (XtAppContext ctx) | |
3137 { | |
3138 XtAppAddActions (ctx, widgetActionsList, 2); | |
3139 } | |
3140 | |
3141 | |
3142 /************************************************************************/ | |
428 | 3143 /* initialization */ |
3144 /************************************************************************/ | |
3145 | |
3146 void | |
3147 syms_of_event_Xt (void) | |
3148 { | |
563 | 3149 DEFSYMBOL (Qsans_modifiers); |
3150 DEFSYMBOL (Qself_insert_command); | |
428 | 3151 } |
3152 | |
3153 void | |
3154 reinit_vars_of_event_Xt (void) | |
3155 { | |
1204 | 3156 Xt_event_stream = xnew_and_zero (struct event_stream); |
428 | 3157 Xt_event_stream->event_pending_p = emacs_Xt_event_pending_p; |
1204 | 3158 Xt_event_stream->force_event_pending_cb= emacs_Xt_force_event_pending; |
428 | 3159 Xt_event_stream->next_event_cb = emacs_Xt_next_event; |
3160 Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event; | |
788 | 3161 Xt_event_stream->format_magic_event_cb = emacs_Xt_format_magic_event; |
3162 Xt_event_stream->compare_magic_event_cb= emacs_Xt_compare_magic_event; | |
3163 Xt_event_stream->hash_magic_event_cb = emacs_Xt_hash_magic_event; | |
428 | 3164 Xt_event_stream->add_timeout_cb = emacs_Xt_add_timeout; |
3165 Xt_event_stream->remove_timeout_cb = emacs_Xt_remove_timeout; | |
3166 Xt_event_stream->select_console_cb = emacs_Xt_select_console; | |
3167 Xt_event_stream->unselect_console_cb = emacs_Xt_unselect_console; | |
3168 Xt_event_stream->select_process_cb = emacs_Xt_select_process; | |
3169 Xt_event_stream->unselect_process_cb = emacs_Xt_unselect_process; | |
1204 | 3170 Xt_event_stream->drain_queue_cb = emacs_Xt_drain_queue; |
853 | 3171 Xt_event_stream->create_io_streams_cb = emacs_Xt_create_io_streams; |
3172 Xt_event_stream->delete_io_streams_cb = emacs_Xt_delete_io_streams; | |
442 | 3173 Xt_event_stream->current_event_timestamp_cb = |
3174 emacs_Xt_current_event_timestamp; | |
428 | 3175 |
3176 the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype); | |
3177 | |
3178 last_quit_check_signal_tick_count = 0; | |
3179 | |
3180 /* this function only makes safe calls */ | |
3181 init_what_input_once (); | |
3182 } | |
3183 | |
3184 void | |
3185 vars_of_event_Xt (void) | |
3186 { | |
3187 DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /* | |
3188 *Non-nil means to allow synthetic events. Nil means they are ignored. | |
3189 Beware: allowing emacs to process SendEvents opens a big security hole. | |
3190 */ ); | |
3191 x_allow_sendevents = 0; | |
3192 | |
3193 #ifdef DEBUG_XEMACS | |
442 | 3194 DEFVAR_INT ("debug-x-events", &debug_x_events /* |
428 | 3195 If non-zero, display debug information about X events that XEmacs sees. |
3196 Information is displayed on stderr. Currently defined values are: | |
3197 | |
3198 1 == non-verbose output | |
3199 2 == verbose output | |
3200 */ ); | |
442 | 3201 debug_x_events = 0; |
428 | 3202 #endif |
3171 | 3203 DEFVAR_LISP ("x-us-keymap-description", &Vx_us_keymap_description /* |
3204 X11-specific vector describing the current keyboard hardware, and how to map | |
3205 from its keycodes to those alphanumeric and punctuation characters that | |
3206 would be produced by it if a US layout were configured in software. | |
3207 | |
3208 We use this to make possible the usage of standard key bindings on keyboards | |
3209 where the keys that those bindings assume are not available; for example, on | |
3210 a Russian keyboard, one can type C-Cyrillic_che C-Cyrillic_a and have XEmacs | |
3211 use the binding for C-x C-f, rather than give an error message that | |
3212 C-Cyrillic_che C-Cyrillic_a is not bound. | |
3213 | |
3214 Entries are either nil, which means the corresponding key code does not map | |
3215 to a non-function key in the US layout, a single character, meaning it maps to | |
3216 that character, or a vector of two characters, the first indicating the | |
3217 unshifted mapping, the second the shifted mapping for the US layout. | |
3218 | |
3219 `x-us-keymap-first-keycode' tells XEmacs the keycode of the first entry in | |
3220 this vector. | |
3221 */ ); | |
3222 Vx_us_keymap_description = Qnil; | |
3223 | |
3224 DEFVAR_INT ("x-us-keymap-first-keycode", &Vx_us_keymap_first_keycode /* | |
3225 The X11 keycode that the first entry in `x-us-keymap-description' | |
3226 corresponds to. See the documentation for that variable. | |
3227 | |
3228 The X11 documentation for XDisplayKeycodes says this can never be less than | |
3229 8, but XEmacs doesn't enforce any limitation on what you set it to. | |
3230 */ ); | |
3231 Vx_us_keymap_first_keycode = 0; | |
428 | 3232 } |
3233 | |
3234 /* This mess is a hack that patches the shell widget to treat visual inheritance | |
3235 the same as colormap and depth inheritance */ | |
3236 | |
3237 static XtInitProc orig_shell_init_proc; | |
3238 | |
2956 | 3239 static void ShellVisualPatch(Widget wanted, Widget new_, |
428 | 3240 ArgList args, Cardinal *num_args) |
3241 { | |
3242 Widget p; | |
2956 | 3243 ShellWidget w = (ShellWidget) new_; |
428 | 3244 |
3245 /* first, call the original setup */ | |
2956 | 3246 (*orig_shell_init_proc)(wanted, new_, args, num_args); |
428 | 3247 |
3248 /* if the visual isn't explicitly set, grab it from the nearest shell ancestor */ | |
3249 if (w->shell.visual == CopyFromParent) { | |
3250 p = XtParent(w); | |
3251 while (p && !XtIsShell(p)) p = XtParent(p); | |
3252 if (p) w->shell.visual = ((ShellWidget)p)->shell.visual; | |
3253 } | |
3254 } | |
3255 | |
3256 void | |
3257 init_event_Xt_late (void) /* called when already initialized */ | |
3258 { | |
3259 timeout_id_tick = 1; | |
3260 pending_timeouts = 0; | |
3261 completed_timeouts = 0; | |
3262 | |
3263 event_stream = Xt_event_stream; | |
3264 | |
3265 XtToolkitInitialize (); | |
3266 Xt_app_con = XtCreateApplicationContext (); | |
3267 XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources); | |
3268 | |
442 | 3269 /* In select-x.c */ |
428 | 3270 x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000); |
3271 XSetErrorHandler (x_error_handler); | |
3272 XSetIOErrorHandler (x_IO_error_handler); | |
3273 | |
442 | 3274 #ifndef WIN32_NATIVE |
428 | 3275 XtAppAddInput (Xt_app_con, signal_event_pipe[0], |
3276 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */), | |
3277 Xt_what_callback, 0); | |
3278 #endif | |
3279 | |
3280 XtAppSetTypeConverter (Xt_app_con, XtRString, XtRPixel, | |
3281 EmacsXtCvtStringToPixel, | |
3282 (XtConvertArgList) colorConvertArgs, | |
3283 2, XtCacheByDisplay, EmacsFreePixel); | |
3284 | |
3285 #ifdef XIM_XLIB | |
3286 XtAppSetTypeConverter (Xt_app_con, XtRString, XtRXimStyles, | |
3287 EmacsXtCvtStringToXIMStyles, | |
3288 NULL, 0, | |
3289 XtCacheByDisplay, EmacsFreeXIMStyles); | |
3290 #endif /* XIM_XLIB */ | |
442 | 3291 /* Add extra actions to native widgets to handle focus and friends. */ |
3292 emacs_Xt_event_add_widget_actions (Xt_app_con); | |
428 | 3293 |
3294 /* insert the visual inheritance patch/hack described above */ | |
3295 orig_shell_init_proc = shellClassRec.core_class.initialize; | |
3296 shellClassRec.core_class.initialize = ShellVisualPatch; | |
3297 | |
3298 } |