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