Last active
June 18, 2023 23:36
-
-
Save nilninull/63c821c435935344ab66a2006483794a to your computer and use it in GitHub Desktop.
A function for add a multi-click feature to xbindkeys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use-modules (srfi srfi-19)) | |
;; 100000000 nano seconds -> 0.1s | |
;; 200000000 nano seconds -> 0.2s | |
;; 300000000 nano seconds -> 0.3s | |
;; 400000000 nano seconds -> 0.4s | |
;; 500000000 nano seconds -> 0.5s | |
;; 1000000000 nano seconds -> 1s | |
;; This value is used for judge `clicking are continuously or not' | |
(define click-separation-threshold-nanosec 250000000) | |
(define (time-to-nanosecond time) | |
(+ (* (time-second time) | |
(expt 10 9)) | |
(time-nanosecond time))) | |
(define (emit-command k commands) | |
(let ((cmd (assoc k commands))) | |
(if cmd | |
(eval (cdr cmd) (interaction-environment))))) | |
(define (multi-click-key key commands-normal . commands-long) | |
(let ((time (current-time)) | |
(count 0)) | |
(unless (list? key) | |
(set! key (list key))) | |
(set! commands-long (if (null? commands-long) | |
#f | |
(begin | |
(set! commands-long (car commands-long)) | |
(if (eq? #t commands-long) | |
commands-normal | |
commands-long)))) | |
(xbindkey-function key (lambda () | |
(let ((prev-time time)) | |
(set! time (current-time)) | |
(if (> click-separation-threshold-nanosec (time-to-nanosecond (time-difference time prev-time))) | |
(set! count (+ count 1)) | |
(set! count 1))))) | |
(xbindkey-function (cons 'release key) (lambda () | |
(let ((diff-time (time-to-nanosecond (time-difference (current-time) time)))) | |
(if (> click-separation-threshold-nanosec diff-time) | |
(call-with-new-thread (let ((start-time-count count)) | |
(lambda () | |
(usleep (/ (- click-separation-threshold-nanosec diff-time) 1000)) | |
(if (= count start-time-count) | |
(emit-command start-time-count commands-normal))))) | |
(when commands-long | |
(emit-command count commands-long)))))))) | |
;; some example settings | |
;; simple multi click settings | |
(multi-click-key 'b:10 '((1 . (run-command "xmessage single click")) | |
(2 . (run-command "xmessage double click")) | |
(3 . (run-command "xmessage triple click")) | |
(4 . (run-command "xmessage you can use 4 or more clicks")))) | |
;; the key can specify with modifier keys | |
(multi-click-key '(control b:10) '((1 . (run-command "xmessage single click with modifier keys")))) | |
;; second alist can define long hold click maps. | |
;; `long hold' means `last one click holds longer than click-separation-threshold-nanosec time' | |
(multi-click-key 'b:11 '((1 . (run-command "xmessage single click")) | |
(2 . (run-command "xmessage double click")) | |
(3 . (run-command "xmessage triple click")) | |
(4 . (run-command "xmessage you can use 4 or more clicks"))) | |
'((1 . (run-command "xmessage long hold single click")) | |
(2 . (run-command "xmessage long hold double click (long hold click is only last one click)")) | |
(3 . (run-command "xmessage long hold triple click (long hold click is only last one click)")))) | |
;; If second alist is #t, normal click and long hold click use same mapping. | |
(multi-click-key 'b:12 '((1 . (run-command "xmessage single click")) | |
(2 . (run-command "xmessage double click")) | |
(3 . (run-command "xmessage triple click")) | |
(4 . (run-command "xmessage you can use 4 or more clicks"))) | |
#t) |
I think you can emulate key presses with the xdotool app.
(multi-click-key 'b:1 '((1 . (run-command "xdotool key 'ctrl+f'"))
(2 . (run-command "xdotool key 'ctrl+s'")))
#t)
Please change the number part of b:1 to the corresponding mouse button number.
Thanks for this code.
I'm trying to configure right click to be a normal right click, and double right click to be ctrl+shift+t to reopen a closed tab. This code should work but doesn't:
(multi-click-key 'b:3 '((1 . (run-command "xdotool click 3"))
(2 . (run-command "xdotool key 'ctrl+shift+t'"))
If I substitute click 3 for click 1 (left click) or click 2 (middle click), it works fine. Any ideas?
Considering the last line of your comment, I think `click 3' is looping.
The event caused by xdotool click 3
is once again being captured by xbindkeys process.
Combining the ungrab-all-keys
and grab-all-keys
functions may work well.
sample code
(multi-click-key 'b:3 '((1 . (begin
(ungrab-all-keys)
(run-command "xdotool click 3")
(grab-all-keys)))
(2 . (run-command "xdotool key 'ctrl+shift+t'"))))
I am currently using Wayland, so the above code is unconfirmed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm having some trouble understanding this.
Can you create one such that single click gives (ctrl + f) and double click gives(ctrl + s) for a button