1

The problem manifests on:

  • Emacs 26.3 on Fedora Release 31, using Xming on Windows 7 as X server, whether in -Q mode or not
  • Emacs 24.3 on RHEL7, using MobaXterm 12.2 4204, whether in -Q mode or not

The scrollbar I'm seeing is a medium-dark rectangle (the scrollbar "elevator") with rounded left-hand corners and square right-hand corners (which may have been a wide-scrollbar setting on 26.3; on 24.3 it's as pictured below) in a light-gray vertical area (the scrollbar "track"). When I mouse over the rectangle it switches to dark gray.

When I click it, it turns blue. After about 1/2 second, if not moved, it narrows about 2 pixels on both sides]**, and refuses to move. Moving the mouse will sometimes get one scroll of the window contents, and sometimes not.

If I click it and move it slightly in that 1/2 second, it will move, and continue to be movable even if I hold still for a while. But I have to move it substantially (at least half its height, it seems, in a 2000 line file) or it will then freeze at the 1/2 second mark.

Here's my current .emacs file:

(defun switch-to-next-buffer-frank ()
  (interactive)
  (switch-to-buffer (other-buffer)))

(defun switch-to-prev-window ()
  (interactive)
  (other-window -1))

(defun scroll-one-line-up (&optional arg)
  "Scroll the selected window up (forward in the text) one line (or N lines)."
  (interactive "p")
  (scroll-up (or arg 1)))

(defun scroll-one-line-down (&optional arg)
  "Scroll the selected window down (backward in the text) one line (or N)."
  (interactive "p")
  (scroll-down (or arg 1)))

(global-set-key [(control ?z)]                'scroll-one-line-up)
(global-set-key [(meta ?z)]                   'scroll-one-line-down)
(global-set-key [(meta ?g)]                   'goto-line)
(global-set-key [(control ?x)(k)]             'kill-this-buffer)
(global-set-key [(control meta ?l)]           'switch-to-next-buffer)
(global-set-key [(control shift meta ?l)]     'switch-to-prev-buffer)
(global-set-key [(control tab)]               'other-window)
(global-set-key [(control shift iso-lefttab)] 'switch-to-prev-window)

(modify-syntax-entry ?_ "w")

(setq scroll-bar-mode 'left)
(setq scroll-bar-adjust-thumb-portion nil)





(setq gutter-buffers-tab-visible-p nil)
(setq inhibit-startup-screen t)
(setq mouse-yank-at-point t)
(setq inhibit-startup-buffer-menu t)
(tool-bar-mode -1)
(delete-selection-mode 1)
;(setq inhibit-splash-screen t)
;(setq inhibit-startup-message t)
;(setq initial-scratch-message nil)



;(delete-selection-mode 1)
;
;(defun ask-user-about-supersession-threat (fn)
;  "blatantly ignore files that changed on disk"
;  )





(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(ansi-color-faces-vector
   [default default default italic underline success warning error])
 '(ansi-color-names-vector
   ["#3F3F3F" "#CC9393" "#7F9F7F" "#F0DFAF" "#8CD0D3" "#DC8CC3" "#93E0E3" "#DCDCCC"])
 '(background-color "#000000")
 '(background-mode dark)
 '(company-quickhelp-color-background "#4F4F4F")
 '(company-quickhelp-color-foreground "#DCDCCC")
 '(cursor-color "#ffffff")
 '(custom-enabled-themes (quote (manoj-dark)))
 '(custom-safe-themes
   (quote
    ("54f2d1fcc9bcadedd50398697618f7c34aceb9966a6cbaa99829eb64c0c1f3ca" "4138944fbed88c047c9973f68908b36b4153646a045648a22083bd622d1e636d" "8885761700542f5d0ea63436874bf3f9e279211707d4b1ca9ed6f53522f21934" "59e82a683db7129c0142b4b5a35dbbeaf8e01a4b81588f8c163bd255b76f4d21" default)))
 '(fci-rule-color "#383838")
 '(font-use-system-font t)
 '(foreground-color "#00ff00")
 '(gutter-buffers-tab-visible-p nil t)
 '(indent-tabs-mode nil)
 '(nrepl-message-colors
   (quote
    ("#CC9393" "#DFAF8F" "#F0DFAF" "#7F9F7F" "#BFEBBF" "#93E0E3" "#94BFF3" "#DC8CC3")))
 '(pdf-view-midnight-colors (quote ("#DCDCCC" . "#383838")))
 '(query-user-mail-address nil)
 '(tool-bar-mode nil)
 '(user-mail-address "fsheeran@gmail.com")
 '(vc-annotate-background "#2B2B2B")
 '(vc-annotate-color-map
   (quote
    ((20 . "#BC8383")
     (40 . "#CC9393")
     (60 . "#DFAF8F")
     (80 . "#D0BF8F")
     (100 . "#E0CF9F")
     (120 . "#F0DFAF")
     (140 . "#5F7F5F")
     (160 . "#7F9F7F")
     (180 . "#8FB28F")
     (200 . "#9FC59F")
     (220 . "#AFD8AF")
     (240 . "#BFEBBF")
     (260 . "#93E0E3")
     (280 . "#6CA0A3")
     (300 . "#7CB8BB")
     (320 . "#8CD0D3")
     (340 . "#94BFF3")
     (360 . "#DC8CC3"))))
 '(vc-annotate-very-old-color "#DC8CC3"))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:foreground "#00ff00" :background "#000000" :size "10pt" :family "DejaVu Sans Mono" :foundry "PfEd" :slant normal :weight normal :height 144 :width normal))))
 '(font-lock-builtin-face ((t (:foreground "#00ccff"))))
 '(font-lock-comment-delimiter-face ((t (:foreground "#ffff00" :slant normal))))
 '(font-lock-comment-face ((t (:foreground "#ffff00" :slant normal))))
 '(font-lock-constant-face ((t (:foreground "#00ff99" :weight normal))))
 '(font-lock-function-name-face ((t (:foreground "#00ff00" :weight normal :height 1.0))))
 '(font-lock-preprocessor-face ((t (:foreground "#ff4040"))))
 '(font-lock-string-face ((t (:foreground "#00ffee"))))
 '(font-lock-type-face ((t (:foreground "#33ccff"))))
 '(font-lock-variable-name-face ((t (:foreground "#66ff00"))))
 '(italic ((t nil)))
 '(mode-line ((t (:background "#445555" :foreground "#ffffff" :box (:line-width 2 :color "#445555") :height 1.0))))
 '(mode-line-buffer-id ((t (:background "#445555" :foreground "#55ff55" :weight normal :height 1.0))))
 '(mode-line-emphasis ((t (:weight normal))))
 '(mode-line-highlight ((t (:box (:line-width 2 :color "#445555")))))
 '(mode-line-inactive ((t (:background "#445555" :foreground "#ffffff" :box (:line-width 2 :color "#445555") :weight normal :height 1.0))))
 '(scroll-bar ((t (:background "#334444" :foreground "#ddffff")))))

Here's a screenshot: of emacs -Q 24.3/RHEL7/MobaXterm:enter image description here

Then here is the same window after I've held the top scrollbar about 1 second without moving after clicking down:enter image description here

Swiss Frank
  • 247
  • 1
  • 10
  • 1
    Well, that is pretty weird. I can reproduce it locally, so it's not unique to your system or configuration. – db48x Mar 10 '20 at 01:26
  • If you can reproduce, curious how you can stand it? Are you just in the habit of immediately scrolling enough to avoid this lock? For better or worse I often click once I figure out I need to scroll, but before I figure out how much or what exactly I'll be looking for, so it often locks on me. BTW I've used emacs since like 1989 but only in terminals, then then xemacs since 1995. Only now I'm leaving xemacs for emacs and having something of a learning curve to figure out how to make it do things that worked fine in xemacs (like, scroll!) – Swiss Frank Mar 10 '20 at 01:45
  • 1
    I can stand it because I've never noticed it. I simply never ever click on a scrollbar any more, and probably never have since the scroll wheel was introduced. – db48x Mar 10 '20 at 01:47

2 Answers2

1

Aha, I figured it out. It's a new feature (or "feature", depending on your outlook) of Gtk 3. I haven't found any mention of it in the documentation yet, but here's an article from a Gtk developer: https://blog.gtk.org/2017/10/11/a-scrolling-primer/

I'll quote the relevant portion:

There’s more to scrolling in GTK+ that you may not know about. One feature that we introduced long ago is a ‘zoom’ or ‘fine adjustment’ mode, which slows the scrolling down to allow pixel-precise positioning.

To trigger this mode you can either use a long press or shift-click in the slider. As you can see in the video, once you move the pointer below or above the scrollbar, it will keep scrolling at the same relaxed speed until you let go.

Scrolling by moving the slider triggers mouse events which Emacs turns into calls to scroll-bar-toolkit-scroll. By tracing this function to see what arguments it's called with, I can see the units it's in:

======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (5179898 . 9754353) 0 handle)))
1 <- scroll-bar-toolkit-scroll: 12576
======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (5179899 . 9754353) 0 handle)))
1 <- scroll-bar-toolkit-scroll: 12576
======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (0 . 0) 0 end-scroll)))
1 <- scroll-bar-toolkit-scroll: t

You can see that Gtk is scrolling the document from 5179898/9754353 of the way through document to 5179899/9754353 of the way through the document. This would indeed be pixel-accurate scrolling if the document really was 9754353 pixels tall, but it's not. I'm not sure where that number came from; it doesn't appear to be the number of characters either. Instead, because the units are so odd, the scrolling is very slow, just one line every few seconds. That explains why you sometimes got it to scroll, but other times you didn't.

At any rate, when I don't long click I get this:

======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (5202322 . 9754353) 0 handle)))
1 <- scroll-bar-toolkit-scroll: 12576
======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (5224745 . 9754353) 0 handle)))
1 <- scroll-bar-toolkit-scroll: 12576
======================================================================
1 -> (scroll-bar-toolkit-scroll (mouse-1 (#<window 348 on *Help*> vertical-scroll-bar (0 . 0) 0 end-scroll)))
1 <- scroll-bar-toolkit-scroll: t

Which results in the usual pace of scrolling.

Update:

It looks like the size of the scrollbars that emacs creates are fixed, and that they always go from one to ten million. See gtkutil.h line 30:

/* Minimum and maximum values used for GTK scroll bars  */

#define XG_SB_MIN 1
#define XG_SB_MAX 10000000
#define XG_SB_RANGE (XG_SB_MAX-XG_SB_MIN)
#define YG_SB_MIN 1
#define YG_SB_MAX 10000000
#define YG_SB_RANGE (YG_SB_MAX-YG_SB_MIN)

It may be adjusted slightly from there to account for things like the size of the thumb or the height of the window or something, but that seems to explain the large values. The alternative used by most programs is to measure the height of the document in pixels, and use that.

db48x
  • 15,741
  • 1
  • 19
  • 23
  • OK, I think you're on to something. But 1) how do you do that trace? 2) Even with 20 pix/line, that's not a pixel height unless it's a 500,000 line file!? 3) not much diff between 5179898 and 5202322, so I'm wondering if this is a packed value with like bit fields or'd together with a speed or something. 4) did you note a way to adjust the definition of "long press" e.g. to ten seconds or something? That'd be a solution for me. – Swiss Frank Mar 10 '20 at 02:09
  • 1
    Any Gtk app can invent any units for the scrollbar; you have to tell it how long the document is when you initialize the scrollbar. I've no idea if you can control how Gtk decides on long-click events; that's a Gtk question not an Emacs question. – db48x Mar 10 '20 at 02:25
  • see below for a solution to long-click events. – Swiss Frank Mar 13 '20 at 04:13
0

Short Answer: Create file ~/.config/gtk-3.0/settings.ini as seen at the bottom of this answer.

Long Answer: Starting up emacs under the strace utility, capturing the output:

tcsh> strace emacs MyFile.cpp >& emacs.strace &

Emacs apparently can be built with different kinds of scrollbars, one being gtk. If I search emacs.strace for gtk I find a bunch, so I assume my emacs package was built with gtk and that's what I'm probably looking at. Furthermore, the gtk references typically mention 3.0, so I assume gtk version 3.0:

> grep -i gtk emacs.strace
open("/opt/rh/devtoolset-6/root/usr/lib64/tls/libgtk-3.so.0", O_RDONLY|O_CLOEXEC) = -1 
ENOENT (No such file or directory)
open("/opt/rh/devtoolset-6/root/usr/lib64/libgtk-3.so.0", O_RDONLY|O_CLOEXEC) = -1 
ENOENT (No such file or directory)
open("/opt/rh/devtoolset-6/root/usr/lib/libgtk-3.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT 
(No such file or directory)
open("/lib64/libgtk-3.so.0", O_RDONLY|O_CLOEXEC) = 3
access("/usr/share/gtk-3.0/settings.ini", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/gtk-3.0/settings.ini", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/xdg/gtk-3.0/settings.ini", F_OK) = -1 ENOENT (No such file or directory)
:
:
:

Given that, I read the documentation for Gtk 3.0 scrollbars. There's a little mention of a "fine-tune" mode.

I create a special ~/.config/gtk-3.0/gtk.css file that should highlight this fine-tune mode:

.scrollbar.vertical slider,
scrollbar.vertical slider {
background: #777777;
border-radius:0px;     /* Make the slider rectangular instead of a oval or roundrect.  */
margin:1px;            /* Fix the margin size at 1 pixel whether we're active or note. */
} 

.scrollbar.vertical slider:active,
scrollbar.vertical slider:active {
background: #555555;
} 

.scrollbar.vertical.fine-tune slider:active,
scrollbar.vertical.fine-tune slider:active {
background: red;
}

That should turn the scrollbar slider red if/when the fine-tune mode kicks in, and indeed: as soon as it turns red, it cannot be moved any more.

So searching for Gtk fine-tune, I find that there are hundreds of complaints about this mode since about 2014, and not a single voice in favor. But we still have it, oh well. Luckily, it can be disabled by the following ~/.config/gtk-3.0/settings.ini file:

[Settings]
gtk-long-press-time=99999

The time seems to be measured in units of 2ms, such that a value of 1000 gives about 2 seconds.

Swiss Frank
  • 247
  • 1
  • 10