emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 32e29afe64: Add knob to make `mouse-position' faster on X


From: Po Lu
Subject: master 32e29afe64: Add knob to make `mouse-position' faster on X
Date: Thu, 17 Nov 2022 20:09:36 -0500 (EST)

branch: master
commit 32e29afe64897c2ba821e1c2edc2b7d2eb74e70f
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Add knob to make `mouse-position' faster on X
    
    * etc/PROBLEMS (Improving performance with slow X connections):
    Add new advice.
    * src/xterm.c (XTmouse_position): Add alternative
    implementations for slow connections.
    (syms_of_xterm): Add new variable to enable them.
    * src/xterm.h (struct x_display_info): Update commentary.
---
 etc/PROBLEMS |  56 +++++++++++++++++++--------
 src/xterm.c  | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/xterm.h  |  21 ++++------
 3 files changed, 170 insertions(+), 30 deletions(-)

diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index aaecc41f6e..2169ed0f80 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -1640,16 +1640,21 @@ X expects to find it.
 
 *** 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:
@@ -1665,26 +1670,45 @@ be carried out at the same time:
     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
diff --git a/src/xterm.c b/src/xterm.c
index b17a7edba6..deedc595cb 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -14261,8 +14261,113 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
                  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 ();
 
@@ -31131,6 +31236,7 @@ With MS Windows, Haiku windowing or Nextstep, the value 
is t.  */);
   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.
@@ -31410,4 +31516,19 @@ not bypass window manager focus stealing prevention):
   - 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;
 }
diff --git a/src/xterm.h b/src/xterm.h
index b6ab42e72d..c36920081d 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -580,7 +580,9 @@ struct x_display_info
   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;
 
@@ -1605,22 +1607,15 @@ SELECTION_EVENT_DISPLAY (struct selection_input_event 
*ev)
 
 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 */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]