X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/7583e2a0e23b20ecd29fa0e308e710bde4873ea4..b7e0ef72d0ac61b5d3ef06a3f565695c75ec2540:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 7505aa3936..26ad526762 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23,8 +23,6 @@ along with GNU Emacs. If not, see . */ #include #include -#ifdef HAVE_X_WINDOWS - #include "lisp.h" #include "blockinput.h" #include "syssignal.h" @@ -69,7 +67,6 @@ along with GNU Emacs. If not, see . */ #include "atimer.h" #include "keymap.h" #include "font.h" -#include "fontset.h" #include "xsettings.h" #include "xgselect.h" #include "sysselect.h" @@ -87,7 +84,7 @@ along with GNU Emacs. If not, see . */ #endif #endif -#ifdef USE_LUCID +#if defined (USE_LUCID) || defined (USE_MOTIF) #include "../lwlib/xlwmenu.h" #endif @@ -141,105 +138,32 @@ int use_xim = 1; int use_xim = 0; /* configure --without-xim */ #endif - - /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ -static int any_help_event_p; - -/* Last window where we saw the mouse. Used by mouse-autoselect-window. */ -static Lisp_Object last_window; +static bool any_help_event_p; /* This is a chain of structures for all the X displays currently in use. */ struct x_display_info *x_display_list; -/* This is a list of cons cells, each of the form (NAME - . FONT-LIST-CACHE), one for each element of x_display_list and in - the same order. NAME is the name of the frame. FONT-LIST-CACHE - records previous values returned by x-list-fonts. */ - -Lisp_Object x_display_name_list; - -/* This is a frame waiting to be auto-raised, within XTread_socket. */ - -static struct frame *pending_autoraise_frame; - -/* This is a frame waiting for an event matching mask, within XTread_socket. */ - -static struct { - struct frame *f; - int eventtype; -} pending_event_wait; - #ifdef USE_X_TOOLKIT + /* The application context for Xt use. */ XtAppContext Xt_app_con; static String Xt_default_resources[] = {0}; /* Non-zero means user is interacting with a toolkit scroll bar. */ +static bool toolkit_scroll_bar_interaction; -static int toolkit_scroll_bar_interaction; #endif /* USE_X_TOOLKIT */ /* Non-zero timeout value means ignore next mouse click if it arrives before that timeout elapses (i.e. as part of the same sequence of events resulting from clicking on a frame to select it). */ -static unsigned long ignore_next_mouse_click_timeout; - -/* Mouse movement. - - Formerly, we used PointerMotionHintMask (in standard_event_mask) - so that we would have to call XQueryPointer after each MotionNotify - event to ask for another such event. However, this made mouse tracking - slow, and there was a bug that made it eventually stop. - - Simply asking for MotionNotify all the time seems to work better. - - In order to avoid asking for motion events and then throwing most - of them away or busy-polling the server for mouse positions, we ask - the server for pointer motion hints. This means that we get only - one event per group of mouse movements. "Groups" are delimited by - other kinds of events (focus changes and button clicks, for - example), or by XQueryPointer calls; when one of these happens, we - get another MotionNotify event the next time the mouse moves. This - is at least as efficient as getting motion events when mouse - tracking is on, and I suspect only negligibly worse when tracking - is off. */ - -/* 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. - - If the last X motion event occurred in a scroll bar, we set this so - XTmouse_position can know whether to report a scroll bar motion or - an ordinary motion. - - If the last X motion event didn't occur in a scroll bar, we set - this to Qnil, to tell XTmouse_position to return an ordinary motion - event. */ - -static Lisp_Object last_mouse_scroll_bar; - -/* This is a hack. We would really prefer that XTmouse_position would - return the time associated with the position it returns, but there - doesn't seem to be any way to wrest the time-stamp from the server - along with the position query. So, we just keep track of the time - of the last movement we received, and return that in hopes that - it's somewhat accurate. */ - -static Time last_mouse_movement_time; - -/* Time for last user interaction as returned in X events. */ - -static Time last_user_time; +static Time ignore_next_mouse_click_timeout; /* Incremented by XTread_socket whenever it really tries to read events. */ @@ -289,22 +213,16 @@ enum xembed_message XEMBED_ACTIVATE_ACCELERATOR = 14 }; -/* Used in x_flush. */ - static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *); static void x_set_window_size_1 (struct frame *, int, int, int); static void x_raise_frame (struct frame *); static void x_lower_frame (struct frame *); static const XColor *x_color_cells (Display *, int *); -static void x_update_window_end (struct window *, int, int); - static int x_io_error_quitter (Display *); static struct terminal *x_create_terminal (struct x_display_info *); void x_delete_terminal (struct terminal *); static void x_update_end (struct frame *); static void XTframe_up_to_date (struct frame *); -static void XTset_terminal_modes (struct terminal *); -static void XTreset_terminal_modes (struct terminal *); static void x_clear_frame (struct frame *); static _Noreturn void x_ins_del_lines (struct frame *, int, int); static void frame_highlight (struct frame *); @@ -312,30 +230,29 @@ static void frame_unhighlight (struct frame *); static void x_new_focus_frame (struct x_display_info *, struct frame *); static void x_focus_changed (int, int, struct x_display_info *, struct frame *, struct input_event *); -static void x_detect_focus_change (struct x_display_info *, - XEvent *, struct input_event *); static void XTframe_rehighlight (struct frame *); static void x_frame_rehighlight (struct x_display_info *); static void x_draw_hollow_cursor (struct window *, struct glyph_row *); static void x_draw_bar_cursor (struct window *, struct glyph_row *, int, enum text_cursor_kinds); -static void x_clip_to_row (struct window *, struct glyph_row *, int, GC); +static void x_clip_to_row (struct window *, struct glyph_row *, + enum glyph_row_area, GC); static void x_flush (struct frame *f); static void x_update_begin (struct frame *); static void x_update_window_begin (struct window *); -static void x_after_update_window_line (struct glyph_row *); static struct scroll_bar *x_window_to_scroll_bar (Display *, Window); static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, enum scroll_bar_part *, Lisp_Object *, Lisp_Object *, Time *); -static int x_handle_net_wm_state (struct frame *, XPropertyEvent *); +static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *); static void x_check_fullscreen (struct frame *); static void x_check_expected_move (struct frame *, int, int); static void x_sync_with_move (struct frame *, int, int, int); -static int handle_one_xevent (struct x_display_info *, XEvent *, - int *, struct input_event *); +static int handle_one_xevent (struct x_display_info *, + const XEvent *, int *, + struct input_event *); #ifdef USE_GTK static int x_dispatch_event (XEvent *, Display *); #endif @@ -347,26 +264,19 @@ static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t); static void x_initialize (void); -/* Flush display of frame F, or of all frames if F is null. */ +/* Flush display of frame F. */ static void x_flush (struct frame *f) { + eassert (f && FRAME_X_P (f)); /* Don't call XFlush when it is not safe to redisplay; the X connection may be broken. */ if (!NILP (Vinhibit_redisplay)) return; block_input (); - if (f == NULL) - { - Lisp_Object rest, frame; - FOR_EACH_FRAME (rest, frame) - if (FRAME_X_P (XFRAME (frame))) - x_flush (XFRAME (frame)); - } - else if (FRAME_X_P (f)) - XFlush (FRAME_X_DISPLAY (f)); + XFlush (FRAME_X_DISPLAY (f)); unblock_input (); } @@ -436,7 +346,7 @@ x_find_topmost_parent (struct frame *f) Window win = None, wi = x->parent_desc; Display *dpy = FRAME_X_DISPLAY (f); - while (wi != FRAME_X_DISPLAY_INFO (f)->root_window) + while (wi != FRAME_DISPLAY_INFO (f)->root_window) { Window root; Window *children; @@ -455,7 +365,7 @@ x_find_topmost_parent (struct frame *f) void x_set_frame_alpha (struct frame *f) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Display *dpy = FRAME_X_DISPLAY (f); Window win = FRAME_OUTER_WINDOW (f); double alpha = 1.0; @@ -555,9 +465,7 @@ x_update_begin (struct frame *f) } -/* Start update of window W. Set the global variable updated_window - to the window being updated and set output_cursor to the cursor - position of W. */ +/* Start update of window W. */ static void x_update_window_begin (struct window *w) @@ -565,8 +473,7 @@ x_update_window_begin (struct window *w) struct frame *f = XFRAME (WINDOW_FRAME (w)); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - updated_window = w; - set_output_cursor (&w->cursor); + w->output_cursor = w->cursor; block_input (); @@ -602,7 +509,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1) f->output_data.x->normal_gc, x, y0, x, y1); } -/* End update of window W (which is equal to updated_window). +/* End update of window W. Draw vertical borders between horizontally adjacent windows, and display W's cursor if CURSOR_ON_P is non-zero. @@ -616,18 +523,17 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1) here. */ static void -x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p) +x_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); - if (!w->pseudo_window_p) { block_input (); if (cursor_on_p) - display_and_set_cursor (w, 1, output_cursor.hpos, - output_cursor.vpos, - output_cursor.x, output_cursor.y); + display_and_set_cursor (w, 1, + w->output_cursor.hpos, w->output_cursor.vpos, + w->output_cursor.x, w->output_cursor.y); if (draw_window_fringes (w, 1)) x_draw_vertical_border (w); @@ -638,13 +544,7 @@ x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritt /* If a row with mouse-face was overwritten, arrange for XTframe_up_to_date to redisplay the mouse highlight. */ if (mouse_face_overwritten_p) - { - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - } - - updated_window = NULL; + reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame))); } @@ -665,9 +565,8 @@ x_update_end (struct frame *f) } -/* This function is called from various places in xdisp.c whenever a - complete update has been performed. The global variable - updated_window is not available here. */ +/* This function is called from various places in xdisp.c + whenever a complete update has been performed. */ static void XTframe_up_to_date (struct frame *f) @@ -679,15 +578,13 @@ XTframe_up_to_date (struct frame *f) /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay arrow bitmaps, or clear the fringes if no bitmaps are required - before DESIRED_ROW is made current. The window being updated is - found in updated_window. This function It is called from + before DESIRED_ROW is made current. This function is called from update_window_line only if it is known that there are differences between bitmaps to be drawn between current row and DESIRED_ROW. */ static void -x_after_update_window_line (struct glyph_row *desired_row) +x_after_update_window_line (struct window *w, struct glyph_row *desired_row) { - struct window *w = updated_window; struct frame *f; int width, height; @@ -698,7 +595,7 @@ x_after_update_window_line (struct glyph_row *desired_row) /* When a window has disappeared, make sure that no rest of full-width rows stays visible in the internal border. Could - check here if updated_window is the leftmost/rightmost window, + check here if updated window is the leftmost/rightmost window, but I guess it's not worth doing since vertically split windows are almost never used, internal border is rarely set, and the overhead is very small. */ @@ -714,10 +611,10 @@ x_after_update_window_line (struct glyph_row *desired_row) block_input (); x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - 0, y, width, height, False); + 0, y, width, height); x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_PIXEL_WIDTH (f) - width, - y, width, height, False); + y, width, height); unblock_input (); } } @@ -732,7 +629,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring struct face *face = p->face; /* Must clip because of partially visible lines. */ - x_clip_to_row (w, row, -1, gc); + x_clip_to_row (w, row, ANY_AREA, gc); if (!p->overlay_p) { @@ -825,7 +722,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring if (p->overlay_p) { clipmask = XCreatePixmapFromBitmapData (display, - FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_DISPLAY_INFO (f)->root_window, bits, p->wd, p->h, 1, 0, 1); gcv.clip_mask = clipmask; @@ -849,27 +746,6 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring XSetClipMask (display, gc, None); } - - -/* This is called when starting Emacs and when restarting after - suspend. When starting Emacs, no X window is mapped. And nothing - must be done to Emacs's own window if it is suspended (though that - rarely happens). */ - -static void -XTset_terminal_modes (struct terminal *terminal) -{ -} - -/* This is called when exiting or suspending Emacs. Exiting will make - the X-windows go away, and suspending requires no action. */ - -static void -XTreset_terminal_modes (struct terminal *terminal) -{ -} - - /*********************************************************************** Glyph display ***********************************************************************/ @@ -878,8 +754,6 @@ XTreset_terminal_modes (struct terminal *terminal) static void x_set_glyph_string_clipping (struct glyph_string *); static void x_set_glyph_string_gc (struct glyph_string *); -static void x_draw_glyph_string_background (struct glyph_string *, - int); static void x_draw_glyph_string_foreground (struct glyph_string *); static void x_draw_composite_glyph_string_foreground (struct glyph_string *); static void x_draw_glyph_string_box (struct glyph_string *); @@ -952,14 +826,14 @@ x_set_cursor_gc (struct glyph_string *s) xgcv.graphics_exposures = False; mask = GCForeground | GCBackground | GCGraphicsExposures; - if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) - XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, + if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc) + XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc, mask, &xgcv); else - FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc + FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc = XCreateGC (s->display, s->window, mask, &xgcv); - s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc; + s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; } } @@ -999,14 +873,14 @@ x_set_mouse_face_gc (struct glyph_string *s) xgcv.graphics_exposures = False; mask = GCForeground | GCBackground | GCGraphicsExposures; - if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) - XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, + if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc) + XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc, mask, &xgcv); else - FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc + FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc = XCreateGC (s->display, s->window, mask, &xgcv); - s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc; + s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc; } eassert (s->gc != 0); @@ -1164,7 +1038,7 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) contains the first component of a composition. */ static void -x_draw_glyph_string_background (struct glyph_string *s, int force_p) +x_draw_glyph_string_background (struct glyph_string *s, bool force_p) { /* Nothing to do if background has already been drawn or if it shouldn't be drawn in the first place. */ @@ -1377,7 +1251,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) } else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE) { - sprintf ((char *) buf, "%0*X", + sprintf (buf, "%0*X", glyph->u.glyphless.ch < 0x10000 ? 4 : 6, glyph->u.glyphless.ch); str = buf; @@ -1414,11 +1288,6 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) #ifdef USE_X_TOOLKIT -static Boolean cvt_string_to_pixel (Display *, XrmValue *, Cardinal *, - XrmValue *, XrmValue *, XtPointer *); -static void cvt_pixel_dtor (XtAppContext, XrmValue *, XtPointer, - XrmValue *, Cardinal *); - #ifdef USE_LUCID /* Return the frame on which widget WIDGET is used.. Abort if frame @@ -1447,7 +1316,7 @@ x_frame_of_widget (Widget widget) f = XFRAME (frame); if (FRAME_X_P (f) && f->output_data.nothing != 1 - && FRAME_X_DISPLAY_INFO (f) == dpyinfo + && FRAME_DISPLAY_INFO (f) == dpyinfo && f->output_data.x->widget == widget) return f; } @@ -1656,7 +1525,7 @@ x_color_cells (Display *dpy, int *ncells) void x_query_colors (struct frame *f, XColor *colors, int ncolors) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); if (dpyinfo->color_cells) { @@ -1896,7 +1765,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int unsigned long pixel; unsigned long background = di->relief_background; Colormap cmap = FRAME_X_COLORMAP (f); - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Display *dpy = FRAME_X_DISPLAY (f); xgcv.graphics_exposures = False; @@ -2648,7 +2517,10 @@ x_draw_underwave (struct glyph_string *s) /* Find and set clipping rectangle */ - wave_clip = (XRectangle){ x0, y0, width, wave_height }; + wave_clip.x = x0; + wave_clip.y = y0; + wave_clip.width = width; + wave_clip.height = wave_height; get_glyph_string_clip_rect (s, &string_clip); if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) @@ -2689,7 +2561,7 @@ x_draw_underwave (struct glyph_string *s) static void x_draw_glyph_string (struct glyph_string *s) { - int relief_drawn_p = 0; + bool relief_drawn_p = 0; /* If S draws into the background of its successors, draw the background of the successors first so that S can draw into it. @@ -2988,10 +2860,10 @@ x_delete_glyphs (struct frame *f, register int n) If they are <= 0, this is probably an error. */ void -x_clear_area (Display *dpy, Window window, int x, int y, int width, int height, int exposures) +x_clear_area (Display *dpy, Window window, int x, int y, int width, int height) { eassert (width > 0 && height > 0); - XClearArea (dpy, window, x, y, width, height, exposures); + XClearArea (dpy, window, x, y, width, height, False); } @@ -3003,11 +2875,7 @@ x_clear_frame (struct frame *f) /* Clearing the frame will erase any cursor, so mark them all as no longer visible. */ mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); - output_cursor.hpos = output_cursor.vpos = 0; - output_cursor.x = -1; - /* We don't set the output cursor here because there will always - follow an explicit cursor_to. */ block_input (); XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); @@ -3087,26 +2955,7 @@ XTflash (struct frame *f) /* These will be the left and right margins of the rectangles. */ int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); - - int width; - - /* Don't flash the area between a scroll bar and the frame - edge it is next to. */ - switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f)) - { - case vertical_scroll_bar_left: - flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM; - break; - - case vertical_scroll_bar_right: - flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM; - break; - - default: - break; - } - - width = flash_right - flash_left; + int width = flash_right - flash_left; /* If window is tall, flash top and bottom line. */ if (height > 3 * FRAME_LINE_HEIGHT (f)) @@ -3132,22 +2981,22 @@ XTflash (struct frame *f) x_flush (f); { - EMACS_TIME delay = make_emacs_time (0, 150 * 1000 * 1000); - EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), delay); + struct timespec delay = make_timespec (0, 150 * 1000 * 1000); + struct timespec wakeup = timespec_add (current_timespec (), delay); /* Keep waiting until past the time wakeup or any input gets available. */ while (! detect_input_pending ()) { - EMACS_TIME current = current_emacs_time (); - EMACS_TIME timeout; + struct timespec current = current_timespec (); + struct timespec timeout; /* Break if result would not be positive. */ - if (EMACS_TIME_LE (wakeup, current)) + if (timespec_cmp (wakeup, current) <= 0) break; /* How long `select' should wait. */ - timeout = make_emacs_time (0, 10 * 1000 * 1000); + timeout = make_timespec (0, 10 * 1000 * 1000); /* Try to wait that long--but we might wake up sooner. */ pselect (0, NULL, NULL, NULL, &timeout, NULL); @@ -3193,14 +3042,14 @@ XTflash (struct frame *f) static void -XTtoggle_invisible_pointer (FRAME_PTR f, int invisible) +XTtoggle_invisible_pointer (struct frame *f, int invisible) { block_input (); if (invisible) { - if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0) + if (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0) XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_X_DISPLAY_INFO (f)->invisible_cursor); + FRAME_DISPLAY_INFO (f)->invisible_cursor); } else XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), @@ -3233,20 +3082,6 @@ XTring_bell (struct frame *f) } } - -/* Specify how many text lines, from the top of the window, - should be affected by insert-lines and delete-lines operations. - This, and those operations, are used only within an update - that is bounded by calls to x_update_begin and x_update_end. */ - -static void -XTset_terminal_window (struct frame *f, int n) -{ - /* This function intentionally left blank. */ -} - - - /*********************************************************************** Line Dance ***********************************************************************/ @@ -3272,7 +3107,7 @@ x_scroll_run (struct window *w, struct run *run) /* Get frame-relative bounding box of the text display area of W, without mode lines. Include in this box the left and right fringe of W. */ - window_box (w, -1, &x, &y, &width, &height); + window_box (w, ANY_AREA, &x, &y, &width, &height); #ifdef USE_TOOLKIT_SCROLL_BARS /* If the fringe is adjacent to the left (right) scroll bar of a @@ -3328,7 +3163,6 @@ x_scroll_run (struct window *w, struct run *run) block_input (); /* Cursor off. Will be switched on again in x_update_window_end. */ - updated_window = w; x_clear_cursor (w); XCopyArea (FRAME_X_DISPLAY (f), @@ -3408,9 +3242,9 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame) x_lower_frame (old_focus); if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) - pending_autoraise_frame = dpyinfo->x_focus_frame; + dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame; else - pending_autoraise_frame = 0; + dpyinfo->x_pending_autoraise_frame = NULL; } x_frame_rehighlight (dpyinfo); @@ -3433,13 +3267,12 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra /* Don't stop displaying the initial startup message for a switch-frame event we don't need. */ /* When run as a daemon, Vterminal_frame is always NIL. */ - if ((NILP (Vterminal_frame) || EQ (Fdaemonp(), Qt)) - && CONSP (Vframe_list) - && !NILP (XCDR (Vframe_list))) - { - bufp->kind = FOCUS_IN_EVENT; - XSETFRAME (bufp->frame_or_window, frame); - } + bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt)) + && CONSP (Vframe_list) + && !NILP (XCDR (Vframe_list))) + ? Qt : Qnil); + bufp->kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->frame_or_window, frame); } frame->output_data.x->focus_state |= state; @@ -3457,6 +3290,9 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra { dpyinfo->x_focus_event_frame = 0; x_new_focus_frame (dpyinfo, 0); + + bufp->kind = FOCUS_OUT_EVENT; + XSETFRAME (bufp->frame_or_window, frame); } #ifdef HAVE_X_I18N @@ -3468,18 +3304,192 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra } } +/* Return the Emacs frame-object corresponding to an X window. + It could be the frame's main window or an icon window. */ + +static struct frame * +x_window_to_frame (struct x_display_info *dpyinfo, int wdesc) +{ + Lisp_Object tail, frame; + struct frame *f; + + if (wdesc == None) + return NULL; + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo) + continue; + if (f->output_data.x->hourglass_window == wdesc) + return f; +#ifdef USE_X_TOOLKIT + if ((f->output_data.x->edit_widget + && XtWindow (f->output_data.x->edit_widget) == wdesc) + /* A tooltip frame? */ + || (!f->output_data.x->edit_widget + && FRAME_X_WINDOW (f) == wdesc) + || f->output_data.x->icon_desc == wdesc) + return f; +#else /* not USE_X_TOOLKIT */ +#ifdef USE_GTK + if (f->output_data.x->edit_widget) + { + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); + struct x_output *x = f->output_data.x; + if (gwdesc != 0 && gwdesc == x->edit_widget) + return f; + } +#endif /* USE_GTK */ + if (FRAME_X_WINDOW (f) == wdesc + || f->output_data.x->icon_desc == wdesc) + return f; +#endif /* not USE_X_TOOLKIT */ + } + return 0; +} + +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + +/* Like x_window_to_frame but also compares the window with the widget's + windows. */ + +static struct frame * +x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc) +{ + Lisp_Object tail, frame; + struct frame *f, *found = NULL; + struct x_output *x; + + if (wdesc == None) + return NULL; + + FOR_EACH_FRAME (tail, frame) + { + if (found) + break; + f = XFRAME (frame); + if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo) + { + /* This frame matches if the window is any of its widgets. */ + x = f->output_data.x; + if (x->hourglass_window == wdesc) + found = f; + else if (x->widget) + { +#ifdef USE_GTK + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); + if (gwdesc != 0 + && gtk_widget_get_toplevel (gwdesc) == x->widget) + found = f; +#else + if (wdesc == XtWindow (x->widget) + || wdesc == XtWindow (x->column_widget) + || wdesc == XtWindow (x->edit_widget)) + found = f; + /* Match if the window is this frame's menubar. */ + else if (lw_window_is_in_menubar (wdesc, x->menubar_widget)) + found = f; +#endif + } + else if (FRAME_X_WINDOW (f) == wdesc) + /* A tooltip frame. */ + found = f; + } + } + + return found; +} + +/* Likewise, but consider only the menu bar widget. */ + +static struct frame * +x_menubar_window_to_frame (struct x_display_info *dpyinfo, + const XEvent *event) +{ + Window wdesc = event->xany.window; + Lisp_Object tail, frame; + struct frame *f; + struct x_output *x; + + if (wdesc == None) + return NULL; + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo) + continue; + x = f->output_data.x; +#ifdef USE_GTK + if (x->menubar_widget && xg_event_is_for_menubar (f, event)) + return f; +#else + /* Match if the window is this frame's menubar. */ + if (x->menubar_widget + && lw_window_is_in_menubar (wdesc, x->menubar_widget)) + return f; +#endif + } + return 0; +} + +/* Return the frame whose principal (outermost) window is WDESC. + If WDESC is some other (smaller) window, we return 0. */ + +struct frame * +x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc) +{ + Lisp_Object tail, frame; + struct frame *f; + struct x_output *x; + + if (wdesc == None) + return NULL; + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo) + continue; + x = f->output_data.x; + + if (x->widget) + { + /* This frame matches if the window is its topmost widget. */ +#ifdef USE_GTK + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); + if (gwdesc == x->widget) + return f; +#else + if (wdesc == XtWindow (x->widget)) + return f; +#endif + } + else if (FRAME_X_WINDOW (f) == wdesc) + /* Tooltip frame. */ + return f; + } + return 0; +} + +#else /* !USE_X_TOOLKIT && !USE_GTK */ + +#define x_any_window_to_frame(d, i) x_window_to_frame (d, i) +#define x_top_window_to_frame(d, i) x_window_to_frame (d, i) + +#endif /* USE_X_TOOLKIT || USE_GTK */ + /* The focus may have changed. Figure out if it is a real focus change, by checking both FocusIn/Out and Enter/LeaveNotify events. Returns FOCUS_IN_EVENT event in *BUFP. */ static void -x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp) +x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, + const XEvent *event, struct input_event *bufp) { - struct frame *frame; - - frame = x_any_window_to_frame (dpyinfo, event->xany.window); - if (! frame) + if (!frame) return; switch (event->type) @@ -3541,7 +3551,7 @@ x_mouse_leave (struct x_display_info *dpyinfo) static void XTframe_rehighlight (struct frame *frame) { - x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); + x_frame_rehighlight (FRAME_DISPLAY_INFO (frame)); } static void @@ -3757,9 +3767,25 @@ x_get_keysym_name (int keysym) return value; } +/* Mouse clicks and mouse movement. Rah. - -/* Mouse clicks and mouse movement. Rah. */ + Formerly, we used PointerMotionHintMask (in standard_event_mask) + so that we would have to call XQueryPointer after each MotionNotify + event to ask for another such event. However, this made mouse tracking + slow, and there was a bug that made it eventually stop. + + Simply asking for MotionNotify all the time seems to work better. + + In order to avoid asking for motion events and then throwing most + of them away or busy-polling the server for mouse positions, we ask + the server for pointer motion hints. This means that we get only + one event per group of mouse movements. "Groups" are delimited by + other kinds of events (focus changes and button clicks, for + example), or by XQueryPointer calls; when one of these happens, we + get another MotionNotify event the next time the mouse moves. This + is at least as efficient as getting motion events when mouse + tracking is on, and I suspect only negligibly worse when tracking + is off. */ /* Prepare a mouse-event in *RESULT for placement in the input queue. @@ -3767,14 +3793,16 @@ x_get_keysym_name (int keysym) the mouse. */ static Lisp_Object -construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f) +construct_mouse_click (struct input_event *result, + const XButtonEvent *event, + struct frame *f) { /* Make the event type NO_EVENT; we'll change that when we decide otherwise. */ result->kind = MOUSE_CLICK_EVENT; result->code = event->button - Button1; result->timestamp = event->time; - result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), + result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->state) | (event->type == ButtonRelease ? up_modifier @@ -3787,7 +3815,6 @@ construct_mouse_click (struct input_event *result, XButtonEvent *event, struct f return Qnil; } - /* Function to report a mouse movement to the mainstream Emacs code. The input handler calls this. @@ -3796,65 +3823,49 @@ construct_mouse_click (struct input_event *result, XButtonEvent *event, struct f the mainstream emacs code by setting mouse_moved. If not, ask for another motion event, so we can check again the next time it moves. */ -static XMotionEvent last_mouse_motion_event; -static Lisp_Object last_mouse_motion_frame; - static int -note_mouse_movement (FRAME_PTR frame, XMotionEvent *event) +note_mouse_movement (struct frame *frame, const XMotionEvent *event) { - last_mouse_movement_time = event->time; - last_mouse_motion_event = *event; - XSETFRAME (last_mouse_motion_frame, frame); + XRectangle *r; + struct x_display_info *dpyinfo; if (!FRAME_X_OUTPUT (frame)) return 0; + dpyinfo = FRAME_DISPLAY_INFO (frame); + dpyinfo->last_mouse_movement_time = event->time; + dpyinfo->last_mouse_motion_frame = frame; + dpyinfo->last_mouse_motion_x = event->x; + dpyinfo->last_mouse_motion_y = event->y; + if (event->window != FRAME_X_WINDOW (frame)) { frame->mouse_moved = 1; - last_mouse_scroll_bar = Qnil; + dpyinfo->last_mouse_scroll_bar = NULL; note_mouse_highlight (frame, -1, -1); - last_mouse_glyph_frame = 0; + dpyinfo->last_mouse_glyph_frame = NULL; return 1; } /* Has the mouse moved off the glyph it was on at the last sighting? */ - 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) + r = &dpyinfo->last_mouse_glyph; + if (frame != dpyinfo->last_mouse_glyph_frame + || event->x < r->x || event->x >= r->x + r->width + || event->y < r->y || event->y >= r->y + r->height) { frame->mouse_moved = 1; - last_mouse_scroll_bar = Qnil; + dpyinfo->last_mouse_scroll_bar = NULL; 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; + remember_mouse_glyph (frame, event->x, event->y, r); + dpyinfo->last_mouse_glyph_frame = frame; return 1; } return 0; } - -/************************************************************************ - Mouse Face - ************************************************************************/ - -static void -redo_mouse_highlight (void) -{ - if (!NILP (last_mouse_motion_frame) - && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame))) - note_mouse_highlight (XFRAME (last_mouse_motion_frame), - last_mouse_motion_event.x, - last_mouse_motion_event.y); -} - - - /* Return the current position of the mouse. *FP should be a frame which indicates which display to ask about. @@ -3876,15 +3887,16 @@ redo_mouse_highlight (void) movement. */ static void -XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, +XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, Time *timestamp) { - FRAME_PTR f1; + struct frame *f1; + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); block_input (); - if (! NILP (last_mouse_scroll_bar) && insist == 0) + if (dpyinfo->last_mouse_scroll_bar && insist == 0) x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp); else { @@ -3902,7 +3914,7 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp)) XFRAME (frame)->mouse_moved = 0; - last_mouse_scroll_bar = Qnil; + dpyinfo->last_mouse_scroll_bar = NULL; /* Figure out which root window we're on. */ XQueryPointer (FRAME_X_DISPLAY (*fp), @@ -3940,22 +3952,24 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, x_catch_errors (FRAME_X_DISPLAY (*fp)); - if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) + if (x_mouse_grabbed (dpyinfo)) { /* If mouse was grabbed on a frame, give coords for that frame even if the mouse is now outside it. */ XTranslateCoordinates (FRAME_X_DISPLAY (*fp), - /* From-window, to-window. */ - root, FRAME_X_WINDOW (last_mouse_frame), + /* From-window. */ + root, + + /* To-window. */ + FRAME_X_WINDOW (dpyinfo->last_mouse_frame), /* From-position, to-position. */ root_x, root_y, &win_x, &win_y, /* Child of win. */ &child); - f1 = last_mouse_frame; + f1 = dpyinfo->last_mouse_frame; } else { @@ -3979,7 +3993,7 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, want the edit window. For non-Gtk+ the innermost window is the edit window. For Gtk+ it might not be. It might be the tool bar for example. */ - if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win)) + if (x_window_to_frame (dpyinfo, win)) break; #endif win = child; @@ -4001,10 +4015,10 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, #ifdef USE_GTK /* We don't wan't to know the innermost window. We want the edit window. */ - f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win); + f1 = x_window_to_frame (dpyinfo, win); #else /* Is win one of our frames? */ - f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win); + f1 = x_any_window_to_frame (dpyinfo, win); #endif #ifdef USE_X_TOOLKIT @@ -4050,15 +4064,17 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, on it, i.e. into the same rectangles that matrices on the frame are divided into. */ - remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph); - last_mouse_glyph_frame = f1; + /* FIXME: what if F1 is not an X frame? */ + dpyinfo = FRAME_DISPLAY_INFO (f1); + remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); + dpyinfo->last_mouse_glyph_frame = f1; *bar_window = Qnil; *part = 0; *fp = f1; XSETINT (*x, win_x); XSETINT (*y, win_y); - *timestamp = last_mouse_movement_time; + *timestamp = dpyinfo->last_mouse_movement_time; } } } @@ -4144,23 +4160,13 @@ x_window_to_menu_bar (Window window) #ifdef USE_TOOLKIT_SCROLL_BARS -static void x_scroll_bar_to_input_event (XEvent *, struct input_event *); static void x_send_scroll_bar_event (Lisp_Object, int, int, int); -static void x_create_toolkit_scroll_bar (struct frame *, - struct scroll_bar *); -static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *, - int, int, int); - /* Lisp window being scrolled. Set when starting to interact with a toolkit scroll bar, reset to nil when ending the interaction. */ static Lisp_Object window_being_scrolled; -/* Last scroll bar part sent in xm_scroll_callback. */ - -static int last_scroll_bar_part; - /* Whether this is an Xaw with arrow-scrollbars. This should imply that movements of 1/20 of the screen size are mapped to up/down. */ @@ -4202,33 +4208,29 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name, && WINDOWP (window_being_scrolled)) { struct window *w; + struct scroll_bar *bar; x_send_scroll_bar_event (window_being_scrolled, scroll_bar_end_scroll, 0, 0); w = XWINDOW (window_being_scrolled); + bar = XSCROLL_BAR (w->vertical_scroll_bar); - if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging)) + if (bar->dragging != -1) { - XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil; + bar->dragging = -1; /* The thumb size is incorrect while dragging: fix it. */ set_vertical_scroll_bar (w); } window_being_scrolled = Qnil; - last_scroll_bar_part = -1; - +#if defined (USE_LUCID) + bar->last_seen_part = scroll_bar_nowhere; +#endif /* Xt timeouts no longer needed. */ toolkit_scroll_bar_interaction = 0; } } #endif /* not USE_GTK */ -/* A vector of windows used for communication between - x_send_scroll_bar_event and x_scroll_bar_to_input_event. */ - -static struct window **scroll_bar_windows; -static ptrdiff_t scroll_bar_windows_size; - - /* Send a client message with message type Xatom_Scrollbar for a scroll action to the frame of WINDOW. PART is a value identifying the part of the scroll bar that was clicked on. PORTION is the @@ -4238,47 +4240,33 @@ static void x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) { XEvent event; - XClientMessageEvent *ev = (XClientMessageEvent *) &event; + XClientMessageEvent *ev = &event.xclient; struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - ptrdiff_t i; + intptr_t iw = (intptr_t) w; + enum { BITS_PER_INTPTR = CHAR_BIT * sizeof iw }; + verify (BITS_PER_INTPTR <= 64); + int sign_shift = BITS_PER_INTPTR - 32; block_input (); /* Construct a ClientMessage event to send to the frame. */ ev->type = ClientMessage; - ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar; + ev->message_type = FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar; ev->display = FRAME_X_DISPLAY (f); ev->window = FRAME_X_WINDOW (f); ev->format = 32; - /* We can only transfer 32 bits in the XClientMessageEvent, which is - not enough to store a pointer or Lisp_Object on a 64 bit system. - So, store the window in scroll_bar_windows and pass the index - into that array in the event. */ - for (i = 0; i < scroll_bar_windows_size; ++i) - if (scroll_bar_windows[i] == NULL) - break; - - if (i == scroll_bar_windows_size) - { - ptrdiff_t old_nbytes = - scroll_bar_windows_size * sizeof *scroll_bar_windows; - ptrdiff_t nbytes; - enum { XClientMessageEvent_MAX = 0x7fffffff }; - scroll_bar_windows = - xpalloc (scroll_bar_windows, &scroll_bar_windows_size, 1, - XClientMessageEvent_MAX, sizeof *scroll_bar_windows); - nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows; - memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes); - } - - scroll_bar_windows[i] = w; - ev->data.l[0] = (long) i; - ev->data.l[1] = (long) part; - ev->data.l[2] = (long) 0; - ev->data.l[3] = (long) portion; - ev->data.l[4] = (long) whole; + /* A 32-bit X client on a 64-bit X server can pass a window pointer + as-is. A 64-bit client on a 32-bit X server is in trouble + because a pointer does not fit and would be truncated while + passing through the server. So use two slots and hope that X12 + will resolve such issues someday. */ + ev->data.l[0] = iw >> 31 >> 1; + ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift; + ev->data.l[2] = part; + ev->data.l[3] = portion; + ev->data.l[4] = whole; /* Make Xt timeouts work while the scroll bar is active. */ #ifdef USE_X_TOOLKIT @@ -4298,14 +4286,18 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) in *IEVENT. */ static void -x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent) +x_scroll_bar_to_input_event (const XEvent *event, + struct input_event *ievent) { - XClientMessageEvent *ev = (XClientMessageEvent *) event; + const XClientMessageEvent *ev = &event->xclient; Lisp_Object window; struct window *w; - w = scroll_bar_windows[ev->data.l[0]]; - scroll_bar_windows[ev->data.l[0]] = NULL; + /* See the comment in the function above. */ + intptr_t iw0 = ev->data.l[0]; + intptr_t iw1 = ev->data.l[1]; + intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu); + w = (struct window *) iw; XSETWINDOW (window, w); @@ -4318,10 +4310,10 @@ x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent) ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame))); #endif - ievent->part = ev->data.l[1]; - ievent->code = ev->data.l[2]; - ievent->x = make_number ((int) ev->data.l[3]); - ievent->y = make_number ((int) ev->data.l[4]); + ievent->code = 0; + ievent->part = ev->data.l[2]; + ievent->x = make_number (ev->data.l[3]); + ievent->y = make_number (ev->data.l[4]); ievent->modifiers = 0; } @@ -4340,39 +4332,39 @@ x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent) static void xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) { - struct scroll_bar *bar = (struct scroll_bar *) client_data; - XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data; + struct scroll_bar *bar = client_data; + XmScrollBarCallbackStruct *cs = call_data; int part = -1, whole = 0, portion = 0; switch (cs->reason) { case XmCR_DECREMENT: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_up_arrow; break; case XmCR_INCREMENT: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_down_arrow; break; case XmCR_PAGE_DECREMENT: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_above_handle; break; case XmCR_PAGE_INCREMENT: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_below_handle; break; case XmCR_TO_TOP: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_to_top; break; case XmCR_TO_BOTTOM: - bar->dragging = Qnil; + bar->dragging = -1; part = scroll_bar_to_bottom; break; @@ -4388,7 +4380,7 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) whole = XM_SB_MAX - slider_size; portion = min (cs->value, whole); part = scroll_bar_handle; - bar->dragging = make_number (cs->value); + bar->dragging = cs->value; } break; @@ -4399,7 +4391,6 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) if (part >= 0) { window_being_scrolled = bar->window; - last_scroll_bar_part = part; x_send_scroll_bar_event (bar->window, part, portion, whole); } } @@ -4415,11 +4406,11 @@ xg_scroll_callback (GtkRange *range, gdouble value, gpointer user_data) { - struct scroll_bar *bar = (struct scroll_bar *) user_data; + struct scroll_bar *bar = user_data; gdouble position; int part = -1, whole = 0, portion = 0; GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range)); - FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (range), XG_FRAME_DATA); + struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA); if (xg_ignore_gtk_scrollbar) return FALSE; position = gtk_adjustment_get_value (adj); @@ -4429,53 +4420,52 @@ xg_scroll_callback (GtkRange *range, { case GTK_SCROLL_JUMP: /* Buttons 1 2 or 3 must be grabbed. */ - if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0 - && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4)) + if (FRAME_DISPLAY_INFO (f)->grabbed != 0 + && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4)) { part = scroll_bar_handle; whole = gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj); portion = min ((int)position, whole); - bar->dragging = make_number ((int)portion); + bar->dragging = portion; } break; case GTK_SCROLL_STEP_BACKWARD: part = scroll_bar_up_arrow; - bar->dragging = Qnil; + bar->dragging = -1; break; case GTK_SCROLL_STEP_FORWARD: part = scroll_bar_down_arrow; - bar->dragging = Qnil; + bar->dragging = -1; break; case GTK_SCROLL_PAGE_BACKWARD: part = scroll_bar_above_handle; - bar->dragging = Qnil; + bar->dragging = -1; break; case GTK_SCROLL_PAGE_FORWARD: part = scroll_bar_below_handle; - bar->dragging = Qnil; + bar->dragging = -1; break; } if (part >= 0) { window_being_scrolled = bar->window; - last_scroll_bar_part = part; x_send_scroll_bar_event (bar->window, part, portion, whole); } return FALSE; } -/* Callback for button release. Sets dragging to Qnil when dragging is done. */ +/* Callback for button release. Sets dragging to -1 when dragging is done. */ static gboolean xg_end_scroll_callback (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { - struct scroll_bar *bar = (struct scroll_bar *) user_data; - bar->dragging = Qnil; + struct scroll_bar *bar = user_data; + bar->dragging = -1; if (WINDOWP (window_being_scrolled)) { x_send_scroll_bar_event (window_being_scrolled, @@ -4497,11 +4487,12 @@ xg_end_scroll_callback (GtkWidget *widget, static void xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data) { - struct scroll_bar *bar = (struct scroll_bar *) client_data; - float top = *(float *) call_data; + struct scroll_bar *bar = client_data; + float *top_addr = call_data; + float top = *top_addr; float shown; int whole, portion, height; - int part; + enum scroll_bar_part part; /* Get the size of the thumb, a value between 0 and 1. */ block_input (); @@ -4522,8 +4513,8 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data) part = scroll_bar_handle; window_being_scrolled = bar->window; - bar->dragging = make_number (portion); - last_scroll_bar_part = part; + bar->dragging = portion; + bar->last_seen_part = part; x_send_scroll_bar_event (bar->window, part, portion, whole); } @@ -4539,11 +4530,11 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data) static void xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) { - struct scroll_bar *bar = (struct scroll_bar *) client_data; + struct scroll_bar *bar = client_data; /* The position really is stored cast to a pointer. */ - int position = (long) call_data; + int position = (intptr_t) call_data; Dimension height; - int part; + enum scroll_bar_part part; /* Get the height of the scroll bar. */ block_input (); @@ -4561,8 +4552,8 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) part = scroll_bar_move_ratio; window_being_scrolled = bar->window; - bar->dragging = Qnil; - last_scroll_bar_part = part; + bar->dragging = -1; + bar->last_seen_part = part; x_send_scroll_bar_event (bar->window, part, position, height); } @@ -4837,7 +4828,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio shown = (float) portion / whole; } - if (NILP (bar->dragging)) + if (bar->dragging == -1) { int size, value; @@ -4872,19 +4863,28 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio NULL); /* Massage the top+shown values. */ - if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow) + if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow) top = max (0, min (1, top)); else top = old_top; +#if ! defined (HAVE_XAW3D) + /* With Xaw, 'top' values too closer to 1.0 may + cause the thumb to disappear. Fix that. */ + top = min (top, 0.99f); +#endif /* Keep two pixels available for moving the thumb down. */ shown = max (0, min (1 - top - (2.0f / height), shown)); +#if ! defined (HAVE_XAW3D) + /* Likewise with too small 'shown'. */ + shown = max (shown, 0.01f); +#endif - /* If the call to XawScrollbarSetThumb below doesn't seem to work, - check that your system's configuration file contains a define - for `NARROWPROTO'. See s/freebsd.h for an example. */ + /* If the call to XawScrollbarSetThumb below doesn't seem to + work, check that 'NARROWPROTO' is defined in src/config.h. + If this is not so, most likely you need to fix configure. */ if (top != old_top || shown != old_shown) { - if (NILP (bar->dragging)) + if (bar->dragging == -1) XawScrollbarSetThumb (widget, top, shown); else { @@ -4940,7 +4940,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) a.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask | ExposureMask); - a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; + a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; mask = (CWBackPixel | CWEventMask | CWCursor); @@ -4949,17 +4949,13 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) this case, no clear_frame is generated to reduce flickering. */ if (width > 0 && height > 0) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left, top, width, - window_box_height (w), False); + left, top, width, window_box_height (w)); window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), /* Position and size of scroll bar. */ - left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - top, - width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - height, + left, top, width, height, /* Border width, depth, class, and visual. */ - 0, + 0, CopyFromParent, CopyFromParent, CopyFromParent, @@ -4976,8 +4972,11 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) bar->height = height; bar->start = 0; bar->end = 0; - bar->dragging = Qnil; + bar->dragging = -1; bar->fringe_extended_p = 0; +#if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID) + bar->last_seen_part = scroll_bar_nowhere; +#endif /* Add bar to its frame's list of scroll bars. */ bar->next = FRAME_SCROLL_BARS (f); @@ -4991,19 +4990,11 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) #ifdef USE_TOOLKIT_SCROLL_BARS { #ifdef USE_GTK - xg_update_scrollbar_pos (f, - bar->x_window, - top, - left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1)); + xg_update_scrollbar_pos (f, bar->x_window, top, + left,width, max (height, 1)); #else /* not USE_GTK */ Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); - XtConfigureWidget (scroll_bar, - left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - top, - width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1), 0); + XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); XtMapWidget (scroll_bar); #endif /* not USE_GTK */ } @@ -5034,9 +5025,9 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) static void x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild) { - int dragging = ! NILP (bar->dragging); + bool dragging = bar->dragging != -1; Window w = bar->x_window; - FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); GC gc = f->output_data.x->normal_gc; /* If the display is already accurate, do nothing. */ @@ -5086,11 +5077,9 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild zero-height areas; that means "clear to end of window." */ if (start > 0) x_clear_area (FRAME_X_DISPLAY (f), w, - /* x, y, width, height, and exposures. */ VERTICAL_SCROLL_BAR_LEFT_BORDER, VERTICAL_SCROLL_BAR_TOP_BORDER, - inside_width, start, - False); + inside_width, start); /* Change to proper foreground color if one is specified. */ if (f->output_data.x->scroll_bar_foreground_pixel != -1) @@ -5113,12 +5102,9 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild clear zero-height areas; that means "clear to end of window." */ if (end < inside_height) x_clear_area (FRAME_X_DISPLAY (f), w, - /* x, y, width, height, and exposures. */ VERTICAL_SCROLL_BAR_LEFT_BORDER, VERTICAL_SCROLL_BAR_TOP_BORDER + end, - inside_width, inside_height - end, - False); - + inside_width, inside_height - end); } unblock_input (); @@ -5166,11 +5152,11 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio int top, height, left, sb_left, width, sb_width; int window_y, window_height; #ifdef USE_TOOLKIT_SCROLL_BARS - int fringe_extended_p; + bool fringe_extended_p; #endif /* Get window dimensions. */ - window_box (w, -1, 0, &window_y, 0, &window_height); + window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); top = window_y; width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f); height = window_height; @@ -5199,16 +5185,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio #endif #ifdef USE_TOOLKIT_SCROLL_BARS - if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) - fringe_extended_p = (WINDOW_LEFTMOST_P (w) - && WINDOW_LEFT_FRINGE_WIDTH (w) - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) - || WINDOW_LEFT_MARGIN_COLS (w) == 0)); - else - fringe_extended_p = (WINDOW_RIGHTMOST_P (w) - && WINDOW_RIGHT_FRINGE_WIDTH (w) - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) - || WINDOW_RIGHT_MARGIN_COLS (w) == 0)); + fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w); #endif /* Does the scroll bar exist yet? */ @@ -5220,11 +5197,11 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio #ifdef USE_TOOLKIT_SCROLL_BARS if (fringe_extended_p) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - sb_left, top, sb_width, height, False); + sb_left, top, sb_width, height); else #endif x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left, top, width, height, False); + left, top, width, height); unblock_input (); } @@ -5259,41 +5236,21 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio { if (fringe_extended_p) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - sb_left, top, sb_width, height, False); + sb_left, top, sb_width, height); else x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left, top, width, height, False); + left, top, width, height); } #ifdef USE_GTK - xg_update_scrollbar_pos (f, - bar->x_window, - top, - sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2, - max (height, 1)); + xg_update_scrollbar_pos (f, bar->x_window, top, + sb_left, sb_width, max (height, 1)); #else /* not USE_GTK */ XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar), - sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - top, - sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1), 0); + sb_left, top, sb_width, max (height, 1), 0); #endif /* not USE_GTK */ } #else /* not USE_TOOLKIT_SCROLL_BARS */ - /* Clear areas not covered by the scroll bar because of - VERTICAL_SCROLL_BAR_WIDTH_TRIM. */ - if (VERTICAL_SCROLL_BAR_WIDTH_TRIM) - { - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM, - height, False); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM, - top, VERTICAL_SCROLL_BAR_WIDTH_TRIM, - height, False); - } - /* Clear areas not covered by the scroll bar because it's not as wide as the area reserved for it. This makes sure a previous mode line display is cleared after C-x 2 C-x 1, for @@ -5305,11 +5262,10 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio { if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left + area_width - rest, top, - rest, height, False); + left + area_width - rest, top, rest, height); else x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left, top, rest, height, False); + left, top, rest, height); } } @@ -5318,9 +5274,9 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio { XWindowChanges wc; - wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM; + wc.x = sb_left; wc.y = top; - wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2; + wc.width = sb_width; wc.height = height; XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window, mask, &wc); @@ -5344,7 +5300,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio #else /* not USE_TOOLKIT_SCROLL_BARS */ /* Set the scroll bar's current state, unless we're currently being dragged. */ - if (NILP (bar->dragging)) + if (bar->dragging == -1) { int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height); @@ -5377,7 +5333,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio `*redeem_scroll_bar_hook' is applied to its window before the judgment. */ static void -XTcondemn_scroll_bars (FRAME_PTR frame) +XTcondemn_scroll_bars (struct frame *frame) { /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ while (! NILP (FRAME_SCROLL_BARS (frame))) @@ -5445,7 +5401,7 @@ XTredeem_scroll_bar (struct window *window) last call to `*condemn_scroll_bars_hook'. */ static void -XTjudge_scroll_bars (FRAME_PTR f) +XTjudge_scroll_bars (struct frame *f) { Lisp_Object bar, next; @@ -5478,12 +5434,11 @@ XTjudge_scroll_bars (FRAME_PTR f) mark bits. */ static void -x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event) +x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event) { Window w = bar->x_window; - FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); GC gc = f->output_data.x->normal_gc; - int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM; block_input (); @@ -5496,11 +5451,8 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event) /* Draw a one-pixel border just inside the edges of the scroll bar. */ XDrawRectangle (FRAME_X_DISPLAY (f), w, gc, - /* x, y, width, height */ - 0, 0, - bar->width - 1 - width_trim - width_trim, - bar->height - 1); + 0, 0, bar->width - 1, bar->height - 1); /* Restore the foreground color of the GC if we changed it above. */ if (f->output_data.x->scroll_bar_foreground_pixel != -1) @@ -5520,7 +5472,9 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event) static void -x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event) +x_scroll_bar_handle_click (struct scroll_bar *bar, + const XEvent *event, + struct input_event *emacs_event) { if (! WINDOWP (bar->window)) emacs_abort (); @@ -5528,7 +5482,7 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e emacs_event->kind = SCROLL_BAR_CLICK_EVENT; emacs_event->code = event->xbutton.button - Button1; emacs_event->modifiers - = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO + = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))), event->xbutton.state) | (event->type == ButtonRelease @@ -5554,14 +5508,13 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e #ifndef USE_TOOLKIT_SCROLL_BARS /* If the user has released the handle, set it to its final position. */ - if (event->type == ButtonRelease - && ! NILP (bar->dragging)) + if (event->type == ButtonRelease && bar->dragging != -1) { - int new_start = y - XINT (bar->dragging); + int new_start = y - bar->dragging; int new_end = new_start + bar->end - bar->start; x_scroll_bar_set_handle (bar, new_start, new_end, 0); - bar->dragging = Qnil; + bar->dragging = -1; } #endif @@ -5578,20 +5531,21 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e mark bits. */ static void -x_scroll_bar_note_movement (struct scroll_bar *bar, XEvent *event) +x_scroll_bar_note_movement (struct scroll_bar *bar, + const XMotionEvent *event) { - FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame); - - last_mouse_movement_time = event->xmotion.time; + struct frame *f = XFRAME (XWINDOW (bar->window)->frame); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + dpyinfo->last_mouse_movement_time = event->time; + dpyinfo->last_mouse_scroll_bar = bar; f->mouse_moved = 1; - XSETVECTOR (last_mouse_scroll_bar, bar); /* If we're dragging the bar, display it. */ - if (! NILP (bar->dragging)) + if (bar->dragging != -1) { /* Where should the handle be now? */ - int new_start = event->xmotion.y - XINT (bar->dragging); + int new_start = event->y - bar->dragging; if (new_start != bar->start) { @@ -5608,13 +5562,14 @@ x_scroll_bar_note_movement (struct scroll_bar *bar, XEvent *event) on the scroll bar. */ static void -x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, +x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, Time *timestamp) { - struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); + struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; Window w = bar->x_window; - FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); int win_x, win_y; Window dummy_window; int dummy_coord; @@ -5624,27 +5579,24 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, /* Get the mouse's position relative to the scroll bar window, and report that. */ - if (! XQueryPointer (FRAME_X_DISPLAY (f), w, + if (XQueryPointer (FRAME_X_DISPLAY (f), w, - /* Root, child, root x and root y. */ - &dummy_window, &dummy_window, - &dummy_coord, &dummy_coord, + /* Root, child, root x and root y. */ + &dummy_window, &dummy_window, + &dummy_coord, &dummy_coord, - /* Position relative to scroll bar. */ - &win_x, &win_y, + /* Position relative to scroll bar. */ + &win_x, &win_y, - /* Mouse buttons and modifier keys. */ - &dummy_mask)) - ; - else + /* Mouse buttons and modifier keys. */ + &dummy_mask)) { - int top_range - = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); + int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER; - if (! NILP (bar->dragging)) - win_y -= XINT (bar->dragging); + if (bar->dragging != -1) + win_y -= bar->dragging; if (win_y < 0) win_y = 0; @@ -5654,7 +5606,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, *fp = f; *bar_window = bar->window; - if (! NILP (bar->dragging)) + if (bar->dragging != -1) *part = scroll_bar_handle; else if (win_y < bar->start) *part = scroll_bar_above_handle; @@ -5667,11 +5619,10 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, XSETINT (*y, top_range); f->mouse_moved = 0; - last_mouse_scroll_bar = Qnil; + dpyinfo->last_mouse_scroll_bar = NULL; + *timestamp = dpyinfo->last_mouse_movement_time; } - *timestamp = last_mouse_movement_time; - unblock_input (); } @@ -5682,7 +5633,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, redraw them. */ static void -x_scroll_bar_clear (FRAME_PTR f) +x_scroll_bar_clear (struct frame *f) { #ifndef USE_TOOLKIT_SCROLL_BARS Lisp_Object bar; @@ -5699,18 +5650,7 @@ x_scroll_bar_clear (FRAME_PTR f) #endif /* not USE_TOOLKIT_SCROLL_BARS */ } - -/* The main X event-reading loop - XTread_socket. */ - -/* This holds the state XLookupString needs to implement dead keys - and other tricks known as "compose processing". _X Window System_ - says that a portable program can't use this, but Stephen Gildea assures - me that letting the compiler initialize it to zeros will work okay. - - This must be defined outside of XTread_socket, for the same reasons - given for enter_timestamp, above. */ - -static XComposeStatus compose_status; +#ifdef ENABLE_CHECKING /* Record the last 100 characters stored to help debug the loss-of-chars-during-GC problem. */ @@ -5723,6 +5663,12 @@ static short temp_buffer[100]; temp_index = 0; \ temp_buffer[temp_index++] = (keysym) +#else /* not ENABLE_CHECKING */ + +#define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) + +#endif /* ENABLE_CHECKING */ + /* Set this to nonzero to fake an "X I/O error" on a particular display. */ @@ -5735,20 +5681,6 @@ static struct x_display_info *XTread_socket_fake_io_error; static struct x_display_info *next_noop_dpyinfo; -#if defined USE_X_TOOLKIT || defined USE_GTK -#define SET_SAVED_BUTTON_EVENT \ - do \ - { \ - if (f->output_data.x->saved_menu_event == 0) \ - f->output_data.x->saved_menu_event = \ - xmalloc (sizeof (XEvent)); \ - *f->output_data.x->saved_menu_event = event; \ - inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \ - XSETFRAME (inev.ie.frame_or_window, f); \ - } \ - while (0) -#endif - enum { X_EVENT_NORMAL, @@ -5842,11 +5774,13 @@ static void xembed_send_message (struct frame *f, Time, *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. *FINISH is zero if caller should continue reading events. *FINISH is X_EVENT_DROP if event should not be passed to the toolkit. + *EVENT is unchanged unless we're processing KeyPress event. We return the number of characters stored into the buffer. */ static int -handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, +handle_one_xevent (struct x_display_info *dpyinfo, + const XEvent *event, int *finish, struct input_event *hold_quit) { union { @@ -5856,10 +5790,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, int count = 0; int do_help = 0; ptrdiff_t nbytes = 0; - struct frame *f = NULL; + struct frame *any, *f = NULL; struct coding_system coding; - XEvent event = *eventptr; Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; + /* This holds the state XLookupString needs to implement dead keys + and other tricks known as "compose processing". _X Window System_ + says that a portable program can't use this, but Stephen Gildea assures + me that letting the compiler initialize it to zeros will work okay. */ + static XComposeStatus compose_status; + USE_SAFE_ALLOCA; *finish = X_EVENT_NORMAL; @@ -5868,24 +5807,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (pending_event_wait.eventtype == event.type) - pending_event_wait.eventtype = 0; /* Indicates we got it. */ + any = x_any_window_to_frame (dpyinfo, event->xany.window); - switch (event.type) + if (any && any->wait_event_type == event->type) + any->wait_event_type = 0; /* Indicates we got it. */ + + switch (event->type) { case ClientMessage: { - if (event.xclient.message_type - == dpyinfo->Xatom_wm_protocols - && event.xclient.format == 32) + if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols + && event->xclient.format == 32) { - if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_take_focus) + if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus) { - /* Use x_any_window_to_frame because this - could be the shell widget window - if the frame has no title bar. */ - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + /* Use the value returned by x_any_window_to_frame + because this could be the shell widget window + if the frame has no title bar. */ + f = any; #ifdef HAVE_X_I18N /* Not quite sure this is needed -pd */ if (f && FRAME_XIC (f)) @@ -5909,15 +5848,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, since that might be an event for a deleted frame. */ if (f) { - Display *d = event.xclient.display; + Display *d = event->xclient.display; /* Catch and ignore errors, in case window has been iconified by a window manager such as GWM. */ x_catch_errors (d); - XSetInputFocus (d, event.xclient.window, + XSetInputFocus (d, event->xclient.window, /* The ICCCM says this is the only valid choice. */ RevertToParent, - event.xclient.data.l[1]); + event->xclient.data.l[1]); /* This is needed to detect the error if there is an error. */ XSync (d, False); @@ -5928,8 +5867,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto done; } - if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_save_yourself) + if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself) { /* Save state modify the WM_COMMAND property to something which can reinstate us. This notifies @@ -5944,26 +5882,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, #endif { f = x_top_window_to_frame (dpyinfo, - event.xclient.window); + event->xclient.window); /* This is just so we only give real data once for a single Emacs process. */ if (f == SELECTED_FRAME ()) XSetCommand (FRAME_X_DISPLAY (f), - event.xclient.window, + event->xclient.window, initial_argv, initial_argc); else if (f) XSetCommand (FRAME_X_DISPLAY (f), - event.xclient.window, + event->xclient.window, 0, 0); } goto done; } - if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_delete_window) + if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window) { - f = x_any_window_to_frame (dpyinfo, - event.xclient.window); + f = any; if (!f) goto OTHER; /* May be a dialog that is to be removed */ @@ -5975,20 +5911,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto done; } - if (event.xclient.message_type - == dpyinfo->Xatom_wm_configure_denied) - { - goto done; - } + if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied) + goto done; - if (event.xclient.message_type - == dpyinfo->Xatom_wm_window_moved) + if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved) { int new_x, new_y; - f = x_window_to_frame (dpyinfo, event.xclient.window); + f = x_window_to_frame (dpyinfo, event->xclient.window); - new_x = event.xclient.data.s[0]; - new_y = event.xclient.data.s[1]; + new_x = event->xclient.data.s[0]; + new_y = event->xclient.data.s[1]; if (f) { @@ -5999,28 +5931,25 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } #ifdef HACK_EDITRES - if (event.xclient.message_type - == dpyinfo->Xatom_editres) + if (event->xclient.message_type == dpyinfo->Xatom_editres) { - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + f = any; if (f) - _XEditResCheckMessages (f->output_data.x->widget, NULL, - &event, NULL); + _XEditResCheckMessages (f->output_data.x->widget, + NULL, (XEvent *) event, NULL); goto done; } #endif /* HACK_EDITRES */ - if ((event.xclient.message_type - == dpyinfo->Xatom_DONE) - || (event.xclient.message_type - == dpyinfo->Xatom_PAGE)) + if (event->xclient.message_type == dpyinfo->Xatom_DONE + || event->xclient.message_type == dpyinfo->Xatom_PAGE) { /* Ghostview job completed. Kill it. We could reply with "Next" if we received "Page", but we currently never do because we are interested in images, only, which should have 1 page. */ - Pixmap pixmap = (Pixmap) event.xclient.data.l[1]; - f = x_window_to_frame (dpyinfo, event.xclient.window); + Pixmap pixmap = (Pixmap) event->xclient.data.l[1]; + f = x_window_to_frame (dpyinfo, event->xclient.window); if (!f) goto OTHER; x_kill_gs_process (pixmap, f); @@ -6031,54 +5960,52 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, #ifdef USE_TOOLKIT_SCROLL_BARS /* Scroll bar callbacks send a ClientMessage from which we construct an input_event. */ - if (event.xclient.message_type - == dpyinfo->Xatom_Scrollbar) + if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar) { - x_scroll_bar_to_input_event (&event, &inev.ie); + x_scroll_bar_to_input_event (event, &inev.ie); *finish = X_EVENT_GOTO_OUT; goto done; } #endif /* USE_TOOLKIT_SCROLL_BARS */ /* XEmbed messages from the embedder (if any). */ - if (event.xclient.message_type - == dpyinfo->Xatom_XEMBED) + if (event->xclient.message_type == dpyinfo->Xatom_XEMBED) { - enum xembed_message msg = event.xclient.data.l[1]; + enum xembed_message msg = event->xclient.data.l[1]; if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT) - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, event, &inev.ie); *finish = X_EVENT_GOTO_OUT; goto done; } - xft_settings_event (dpyinfo, &event); + xft_settings_event (dpyinfo, event); - f = x_any_window_to_frame (dpyinfo, event.xclient.window); + f = any; if (!f) goto OTHER; - if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie)) + if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie)) *finish = X_EVENT_DROP; } break; case SelectionNotify: - last_user_time = event.xselection.time; + dpyinfo->last_user_time = event->xselection.time; #ifdef USE_X_TOOLKIT - if (! x_window_to_frame (dpyinfo, event.xselection.requestor)) + if (! x_window_to_frame (dpyinfo, event->xselection.requestor)) goto OTHER; #endif /* not USE_X_TOOLKIT */ - x_handle_selection_notify (&event.xselection); + x_handle_selection_notify (&event->xselection); break; case SelectionClear: /* Someone has grabbed ownership. */ - last_user_time = event.xselectionclear.time; + dpyinfo->last_user_time = event->xselectionclear.time; #ifdef USE_X_TOOLKIT - if (! x_window_to_frame (dpyinfo, event.xselectionclear.window)) + if (! x_window_to_frame (dpyinfo, event->xselectionclear.window)) goto OTHER; #endif /* USE_X_TOOLKIT */ { - XSelectionClearEvent *eventp = &(event.xselectionclear); + const XSelectionClearEvent *eventp = &event->xselectionclear; inev.ie.kind = SELECTION_CLEAR_EVENT; SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; @@ -6088,29 +6015,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, break; case SelectionRequest: /* Someone wants our selection. */ - last_user_time = event.xselectionrequest.time; + dpyinfo->last_user_time = event->xselectionrequest.time; #ifdef USE_X_TOOLKIT - if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner)) + if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner)) goto OTHER; #endif /* USE_X_TOOLKIT */ { - XSelectionRequestEvent *eventp = &(event.xselectionrequest); - - inev.ie.kind = SELECTION_REQUEST_EVENT; - SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; - SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor; - SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; - SELECTION_EVENT_TARGET (&inev.sie) = eventp->target; - SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property; - SELECTION_EVENT_TIME (&inev.sie) = eventp->time; + const XSelectionRequestEvent *eventp = &event->xselectionrequest; + + inev.ie.kind = SELECTION_REQUEST_EVENT; + SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; + SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor; + SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; + SELECTION_EVENT_TARGET (&inev.sie) = eventp->target; + SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property; + SELECTION_EVENT_TIME (&inev.sie) = eventp->time; } break; case PropertyNotify: - last_user_time = event.xproperty.time; - f = x_top_window_to_frame (dpyinfo, event.xproperty.window); - if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state) - if (x_handle_net_wm_state (f, &event.xproperty) + dpyinfo->last_user_time = event->xproperty.time; + f = x_top_window_to_frame (dpyinfo, event->xproperty.window); + if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state) + if (x_handle_net_wm_state (f, &event->xproperty) && FRAME_ICONIFIED_P (f) && f->output_data.x->net_wm_state_hidden_seen) { @@ -6125,40 +6052,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, XSETFRAME (inev.ie.frame_or_window, f); } - x_handle_property_notify (&event.xproperty); - xft_settings_event (dpyinfo, &event); + x_handle_property_notify (&event->xproperty); + xft_settings_event (dpyinfo, event); goto OTHER; case ReparentNotify: - f = x_top_window_to_frame (dpyinfo, event.xreparent.window); + f = x_top_window_to_frame (dpyinfo, event->xreparent.window); if (f) { - int x, y; - f->output_data.x->parent_desc = event.xreparent.parent; - x_real_positions (f, &x, &y); - f->left_pos = x; - f->top_pos = y; + f->output_data.x->parent_desc = event->xreparent.parent; + x_real_positions (f, &f->left_pos, &f->top_pos); /* Perhaps reparented due to a WM restart. Reset this. */ - FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; - FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0; + FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; + FRAME_DISPLAY_INFO (f)->net_supported_window = 0; x_set_frame_alpha (f); } goto OTHER; case Expose: - f = x_window_to_frame (dpyinfo, event.xexpose.window); + f = x_window_to_frame (dpyinfo, event->xexpose.window); if (f) { -#ifdef USE_GTK - /* This seems to be needed for GTK 2.6. */ - x_clear_area (event.xexpose.display, - event.xexpose.window, - event.xexpose.x, event.xexpose.y, - event.xexpose.width, event.xexpose.height, - FALSE); -#endif if (!FRAME_VISIBLE_P (f)) { SET_FRAME_VISIBLE (f, 1); @@ -6167,9 +6083,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, SET_FRAME_GARBAGED (f); } else - expose_frame (f, - event.xexpose.x, event.xexpose.y, - event.xexpose.width, event.xexpose.height); + { +#ifdef USE_GTK + /* This seems to be needed for GTK 2.6 and later, see + http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ + x_clear_area (event->xexpose.display, + event->xexpose.window, + event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height); +#endif + expose_frame (f, event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height); + } } else { @@ -6181,8 +6106,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, themselves, so there's no way to dispatch events to them. Recognize this case separately. */ { - Widget widget - = x_window_to_menu_bar (event.xexpose.window); + Widget widget = x_window_to_menu_bar (event->xexpose.window); if (widget) xlwmenu_redisplay (widget); } @@ -6192,11 +6116,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, /* Dispatch event to the widget. */ goto OTHER; #else /* not USE_TOOLKIT_SCROLL_BARS */ - bar = x_window_to_scroll_bar (event.xexpose.display, - event.xexpose.window); + bar = x_window_to_scroll_bar (event->xexpose.display, + event->xexpose.window); if (bar) - x_scroll_bar_expose (bar, &event); + x_scroll_bar_expose (bar, event); #ifdef USE_X_TOOLKIT else goto OTHER; @@ -6208,14 +6132,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, case GraphicsExpose: /* This occurs when an XCopyArea's source area was obscured or not available. */ - f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable); + f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable); if (f) - { - expose_frame (f, - event.xgraphicsexpose.x, event.xgraphicsexpose.y, - event.xgraphicsexpose.width, - event.xgraphicsexpose.height); - } + expose_frame (f, event->xgraphicsexpose.x, + event->xgraphicsexpose.y, + event->xgraphicsexpose.width, + event->xgraphicsexpose.height); #ifdef USE_X_TOOLKIT else goto OTHER; @@ -6229,13 +6151,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, case UnmapNotify: /* Redo the mouse-highlight after the tooltip has gone. */ - if (event.xmap.window == tip_window) + if (event->xunmap.window == tip_window) { tip_window = 0; - redo_mouse_highlight (); + x_redo_mouse_highlight (dpyinfo); } - f = x_top_window_to_frame (dpyinfo, event.xunmap.window); + f = x_top_window_to_frame (dpyinfo, event->xunmap.window); if (f) /* F may no longer exist if the frame was deleted. */ { @@ -6260,7 +6182,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto OTHER; case MapNotify: - if (event.xmap.window == tip_window) + if (event->xmap.window == tip_window) /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED below. */ goto OTHER; @@ -6268,7 +6190,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, /* We use x_top_window_to_frame because map events can come for sub-windows and they don't mean that the frame is visible. */ - f = x_top_window_to_frame (dpyinfo, event.xmap.window); + f = x_top_window_to_frame (dpyinfo, event->xmap.window); if (f) { bool iconified = FRAME_ICONIFIED_P (f); @@ -6308,7 +6230,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, case KeyPress: - last_user_time = event.xkey.time; + dpyinfo->last_user_time = event->xkey.time; ignore_next_mouse_click_timeout = 0; #if defined (USE_X_TOOLKIT) || defined (USE_GTK) @@ -6317,8 +6239,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, goto OTHER; #endif - f = x_any_window_to_frame (dpyinfo, event.xkey.window); + f = any; +#if ! defined (USE_GTK) /* If mouse-highlight is an integer, input clears out mouse highlighting. */ if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) @@ -6328,6 +6251,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, clear_mouse_face (hlinfo); hlinfo->mouse_face_hidden = 1; } +#endif #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS if (f == 0) @@ -6335,7 +6259,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, /* Scroll bars consume key events, but we want the keys to go to the scroll bar's frame. */ Widget widget = XtWindowToWidget (dpyinfo->display, - event.xkey.window); + event->xkey.window); if (widget && XmIsScrollBar (widget)) { widget = XtParent (widget); @@ -6364,6 +6288,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, int modifiers; Lisp_Object coding_system = Qlatin_1; Lisp_Object c; + /* Event will be modified. */ + XKeyEvent xkey = event->xkey; #ifdef USE_GTK /* Don't pass keys to GTK. A Tab will shift focus to the @@ -6373,20 +6299,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, *finish = X_EVENT_DROP; #endif - event.xkey.state - |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), - extra_keyboard_modifiers); - modifiers = event.xkey.state; + xkey.state |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f), + extra_keyboard_modifiers); + modifiers = xkey.state; /* This will have to go some day... */ /* make_lispy_event turns chars into control chars. Don't do it here because XLookupString is too eager. */ - event.xkey.state &= ~ControlMask; - event.xkey.state &= ~(dpyinfo->meta_mod_mask - | dpyinfo->super_mod_mask - | dpyinfo->hyper_mod_mask - | dpyinfo->alt_mod_mask); + xkey.state &= ~ControlMask; + xkey.state &= ~(dpyinfo->meta_mod_mask + | dpyinfo->super_mod_mask + | dpyinfo->hyper_mod_mask + | dpyinfo->alt_mod_mask); /* In case Meta is ComposeCharacter, clear its status. According to Markus Ehrnsperger @@ -6403,7 +6328,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, coding_system = Vlocale_coding_system; nbytes = XmbLookupString (FRAME_XIC (f), - &event.xkey, (char *) copy_bufptr, + &xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &status_return); if (status_return == XBufferOverflow) @@ -6411,7 +6336,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, copy_bufsiz = nbytes + 1; copy_bufptr = alloca (copy_bufsiz); nbytes = XmbLookupString (FRAME_XIC (f), - &event.xkey, (char *) copy_bufptr, + &xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &status_return); } @@ -6428,11 +6353,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, emacs_abort (); } else - nbytes = XLookupString (&event.xkey, (char *) copy_bufptr, + nbytes = XLookupString (&xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &compose_status); #else - nbytes = XLookupString (&event.xkey, (char *) copy_bufptr, + nbytes = XLookupString (&xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &compose_status); #endif @@ -6448,8 +6373,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, /* Common for all keysym input events. */ XSETFRAME (inev.ie.frame_or_window, f); inev.ie.modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers); - inev.ie.timestamp = event.xkey.time; + = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers); + inev.ie.timestamp = xkey.time; /* First deal with keysyms which have defined translations to characters. */ @@ -6625,6 +6550,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (keysym == NoSymbol) break; } + /* FIXME: check side effects and remove this. */ + ((XEvent *) event)->xkey = xkey; } done_keysym: #ifdef HAVE_X_I18N @@ -6637,7 +6564,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, #endif case KeyRelease: - last_user_time = event.xkey.time; + dpyinfo->last_user_time = event->xkey.time; #ifdef HAVE_X_I18N /* Don't dispatch this event since XtDispatchEvent calls XFilterEvent, and two calls in a row may freeze the @@ -6648,35 +6575,35 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, #endif case EnterNotify: - last_user_time = event.xcrossing.time; - x_detect_focus_change (dpyinfo, &event, &inev.ie); + dpyinfo->last_user_time = event->xcrossing.time; + x_detect_focus_change (dpyinfo, any, event, &inev.ie); - f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); + f = any; if (f && x_mouse_click_focus_ignore_position) - ignore_next_mouse_click_timeout = event.xmotion.time + 200; + ignore_next_mouse_click_timeout = event->xmotion.time + 200; /* EnterNotify counts as mouse movement, so update things that depend on mouse position. */ if (f && !f->output_data.x->hourglass_p) - note_mouse_movement (f, &event.xmotion); + 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.xmotion); + if (!f && dpyinfo->last_mouse_glyph_frame) + note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion); #endif goto OTHER; case FocusIn: - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, event, &inev.ie); goto OTHER; case LeaveNotify: - last_user_time = event.xcrossing.time; - x_detect_focus_change (dpyinfo, &event, &inev.ie); + dpyinfo->last_user_time = event->xcrossing.time; + x_detect_focus_change (dpyinfo, any, event, &inev.ie); - f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); + f = x_top_window_to_frame (dpyinfo, event->xcrossing.window); if (f) { if (f == hlinfo->mouse_face_mouse_frame) @@ -6696,26 +6623,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } #ifdef USE_GTK /* See comment in EnterNotify above */ - else if (last_mouse_glyph_frame) - note_mouse_movement (last_mouse_glyph_frame, &event.xmotion); + else if (dpyinfo->last_mouse_glyph_frame) + note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion); #endif goto OTHER; case FocusOut: - x_detect_focus_change (dpyinfo, &event, &inev.ie); + x_detect_focus_change (dpyinfo, any, event, &inev.ie); goto OTHER; case MotionNotify: { - last_user_time = event.xmotion.time; + dpyinfo->last_user_time = event->xmotion.time; previous_help_echo_string = help_echo_string; help_echo_string = Qnil; - if (dpyinfo->grabbed && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) - f = last_mouse_frame; - else - f = x_window_to_frame (dpyinfo, event.xmotion.window); + f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame + : x_window_to_frame (dpyinfo, event->xmotion.window)); if (hlinfo->mouse_face_hidden) { @@ -6724,7 +6648,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } #ifdef USE_GTK - if (f && xg_event_is_for_scrollbar (f, &event)) + if (f && xg_event_is_for_scrollbar (f, event)) f = 0; #endif if (f) @@ -6733,18 +6657,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, /* Generate SELECT_WINDOW_EVENTs when needed. Don't let popup menus influence things (bug#1261). */ if (!NILP (Vmouse_autoselect_window) && !popup_activated ()) - { - Lisp_Object window; - - window = window_from_coordinates (f, - event.xmotion.x, event.xmotion.y, - 0, 0); - - /* Window will be selected only when it is not selected now and - last mouse movement event was not in it. Minibuffer window - will be selected only when it is active. */ - if (WINDOWP (window) - && !EQ (window, last_window) + { + static Lisp_Object last_mouse_window; + Lisp_Object window = window_from_coordinates + (f, event->xmotion.x, event->xmotion.y, 0, 0); + + /* Window will be selected only when it is not selected now and + last mouse movement event was not in it. Minibuffer window + will be selected only when it is active. */ + if (WINDOWP (window) + && !EQ (window, last_mouse_window) && !EQ (window, selected_window) /* For click-to-focus window managers create event iff we don't leave the @@ -6752,25 +6674,25 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, && (focus_follows_mouse || (EQ (XWINDOW (window)->frame, XWINDOW (selected_window)->frame)))) - { - inev.ie.kind = SELECT_WINDOW_EVENT; - inev.ie.frame_or_window = window; - } - - last_window=window; - } - if (!note_mouse_movement (f, &event.xmotion)) + { + inev.ie.kind = SELECT_WINDOW_EVENT; + inev.ie.frame_or_window = window; + } + /* Remember the last window where we saw the mouse. */ + last_mouse_window = window; + } + if (!note_mouse_movement (f, &event->xmotion)) help_echo_string = previous_help_echo_string; } else { #ifndef USE_TOOLKIT_SCROLL_BARS struct scroll_bar *bar - = x_window_to_scroll_bar (event.xmotion.display, - event.xmotion.window); + = x_window_to_scroll_bar (event->xmotion.display, + event->xmotion.window); if (bar) - x_scroll_bar_note_movement (bar, &event); + x_scroll_bar_note_movement (bar, &event->xmotion); #endif /* USE_TOOLKIT_SCROLL_BARS */ /* If we move outside the frame, then we're @@ -6787,14 +6709,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } case ConfigureNotify: - f = x_top_window_to_frame (dpyinfo, event.xconfigure.window); + f = x_top_window_to_frame (dpyinfo, event->xconfigure.window); #ifdef USE_GTK if (!f - && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window)) - && event.xconfigure.window == FRAME_X_WINDOW (f)) + && (f = any) + && event->xconfigure.window == FRAME_X_WINDOW (f)) { - xg_frame_resized (f, event.xconfigure.width, - event.xconfigure.height); + xg_frame_resized (f, event->xconfigure.width, + event->xconfigure.height); f = 0; } #endif @@ -6802,8 +6724,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, { #ifndef USE_X_TOOLKIT #ifndef USE_GTK - int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height); - int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width); + int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event->xconfigure.height); + int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event->xconfigure.width); /* In the toolkit version, change_frame_size is called by the code that handles resizing @@ -6814,16 +6736,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, to check the pixel dimensions as well. */ if (columns != FRAME_COLS (f) || rows != FRAME_LINES (f) - || event.xconfigure.width != FRAME_PIXEL_WIDTH (f) - || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f)) + || event->xconfigure.width != FRAME_PIXEL_WIDTH (f) + || event->xconfigure.height != FRAME_PIXEL_HEIGHT (f)) { change_frame_size (f, rows, columns, 0, 1, 0); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } - FRAME_PIXEL_WIDTH (f) = event.xconfigure.width; - FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height; + FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; + FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; #endif /* not USE_GTK */ #endif @@ -6833,9 +6755,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (FRAME_GTK_OUTER_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f))) #endif - { - x_real_positions (f, &f->left_pos, &f->top_pos); - } + x_real_positions (f, &f->left_pos, &f->top_pos); #ifdef HAVE_X_I18N if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea)) @@ -6850,44 +6770,39 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, { /* If we decide we want to generate an event to be seen by the rest of Emacs, we put it here. */ - int tool_bar_p = 0; + bool tool_bar_p = 0; - memset (&compose_status, 0, sizeof (compose_status)); - last_mouse_glyph_frame = 0; - last_user_time = event.xbutton.time; + memset (&compose_status, 0, sizeof (compose_status)); + dpyinfo->last_mouse_glyph_frame = NULL; + dpyinfo->last_user_time = event->xbutton.time; - if (dpyinfo->grabbed - && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) - f = last_mouse_frame; - else - f = x_window_to_frame (dpyinfo, event.xbutton.window); + f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame + : x_window_to_frame (dpyinfo, event->xbutton.window)); #ifdef USE_GTK - if (f && xg_event_is_for_scrollbar (f, &event)) + if (f && xg_event_is_for_scrollbar (f, event)) f = 0; #endif if (f) { +#if ! defined (USE_GTK) /* Is this in the tool-bar? */ if (WINDOWP (f->tool_bar_window) && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window))) { Lisp_Object window; - int x = event.xbutton.x; - int y = event.xbutton.y; + int x = event->xbutton.x; + int y = event->xbutton.y; window = window_from_coordinates (f, x, y, 0, 1); tool_bar_p = EQ (window, f->tool_bar_window); - if (tool_bar_p && event.xbutton.button < 4) - { - handle_tool_bar_click (f, x, y, - event.xbutton.type == ButtonPress, - x_x_to_emacs_modifiers (dpyinfo, - event.xbutton.state)); - } + if (tool_bar_p && event->xbutton.button < 4) + handle_tool_bar_click + (f, x, y, event->xbutton.type == ButtonPress, + x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state)); } +#endif /* !USE_GTK */ if (!tool_bar_p) #if defined (USE_X_TOOLKIT) || defined (USE_GTK) @@ -6896,52 +6811,52 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, { if (ignore_next_mouse_click_timeout) { - if (event.type == ButtonPress - && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0) + if (event->type == ButtonPress + && event->xbutton.time > ignore_next_mouse_click_timeout) { ignore_next_mouse_click_timeout = 0; - construct_mouse_click (&inev.ie, &event.xbutton, f); + construct_mouse_click (&inev.ie, &event->xbutton, f); } - if (event.type == ButtonRelease) + if (event->type == ButtonRelease) ignore_next_mouse_click_timeout = 0; } else - construct_mouse_click (&inev.ie, &event.xbutton, f); + construct_mouse_click (&inev.ie, &event->xbutton, f); } if (FRAME_X_EMBEDDED_P (f)) - xembed_send_message (f, event.xbutton.time, + xembed_send_message (f, event->xbutton.time, XEMBED_REQUEST_FOCUS, 0, 0, 0); } else { struct scroll_bar *bar - = x_window_to_scroll_bar (event.xbutton.display, - event.xbutton.window); + = x_window_to_scroll_bar (event->xbutton.display, + event->xbutton.window); #ifdef USE_TOOLKIT_SCROLL_BARS /* Make the "Ctrl-Mouse-2 splits window" work for toolkit scroll bars. */ - if (bar && event.xbutton.state & ControlMask) + if (bar && event->xbutton.state & ControlMask) { - x_scroll_bar_handle_click (bar, &event, &inev.ie); + x_scroll_bar_handle_click (bar, event, &inev.ie); *finish = X_EVENT_DROP; } #else /* not USE_TOOLKIT_SCROLL_BARS */ if (bar) - x_scroll_bar_handle_click (bar, &event, &inev.ie); + x_scroll_bar_handle_click (bar, event, &inev.ie); #endif /* not USE_TOOLKIT_SCROLL_BARS */ } - if (event.type == ButtonPress) + if (event->type == ButtonPress) { - dpyinfo->grabbed |= (1 << event.xbutton.button); - last_mouse_frame = f; + dpyinfo->grabbed |= (1 << event->xbutton.button); + dpyinfo->last_mouse_frame = f; if (!tool_bar_p) last_tool_bar_item = -1; } else - dpyinfo->grabbed &= ~(1 << event.xbutton.button); + dpyinfo->grabbed &= ~(1 << event->xbutton.button); /* Ignore any mouse motion that happened before this event; any subsequent mouse-movement Emacs events should reflect @@ -6950,7 +6865,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, f->mouse_moved = 0; #if defined (USE_X_TOOLKIT) || defined (USE_GTK) - f = x_menubar_window_to_frame (dpyinfo, &event); + f = x_menubar_window_to_frame (dpyinfo, event); /* For a down-event in the menu bar, don't pass it to Xt right now. Instead, save it away @@ -6959,25 +6874,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (! popup_activated () #ifdef USE_GTK /* Gtk+ menus only react to the first three buttons. */ - && event.xbutton.button < 3 + && event->xbutton.button < 3 #endif - && f && event.type == ButtonPress + && f && event->type == ButtonPress /* Verify the event is really within the menu bar and not just sent to it due to grabbing. */ - && event.xbutton.x >= 0 - && event.xbutton.x < FRAME_PIXEL_WIDTH (f) - && event.xbutton.y >= 0 - && event.xbutton.y < f->output_data.x->menubar_height - && event.xbutton.same_screen) + && event->xbutton.x >= 0 + && event->xbutton.x < FRAME_PIXEL_WIDTH (f) + && event->xbutton.y >= 0 + && event->xbutton.y < f->output_data.x->menubar_height + && event->xbutton.same_screen) { - SET_SAVED_BUTTON_EVENT; - XSETFRAME (last_mouse_press_frame, f); - *finish = X_EVENT_DROP; - } - else if (event.type == ButtonPress) - { - last_mouse_press_frame = Qnil; - goto OTHER; + if (!f->output_data.x->saved_menu_event) + f->output_data.x->saved_menu_event = xmalloc (sizeof *event); + *f->output_data.x->saved_menu_event = *event; + inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + *finish = X_EVENT_DROP; } else goto OTHER; @@ -6997,18 +6910,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, case MappingNotify: /* Someone has changed the keyboard mapping - update the local cache. */ - switch (event.xmapping.request) + switch (event->xmapping.request) { case MappingModifier: x_find_modifier_meanings (dpyinfo); /* This is meant to fall through. */ case MappingKeyboard: - XRefreshKeyboardMapping (&event.xmapping); + XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping); } goto OTHER; case DestroyNotify: - xft_settings_event (dpyinfo, &event); + xft_settings_event (dpyinfo, event); break; default: @@ -7016,7 +6929,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, #ifdef USE_X_TOOLKIT block_input (); if (*finish != X_EVENT_DROP) - XtDispatchEvent (&event); + XtDispatchEvent ((XEvent *) event); unblock_input (); #endif /* USE_X_TOOLKIT */ break; @@ -7054,7 +6967,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } SAFE_FREE (); - *eventptr = event; return count; } @@ -7094,6 +7006,7 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) { int count = 0; int event_found = 0; + struct x_display_info *dpyinfo = terminal->display_info.x; block_input (); @@ -7101,36 +7014,33 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) input_signal_count++; /* For debugging, this gives a way to fake an I/O error. */ - if (terminal->display_info.x == XTread_socket_fake_io_error) + if (dpyinfo == XTread_socket_fake_io_error) { XTread_socket_fake_io_error = 0; - x_io_error_quitter (terminal->display_info.x->display); + x_io_error_quitter (dpyinfo->display); } #ifndef USE_GTK - while (XPending (terminal->display_info.x->display)) + while (XPending (dpyinfo->display)) { int finish; XEvent event; - XNextEvent (terminal->display_info.x->display, &event); + XNextEvent (dpyinfo->display, &event); #ifdef HAVE_X_I18N /* Filter events for the current X input method. */ - if (x_filter_event (terminal->display_info.x, &event)) + if (x_filter_event (dpyinfo, &event)) continue; #endif event_found = 1; - count += handle_one_xevent (terminal->display_info.x, - &event, &finish, hold_quit); + count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit); if (finish == X_EVENT_GOTO_OUT) - goto out; + break; } - out:; - #else /* USE_GTK */ /* For GTK we must use the GTK event loop. But XEvents gets passed @@ -7180,12 +7090,11 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) } /* If the focus was just given to an auto-raising frame, - raise it now. */ - /* ??? This ought to be able to handle more than one such frame. */ - if (pending_autoraise_frame) + raise it now. FIXME: handle more than one such frame. */ + if (dpyinfo->x_pending_autoraise_frame) { - x_raise_frame (pending_autoraise_frame); - pending_autoraise_frame = 0; + x_raise_frame (dpyinfo->x_pending_autoraise_frame); + dpyinfo->x_pending_autoraise_frame = NULL; } unblock_input (); @@ -7208,7 +7117,8 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) mode lines must be clipped to the whole window. */ static void -x_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc) +x_clip_to_row (struct window *w, struct glyph_row *row, + enum glyph_row_area area, GC gc) { struct frame *f = XFRAME (WINDOW_FRAME (w)); XRectangle clip_rect; @@ -7232,7 +7142,7 @@ static void x_draw_hollow_cursor (struct window *w, struct glyph_row *row) { struct frame *f = XFRAME (WINDOW_FRAME (w)); - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Display *dpy = FRAME_X_DISPLAY (f); int x, y, wd, h; XGCValues xgcv; @@ -7299,7 +7209,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text { Display *dpy = FRAME_X_DISPLAY (f); Window window = FRAME_X_WINDOW (f); - GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc; + GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc; unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures; struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); XGCValues xgcv; @@ -7320,7 +7230,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text else { gc = XCreateGC (dpy, window, mask, &xgcv); - FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc; + FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; } x_clip_to_row (w, row, TEXT_AREA, gc); @@ -7385,8 +7295,7 @@ x_define_frame_cursor (struct frame *f, Cursor cursor) static void x_clear_frame_area (struct frame *f, int x, int y, int width, int height) { - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - x, y, width, height, False); + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), x, y, width, height); #ifdef USE_GTK /* Must queue a redraw, because scroll bars might have been cleared. */ if (FRAME_GTK_WIDGET (f)) @@ -7398,7 +7307,9 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height) /* RIF: Draw cursor on window W. */ static void -x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p) +x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, + int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) { struct frame *f = XFRAME (WINDOW_FRAME (w)); @@ -7451,9 +7362,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int #endif } -#ifndef XFlush XFlush (FRAME_X_DISPLAY (f)); -#endif } @@ -7488,7 +7397,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) else { /* Create the GNU bitmap and mask if necessary. */ - if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) + if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0) { ptrdiff_t rc = -1; @@ -7502,7 +7411,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits); if (rc != -1) - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc; #endif @@ -7514,8 +7423,8 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) 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); + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc; + x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id); } } @@ -7523,9 +7432,9 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) this increments the ref-count one extra time. As a result, the GNU bitmap and mask are never freed. That way, we don't have to worry about allocating it again. */ - x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + x_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id); - bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id; + bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id; } x_wm_set_icon_pixmap (f, bitmap_id); @@ -7659,7 +7568,7 @@ x_check_errors (Display *dpy, const char *format) /* Nonzero if we had any X protocol errors since we did x_catch_errors on DPY. */ -int +bool x_had_errors_p (Display *dpy) { /* Make sure to catch any errors incurred so far. */ @@ -7739,7 +7648,7 @@ x_connection_closed (Display *dpy, const char *error_message) if (FRAME_X_P (XFRAME (frame)) && FRAME_X_P (XFRAME (minibuf_frame)) && ! EQ (frame, minibuf_frame) - && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo) + && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo) delete_frame (frame, Qnoelisp); } @@ -7748,7 +7657,7 @@ x_connection_closed (Display *dpy, const char *error_message) for another frame that we need to delete. */ FOR_EACH_FRAME (tail, frame) if (FRAME_X_P (XFRAME (frame)) - && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) + && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) { /* Set this to t so that delete_frame won't get confused trying to find a replacement. */ @@ -7824,10 +7733,9 @@ static void x_error_quitter (Display *, XErrorEvent *); static int x_error_handler (Display *display, XErrorEvent *event) { -#ifdef HAVE_GTK3 - if (event->error_code == BadMatch - && event->request_code == X_SetInputFocus - && event->minor_code == 0) +#if defined USE_GTK && defined HAVE_GTK3 + if ((event->error_code == BadMatch || event->error_code == BadWindow) + && event->request_code == X_SetInputFocus) { return 0; } @@ -7972,7 +7880,7 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data) FOR_EACH_FRAME (tail, frame) { struct frame *f = XFRAME (frame); - if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo) + if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo) { FRAME_XIC (f) = NULL; xic_free_xfontset (f); @@ -8063,7 +7971,7 @@ xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_ struct frame *f = XFRAME (frame); if (FRAME_X_P (f) - && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo) + && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo) if (FRAME_XIC (f) == NULL) { create_frame_xic (f); @@ -8098,13 +8006,10 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) { #ifdef HAVE_X11R6_XIM struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst); - ptrdiff_t len; dpyinfo->xim_callback_data = xim_inst; xim_inst->dpyinfo = dpyinfo; - len = strlen (resource_name); - xim_inst->resource_name = xmalloc (len + 1); - memcpy (xim_inst->resource_name, resource_name, len + 1); + xim_inst->resource_name = xstrdup (resource_name); XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb, resource_name, emacs_class, xim_instantiate_callback, @@ -8164,7 +8069,7 @@ x_calc_absolute_position (struct frame *f) /* Treat negative positions as relative to the leftmost bottommost position that fits on the screen. */ if (flags & XNegative) - f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)) + f->left_pos = x_display_pixel_width (FRAME_DISPLAY_INFO (f)) - FRAME_PIXEL_WIDTH (f) + f->left_pos; { @@ -8187,7 +8092,7 @@ x_calc_absolute_position (struct frame *f) #endif if (flags & YNegative) - f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)) + f->top_pos = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height + f->top_pos; } @@ -8210,9 +8115,6 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ if (change_gravity > 0) { - FRAME_X_OUTPUT (f)->left_before_move = f->left_pos; - FRAME_X_OUTPUT (f)->top_before_move = f->top_pos; - f->top_pos = yoff; f->left_pos = xoff; f->size_hint_flags &= ~ (XNegative | YNegative); @@ -8230,7 +8132,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ modified_left = f->left_pos; modified_top = f->top_pos; - if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A) + if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A) { /* Some WMs (twm, wmaker at least) has an offset that is smaller than the WM decorations. So we use the calculated offset instead @@ -8243,7 +8145,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ modified_left, modified_top); x_sync_with_move (f, f->left_pos, f->top_pos, - FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN + FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN ? 1 : 0); /* change_gravity is non-zero when this function is called from Lisp to @@ -8257,8 +8159,8 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ need to compute the top/left offset adjustment for this frame. */ if (change_gravity != 0 && - (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN - || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A + (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN + || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A && (FRAME_X_OUTPUT (f)->move_offset_left == 0 && FRAME_X_OUTPUT (f)->move_offset_top == 0)))) x_check_expected_move (f, modified_left, modified_top); @@ -8279,7 +8181,7 @@ wm_supports (struct frame *f, Atom want_atom) unsigned long actual_size, bytes_remaining; int i, rc, actual_format; Window wmcheck_window; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Window target_window = dpyinfo->root_window; long max_len = 65536; Display *dpy = FRAME_X_DISPLAY (f); @@ -8360,7 +8262,7 @@ wm_supports (struct frame *f, Atom want_atom) static void set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame)); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame)); x_send_client_event (frame, make_number (0), frame, dpyinfo->Xatom_net_wm_state, @@ -8370,16 +8272,16 @@ set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value) (make_number (add ? 1 : 0), Fcons (make_fixnum_or_float (atom), - value != 0 - ? Fcons (make_fixnum_or_float (value), Qnil) - : Qnil))); + (value != 0 + ? list1 (make_fixnum_or_float (value)) + : Qnil)))); } void x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { Lisp_Object frame; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); XSETFRAME (frame, f); @@ -8402,7 +8304,7 @@ get_current_wm_state (struct frame *f, Atom actual_type; unsigned long actual_size, bytes_remaining; int i, rc, actual_format, is_hidden = 0; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); long max_len = 65536; Display *dpy = FRAME_X_DISPLAY (f); unsigned char *tmp_data = NULL; @@ -8466,7 +8368,7 @@ get_current_wm_state (struct frame *f, static int do_ewmh_fullscreen (struct frame *f) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state); int cur, dummy; @@ -8533,7 +8435,7 @@ do_ewmh_fullscreen (struct frame *f) } static void -XTfullscreen_hook (FRAME_PTR f) +XTfullscreen_hook (struct frame *f) { if (FRAME_VISIBLE_P (f)) { @@ -8546,7 +8448,7 @@ XTfullscreen_hook (FRAME_PTR f) static int -x_handle_net_wm_state (struct frame *f, XPropertyEvent *event) +x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event) { int value = FULLSCREEN_NONE; Lisp_Object lval; @@ -8584,7 +8486,7 @@ x_check_fullscreen (struct frame *f) if (do_ewmh_fullscreen (f)) return; - if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window) + if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window) return; /* Only fullscreen without WM or with EWM hints (above). */ /* Setting fullscreen to nil doesn't do anything. We could save the @@ -8594,7 +8496,7 @@ x_check_fullscreen (struct frame *f) if (f->want_fullscreen != FULLSCREEN_NONE) { int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f); - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); switch (f->want_fullscreen) { @@ -8641,7 +8543,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top) int adjusted_left; int adjusted_top; - FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A; + FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A; FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left; FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top; @@ -8659,7 +8561,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top) /* It's a "Type B" window manager. We don't have to adjust the frame's position. */ - FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; + FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; } @@ -8711,19 +8613,18 @@ x_wait_for_event (struct frame *f, int eventtype) { int level = interrupt_input_blocked; - SELECT_TYPE fds; - EMACS_TIME tmo, tmo_at, time_now; + fd_set fds; + struct timespec tmo, tmo_at, time_now; int fd = ConnectionNumber (FRAME_X_DISPLAY (f)); - pending_event_wait.f = f; - pending_event_wait.eventtype = eventtype; + f->wait_event_type = eventtype; /* Set timeout to 0.1 second. Hopefully not noticeable. Maybe it should be configurable. */ - tmo = make_emacs_time (0, 100 * 1000 * 1000); - tmo_at = add_emacs_time (current_emacs_time (), tmo); + tmo = make_timespec (0, 100 * 1000 * 1000); + tmo_at = timespec_add (current_timespec (), tmo); - while (pending_event_wait.eventtype) + while (f->wait_event_type) { pending_signals = 1; totally_unblock_input (); @@ -8734,16 +8635,16 @@ x_wait_for_event (struct frame *f, int eventtype) FD_ZERO (&fds); FD_SET (fd, &fds); - time_now = current_emacs_time (); - if (EMACS_TIME_LT (tmo_at, time_now)) + time_now = current_timespec (); + if (timespec_cmp (tmo_at, time_now) < 0) break; - tmo = sub_emacs_time (tmo_at, time_now); + tmo = timespec_sub (tmo_at, time_now); if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0) break; /* Timeout */ } - pending_event_wait.f = 0; - pending_event_wait.eventtype = 0; + + f->wait_event_type = 0; } @@ -8934,7 +8835,7 @@ x_lower_frame (struct frame *f) /* Request focus with XEmbed */ void -xembed_request_focus (FRAME_PTR f) +xembed_request_focus (struct frame *f) { /* See XEmbed Protocol Specification at http://freedesktop.org/wiki/Specifications/xembed-spec */ @@ -8946,25 +8847,26 @@ xembed_request_focus (FRAME_PTR f) /* Activate frame with Extended Window Manager Hints */ void -x_ewmh_activate_frame (FRAME_PTR f) +x_ewmh_activate_frame (struct frame *f) { /* See Window Manager Specification/Extended Window Manager Hints at http://freedesktop.org/wiki/Specifications/wm-spec */ - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window)) { Lisp_Object frame; XSETFRAME (frame, f); x_send_client_event (frame, make_number (0), frame, - dpyinfo->Xatom_net_active_window, - make_number (32), list2i (1, last_user_time)); + dpyinfo->Xatom_net_active_window, + make_number (32), + list2i (1, dpyinfo->last_user_time)); } } static void -XTframe_raise_lower (FRAME_PTR f, int raise_flag) +XTframe_raise_lower (struct frame *f, int raise_flag) { if (raise_flag) x_raise_frame (f); @@ -8984,7 +8886,7 @@ static void xembed_set_info (struct frame *f, enum xembed_info flags) { unsigned long data[2]; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); data[0] = XEMBED_VERSION; data[1] = flags; @@ -9003,7 +8905,7 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg, event.xclient.type = ClientMessage; event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc; - event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED; + event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED; event.xclient.format = 32; event.xclient.data.l[0] = t; event.xclient.data.l[1] = msg; @@ -9028,7 +8930,6 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg, void x_make_frame_visible (struct frame *f) { - Lisp_Object type; int original_top, original_left; int retry_count = 2; @@ -9036,9 +8937,7 @@ x_make_frame_visible (struct frame *f) block_input (); - type = x_icon_type (f); - if (!NILP (type)) - x_bitmap_icon (f, type); + x_set_bitmap_icon (f); if (! FRAME_VISIBLE_P (f)) { @@ -9193,8 +9092,8 @@ x_make_frame_invisible (struct frame *f) window = FRAME_OUTER_WINDOW (f); /* Don't keep the highlight on an invisible frame. */ - if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) - FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0; + if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f) + FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0; block_input (); @@ -9245,20 +9144,17 @@ x_iconify_frame (struct frame *f) #ifdef USE_X_TOOLKIT int result; #endif - Lisp_Object type; /* Don't keep the highlight on an invisible frame. */ - if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) - FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0; + if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f) + FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0; if (FRAME_ICONIFIED_P (f)) return; block_input (); - type = x_icon_type (f); - if (!NILP (type)) - x_bitmap_icon (f, type); + x_set_bitmap_icon (f); #if defined (USE_GTK) if (FRAME_GTK_OUTER_WIDGET (f)) @@ -9324,7 +9220,7 @@ x_iconify_frame (struct frame *f) msg.xclient.window = FRAME_X_WINDOW (f); msg.xclient.type = ClientMessage; - msg.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state; + msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state; msg.xclient.format = 32; msg.xclient.data.l[0] = IconicState; @@ -9363,7 +9259,7 @@ x_iconify_frame (struct frame *f) void x_free_frame_resources (struct frame *f) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; #ifdef USE_X_TOOLKIT Lisp_Object bar; @@ -9448,6 +9344,19 @@ x_free_frame_resources (struct frame *f) unload_color (f, f->output_data.x->black_relief.pixel); x_free_gcs (f); + + /* Free extra GCs allocated by x_setup_relief_colors. */ + if (f->output_data.x->white_relief.gc) + { + XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc); + f->output_data.x->white_relief.gc = 0; + } + if (f->output_data.x->black_relief.gc) + { + XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc); + f->output_data.x->black_relief.gc = 0; + } + XFlush (FRAME_X_DISPLAY (f)); } @@ -9461,16 +9370,8 @@ x_free_frame_resources (struct frame *f) dpyinfo->x_focus_event_frame = 0; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; - if (f == hlinfo->mouse_face_mouse_frame) - { - hlinfo->mouse_face_beg_row - = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row - = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - hlinfo->mouse_face_mouse_frame = 0; - } + reset_mouse_highlight (hlinfo); unblock_input (); } @@ -9481,7 +9382,7 @@ x_free_frame_resources (struct frame *f) static void x_destroy_window (struct frame *f) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); /* If a display connection is dead, don't try sending more commands to the X server. */ @@ -9527,9 +9428,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) size_hints.width_inc = FRAME_COLUMN_WIDTH (f); size_hints.height_inc = FRAME_LINE_HEIGHT (f); - size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)) + size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f)) - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); - size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)) + size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); /* Calculate the base and minimum sizes. */ @@ -9813,18 +9714,11 @@ get_bits_and_offset (long unsigned int mask, int *bits, int *offset) /* Return 1 if display DISPLAY is available for use, 0 otherwise. But don't permanently open it, just test its availability. */ -int +bool x_display_ok (const char *display) { - int dpy_ok = 1; - Display *dpy; - - dpy = XOpenDisplay (display); - if (dpy) - XCloseDisplay (dpy); - else - dpy_ok = 0; - return dpy_ok; + Display *dpy = XOpenDisplay (display); + return dpy ? (XCloseDisplay (dpy), 1) : 0; } #ifdef USE_GTK @@ -9849,7 +9743,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) struct terminal *terminal; struct x_display_info *dpyinfo; XrmDatabase xrdb; - Mouse_HLInfo *hlinfo; ptrdiff_t lim; block_input (); @@ -9990,32 +9883,20 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) /* We have definitely succeeded. Record the new connection. */ dpyinfo = xzalloc (sizeof *dpyinfo); - hlinfo = &dpyinfo->mouse_highlight; - terminal = x_create_terminal (dpyinfo); { struct x_display_info *share; - Lisp_Object tail; - for (share = x_display_list, tail = x_display_name_list; share; - share = share->next, tail = XCDR (tail)) - if (same_x_server (SSDATA (XCAR (XCAR (tail))), + for (share = x_display_list; share; share = share->next) + if (same_x_server (SSDATA (XCAR (share->name_list_element)), SSDATA (display_name))) break; if (share) terminal->kboard = share->terminal->kboard; else { - terminal->kboard = xmalloc (sizeof *terminal->kboard); - init_kboard (terminal->kboard); - kset_window_system (terminal->kboard, Qx); - - /* Add the keyboard to the list before running Lisp code (via - Qvendor_specific_keysyms below), since these are not traced - via terminals but only through all_kboards. */ - terminal->kboard->next_kboard = all_kboards; - all_kboards = terminal->kboard; + terminal->kboard = allocate_kboard (Qx); if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound)) { @@ -10054,17 +9935,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->next = x_display_list; x_display_list = dpyinfo; - /* Put it on x_display_name_list as well, to keep them parallel. */ - x_display_name_list = Fcons (Fcons (display_name, Qnil), - x_display_name_list); - dpyinfo->name_list_element = XCAR (x_display_name_list); - + dpyinfo->name_list_element = Fcons (display_name, Qnil); dpyinfo->display = dpy; /* Set the name of the terminal. */ - terminal->name = xmalloc (SBYTES (display_name) + 1); - memcpy (terminal->name, SSDATA (display_name), SBYTES (display_name)); - terminal->name[SBYTES (display_name)] = 0; + terminal->name = xlispstrdup (display_name); #if 0 XSetAfterFunction (x_current_display, x_trace_wire); @@ -10106,33 +9981,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) select_visual (dpyinfo); dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen); dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen); - dpyinfo->client_leader_window = 0; - dpyinfo->grabbed = 0; - dpyinfo->reference_count = 0; dpyinfo->icon_bitmap_id = -1; - dpyinfo->n_fonts = 0; - dpyinfo->bitmaps = 0; - dpyinfo->bitmaps_size = 0; - dpyinfo->bitmaps_last = 0; - dpyinfo->scratch_cursor_gc = 0; - hlinfo->mouse_face_mouse_frame = 0; - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_face_id = DEFAULT_FACE_ID; - hlinfo->mouse_face_window = Qnil; - hlinfo->mouse_face_overlay = Qnil; - hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0; - hlinfo->mouse_face_defer = 0; - hlinfo->mouse_face_hidden = 0; - dpyinfo->x_focus_frame = 0; - dpyinfo->x_focus_event_frame = 0; - dpyinfo->x_highlight_frame = 0; dpyinfo->wm_type = X_WMTYPE_UNKNOWN; - /* See if we can construct pixel values from RGB values. */ - dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0; - dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0; + reset_mouse_highlight (&dpyinfo->mouse_highlight); + /* See if we can construct pixel values from RGB values. */ if (dpyinfo->visual->class == TrueColor) { get_bits_and_offset (dpyinfo->visual->red_mask, @@ -10192,71 +10046,73 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } { - const struct + static const struct { const char *name; - Atom *atom; + int offset; } atom_refs[] = { - { "WM_PROTOCOLS", &dpyinfo->Xatom_wm_protocols }, - { "WM_TAKE_FOCUS", &dpyinfo->Xatom_wm_take_focus }, - { "WM_SAVE_YOURSELF", &dpyinfo->Xatom_wm_save_yourself }, - { "WM_DELETE_WINDOW", &dpyinfo->Xatom_wm_delete_window }, - { "WM_CHANGE_STATE", &dpyinfo->Xatom_wm_change_state }, - { "WM_CONFIGURE_DENIED", &dpyinfo->Xatom_wm_configure_denied }, - { "WM_MOVED", &dpyinfo->Xatom_wm_window_moved }, - { "WM_CLIENT_LEADER", &dpyinfo->Xatom_wm_client_leader }, - { "Editres", &dpyinfo->Xatom_editres }, - { "CLIPBOARD", &dpyinfo->Xatom_CLIPBOARD }, - { "TIMESTAMP", &dpyinfo->Xatom_TIMESTAMP }, - { "TEXT", &dpyinfo->Xatom_TEXT }, - { "COMPOUND_TEXT", &dpyinfo->Xatom_COMPOUND_TEXT }, - { "UTF8_STRING", &dpyinfo->Xatom_UTF8_STRING }, - { "DELETE", &dpyinfo->Xatom_DELETE }, - { "MULTIPLE", &dpyinfo->Xatom_MULTIPLE }, - { "INCR", &dpyinfo->Xatom_INCR }, - { "_EMACS_TMP_", &dpyinfo->Xatom_EMACS_TMP }, - { "TARGETS", &dpyinfo->Xatom_TARGETS }, - { "NULL", &dpyinfo->Xatom_NULL }, - { "ATOM", &dpyinfo->Xatom_ATOM }, - { "ATOM_PAIR", &dpyinfo->Xatom_ATOM_PAIR }, - { "CLIPBOARD_MANAGER", &dpyinfo->Xatom_CLIPBOARD_MANAGER }, - { "_XEMBED_INFO", &dpyinfo->Xatom_XEMBED_INFO }, +#define ATOM_REFS_INIT(string, member) \ + { string, offsetof (struct x_display_info, member) }, + ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols) + ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus) + ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself) + ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window) + ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state) + ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied) + ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved) + ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader) + ATOM_REFS_INIT ("Editres", Xatom_editres) + ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD) + ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP) + ATOM_REFS_INIT ("TEXT", Xatom_TEXT) + ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT) + ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING) + ATOM_REFS_INIT ("DELETE", Xatom_DELETE) + ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE) + ATOM_REFS_INIT ("INCR", Xatom_INCR) + ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP) + ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS) + ATOM_REFS_INIT ("NULL", Xatom_NULL) + ATOM_REFS_INIT ("ATOM", Xatom_ATOM) + ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR) + ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) + ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) /* For properties of font. */ - { "PIXEL_SIZE", &dpyinfo->Xatom_PIXEL_SIZE }, - { "AVERAGE_WIDTH", &dpyinfo->Xatom_AVERAGE_WIDTH }, - { "_MULE_BASELINE_OFFSET", &dpyinfo->Xatom_MULE_BASELINE_OFFSET }, - { "_MULE_RELATIVE_COMPOSE", &dpyinfo->Xatom_MULE_RELATIVE_COMPOSE }, - { "_MULE_DEFAULT_ASCENT", &dpyinfo->Xatom_MULE_DEFAULT_ASCENT }, + ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE) + ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH) + ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET) + ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE) + ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT) /* Ghostscript support. */ - { "DONE", &dpyinfo->Xatom_DONE }, - { "PAGE", &dpyinfo->Xatom_PAGE }, - { "SCROLLBAR", &dpyinfo->Xatom_Scrollbar }, - { "_XEMBED", &dpyinfo->Xatom_XEMBED }, + ATOM_REFS_INIT ("DONE", Xatom_DONE) + ATOM_REFS_INIT ("PAGE", Xatom_PAGE) + ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) + ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) /* EWMH */ - { "_NET_WM_STATE", &dpyinfo->Xatom_net_wm_state }, - { "_NET_WM_STATE_FULLSCREEN", &dpyinfo->Xatom_net_wm_state_fullscreen }, - { "_NET_WM_STATE_MAXIMIZED_HORZ", - &dpyinfo->Xatom_net_wm_state_maximized_horz }, - { "_NET_WM_STATE_MAXIMIZED_VERT", - &dpyinfo->Xatom_net_wm_state_maximized_vert }, - { "_NET_WM_STATE_STICKY", &dpyinfo->Xatom_net_wm_state_sticky }, - { "_NET_WM_STATE_HIDDEN", &dpyinfo->Xatom_net_wm_state_hidden }, - { "_NET_WM_WINDOW_TYPE", &dpyinfo->Xatom_net_window_type }, - { "_NET_WM_WINDOW_TYPE_TOOLTIP", - &dpyinfo->Xatom_net_window_type_tooltip }, - { "_NET_WM_ICON_NAME", &dpyinfo->Xatom_net_wm_icon_name }, - { "_NET_WM_NAME", &dpyinfo->Xatom_net_wm_name }, - { "_NET_SUPPORTED", &dpyinfo->Xatom_net_supported }, - { "_NET_SUPPORTING_WM_CHECK", &dpyinfo->Xatom_net_supporting_wm_check }, - { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity }, - { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window }, - { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents }, - { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop }, - { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea }, + ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) + ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen) + ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ", + Xatom_net_wm_state_maximized_horz) + ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT", + Xatom_net_wm_state_maximized_vert) + ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky) + ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden) + ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type) + ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP", + Xatom_net_window_type_tooltip) + ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name) + ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name) + ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported) + ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check) + ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity) + ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window) + ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents) + ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop) + ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea) /* Session management */ - { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID }, - { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop }, - { "MANAGER", &dpyinfo->Xatom_xsettings_mgr }, + ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) + ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) + ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) }; int i; @@ -10281,7 +10137,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) False, atoms_return); for (i = 0; i < atom_count; i++) - *atom_refs[i].atom = atoms_return[i]; + *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i]; /* Manual copy of last atom */ dpyinfo->Xatom_xsettings_sel = atoms_return[i]; @@ -10291,16 +10147,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } dpyinfo->x_dnd_atoms_size = 8; - dpyinfo->x_dnd_atoms_length = 0; dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms * dpyinfo->x_dnd_atoms_size); - - dpyinfo->net_supported_atoms = NULL; - dpyinfo->nr_net_supported_atoms = 0; - dpyinfo->net_supported_window = 0; - - connection = ConnectionNumber (dpyinfo->display); - dpyinfo->connection = connection; dpyinfo->gray = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, gray_bits, gray_width, gray_height, @@ -10312,6 +10160,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) xsettings_initialize (dpyinfo); + connection = ConnectionNumber (dpyinfo->display); + /* This is only needed for distinguishing keyboard and process input. */ if (connection != 0) add_keyboard_wait_descriptor (connection); @@ -10412,29 +10262,6 @@ x_delete_display (struct x_display_info *dpyinfo) break; } - delete_keyboard_wait_descriptor (dpyinfo->connection); - - /* Discard this display from x_display_name_list and x_display_list. - We can't use Fdelq because that can quit. */ - if (! NILP (x_display_name_list) - && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element)) - x_display_name_list = XCDR (x_display_name_list); - else - { - Lisp_Object tail; - - tail = x_display_name_list; - while (CONSP (tail) && CONSP (XCDR (tail))) - { - if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element)) - { - XSETCDR (tail, XCDR (XCDR (tail))); - break; - } - tail = XCDR (tail); - } - } - if (next_noop_dpyinfo == dpyinfo) next_noop_dpyinfo = dpyinfo->next; @@ -10491,7 +10318,7 @@ x_activate_timeout_atimer (void) block_input (); if (!x_timeout_atimer_activated_flag) { - EMACS_TIME interval = make_emacs_time (0, 100 * 1000 * 1000); + struct timespec interval = make_timespec (0, 100 * 1000 * 1000); start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0); x_timeout_atimer_activated_flag = 1; } @@ -10514,13 +10341,7 @@ static struct redisplay_interface x_redisplay_interface = x_after_update_window_line, x_update_window_begin, x_update_window_end, - x_cursor_to, - x_flush, -#ifdef XFlush x_flush, -#else - 0, /* flush_display_optional */ -#endif x_clear_window_mouse_face, x_get_glyph_overhangs, x_fix_overlapping_area, @@ -10542,6 +10363,7 @@ void x_delete_terminal (struct terminal *terminal) { struct x_display_info *dpyinfo = terminal->display_info.x; + int connection = -1; /* Protect against recursive calls. delete_frame in delete_terminal calls us back when it deletes our last frame. */ @@ -10560,6 +10382,8 @@ x_delete_terminal (struct terminal *terminal) and dpyinfo->display was set to 0 to indicate that. */ if (dpyinfo->display) { + connection = ConnectionNumber (dpyinfo->display); + x_destroy_all_bitmaps (dpyinfo); XSetCloseDownMode (dpyinfo->display, DestroyAll); @@ -10600,6 +10424,10 @@ x_delete_terminal (struct terminal *terminal) #endif /* ! USE_GTK */ } + /* No more input on this descriptor. */ + if (connection != -1) + delete_keyboard_wait_descriptor (connection); + /* Mark as dead. */ dpyinfo->display = NULL; x_delete_display (dpyinfo); @@ -10627,11 +10455,11 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->delete_glyphs_hook = x_delete_glyphs; terminal->ring_bell_hook = XTring_bell; terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer; - terminal->reset_terminal_modes_hook = XTreset_terminal_modes; - terminal->set_terminal_modes_hook = XTset_terminal_modes; + terminal->reset_terminal_modes_hook = NULL; + terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = x_update_begin; terminal->update_end_hook = x_update_end; - terminal->set_terminal_window_hook = XTset_terminal_window; + terminal->set_terminal_window_hook = NULL; terminal->read_socket_hook = XTread_socket; terminal->frame_up_to_date_hook = XTframe_up_to_date; terminal->mouse_position_hook = XTmouse_position; @@ -10647,12 +10475,6 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->delete_terminal_hook = x_delete_terminal; terminal->rif = &x_redisplay_interface; - terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */ - terminal->char_ins_del_ok = 1; - terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */ - terminal->fast_clear_end_of_line = 1; /* X does this well. */ - terminal->memory_below_frame = 0; /* We don't remember what scrolls - off the bottom. */ return terminal; } @@ -10697,10 +10519,6 @@ x_initialize (void) #endif #endif - pending_autoraise_frame = 0; - pending_event_wait.f = 0; - pending_event_wait.eventtype = 0; - /* Note that there is no real way portable across R3/R4 to get the original error handler. */ XSetErrorHandler (x_error_handler); @@ -10713,18 +10531,9 @@ syms_of_xterm (void) { x_error_message = NULL; - staticpro (&x_display_name_list); - x_display_name_list = Qnil; - - staticpro (&last_mouse_scroll_bar); - last_mouse_scroll_bar = Qnil; - DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); - staticpro (&last_mouse_press_frame); - last_mouse_press_frame = Qnil; - #ifdef USE_GTK xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); staticpro (&xg_default_icon_file); @@ -10780,9 +10589,6 @@ With MS Windows or Nextstep, the value is t. */); Vx_toolkit_scroll_bars = Qnil; #endif - staticpro (&last_mouse_motion_frame); - last_mouse_motion_frame = Qnil; - Qmodifier_value = intern_c_string ("modifier-value"); Qalt = intern_c_string ("alt"); Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); @@ -10828,5 +10634,3 @@ default is nil, which is the same as `super'. */); make_float (DEFAULT_REHASH_THRESHOLD), Qnil); } - -#endif /* HAVE_X_WINDOWS */