X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/cc9e7d9176843a243ca4217229302c1b396dbb6e..7857982c9fdd085806380117936fec0f529894e8:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 743247771d..92b245f2b3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1,6 +1,6 @@ /* X Communication module for terminals which understand the X protocol. Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -249,6 +249,7 @@ static unsigned long ignore_next_mouse_click_timeout; /* Where the mouse was last time we reported a mouse event. */ static XRectangle last_mouse_glyph; +static FRAME_PTR last_mouse_glyph_frame; static Lisp_Object last_mouse_press_frame; /* The scroll bar in which the last X motion event occurred. @@ -321,11 +322,10 @@ static void x_set_window_size_1 P_ ((struct frame *, int, int, int)); static const XColor *x_color_cells P_ ((Display *, int *)); static void x_update_window_end P_ ((struct window *, int, int)); void x_delete_display P_ ((struct x_display_info *)); -static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, - unsigned)); + static int x_io_error_quitter P_ ((Display *)); -int x_catch_errors P_ ((Display *)); -void x_uncatch_errors P_ ((Display *, int)); +void x_catch_errors P_ ((Display *)); +void x_uncatch_errors P_ ((void)); void x_lower_frame P_ ((struct frame *)); void x_scroll_bar_clear P_ ((struct frame *)); int x_had_errors_p P_ ((Display *)); @@ -3463,7 +3463,7 @@ x_find_modifier_meanings (dpyinfo) /* Convert between the modifier bits X uses and the modifier bits Emacs uses. */ -static unsigned int +unsigned int x_x_to_emacs_modifiers (dpyinfo, state) struct x_display_info *dpyinfo; unsigned int state; @@ -3582,7 +3582,7 @@ construct_mouse_click (result, event, f) static XMotionEvent last_mouse_motion_event; static Lisp_Object last_mouse_motion_frame; -static void +static int note_mouse_movement (frame, event) FRAME_PTR frame; XMotionEvent *event; @@ -3591,25 +3591,36 @@ note_mouse_movement (frame, event) last_mouse_motion_event = *event; XSETFRAME (last_mouse_motion_frame, frame); + if (!FRAME_X_OUTPUT (frame)) + return 0; + if (event->window != FRAME_X_WINDOW (frame)) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, -1, -1); + last_mouse_glyph_frame = 0; + return 1; } + /* Has the mouse moved off the glyph it was on at the last sighting? */ - else if (event->x < last_mouse_glyph.x - || event->x >= last_mouse_glyph.x + last_mouse_glyph.width - || event->y < last_mouse_glyph.y - || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) + if (frame != last_mouse_glyph_frame + || event->x < last_mouse_glyph.x + || event->x >= last_mouse_glyph.x + last_mouse_glyph.width + || event->y < last_mouse_glyph.y + || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, event->x, event->y); /* Remember which glyph we're now on. */ remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph); + last_mouse_glyph_frame = frame; + return 1; } + + return 0; } @@ -3708,7 +3719,6 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) Window win, child; int win_x, win_y; int parent_x = 0, parent_y = 0; - int count; win = root; @@ -3716,7 +3726,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) structure is changing at the same time this function is running. So at least we must not crash from them. */ - count = x_catch_errors (FRAME_X_DISPLAY (*fp)); + x_catch_errors (FRAME_X_DISPLAY (*fp)); if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -3785,7 +3795,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) if (x_had_errors_p (FRAME_X_DISPLAY (*fp))) f1 = 0; - x_uncatch_errors (FRAME_X_DISPLAY (*fp), count); + x_uncatch_errors (); /* If not, is it one of our scroll bars? */ if (! f1) @@ -3816,6 +3826,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) the frame are divided into. */ remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph); + last_mouse_glyph_frame = f1; *bar_window = Qnil; *part = 0; @@ -5701,7 +5712,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) Display *d = event.xclient.display; /* Catch and ignore errors, in case window has been iconified by a window manager such as GWM. */ - int count = x_catch_errors (d); + x_catch_errors (d); XSetInputFocus (d, event.xclient.window, /* The ICCCM says this is the only valid choice. */ @@ -5710,7 +5721,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) /* This is needed to detect the error if there is an error. */ XSync (d, False); - x_uncatch_errors (d, count); + x_uncatch_errors (); } /* Not certain about handling scroll bars here */ #endif /* 0 */ @@ -6231,6 +6242,44 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) goto done_keysym; } + /* Keysyms directly mapped to supported Unicode characters. */ + if ((keysym >= 0x01000000 && keysym <= 0x010033ff) + || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + { + int code = keysym & 0xFFFF, charset_id, c1, c2; + + if (code < 0x80) + { + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + inev.ie.code = code; + } + else if (code < 0x100) + { + if (code < 0xA0) + charset_id = CHARSET_8_BIT_CONTROL; + else + charset_id = charset_latin_iso8859_1; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = MAKE_CHAR (charset_id, code, 0); + } + else + { + if (code < 0x2500) + charset_id = charset_mule_unicode_0100_24ff, + code -= 0x100; + else if (code < 0xE000) + charset_id = charset_mule_unicode_2500_33ff, + code -= 0x2500; + else + charset_id = charset_mule_unicode_e000_ffff, + code -= 0xE000; + c1 = (code / 96) + 32, c2 = (code % 96) + 32; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = MAKE_CHAR (charset_id, c1, c2); + } + goto done_keysym; + } + /* Now non-ASCII. */ if (HASH_TABLE_P (Vx_keysym_table) && (NATNUMP (c = Fgethash (make_number (keysym), @@ -6447,6 +6496,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) so update things that depend on mouse position. */ if (f && !f->output_data.x->hourglass_p) note_mouse_movement (f, &event.xmotion); +#ifdef USE_GTK + /* We may get an EnterNotify on the buttons in the toolbar. In that + case we moved out of any highlighted area and need to note this. */ + if (!f && last_mouse_glyph_frame) + note_mouse_movement (last_mouse_glyph_frame, &event); +#endif goto OTHER; case FocusIn: @@ -6474,6 +6529,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (any_help_event_p) do_help = -1; } +#ifdef USE_GTK + /* See comment in EnterNotify above */ + else if (last_mouse_glyph_frame) + note_mouse_movement (last_mouse_glyph_frame, &event); +#endif goto OTHER; case FocusOut: @@ -6483,8 +6543,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) case MotionNotify: { previous_help_echo_string = help_echo_string; - help_echo_string = help_echo_object = help_echo_window = Qnil; - help_echo_pos = -1; + help_echo_string = Qnil; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -6523,7 +6582,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) last_window=window; } - note_mouse_movement (f, &event.xmotion); + if (!note_mouse_movement (f, &event.xmotion)) + help_echo_string = previous_help_echo_string; } else { @@ -6632,6 +6692,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) int tool_bar_p = 0; bzero (&compose_status, sizeof (compose_status)); + last_mouse_glyph_frame = 0; if (dpyinfo->grabbed && last_mouse_frame @@ -7117,7 +7178,7 @@ x_draw_hollow_cursor (w, row) /* Set clipping, draw the rectangle, and reset clipping again. */ x_clip_to_row (w, row, TEXT_AREA, gc); - XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h); + XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1); XSetClipMask (dpy, gc, None); } @@ -7330,10 +7391,30 @@ x_bitmap_icon (f, file) /* Create the GNU bitmap and mask if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) { - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id - = x_create_bitmap_from_data (f, gnu_bits, - gnu_width, gnu_height); - x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + int rc = -1; + +#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) +#ifdef USE_GTK + if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + return 0; +#else + rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits); + if (rc != -1) + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; +#endif /* USE_GTK */ +#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ + + /* If all else fails, use the (black and white) xbm image. */ + if (rc == -1) + { + rc = x_create_bitmap_from_data (f, gnu_xbm_bits, + gnu_xbm_width, gnu_xbm_height); + if (rc == -1) + return 1; + + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; + x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + } } /* The first time we create the GNU bitmap and mask, @@ -7387,9 +7468,18 @@ x_text_icon (f, icon_name) #define X_ERROR_MESSAGE_SIZE 200 /* If non-nil, this should be a string. - It means catch X errors and store the error message in this string. */ + It means catch X errors and store the error message in this string. -static Lisp_Object x_error_message_string; + The reason we use a stack is that x_catch_error/x_uncatch_error can + be called from a signal handler. +*/ + +struct x_error_message_stack { + char string[X_ERROR_MESSAGE_SIZE]; + Display *dpy; + struct x_error_message_stack *prev; +}; +static struct x_error_message_stack *x_error_message; /* An X error handler which stores the error message in x_error_message_string. This is called from x_error_handler if @@ -7401,7 +7491,7 @@ x_error_catcher (display, error) XErrorEvent *error; { XGetErrorText (display, error->error_code, - SDATA (x_error_message_string), + x_error_message->string, X_ERROR_MESSAGE_SIZE); } @@ -7419,47 +7509,42 @@ x_error_catcher (display, error) Calling x_uncatch_errors resumes the normal error handling. */ void x_check_errors (); -static Lisp_Object x_catch_errors_unwind (); -int +void x_catch_errors (dpy) Display *dpy; { - int count = SPECPDL_INDEX (); + struct x_error_message_stack *data = xmalloc (sizeof (*data)); /* Make sure any errors from previous requests have been dealt with. */ XSync (dpy, False); - record_unwind_protect (x_catch_errors_unwind, - Fcons (make_save_value (dpy, 0), - x_error_message_string)); - - x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE); - SSET (x_error_message_string, 0, 0); - - return count; + data->dpy = dpy; + data->string[0] = 0; + data->prev = x_error_message; + x_error_message = data; } -/* Unbind the binding that we made to check for X errors. */ +/* Undo the last x_catch_errors call. + DPY should be the display that was passed to x_catch_errors. */ -static Lisp_Object -x_catch_errors_unwind (old_val) - Lisp_Object old_val; +void +x_uncatch_errors () { - Lisp_Object first = XCAR (old_val); - Display *dpy = XSAVE_VALUE (first)->pointer; + struct x_error_message_stack *tmp; /* The display may have been closed before this function is called. Check if it is still open before calling XSync. */ - if (x_display_info_for_display (dpy) != 0) + if (x_display_info_for_display (x_error_message->dpy) != 0) { BLOCK_INPUT; - XSync (dpy, False); + XSync (x_error_message->dpy, False); UNBLOCK_INPUT; } - x_error_message_string = XCDR (old_val); - return Qnil; + tmp = x_error_message; + x_error_message = x_error_message->prev; + xfree (tmp); } /* If any X protocol errors have arrived since the last call to @@ -7474,8 +7559,13 @@ x_check_errors (dpy, format) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - if (SREF (x_error_message_string, 0)) - error (format, SDATA (x_error_message_string)); + if (x_error_message->string[0]) + { + char string[X_ERROR_MESSAGE_SIZE]; + bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE); + x_uncatch_errors (); + error (format, string); + } } /* Nonzero if we had any X protocol errors @@ -7488,7 +7578,7 @@ x_had_errors_p (dpy) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - return SREF (x_error_message_string, 0) != 0; + return x_error_message->string[0] != 0; } /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ @@ -7497,20 +7587,24 @@ void x_clear_errors (dpy) Display *dpy; { - SSET (x_error_message_string, 0, 0); + x_error_message->string[0] = 0; } -/* Stop catching X protocol errors and let them make Emacs die. - DPY should be the display that was passed to x_catch_errors. - COUNT should be the value that was returned by - the corresponding call to x_catch_errors. */ +/* Close off all unclosed x_catch_errors calls. */ void -x_uncatch_errors (dpy, count) - Display *dpy; - int count; +x_fully_uncatch_errors () { - unbind_to (count, Qnil); + while (x_error_message) + x_uncatch_errors (); +} + +/* Nonzero if x_catch_errors has been done and not yet canceled. */ + +int +x_catching_errors () +{ + return x_error_message != 0; } #if 0 @@ -7569,7 +7663,6 @@ x_connection_closed (dpy, error_message) { struct x_display_info *dpyinfo = x_display_info_for_display (dpy); Lisp_Object frame, tail; - int count; error_msg = (char *) alloca (strlen (error_message) + 1); strcpy (error_msg, error_message); @@ -7579,7 +7672,7 @@ x_connection_closed (dpy, error_message) below. Otherwise, we might end up with printing ``can't find per display information'' in the recursive call instead of printing the original message here. */ - count = x_catch_errors (dpy); + x_catch_errors (dpy); /* We have to close the display to inform Xt that it doesn't exist anymore. If we don't, Xt will continue to wait for @@ -7647,7 +7740,7 @@ x_connection_closed (dpy, error_message) if (dpyinfo) x_delete_display (dpyinfo); - x_uncatch_errors (dpy, count); + x_uncatch_errors (); if (x_display_list == 0) { @@ -7679,7 +7772,7 @@ x_error_handler (display, error) Display *display; XErrorEvent *error; { - if (! NILP (x_error_message_string)) + if (x_error_message) x_error_catcher (display, error); else x_error_quitter (display, error); @@ -8063,7 +8156,6 @@ void x_calc_absolute_position (f) struct frame *f; { - int win_x = 0, win_y = 0; int flags = f->size_hint_flags; /* We have nothing to do if the current position @@ -9254,7 +9346,6 @@ x_list_fonts (f, pattern, size, maxnames) = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list; Display *dpy = dpyinfo->display; int try_XLoadQueryFont = 0; - int count; int allow_auto_scaled_font = 0; if (size < 0) @@ -9294,7 +9385,7 @@ x_list_fonts (f, pattern, size, maxnames) /* At first, put PATTERN in the cache. */ BLOCK_INPUT; - count = x_catch_errors (dpy); + x_catch_errors (dpy); if (try_XLoadQueryFont) { @@ -9375,7 +9466,7 @@ x_list_fonts (f, pattern, size, maxnames) } } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (names) @@ -9466,7 +9557,7 @@ x_list_fonts (f, pattern, size, maxnames) XFontStruct *thisinfo; BLOCK_INPUT; - count = x_catch_errors (dpy); + x_catch_errors (dpy); thisinfo = XLoadQueryFont (dpy, SDATA (XCAR (tem))); if (x_had_errors_p (dpy)) @@ -9476,7 +9567,7 @@ x_list_fonts (f, pattern, size, maxnames) thisinfo = NULL; x_clear_errors (dpy); } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (thisinfo) @@ -9632,7 +9723,6 @@ x_load_font (f, fontname, size) { struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); Lisp_Object font_names; - int count; /* Get a list of all the fonts that match this name. Once we have a list of matching fonts, we compare them against the fonts @@ -9671,7 +9761,7 @@ x_load_font (f, fontname, size) fontname = (char *) SDATA (XCAR (font_names)); BLOCK_INPUT; - count = x_catch_errors (FRAME_X_DISPLAY (f)); + x_catch_errors (FRAME_X_DISPLAY (f)); font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); if (x_had_errors_p (FRAME_X_DISPLAY (f))) { @@ -9680,7 +9770,7 @@ x_load_font (f, fontname, size) font = NULL; x_clear_errors (FRAME_X_DISPLAY (f)); } - x_uncatch_errors (FRAME_X_DISPLAY (f), count); + x_uncatch_errors (); UNBLOCK_INPUT; if (!font) return NULL; @@ -10453,7 +10543,6 @@ x_term_init (display_name, xrm_option, resource_name) Display *dpy = dpyinfo->display; XrmValue d, fr, to; Font font; - int count; d.addr = (XPointer)&dpy; d.size = sizeof (Display *); @@ -10461,12 +10550,12 @@ x_term_init (display_name, xrm_option, resource_name) fr.size = sizeof (XtDefaultFont); to.size = sizeof (Font *); to.addr = (XPointer)&font; - count = x_catch_errors (dpy); + x_catch_errors (dpy); if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) abort (); if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); - x_uncatch_errors (dpy, count); + x_uncatch_errors (); } #endif #endif @@ -10750,8 +10839,7 @@ x_initialize () void syms_of_xterm () { - staticpro (&x_error_message_string); - x_error_message_string = Qnil; + x_error_message = NULL; staticpro (&x_display_name_list); x_display_name_list = Qnil;