diff options
| author | Po Lu | 2022-11-18 09:08:59 +0800 |
|---|---|---|
| committer | Po Lu | 2022-11-18 09:09:10 +0800 |
| commit | 32e29afe64897c2ba821e1c2edc2b7d2eb74e70f (patch) | |
| tree | e2e1ef06d23f5654c9e435019d4e6e560f8bf2b4 | |
| parent | 682b068ba712075cea34d8bc790620ba82169d6c (diff) | |
| download | emacs-32e29afe64897c2ba821e1c2edc2b7d2eb74e70f.tar.gz emacs-32e29afe64897c2ba821e1c2edc2b7d2eb74e70f.zip | |
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.
| -rw-r--r-- | etc/PROBLEMS | 56 | ||||
| -rw-r--r-- | src/xterm.c | 123 | ||||
| -rw-r--r-- | src/xterm.h | 21 |
3 files changed, 170 insertions, 30 deletions
diff --git a/etc/PROBLEMS b/etc/PROBLEMS index aaecc41f6e8..2169ed0f80b 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS | |||
| @@ -1640,16 +1640,21 @@ X expects to find it. | |||
| 1640 | 1640 | ||
| 1641 | *** Improving performance with slow X connections. | 1641 | *** Improving performance with slow X connections. |
| 1642 | 1642 | ||
| 1643 | There are several ways to improve this performance, any subset of which can | 1643 | There are several ways to improve this performance, any subset of |
| 1644 | be carried out at the same time: | 1644 | which can be carried out at the same time: |
| 1645 | 1645 | ||
| 1646 | 1) If you don't need X Input Methods (XIM) for entering text in some | 1646 | 1) Use the "--with-x-toolkit=no" build of Emacs. By not relying on |
| 1647 | any toolkit (exhibiting potentially slow behavior), it has been | ||
| 1648 | made very fast over networks exhibiting high latency, but suitable | ||
| 1649 | bandwidth. | ||
| 1650 | |||
| 1651 | 2) If you don't need X Input Methods (XIM) for entering text in some | ||
| 1647 | language you use, you can improve performance on WAN links by using | 1652 | language you use, you can improve performance on WAN links by using |
| 1648 | the X resource useXIM to turn off use of XIM. This does not affect | 1653 | the X resource useXIM to turn off use of XIM. This does not affect |
| 1649 | the use of Emacs's own input methods, which are part of the Leim | 1654 | the use of Emacs's own input methods, which are part of the Leim |
| 1650 | package. | 1655 | package. |
| 1651 | 1656 | ||
| 1652 | 2) If the connection is very slow, you might also want to consider | 1657 | 3) If the connection is very slow, you might also want to consider |
| 1653 | switching off scroll bars, menu bar, and tool bar. Adding the | 1658 | switching off scroll bars, menu bar, and tool bar. Adding the |
| 1654 | following forms to your .emacs file will accomplish that, but only | 1659 | following forms to your .emacs file will accomplish that, but only |
| 1655 | after the initial frame is displayed: | 1660 | after the initial frame is displayed: |
| @@ -1665,26 +1670,45 @@ be carried out at the same time: | |||
| 1665 | Emacs.menuBar: off | 1670 | Emacs.menuBar: off |
| 1666 | Emacs.toolBar: off | 1671 | Emacs.toolBar: off |
| 1667 | 1672 | ||
| 1668 | 3) Use ssh to forward the X connection, and enable compression on this | 1673 | 4) Use ssh to forward the X connection, and enable compression on this |
| 1669 | forwarded X connection (ssh -XC remotehostname emacs ...). | 1674 | forwarded X connection (ssh -XC remotehostname emacs ...). |
| 1670 | 1675 | ||
| 1671 | 4) Use lbxproxy on the remote end of the connection. This is an interface | 1676 | Keep in mind that this does not help with latency problems, only |
| 1672 | to the low bandwidth X extension in most modern X servers, which | 1677 | andwidth ones. |
| 1673 | improves performance dramatically, at the slight expense of correctness | 1678 | |
| 1674 | of the X protocol. lbxproxy achieves the performance gain by grouping | 1679 | 5) Use lbxproxy on the remote end of the connection. This is an |
| 1675 | several X requests in one TCP packet and sending them off together, | 1680 | interface to the low bandwidth X extension in some outdated X |
| 1676 | instead of requiring a round-trip for each X request in a separate | 1681 | servers, which improves performance dramatically, at the slight |
| 1677 | packet. The switches that seem to work best for emacs are: | 1682 | expense of correctness of the X protocol. lbxproxy achieves the |
| 1678 | -noatomsfile -nowinattr -cheaterrors -cheatevents | 1683 | performance gain by grouping several X requests in one TCP packet |
| 1679 | Note that the -nograbcmap option is known to cause problems. | 1684 | and sending them off together, instead of requiring a round-trip |
| 1680 | For more about lbxproxy, see: | 1685 | for each X request in a separate packet. The switches that seem to |
| 1686 | work best for emacs are: -noatomsfile -nowinattr -cheaterrors | ||
| 1687 | -cheatevents Note that the -nograbcmap option is known to cause | ||
| 1688 | problems. For more about lbxproxy, see: | ||
| 1681 | http://www.x.org/archive/X11R6.8.0/doc/lbxproxy.1.html | 1689 | http://www.x.org/archive/X11R6.8.0/doc/lbxproxy.1.html |
| 1682 | 1690 | ||
| 1683 | 5) If copying and killing is slow, try to disable the interaction with the | 1691 | Keep in mind that lbxproxy and the LBX extension are now obsolete. |
| 1692 | |||
| 1693 | 6) If copying and killing is slow, try to disable the interaction with the | ||
| 1684 | native system's clipboard by adding these lines to your .emacs file: | 1694 | native system's clipboard by adding these lines to your .emacs file: |
| 1695 | |||
| 1685 | (setq interprogram-cut-function nil) | 1696 | (setq interprogram-cut-function nil) |
| 1686 | (setq interprogram-paste-function nil) | 1697 | (setq interprogram-paste-function nil) |
| 1687 | 1698 | ||
| 1699 | 7) If selecting text with the mouse is slow, the main culprit is | ||
| 1700 | likely `select-active-regions', coupled with a program monitoring | ||
| 1701 | the clipboard on the X server you are connected to. Try turning | ||
| 1702 | that off. | ||
| 1703 | |||
| 1704 | However, over networks with moderate to high latency, with no | ||
| 1705 | clipboard monitor running, the bottleneck is likely to be | ||
| 1706 | `mouse-position' instead. Set the variable | ||
| 1707 | `x-use-fast-mouse-position' to either any non-nil value, or to the | ||
| 1708 | symbol `really-fast' if that is still too slow. Doing so will also | ||
| 1709 | cause Emacs features that relies on accurate mouse position | ||
| 1710 | reporting to stop working reliably. | ||
| 1711 | |||
| 1688 | *** Emacs gives the error, Couldn't find per display information. | 1712 | *** Emacs gives the error, Couldn't find per display information. |
| 1689 | 1713 | ||
| 1690 | This can result if the X server runs out of memory because Emacs uses | 1714 | 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 b17a7edba68..deedc595cb2 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -14261,8 +14261,113 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, | |||
| 14261 | Time *timestamp) | 14261 | Time *timestamp) |
| 14262 | { | 14262 | { |
| 14263 | struct frame *f1, *maybe_tooltip; | 14263 | struct frame *f1, *maybe_tooltip; |
| 14264 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); | 14264 | struct x_display_info *dpyinfo; |
| 14265 | bool unrelated_tooltip; | 14265 | bool unrelated_tooltip; |
| 14266 | Lisp_Object tail, frame; | ||
| 14267 | |||
| 14268 | dpyinfo = FRAME_DISPLAY_INFO (*fp); | ||
| 14269 | |||
| 14270 | if (!NILP (Vx_use_fast_mouse_position)) | ||
| 14271 | { | ||
| 14272 | /* The user says that Emacs is running over the network, and a | ||
| 14273 | fast approximation of `mouse-position' should be used. | ||
| 14274 | |||
| 14275 | Depending on what the value of `x-use-fast-mouse-position' | ||
| 14276 | is, do one of two things: only perform the XQueryPointer to | ||
| 14277 | obtain the coordinates from the last mouse frame, or only | ||
| 14278 | return the last mouse motion frame and the | ||
| 14279 | last_mouse_motion_x and Y. */ | ||
| 14280 | |||
| 14281 | if (!EQ (Vx_use_fast_mouse_position, Qreally_fast)) | ||
| 14282 | { | ||
| 14283 | int root_x, root_y, win_x, win_y; | ||
| 14284 | unsigned int mask; | ||
| 14285 | Window dummy; | ||
| 14286 | |||
| 14287 | /* This means that Emacs should select a frame and report | ||
| 14288 | the mouse position relative to it. The approach used | ||
| 14289 | here avoids making multiple roundtrips to the X server | ||
| 14290 | querying for the window beneath the pointer, and was | ||
| 14291 | borrowed from haiku_mouse_position in haikuterm.c. */ | ||
| 14292 | |||
| 14293 | FOR_EACH_FRAME (tail, frame) | ||
| 14294 | { | ||
| 14295 | if (FRAME_X_P (XFRAME (frame))) | ||
| 14296 | XFRAME (frame)->mouse_moved = false; | ||
| 14297 | } | ||
| 14298 | |||
| 14299 | if (gui_mouse_grabbed (dpyinfo) | ||
| 14300 | && !EQ (track_mouse, Qdropping) | ||
| 14301 | && !EQ (track_mouse, Qdrag_source)) | ||
| 14302 | /* Pick the last mouse frame if dropping. */ | ||
| 14303 | f1 = x_display_list->last_mouse_frame; | ||
| 14304 | else | ||
| 14305 | /* Otherwise, pick the last mouse motion frame. */ | ||
| 14306 | f1 = x_display_list->last_mouse_motion_frame; | ||
| 14307 | |||
| 14308 | if (!f1 && FRAME_X_P (SELECTED_FRAME ())) | ||
| 14309 | f1 = SELECTED_FRAME (); | ||
| 14310 | |||
| 14311 | if (!f1 || (!FRAME_X_P (f1) && (insist > 0))) | ||
| 14312 | FOR_EACH_FRAME (tail, frame) | ||
| 14313 | if (FRAME_X_P (XFRAME (frame)) && | ||
| 14314 | !FRAME_X_P (XFRAME (frame))) | ||
| 14315 | f1 = XFRAME (frame); | ||
| 14316 | |||
| 14317 | if (f1 && FRAME_TOOLTIP_P (f1)) | ||
| 14318 | f1 = NULL; | ||
| 14319 | |||
| 14320 | if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1)) | ||
| 14321 | { | ||
| 14322 | if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1), | ||
| 14323 | &dummy, &dummy, &root_x, &root_y, | ||
| 14324 | &win_x, &win_y, &mask)) | ||
| 14325 | /* The pointer is out of the screen. */ | ||
| 14326 | return; | ||
| 14327 | |||
| 14328 | remember_mouse_glyph (f1, win_x, win_y, | ||
| 14329 | &dpyinfo->last_mouse_glyph); | ||
| 14330 | x_display_list->last_mouse_glyph_frame = f1; | ||
| 14331 | |||
| 14332 | *bar_window = Qnil; | ||
| 14333 | *part = scroll_bar_nowhere; | ||
| 14334 | |||
| 14335 | /* If track-mouse is `drag-source' and the mouse pointer is | ||
| 14336 | certain to not be actually under the chosen frame, return | ||
| 14337 | NULL in FP. */ | ||
| 14338 | if (EQ (track_mouse, Qdrag_source) | ||
| 14339 | && (win_x < 0 || win_y < 0 | ||
| 14340 | || win_x >= FRAME_PIXEL_WIDTH (f1) | ||
| 14341 | || win_y >= FRAME_PIXEL_HEIGHT (f1))) | ||
| 14342 | *fp = NULL; | ||
| 14343 | else | ||
| 14344 | *fp = f1; | ||
| 14345 | |||
| 14346 | *timestamp = dpyinfo->last_mouse_movement_time; | ||
| 14347 | XSETINT (*x, win_x); | ||
| 14348 | XSETINT (*y, win_y); | ||
| 14349 | } | ||
| 14350 | } | ||
| 14351 | else | ||
| 14352 | { | ||
| 14353 | /* This means Emacs should only report the coordinates of | ||
| 14354 | the last mouse motion. */ | ||
| 14355 | |||
| 14356 | if (dpyinfo->last_mouse_motion_frame) | ||
| 14357 | { | ||
| 14358 | *fp = dpyinfo->last_mouse_motion_frame; | ||
| 14359 | *timestamp = dpyinfo->last_mouse_movement_time; | ||
| 14360 | *x = make_fixnum (dpyinfo->last_mouse_motion_x); | ||
| 14361 | *y = make_fixnum (dpyinfo->last_mouse_motion_y); | ||
| 14362 | *bar_window = Qnil; | ||
| 14363 | *part = scroll_bar_nowhere; | ||
| 14364 | |||
| 14365 | dpyinfo->last_mouse_motion_frame->mouse_moved = false; | ||
| 14366 | } | ||
| 14367 | } | ||
| 14368 | |||
| 14369 | return; | ||
| 14370 | } | ||
| 14266 | 14371 | ||
| 14267 | block_input (); | 14372 | block_input (); |
| 14268 | 14373 | ||
| @@ -31131,6 +31236,7 @@ With MS Windows, Haiku windowing or Nextstep, the value is t. */); | |||
| 31131 | DEFSYM (Qimitate_pager, "imitate-pager"); | 31236 | DEFSYM (Qimitate_pager, "imitate-pager"); |
| 31132 | DEFSYM (Qnewer_time, "newer-time"); | 31237 | DEFSYM (Qnewer_time, "newer-time"); |
| 31133 | DEFSYM (Qraise_and_focus, "raise-and-focus"); | 31238 | DEFSYM (Qraise_and_focus, "raise-and-focus"); |
| 31239 | DEFSYM (Qreally_fast, "really-fast"); | ||
| 31134 | 31240 | ||
| 31135 | DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, | 31241 | DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, |
| 31136 | doc: /* Which keys Emacs uses for the ctrl modifier. | 31242 | doc: /* Which keys Emacs uses for the ctrl modifier. |
| @@ -31410,4 +31516,19 @@ not bypass window manager focus stealing prevention): | |||
| 31410 | - The symbol `raise-and-focus', which means to raise the window and | 31516 | - The symbol `raise-and-focus', which means to raise the window and |
| 31411 | focus it manually. */); | 31517 | focus it manually. */); |
| 31412 | Vx_allow_focus_stealing = Qnewer_time; | 31518 | Vx_allow_focus_stealing = Qnewer_time; |
| 31519 | |||
| 31520 | DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position, | ||
| 31521 | doc: /* How to make `mouse-position' faster. | ||
| 31522 | |||
| 31523 | `mouse-position' and `mouse-pixel-position' default to querying the X | ||
| 31524 | server for the window under the mouse pointer. This results in | ||
| 31525 | accurate results, but is also very slow when the X connection has | ||
| 31526 | moderate to high latency. Setting this variable to a non-nil value | ||
| 31527 | makes Emacs query only for the position of the pointer, which is | ||
| 31528 | usually faster. Doing so improves the performance of dragging to | ||
| 31529 | select text over slow X connections. | ||
| 31530 | |||
| 31531 | If that is still too slow, setting this variable to the symbol | ||
| 31532 | `really-fast' will make Emacs return only cached values. */); | ||
| 31533 | Vx_use_fast_mouse_position = Qnil; | ||
| 31413 | } | 31534 | } |
diff --git a/src/xterm.h b/src/xterm.h index b6ab42e72d2..c36920081d3 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -580,7 +580,9 @@ struct x_display_info | |||
| 580 | Time last_user_time; | 580 | Time last_user_time; |
| 581 | 581 | ||
| 582 | /* Position where the mouse was last time we reported a motion. | 582 | /* Position where the mouse was last time we reported a motion. |
| 583 | This is a position on last_mouse_motion_frame. */ | 583 | This is a position on last_mouse_motion_frame. It is used in |
| 584 | some situations to report the mouse position as well: see | ||
| 585 | XTmouse_position. */ | ||
| 584 | int last_mouse_motion_x; | 586 | int last_mouse_motion_x; |
| 585 | int last_mouse_motion_y; | 587 | int last_mouse_motion_y; |
| 586 | 588 | ||
| @@ -1605,22 +1607,15 @@ SELECTION_EVENT_DISPLAY (struct selection_input_event *ev) | |||
| 1605 | 1607 | ||
| 1606 | extern void x_free_gcs (struct frame *); | 1608 | extern void x_free_gcs (struct frame *); |
| 1607 | extern void x_relative_mouse_position (struct frame *, int *, int *); | 1609 | extern void x_relative_mouse_position (struct frame *, int *, int *); |
| 1608 | extern void x_real_pos_and_offsets (struct frame *f, | 1610 | extern void x_real_pos_and_offsets (struct frame *, int *, int *, int *, |
| 1609 | int *left_offset_x, | 1611 | int *, int *, int *, int *, int *, |
| 1610 | int *right_offset_x, | 1612 | int *); |
| 1611 | int *top_offset_y, | ||
| 1612 | int *bottom_offset_y, | ||
| 1613 | int *x_pixels_diff, | ||
| 1614 | int *y_pixels_diff, | ||
| 1615 | int *xptr, | ||
| 1616 | int *yptr, | ||
| 1617 | int *outer_border); | ||
| 1618 | extern void x_default_font_parameter (struct frame *, Lisp_Object); | 1613 | extern void x_default_font_parameter (struct frame *, Lisp_Object); |
| 1619 | 1614 | ||
| 1620 | /* From xrdb.c. */ | 1615 | /* From xrdb.c. */ |
| 1621 | 1616 | ||
| 1622 | XrmDatabase x_load_resources (Display *, const char *, const char *, | 1617 | extern XrmDatabase x_load_resources (Display *, const char *, const char *, |
| 1623 | const char *); | 1618 | const char *); |
| 1624 | extern const char *x_get_string_resource (void *, const char *, const char *); | 1619 | extern const char *x_get_string_resource (void *, const char *, const char *); |
| 1625 | 1620 | ||
| 1626 | /* Defined in xterm.c */ | 1621 | /* Defined in xterm.c */ |