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