X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/7a22490f14441898e1c4f6679f5924f097f3bb34..b7e0ef72d0ac61b5d3ef06a3f565695c75ec2540:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 6f57836c9a..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" @@ -86,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 @@ -140,104 +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 bool any_help_event_p; -/* Last window where we saw the mouse. Used by mouse-autoselect-window. */ -static Lisp_Object last_window; - /* 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 struct frame *last_mouse_glyph_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. */ @@ -292,15 +218,11 @@ 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 *); @@ -308,15 +230,14 @@ 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 *); @@ -325,12 +246,13 @@ 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 @@ -342,29 +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) - { - eassert (FRAME_X_P (f)); - XFlush (FRAME_X_DISPLAY (f)); - } - else - { - /* Flush all displays and so all frames on them. */ - struct x_display_info *xdi; - for (xdi = x_display_list; xdi; xdi = xdi->next) - XFlush (xdi->display); - } + XFlush (FRAME_X_DISPLAY (f)); unblock_input (); } @@ -434,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; @@ -453,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; @@ -553,8 +465,7 @@ x_update_begin (struct frame *f) } -/* Start update of window W. Set output_cursor to the cursor - position of W. */ +/* Start update of window W. */ static void x_update_window_begin (struct window *w) @@ -562,7 +473,7 @@ x_update_window_begin (struct window *w) struct frame *f = XFRAME (WINDOW_FRAME (w)); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - set_output_cursor (&w->cursor); + w->output_cursor = w->cursor; block_input (); @@ -612,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); @@ -634,11 +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; - } + reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame))); } @@ -705,10 +611,10 @@ x_after_update_window_line (struct window *w, 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 (); } } @@ -723,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) { @@ -816,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; @@ -840,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 ***********************************************************************/ @@ -941,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; } } @@ -988,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); @@ -1431,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; } @@ -1640,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) { @@ -1880,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; @@ -2975,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); } @@ -2990,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)); @@ -3074,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)) @@ -3119,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); @@ -3185,9 +3047,9 @@ 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), @@ -3220,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 ***********************************************************************/ @@ -3259,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 @@ -3394,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); @@ -3456,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) @@ -3529,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 @@ -3745,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. @@ -3755,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 @@ -3775,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. @@ -3784,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 (struct frame *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. @@ -3869,10 +3892,11 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, Time *timestamp) { 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 { @@ -3890,7 +3914,7 @@ XTmouse_position (struct frame **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), @@ -3928,22 +3952,24 @@ XTmouse_position (struct frame **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 { @@ -3967,7 +3993,7 @@ XTmouse_position (struct frame **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; @@ -3989,10 +4015,10 @@ XTmouse_position (struct frame **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 @@ -4038,15 +4064,17 @@ XTmouse_position (struct frame **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; } } } @@ -4132,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. */ @@ -4190,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 @@ -4226,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 @@ -4286,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); @@ -4306,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; } @@ -4335,32 +4339,32 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) 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; @@ -4376,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; @@ -4387,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); } } @@ -4417,45 +4420,44 @@ 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, @@ -4463,7 +4465,7 @@ xg_end_scroll_callback (GtkWidget *widget, gpointer user_data) { struct scroll_bar *bar = user_data; - bar->dragging = Qnil; + bar->dragging = -1; if (WINDOWP (window_being_scrolled)) { x_send_scroll_bar_event (window_being_scrolled, @@ -4490,7 +4492,7 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer 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 (); @@ -4511,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); } @@ -4532,7 +4534,7 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) /* The position really is stored cast to a pointer. */ int position = (intptr_t) call_data; Dimension height; - int part; + enum scroll_bar_part part; /* Get the height of the scroll bar. */ block_input (); @@ -4550,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); } @@ -4826,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; @@ -4861,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 { @@ -4929,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); @@ -4938,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, @@ -4965,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); @@ -4980,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 */ } @@ -5023,7 +5025,7 @@ 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; struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); GC gc = f->output_data.x->normal_gc; @@ -5075,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) @@ -5102,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 (); @@ -5155,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; @@ -5188,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? */ @@ -5209,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 (); } @@ -5248,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 @@ -5294,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); } } @@ -5307,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); @@ -5333,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); @@ -5467,12 +5434,11 @@ XTjudge_scroll_bars (struct frame *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; 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 (); @@ -5485,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) @@ -5509,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 (); @@ -5517,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 @@ -5543,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 @@ -5567,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) { struct frame *f = XFRAME (XWINDOW (bar->window)->frame); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - last_mouse_movement_time = event->xmotion.time; - + 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) { @@ -5601,7 +5566,8 @@ 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; struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); int win_x, win_y; @@ -5613,27 +5579,24 @@ x_scroll_bar_report_motion (struct frame **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; @@ -5643,7 +5606,7 @@ x_scroll_bar_report_motion (struct frame **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; @@ -5656,11 +5619,10 @@ x_scroll_bar_report_motion (struct frame **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 (); } @@ -5688,18 +5650,7 @@ x_scroll_bar_clear (struct frame *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. */ @@ -5712,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. */ @@ -5724,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, @@ -5831,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 { @@ -5845,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; @@ -5857,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)) @@ -5898,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); @@ -5917,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 @@ -5933,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 */ @@ -5964,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) { @@ -5988,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); @@ -6020,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; @@ -6077,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) { @@ -6114,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); @@ -6156,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 { @@ -6170,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); } @@ -6181,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; @@ -6197,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; @@ -6218,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. */ { @@ -6249,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; @@ -6257,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); @@ -6297,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) @@ -6306,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) @@ -6317,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) @@ -6324,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); @@ -6353,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 @@ -6362,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 @@ -6392,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) @@ -6400,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); } @@ -6417,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 @@ -6437,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. */ @@ -6614,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 @@ -6626,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 @@ -6637,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) @@ -6685,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) { @@ -6713,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) @@ -6722,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 @@ -6741,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 @@ -6776,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 @@ -6791,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 @@ -6803,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 @@ -6822,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)) @@ -6841,42 +6772,37 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, by the rest of Emacs, we put it here. */ 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) @@ -6885,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 @@ -6939,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 @@ -6948,19 +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; - *finish = X_EVENT_DROP; + 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; @@ -6980,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: @@ -6999,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; @@ -7037,7 +6967,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } SAFE_FREE (); - *eventptr = event; return count; } @@ -7077,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 (); @@ -7084,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 @@ -7163,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 (); @@ -7191,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; @@ -7215,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; @@ -7282,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; @@ -7303,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); @@ -7368,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)) @@ -7381,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)); @@ -7434,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 } @@ -7471,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; @@ -7485,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 @@ -7497,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); } } @@ -7506,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); @@ -7722,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); } @@ -7731,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. */ @@ -7954,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); @@ -8045,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); @@ -8143,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; { @@ -8166,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; } @@ -8189,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); @@ -8209,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 @@ -8222,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 @@ -8236,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); @@ -8258,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); @@ -8339,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, @@ -8358,7 +8281,7 @@ 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); @@ -8381,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; @@ -8445,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; @@ -8525,7 +8448,7 @@ XTfullscreen_hook (struct frame *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; @@ -8563,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 @@ -8573,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) { @@ -8620,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; @@ -8638,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; } @@ -8690,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 (); @@ -8713,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; } @@ -8930,15 +8852,16 @@ 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)); } } @@ -8963,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; @@ -8982,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; @@ -9007,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; @@ -9015,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)) { @@ -9172,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 (); @@ -9224,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)) @@ -9303,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; @@ -9342,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; @@ -9453,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 (); } @@ -9473,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. */ @@ -9519,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. */ @@ -9834,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 (); @@ -9975,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)) { @@ -10039,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); @@ -10091,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, @@ -10278,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, @@ -10299,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); @@ -10399,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; @@ -10478,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; } @@ -10501,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, @@ -10529,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. */ @@ -10547,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); @@ -10587,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); @@ -10614,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; @@ -10634,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; } @@ -10684,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); @@ -10700,12 +10531,6 @@ 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"); @@ -10764,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)); @@ -10812,5 +10634,3 @@ default is nil, which is the same as `super'. */); make_float (DEFAULT_REHASH_THRESHOLD), Qnil); } - -#endif /* HAVE_X_WINDOWS */