*** Improving performance with slow X connections.
-There are several ways to improve this performance, any subset of which can
-be carried out at the same time:
+There are several ways to improve this performance, any subset of
+which can be carried out at the same time:
-1) If you don't need X Input Methods (XIM) for entering text in some
+1) Use the "--with-x-toolkit=no" build of Emacs. By not relying on
+ any toolkit (exhibiting potentially slow behavior), it has been
+ made very fast over networks exhibiting high latency, but suitable
+ bandwidth.
+
+2) If you don't need X Input Methods (XIM) for entering text in some
language you use, you can improve performance on WAN links by using
the X resource useXIM to turn off use of XIM. This does not affect
the use of Emacs's own input methods, which are part of the Leim
package.
-2) If the connection is very slow, you might also want to consider
+3) If the connection is very slow, you might also want to consider
switching off scroll bars, menu bar, and tool bar. Adding the
following forms to your .emacs file will accomplish that, but only
after the initial frame is displayed:
Emacs.menuBar: off
Emacs.toolBar: off
-3) Use ssh to forward the X connection, and enable compression on this
+4) Use ssh to forward the X connection, and enable compression on this
forwarded X connection (ssh -XC remotehostname emacs ...).
-4) Use lbxproxy on the remote end of the connection. This is an interface
- to the low bandwidth X extension in most modern X servers, which
- improves performance dramatically, at the slight expense of correctness
- of the X protocol. lbxproxy achieves the performance gain by grouping
- several X requests in one TCP packet and sending them off together,
- instead of requiring a round-trip for each X request in a separate
- packet. The switches that seem to work best for emacs are:
- -noatomsfile -nowinattr -cheaterrors -cheatevents
- Note that the -nograbcmap option is known to cause problems.
- For more about lbxproxy, see:
+ Keep in mind that this does not help with latency problems, only
+ andwidth ones.
+
+5) Use lbxproxy on the remote end of the connection. This is an
+ interface to the low bandwidth X extension in some outdated X
+ servers, which improves performance dramatically, at the slight
+ expense of correctness of the X protocol. lbxproxy achieves the
+ performance gain by grouping several X requests in one TCP packet
+ and sending them off together, instead of requiring a round-trip
+ for each X request in a separate packet. The switches that seem to
+ work best for emacs are: -noatomsfile -nowinattr -cheaterrors
+ -cheatevents Note that the -nograbcmap option is known to cause
+ problems. For more about lbxproxy, see:
http://www.x.org/archive/X11R6.8.0/doc/lbxproxy.1.html
-5) If copying and killing is slow, try to disable the interaction with the
+ Keep in mind that lbxproxy and the LBX extension are now obsolete.
+
+6) If copying and killing is slow, try to disable the interaction with the
native system's clipboard by adding these lines to your .emacs file:
+
(setq interprogram-cut-function nil)
(setq interprogram-paste-function nil)
+7) If selecting text with the mouse is slow, the main culprit is
+ likely `select-active-regions', coupled with a program monitoring
+ the clipboard on the X server you are connected to. Try turning
+ that off.
+
+ However, over networks with moderate to high latency, with no
+ clipboard monitor running, the bottleneck is likely to be
+ `mouse-position' instead. Set the variable
+ `x-use-fast-mouse-position' to either any non-nil value, or to the
+ symbol `really-fast' if that is still too slow. Doing so will also
+ cause Emacs features that relies on accurate mouse position
+ reporting to stop working reliably.
+
*** Emacs gives the error, Couldn't find per display information.
This can result if the X server runs out of memory because Emacs uses
Time *timestamp)
{
struct frame *f1, *maybe_tooltip;
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ struct x_display_info *dpyinfo;
bool unrelated_tooltip;
+ Lisp_Object tail, frame;
+
+ dpyinfo = FRAME_DISPLAY_INFO (*fp);
+
+ if (!NILP (Vx_use_fast_mouse_position))
+ {
+ /* The user says that Emacs is running over the network, and a
+ fast approximation of `mouse-position' should be used.
+
+ Depending on what the value of `x-use-fast-mouse-position'
+ is, do one of two things: only perform the XQueryPointer to
+ obtain the coordinates from the last mouse frame, or only
+ return the last mouse motion frame and the
+ last_mouse_motion_x and Y. */
+
+ if (!EQ (Vx_use_fast_mouse_position, Qreally_fast))
+ {
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+ Window dummy;
+
+ /* This means that Emacs should select a frame and report
+ the mouse position relative to it. The approach used
+ here avoids making multiple roundtrips to the X server
+ querying for the window beneath the pointer, and was
+ borrowed from haiku_mouse_position in haikuterm.c. */
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_X_P (XFRAME (frame)))
+ XFRAME (frame)->mouse_moved = false;
+ }
+
+ if (gui_mouse_grabbed (dpyinfo)
+ && !EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source))
+ /* Pick the last mouse frame if dropping. */
+ f1 = x_display_list->last_mouse_frame;
+ else
+ /* Otherwise, pick the last mouse motion frame. */
+ f1 = x_display_list->last_mouse_motion_frame;
+
+ if (!f1 && FRAME_X_P (SELECTED_FRAME ()))
+ f1 = SELECTED_FRAME ();
+
+ if (!f1 || (!FRAME_X_P (f1) && (insist > 0)))
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_X_P (XFRAME (frame)) &&
+ !FRAME_X_P (XFRAME (frame)))
+ f1 = XFRAME (frame);
+
+ if (f1 && FRAME_TOOLTIP_P (f1))
+ f1 = NULL;
+
+ if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1))
+ {
+ if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1),
+ &dummy, &dummy, &root_x, &root_y,
+ &win_x, &win_y, &mask))
+ /* The pointer is out of the screen. */
+ return;
+
+ remember_mouse_glyph (f1, win_x, win_y,
+ &dpyinfo->last_mouse_glyph);
+ x_display_list->last_mouse_glyph_frame = f1;
+
+ *bar_window = Qnil;
+ *part = scroll_bar_nowhere;
+
+ /* If track-mouse is `drag-source' and the mouse pointer is
+ certain to not be actually under the chosen frame, return
+ NULL in FP. */
+ if (EQ (track_mouse, Qdrag_source)
+ && (win_x < 0 || win_y < 0
+ || win_x >= FRAME_PIXEL_WIDTH (f1)
+ || win_y >= FRAME_PIXEL_HEIGHT (f1)))
+ *fp = NULL;
+ else
+ *fp = f1;
+
+ *timestamp = dpyinfo->last_mouse_movement_time;
+ XSETINT (*x, win_x);
+ XSETINT (*y, win_y);
+ }
+ }
+ else
+ {
+ /* This means Emacs should only report the coordinates of
+ the last mouse motion. */
+
+ if (dpyinfo->last_mouse_motion_frame)
+ {
+ *fp = dpyinfo->last_mouse_motion_frame;
+ *timestamp = dpyinfo->last_mouse_movement_time;
+ *x = make_fixnum (dpyinfo->last_mouse_motion_x);
+ *y = make_fixnum (dpyinfo->last_mouse_motion_y);
+ *bar_window = Qnil;
+ *part = scroll_bar_nowhere;
+
+ dpyinfo->last_mouse_motion_frame->mouse_moved = false;
+ }
+ }
+
+ return;
+ }
block_input ();
DEFSYM (Qimitate_pager, "imitate-pager");
DEFSYM (Qnewer_time, "newer-time");
DEFSYM (Qraise_and_focus, "raise-and-focus");
+ DEFSYM (Qreally_fast, "really-fast");
DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
doc: /* Which keys Emacs uses for the ctrl modifier.
- The symbol `raise-and-focus', which means to raise the window and
focus it manually. */);
Vx_allow_focus_stealing = Qnewer_time;
+
+ DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position,
+ doc: /* How to make `mouse-position' faster.
+
+`mouse-position' and `mouse-pixel-position' default to querying the X
+server for the window under the mouse pointer. This results in
+accurate results, but is also very slow when the X connection has
+moderate to high latency. Setting this variable to a non-nil value
+makes Emacs query only for the position of the pointer, which is
+usually faster. Doing so improves the performance of dragging to
+select text over slow X connections.
+
+If that is still too slow, setting this variable to the symbol
+`really-fast' will make Emacs return only cached values. */);
+ Vx_use_fast_mouse_position = Qnil;
}
Time last_user_time;
/* Position where the mouse was last time we reported a motion.
- This is a position on last_mouse_motion_frame. */
+ This is a position on last_mouse_motion_frame. It is used in
+ some situations to report the mouse position as well: see
+ XTmouse_position. */
int last_mouse_motion_x;
int last_mouse_motion_y;
extern void x_free_gcs (struct frame *);
extern void x_relative_mouse_position (struct frame *, int *, int *);
-extern void x_real_pos_and_offsets (struct frame *f,
- int *left_offset_x,
- int *right_offset_x,
- int *top_offset_y,
- int *bottom_offset_y,
- int *x_pixels_diff,
- int *y_pixels_diff,
- int *xptr,
- int *yptr,
- int *outer_border);
+extern void x_real_pos_and_offsets (struct frame *, int *, int *, int *,
+ int *, int *, int *, int *, int *,
+ int *);
extern void x_default_font_parameter (struct frame *, Lisp_Object);
/* From xrdb.c. */
-XrmDatabase x_load_resources (Display *, const char *, const char *,
- const char *);
+extern XrmDatabase x_load_resources (Display *, const char *, const char *,
+ const char *);
extern const char *x_get_string_resource (void *, const char *, const char *);
/* Defined in xterm.c */