X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d337aad50b46c762b3bdf92e34ebc143a898c7a3..8030369ccb5c871d3ce11b96c220f318bc741ed8:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 6f314ae9d5..338fd65613 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA. */ #endif #ifdef USE_LUCID -extern int xlwmenu_window_p (Widget w, Window window); +extern int xlwmenu_window_p P_ ((Widget w, Window window)); extern void xlwmenu_redisplay P_ ((Widget)); #endif @@ -466,6 +466,16 @@ static void x_clear_cursor P_ ((struct window *)); static void frame_highlight P_ ((struct frame *)); static void frame_unhighlight P_ ((struct frame *)); static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); +static int x_focus_changed P_ ((int, + int, + struct x_display_info *, + struct frame *, + struct input_event *, + int)); +static int x_detect_focus_change P_ ((struct x_display_info *, + XEvent *, + struct input_event *, + int)); static void XTframe_rehighlight P_ ((struct frame *)); static void x_frame_rehighlight P_ ((struct x_display_info *)); static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); @@ -475,6 +485,8 @@ static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *, XRectangle *)); static void expose_frame P_ ((struct frame *, int, int, int, int)); static int expose_window_tree P_ ((struct window *, XRectangle *)); +static void expose_overlaps P_ ((struct window *, struct glyph_row *, + struct glyph_row *)); static int expose_window P_ ((struct window *, XRectangle *)); static void expose_area P_ ((struct window *, struct glyph_row *, XRectangle *, enum glyph_row_area)); @@ -6060,6 +6072,39 @@ x_phys_cursor_in_rect_p (w, r) } +/* Redraw those parts of glyphs rows during expose event handling that + overlap other rows. Redrawing of an exposed line writes over parts + of lines overlapping that exposed line; this function fixes that. + + W is the window being exposed. FIRST_OVERLAPPING_ROW is the first + row in W's current matrix that is exposed and overlaps other rows. + LAST_OVERLAPPING_ROW is the last such row. */ + +static void +expose_overlaps (w, first_overlapping_row, last_overlapping_row) + struct window *w; + struct glyph_row *first_overlapping_row; + struct glyph_row *last_overlapping_row; +{ + struct glyph_row *row; + + for (row = first_overlapping_row; row <= last_overlapping_row; ++row) + if (row->overlapping_p) + { + xassert (row->enabled_p && !row->mode_line_p); + + if (row->used[LEFT_MARGIN_AREA]) + x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA); + + if (row->used[TEXT_AREA]) + x_fix_overlapping_area (w, row, TEXT_AREA); + + if (row->used[RIGHT_MARGIN_AREA]) + x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); + } +} + + /* Redraw the part of window W intersection rectangle FR. Pixel coordinates in FR are frame-relative. Call this function with input blocked. Value is non-zero if the exposure overwrites @@ -6101,6 +6146,7 @@ expose_window (w, fr) int yb = window_text_bottom_y (w); struct glyph_row *row; int cursor_cleared_p; + struct glyph_row *first_overlapping_row, *last_overlapping_row; TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height)); @@ -6119,7 +6165,8 @@ expose_window (w, fr) else cursor_cleared_p = 0; - /* Find the first row intersecting the rectangle R. */ + /* Update lines intersecting rectangle R. */ + first_overlapping_row = last_overlapping_row = NULL; for (row = w->current_matrix->rows; row->enabled_p; ++row) @@ -6132,6 +6179,13 @@ expose_window (w, fr) || (r.y >= y0 && r.y < y1) || (r.y + r.height > y0 && r.y + r.height < y1)) { + if (row->overlapping_p) + { + if (first_overlapping_row == NULL) + first_overlapping_row = row; + last_overlapping_row = row; + } + if (expose_line (w, row, &r)) mouse_face_overwritten_p = 1; } @@ -6152,6 +6206,10 @@ expose_window (w, fr) if (!w->pseudo_window_p) { + /* Fix the display of overlapping rows. */ + if (first_overlapping_row) + expose_overlaps (w, first_overlapping_row, last_overlapping_row); + /* Draw border between windows. */ x_draw_vertical_border (w); @@ -6291,6 +6349,121 @@ x_new_focus_frame (dpyinfo, frame) x_frame_rehighlight (dpyinfo); } +/* Handle FocusIn and FocusOut state changes for FRAME. + If FRAME has focus and there exists more than one frame, puts + an FOCUS_IN_EVENT into BUFP. + Returns number of events inserted into BUFP. */ + +static int +x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) + int type; + int state; + struct x_display_info *dpyinfo; + struct frame *frame; + struct input_event *bufp; + int numchars; +{ + int nr_events = 0; + + if (type == FocusIn) + { + if (dpyinfo->x_focus_event_frame != frame) + { + x_new_focus_frame (dpyinfo, frame); + dpyinfo->x_focus_event_frame = frame; + + /* Don't stop displaying the initial startup message + for a switch-frame event we don't need. */ + if (numchars > 0 + && GC_NILP (Vterminal_frame) + && GC_CONSP (Vframe_list) + && !GC_NILP (XCDR (Vframe_list))) + { + bufp->kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->frame_or_window, frame); + bufp->arg = Qnil; + ++bufp; + numchars--; + ++nr_events; + } + } + + frame->output_data.x->focus_state |= state; + +#ifdef HAVE_X_I18N + if (FRAME_XIC (frame)) + XSetICFocus (FRAME_XIC (frame)); +#endif + } + else if (type == FocusOut) + { + frame->output_data.x->focus_state &= ~state; + + if (dpyinfo->x_focus_event_frame == frame) + { + dpyinfo->x_focus_event_frame = 0; + x_new_focus_frame (dpyinfo, 0); + } + +#ifdef HAVE_X_I18N + if (FRAME_XIC (frame)) + XUnsetICFocus (FRAME_XIC (frame)); +#endif + } + + return nr_events; +} + +/* The focus may have changed. Figure out if it is a real focus change, + by checking both FocusIn/Out and Enter/LeaveNotify events. + + Returns number of events inserted into BUFP. */ + +static int +x_detect_focus_change (dpyinfo, event, bufp, numchars) + struct x_display_info *dpyinfo; + XEvent *event; + struct input_event *bufp; + int numchars; +{ + struct frame *frame; + int nr_events = 0; + + frame = x_top_window_to_frame (dpyinfo, event->xany.window); + if (! frame) return nr_events; + + switch (event->type) + { + case EnterNotify: + case LeaveNotify: + if (event->xcrossing.detail != NotifyInferior + && event->xcrossing.focus + && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT)) + nr_events = x_focus_changed ((event->type == EnterNotify + ? FocusIn : FocusOut), + FOCUS_IMPLICIT, + dpyinfo, + frame, + bufp, + numchars); + break; + + case FocusIn: + case FocusOut: + nr_events = x_focus_changed (event->type, + (event->xfocus.detail == NotifyPointer + ? FOCUS_IMPLICIT : FOCUS_EXPLICIT), + dpyinfo, + frame, + bufp, + numchars); + break; + } + + return nr_events; +} + + /* Handle an event saying the mouse has moved out of an Emacs frame. */ void @@ -7144,7 +7317,7 @@ note_mouse_highlight (f, x, y) if (NILP (b)) b = make_number (0); if (NILP (e)) - e = make_number (XSTRING (object)->size - 1); + e = make_number (SCHARS (object) - 1); fast_find_string_pos (w, XINT (b), object, &dpyinfo->mouse_face_beg_col, &dpyinfo->mouse_face_beg_row, @@ -7242,7 +7415,7 @@ note_mouse_highlight (f, x, y) /* Try text properties. */ if (STRINGP (object) && charpos >= 0 - && charpos < XSTRING (object)->size) + && charpos < SCHARS (object)) { help = Fget_text_property (make_number (charpos), Qhelp_echo, object); @@ -8478,7 +8651,7 @@ x_scroll_bar_to_input_event (event, ievent) /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the scroll_bar structure. - CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */ + CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */ static void xm_scroll_callback (widget, client_data, call_data) @@ -8812,7 +8985,7 @@ x_create_toolkit_scroll_bar (f, bar) #endif /* !USE_MOTIF */ - /* Install an action hook that let's us detect when the user + /* Install an action hook that lets us detect when the user finishes interacting with a scroll bar. */ if (action_hook_id == 0) action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0); @@ -10751,15 +10924,16 @@ XTread_socket (sd, bufp, numchars, expected) goto OTHER; #endif - /* Here's a possible interpretation of the whole - FocusIn-EnterNotify FocusOut-LeaveNotify mess. If - you get a FocusIn event, you have to get a FocusOut - event before you relinquish the focus. If you - haven't received a FocusIn event, then a mere - LeaveNotify is enough to free you. */ - case EnterNotify: { + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); #if 0 @@ -10786,34 +10960,29 @@ XTread_socket (sd, bufp, numchars, expected) } case FocusIn: - f = x_any_window_to_frame (dpyinfo, event.xfocus.window); - if (event.xfocus.detail != NotifyPointer) - dpyinfo->x_focus_event_frame = f; - if (f) - { - x_new_focus_frame (dpyinfo, f); + { + int n; - /* Don't stop displaying the initial startup message - for a switch-frame event we don't need. */ - if (GC_NILP (Vterminal_frame) - && GC_CONSP (Vframe_list) - && !GC_NILP (XCDR (Vframe_list))) - { - bufp->kind = FOCUS_IN_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - ++bufp, ++count, --numchars; - } - } - -#ifdef HAVE_X_I18N - if (f && FRAME_XIC (f)) - XSetICFocus (FRAME_XIC (f)); -#endif + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + } goto OTHER; case LeaveNotify: + { + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + } + f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); if (f) { @@ -10841,32 +11010,19 @@ XTread_socket (sd, bufp, numchars, expected) bufp += n, count += n, numchars -= n; } -#if 0 - if (event.xcrossing.focus) - x_mouse_leave (dpyinfo); - else - { - if (f == dpyinfo->x_focus_event_frame) - dpyinfo->x_focus_event_frame = 0; - if (f == dpyinfo->x_focus_frame) - x_new_focus_frame (dpyinfo, 0); - } -#endif } goto OTHER; case FocusOut: - f = x_any_window_to_frame (dpyinfo, event.xfocus.window); - if (event.xfocus.detail != NotifyPointer - && f == dpyinfo->x_focus_event_frame) - dpyinfo->x_focus_event_frame = 0; - if (f && f == dpyinfo->x_focus_frame) - x_new_focus_frame (dpyinfo, 0); + { + int n; -#ifdef HAVE_X_I18N - if (f && FRAME_XIC (f)) - XUnsetICFocus (FRAME_XIC (f)); -#endif + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + } goto OTHER; @@ -11729,7 +11885,10 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) struct buffer *b = XBUFFER (w->buffer); if (EQ (b->cursor_type, Qt)) - new_cursor_type = FRAME_DESIRED_CURSOR (f); + { + new_cursor_type = FRAME_DESIRED_CURSOR (f); + new_cursor_width = FRAME_CURSOR_WIDTH (f); + } else new_cursor_type = x_specified_cursor_type (b->cursor_type, &new_cursor_width); @@ -11991,7 +12150,7 @@ x_error_catcher (display, error) XErrorEvent *error; { XGetErrorText (display, error->error_code, - XSTRING (x_error_message_string)->data, + SDATA (x_error_message_string), X_ERROR_MESSAGE_SIZE); } @@ -12015,7 +12174,7 @@ int x_catch_errors (dpy) Display *dpy; { - int count = specpdl_ptr - specpdl; + int count = SPECPDL_INDEX (); /* Make sure any errors from previous requests have been dealt with. */ XSync (dpy, False); @@ -12023,7 +12182,7 @@ x_catch_errors (dpy) record_unwind_protect (x_catch_errors_unwind, x_error_message_string); x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE); - XSTRING (x_error_message_string)->data[0] = 0; + SSET (x_error_message_string, 0, 0); return count; } @@ -12050,8 +12209,8 @@ x_check_errors (dpy, format) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - if (XSTRING (x_error_message_string)->data[0]) - error (format, XSTRING (x_error_message_string)->data); + if (SREF (x_error_message_string, 0)) + error (format, SDATA (x_error_message_string)); } /* Nonzero if we had any X protocol errors @@ -12064,7 +12223,7 @@ x_had_errors_p (dpy) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - return XSTRING (x_error_message_string)->data[0] != 0; + return SREF (x_error_message_string, 0) != 0; } /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ @@ -12073,7 +12232,7 @@ void x_clear_errors (dpy) Display *dpy; { - XSTRING (x_error_message_string)->data[0] = 0; + SSET (x_error_message_string, 0, 0); } /* Stop catching X protocol errors and let them make Emacs die. @@ -12373,7 +12532,7 @@ x_new_fontset (f, fontsetname) to do. */ return fontset_name (fontset); - result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data)); + result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); if (!STRINGP (result)) /* Can't load ASCII font. */ @@ -12385,7 +12544,7 @@ x_new_fontset (f, fontsetname) #ifdef HAVE_X_I18N if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea))) - xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data); + xic_set_xfontset (f, SDATA (fontset_ascii (fontset))); #endif return build_string (fontsetname); @@ -13985,7 +14144,7 @@ x_list_fonts (f, pattern, size, maxnames) XFontStruct *font; unsigned long value; - font = XLoadQueryFont (dpy, XSTRING (pattern)->data); + font = XLoadQueryFont (dpy, SDATA (pattern)); if (x_had_errors_p (dpy)) { /* This error is perhaps due to insufficient memory on X @@ -14028,7 +14187,7 @@ x_list_fonts (f, pattern, size, maxnames) { /* We try at least 10 fonts because XListFonts will return auto-scaled fonts at the head. */ - names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10), + names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10), &num_fonts); if (x_had_errors_p (dpy)) { @@ -14129,7 +14288,7 @@ x_list_fonts (f, pattern, size, maxnames) BLOCK_INPUT; count = x_catch_errors (dpy); thisinfo = XLoadQueryFont (dpy, - XSTRING (XCAR (tem))->data); + SDATA (XCAR (tem))); if (x_had_errors_p (dpy)) { /* This error is perhaps due to insufficient memory on X @@ -14309,9 +14468,9 @@ x_load_font (f, fontname, size) for (tail = font_names; CONSP (tail); tail = XCDR (tail)) if (dpyinfo->font_table[i].name && (!strcmp (dpyinfo->font_table[i].name, - XSTRING (XCAR (tail))->data) + SDATA (XCAR (tail))) || !strcmp (dpyinfo->font_table[i].full_name, - XSTRING (XCAR (tail))->data))) + SDATA (XCAR (tail))))) return (dpyinfo->font_table + i); } @@ -14329,7 +14488,7 @@ x_load_font (f, fontname, size) a bug of not finding a font even if the font surely exists and is loadable by XLoadQueryFont. */ if (size > 0 && !NILP (font_names)) - fontname = (char *) XSTRING (XCAR (font_names))->data; + fontname = (char *) SDATA (XCAR (font_names)); BLOCK_INPUT; count = x_catch_errors (FRAME_X_DISPLAY (f)); @@ -14578,10 +14737,10 @@ static int x_initialized; the screen number from the server number. */ static int same_x_server (name1, name2) - char *name1, *name2; + const char *name1, *name2; { int seen_colon = 0; - unsigned char *system_name = XSTRING (Vsystem_name)->data; + const unsigned char *system_name = SDATA (Vsystem_name); int system_name_length = strlen (system_name); int length_until_period = 0; @@ -14662,10 +14821,12 @@ x_term_init (display_name, xrm_option, resource_name) argv[argc++] = "-xrm"; argv[argc++] = xrm_option; } - dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data, + stop_polling (); + dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name), resource_name, EMACS_CLASS, emacs_options, XtNumber (emacs_options), &argc, argv); + start_polling (); #ifdef HAVE_X11XTR6 /* I think this is to compensate for XtSetLanguageProc. */ @@ -14677,7 +14838,7 @@ x_term_init (display_name, xrm_option, resource_name) #ifdef HAVE_X11R5 XSetLocaleModifiers (""); #endif - dpy = XOpenDisplay (XSTRING (display_name)->data); + dpy = XOpenDisplay (SDATA (display_name)); #endif /* not USE_X_TOOLKIT */ /* Detect failure. */ @@ -14699,8 +14860,8 @@ x_term_init (display_name, xrm_option, resource_name) for (share = x_display_list, tail = x_display_name_list; share; share = share->next, tail = XCDR (tail)) - if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data, - XSTRING (display_name)->data)) + if (same_x_server (SDATA (XCAR (XCAR (tail))), + SDATA (display_name))) break; if (share) dpyinfo->kboard = share->kboard; @@ -14746,11 +14907,11 @@ x_term_init (display_name, xrm_option, resource_name) #endif /* ! 0 */ dpyinfo->x_id_name - = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name)) - + STRING_BYTES (XSTRING (Vsystem_name)) + = (char *) xmalloc (SBYTES (Vinvocation_name) + + SBYTES (Vsystem_name) + 2); sprintf (dpyinfo->x_id_name, "%s@%s", - XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); + SDATA (Vinvocation_name), SDATA (Vsystem_name)); /* Figure out which modifier bits mean what. */ x_find_modifier_meanings (dpyinfo); @@ -14813,8 +14974,8 @@ x_term_init (display_name, xrm_option, resource_name) build_string ("PrivateColormap"), Qnil, Qnil); if (STRINGP (value) - && (!strcmp (XSTRING (value)->data, "true") - || !strcmp (XSTRING (value)->data, "on"))) + && (!strcmp (SDATA (value), "true") + || !strcmp (SDATA (value), "on"))) dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap); } } @@ -14974,8 +15135,8 @@ x_term_init (display_name, xrm_option, resource_name) build_string ("Synchronous"), Qnil, Qnil); if (STRINGP (value) - && (!strcmp (XSTRING (value)->data, "true") - || !strcmp (XSTRING (value)->data, "on"))) + && (!strcmp (SDATA (value), "true") + || !strcmp (SDATA (value), "on"))) XSynchronize (dpyinfo->display, True); }