X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fevent-Xt.c;h=38b17814a19ea959248b163a7d577d7f4b737805;hb=f2025090f01da2850dd72008074d6b8dc33c0113;hp=e852322da261d8d7b543c391c03f437525b5bbdb;hpb=6883ee56ec887c2c48abe5b06b5e66aa74031910;p=chise%2Fxemacs-chise.git diff --git a/src/event-Xt.c b/src/event-Xt.c index e852322..38b1781 100644 --- a/src/event-Xt.c +++ b/src/event-Xt.c @@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA. */ #include "blocktype.h" #include "buffer.h" -#include "commands.h" #include "console.h" #include "console-tty.h" #include "events.h" @@ -79,6 +78,7 @@ Boston, MA 02111-1307, USA. */ #include "events-mod.h" static void enqueue_Xt_dispatch_event (Lisp_Object event); +static void handle_focus_event_1 (struct frame *f, int in_p); static struct event_stream *Xt_event_stream; @@ -181,7 +181,7 @@ x_reset_key_mapping (struct device *d) Display *display = DEVICE_X_DISPLAY (d); struct x_device *xd = DEVICE_X_DATA (d); KeySym *keysym, *keysym_end; - Lisp_Object hashtable; + Lisp_Object hash_table; int key_code_count, keysyms_per_code; if (xd->x_keysym_map) @@ -194,12 +194,12 @@ x_reset_key_mapping (struct device *d) XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count, &xd->x_keysym_map_keysyms_per_code); - hashtable = xd->x_keysym_map_hashtable; - if (HASHTABLEP (hashtable)) - Fclrhash (hashtable); + hash_table = xd->x_keysym_map_hash_table; + if (HASH_TABLEP (hash_table)) + Fclrhash (hash_table); else - xd->x_keysym_map_hashtable = hashtable = - make_lisp_hashtable (128, HASHTABLE_NONWEAK, HASHTABLE_EQUAL); + xd->x_keysym_map_hash_table = hash_table = + make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); for (keysym = xd->x_keysym_map, keysyms_per_code = xd->x_keysym_map_keysyms_per_code, @@ -217,8 +217,8 @@ x_reset_key_mapping (struct device *d) Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[0], 0); if (name) { - Fputhash (build_string (name), Qsans_modifiers, hashtable); - Fputhash (sym, Qsans_modifiers, hashtable); + Fputhash (build_string (name), Qsans_modifiers, hash_table); + Fputhash (sym, Qsans_modifiers, hash_table); } } @@ -229,10 +229,10 @@ x_reset_key_mapping (struct device *d) { char *name = XKeysymToString (keysym[j]); Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[j], 0); - if (name && NILP (Fgethash (sym, hashtable, Qnil))) + if (name && NILP (Fgethash (sym, hash_table, Qnil))) { - Fputhash (build_string (name), Qt, hashtable); - Fputhash (sym, Qt, hashtable); + Fputhash (build_string (name), Qt, hash_table); + Fputhash (sym, Qt, hash_table); } } } @@ -450,7 +450,7 @@ void x_init_modifier_mapping (struct device *d) { struct x_device *xd = DEVICE_X_DATA (d); - xd->x_keysym_map_hashtable = Qnil; + xd->x_keysym_map_hash_table = Qnil; xd->x_keysym_map = NULL; xd->x_modifier_keymap = NULL; x_reset_modifier_mapping (d); @@ -658,6 +658,9 @@ void emacs_Xt_mapping_action (Widget w, XEvent* event) { struct device *d = get_device_from_display (event->xany.display); + + if (DEVICE_X_BEING_DELETED (d)) + return; #if 0 /* nyet. Now this is handled by Xt. */ XRefreshKeyboardMapping (&event->xmapping); @@ -794,7 +797,8 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p) than passing in 0) to avoid crashes on German IRIX */ char dummy[256]; XLookupString (event, dummy, 200, &keysym, 0); - return x_keysym_to_emacs_keysym (keysym, simple_p); + return (IsModifierKey (keysym) || keysym == XK_Mode_switch ) + ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p); } #endif /* ! XIM_MOTIF */ @@ -804,7 +808,8 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p) len = XmImMbLookupString (XtWindowToWidget (event->display, event->window), event, bufptr, bufsiz, &keysym, &status); #else /* XIM_XLIB */ - len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status); + if (xic) + len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status); #endif /* HAVE_XIM */ #ifdef DEBUG_XEMACS @@ -843,7 +848,8 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p) { case XLookupKeySym: case XLookupBoth: - return x_keysym_to_emacs_keysym (keysym, simple_p); + return (IsModifierKey (keysym) || keysym == XK_Mode_switch ) + ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p); case XLookupChars: { @@ -921,6 +927,10 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) struct device *d = get_device_from_display (display); struct x_device *xd = DEVICE_X_DATA (d); + if (DEVICE_X_BEING_DELETED (d)) + /* #### Uh, is this 0 correct? */ + return 0; + set_last_server_timestamp (d, x_event); switch (x_event->type) @@ -983,20 +993,16 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) { Lisp_Object keysym; XKeyEvent *ev = &x_event->xkey; - KeyCode keycode = ev->keycode; - - if (x_key_is_modifier_p (keycode, d)) /* it's a modifier key */ - return 0; - /* This used to compute the frame from the given X window and store it here, but we really don't care about the frame. */ emacs_event->channel = DEVICE_CONSOLE (d); keysym = x_to_emacs_keysym (&x_event->xkey, 0); - /* If the emacs keysym is nil, then that means that the - X keysym was NoSymbol, which probably means that - we're in the midst of reading a Multi_key sequence, - or a "dead" key prefix, or XIM input. Ignore it. */ + /* If the emacs keysym is nil, then that means that the X + keysym was either a Modifier or NoSymbol, which + probably means that we're in the midst of reading a + Multi_key sequence, or a "dead" key prefix, or XIM + input. Ignore it. */ if (NILP (keysym)) return 0; @@ -1042,6 +1048,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) { XButtonEvent *ev = &x_event->xbutton; struct frame *frame = x_window_to_frame (d, ev->window); + if (! frame) return 0; /* not for us */ XSETFRAME (emacs_event->channel, frame); @@ -1054,7 +1061,11 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) emacs_event->event.button.button = ev->button; emacs_event->event.button.x = ev->x; emacs_event->event.button.y = ev->y; - + /* because we don't seem to get a FocusIn event for button clicks + when a widget-glyph is selected we will assume that we want the + focus if a button gets pressed. */ + if (x_event->type == ButtonPress) + handle_focus_event_1 (frame, 1); } } break; @@ -1131,7 +1142,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) emacs_event->timestamp = DEVICE_X_LAST_SERVER_TIMESTAMP (d); state=DndDragButtons(x_event); - + if (state & ShiftMask) modifiers |= MOD_SHIFT; if (state & ControlMask) modifiers |= MOD_CONTROL; if (state & xd->MetaMask) modifiers |= MOD_META; @@ -1178,7 +1189,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) l_type = Qdragdrop_MIME; l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ), make_string ((Bufbyte *)"8bit", 4), - make_ext_string ((Extbyte *)data, + make_ext_string ((Extbyte *)data, strlen((char *)data), FORMAT_CTEXT) ) ); break; @@ -1200,7 +1211,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) case DndLink: case DndExe: { - char *hurl = dnd_url_hexify_string (data, "file:"); + char *hurl = dnd_url_hexify_string ((char *) data, "file:"); l_dndlist = list1 ( make_string ((Bufbyte *)hurl, strlen (hurl)) ); @@ -1212,7 +1223,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) case DndURL: /* as it is a real URL it should already be escaped and escaping again will break them (cause % is unsave) */ - l_dndlist = list1 ( make_ext_string ((Extbyte *)data, + l_dndlist = list1 ( make_ext_string ((Extbyte *)data, strlen ((char *)data), FORMAT_FILENAME) ); l_type = Qdragdrop_URL; @@ -1300,6 +1311,9 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) static void handle_focus_event_1 (struct frame *f, int in_p) { +#if XtSpecificationRelease > 5 + Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f)); +#endif #ifdef HAVE_XIM XIM_focus_event (f, in_p); #endif /* HAVE_XIM */ @@ -1315,7 +1329,26 @@ handle_focus_event_1 (struct frame *f, int in_p) Actually, we half handle it: we handle it as far as changing the box cursor for redisplay, but we don't call any hooks or do any select-frame stuff until after the sit-for. - */ + + Unfortunately native widgets break the model because they grab + the keyboard focus and nothing sets it back again. I cannot find + any reasonable way to do this elsewhere so we assert here that + the keyboard focus is on the emacs text widget. Menus and dialogs + do this in their selection callback, but we don't want that since + a button having focus is legitimate. An edit field having focus + is mandatory. Weirdly you get a FocusOut event when you click in + a widget-glyph but you don't get a correspondng FocusIn when you + click in the frame. Why is this? */ + if (in_p +#if XtSpecificationRelease > 5 + && FRAME_X_TEXT_WIDGET (f) != focus_widget +#endif + ) + { + lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), + FRAME_X_TEXT_WIDGET (f)); + } + /* do the generic event-stream stuff. */ { Lisp_Object frm; Lisp_Object conser; @@ -1337,14 +1370,17 @@ void emacs_Xt_handle_focus_event (XEvent *event); void emacs_Xt_handle_focus_event (XEvent *event) { + struct device *d = get_device_from_display (event->xany.display); + struct frame *f; + + if (DEVICE_X_BEING_DELETED (d)) + return; + /* * It's curious that we're using x_any_window_to_frame() instead * of x_window_to_frame(). I don't know what the impact of this is. */ - - struct frame *f = - x_any_window_to_frame (get_device_from_display (event->xany.display), - event->xfocus.window); + f = x_any_window_to_frame (d, event->xfocus.window); if (!f) /* focus events are sometimes generated just before a frame is destroyed. */ @@ -1397,7 +1433,7 @@ handle_map_event (struct frame *f, XEvent *event) /* Bleagh!!!!!! Apparently some window managers (e.g. MWM) send synthetic MapNotify events when a window is first - created, EVENT IF IT'S CREATED ICONIFIED OR INVISIBLE. + created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE. Or something like that. We initially tried a different solution below, but that ran into a different window- manager bug. @@ -1511,7 +1547,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event) XEvent *event = &emacs_event->event.magic.underlying_x_event; struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event)); - if (!FRAME_LIVE_P (f)) + if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f)))) return; switch (event->type) @@ -1572,6 +1608,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event) case FocusIn: case FocusOut: + #ifdef EXTERNAL_WIDGET /* External widget lossage: Ben said: YUCK. The only way to make focus changes work properly is to @@ -1587,7 +1624,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event) handle_client_message (f, event); break; - case VisibilityNotify: /* window visiblity has changed */ + case VisibilityNotify: /* window visibility has changed */ if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f))) { FRAME_X_TOTALLY_VISIBLE_P (f) = @@ -1686,7 +1723,7 @@ emacs_Xt_remove_timeout (int id) struct Xt_timeout *timeout, *t2; timeout = NULL; - + /* Find the timeout on the list of pending ones, if it's still there. */ if (pending_timeouts) { @@ -1749,6 +1786,8 @@ Xt_timeout_to_emacs_event (struct Lisp_Event *emacs_event) /* timeout events have nil as channel */ emacs_event->timestamp = 0; /* #### wrong!! */ emacs_event->event.timeout.interval_id = timeout->id; + emacs_event->event.timeout.function = Qnil; + emacs_event->event.timeout.object = Qnil; Blocktype_free (the_Xt_timeout_blocktype, timeout); } @@ -2889,18 +2928,18 @@ vars_of_event_Xt (void) init_what_input_once (); Xt_event_stream = xnew (struct event_stream); - Xt_event_stream->event_pending_p = emacs_Xt_event_pending_p; - Xt_event_stream->next_event_cb = emacs_Xt_next_event; - Xt_event_stream->handle_magic_event_cb= emacs_Xt_handle_magic_event; - Xt_event_stream->add_timeout_cb = emacs_Xt_add_timeout; - Xt_event_stream->remove_timeout_cb = emacs_Xt_remove_timeout; - Xt_event_stream->select_console_cb = emacs_Xt_select_console; - Xt_event_stream->unselect_console_cb = emacs_Xt_unselect_console; - Xt_event_stream->select_process_cb = emacs_Xt_select_process; - Xt_event_stream->unselect_process_cb = emacs_Xt_unselect_process; - Xt_event_stream->quit_p_cb = emacs_Xt_quit_p; - Xt_event_stream->create_stream_pair_cb= emacs_Xt_create_stream_pair; - Xt_event_stream->delete_stream_pair_cb= emacs_Xt_delete_stream_pair; + Xt_event_stream->event_pending_p = emacs_Xt_event_pending_p; + Xt_event_stream->next_event_cb = emacs_Xt_next_event; + Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event; + Xt_event_stream->add_timeout_cb = emacs_Xt_add_timeout; + Xt_event_stream->remove_timeout_cb = emacs_Xt_remove_timeout; + Xt_event_stream->select_console_cb = emacs_Xt_select_console; + Xt_event_stream->unselect_console_cb = emacs_Xt_unselect_console; + Xt_event_stream->select_process_cb = emacs_Xt_select_process; + Xt_event_stream->unselect_process_cb = emacs_Xt_unselect_process; + Xt_event_stream->quit_p_cb = emacs_Xt_quit_p; + Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair; + Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair; DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /* *Non-nil makes modifier keys sticky.