Skip to content

Commit efcc681

Browse files
committed
Implemented better mouse hover using posframe
1 parent 9325e11 commit efcc681

File tree

2 files changed

+91
-49
lines changed

2 files changed

+91
-49
lines changed

dap-mouse.el

Lines changed: 85 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,44 @@ applied with lower priority than the syntax highlighting."
3737
:group 'dap
3838
:package-version '(dap "0.9.1"))
3939

40+
(defvar dap-mouse--hide-timer nil)
41+
42+
(defvar dap-mouse-posframe-properties
43+
(list :min-width 50
44+
:internal-border-width 2
45+
:internal-border-color (face-attribute 'mode-line :background)
46+
:width 50
47+
:min-height 10)
48+
"The properties which will be used for creating the `posframe'.")
49+
50+
(defconst dap-mouse-buffer "*dap-mouse*")
51+
52+
(defun dap-mouse--hide-popup? ()
53+
(let ((buffer-under-mouse (window-buffer (cl-first (window-list (cl-first (mouse-position))))))
54+
(popup-buffer (get-buffer dap-mouse-buffer)))
55+
(not (or (and (eq (current-buffer) popup-buffer)
56+
(eq buffer-under-mouse popup-buffer))
57+
(eq buffer-under-mouse popup-buffer)))))
58+
59+
(defcustom dap-mouse-popup-timeout 0.3
60+
"The time to wait after command before hiding the popup.")
61+
4062
;;;###autoload
4163
(define-minor-mode dap-tooltip-mode
4264
"Toggle the display of GUD tooltips."
4365
:global t
4466
:group 'dap-mouse
4567
:group 'tooltip (require 'tooltip)
46-
(if dap-tooltip-mode
47-
(progn
48-
(add-hook 'pre-command-hook 'tooltip-hide)
49-
(add-hook 'tooltip-functions 'dap-tooltip-tips)
50-
(add-hook 'lsp-mode-hook 'dap-tooltip-activate-mouse-motions-if-enabled)
51-
(define-key lsp-mode-map [mouse-movement] 'dap-tooltip-mouse-motion))
52-
(unless tooltip-mode
53-
(remove-hook 'pre-command-hook 'tooltip-hide)
54-
(remove-hook 'tooltip-functions 'dap-tooltip-tips)
55-
(define-key lsp-mode-map [mouse-movement] 'ignore)
56-
(remove-hook 'lsp-mode-hook 'dap-tooltip-activate-mouse-motions-if-enabled)))
57-
(dap-tooltip-activate-mouse-motions-if-enabled))
68+
(cond
69+
(dap-tooltip-mode
70+
(add-hook 'tooltip-functions 'dap-tooltip-tips)
71+
(add-hook 'lsp-mode-hook 'dap-tooltip-update-mouse-motions-if-enabled)
72+
(define-key lsp-mode-map [mouse-movement] 'dap-tooltip-mouse-motion))
73+
((not tooltip-mode)
74+
(remove-hook 'tooltip-functions 'dap-tooltip-tips)
75+
(define-key lsp-mode-map [mouse-movement] 'ignore)
76+
(remove-hook 'lsp-mode-hook 'dap-tooltip-update-mouse-motions-if-enabled)))
77+
(dap-tooltip-update-mouse-motions-if-enabled))
5878

5979
(defcustom dap-tooltip-echo-area nil
6080
"Use the echo area instead of frames for DAP tooltips."
@@ -64,10 +84,10 @@ applied with lower priority than the syntax highlighting."
6484

6585
;;; Reacting on mouse movements
6686

67-
(defun dap-tooltip-activate-mouse-motions-if-enabled ()
87+
(defun dap-tooltip-update-mouse-motions-if-enabled ()
6888
"Reconsider for all buffers whether mouse motion events are desired."
6989
(remove-hook 'post-command-hook
70-
'dap-tooltip-activate-mouse-motions-if-enabled)
90+
'dap-tooltip-update-mouse-motions-if-enabled)
7191
(dolist (buffer (buffer-list))
7292
(with-current-buffer buffer
7393
(if (and dap-tooltip-mode lsp-mode)
@@ -111,25 +131,37 @@ If there is an active selection - return it."
111131

112132
(defun dap-tooltip-post-tooltip ()
113133
"Clean tooltip properties."
114-
(remove-hook 'post-command-hook #'dap-tooltip-post-tooltip)
115-
116-
(when dap-tooltip-bounds
117-
(remove-text-properties (car dap-tooltip-bounds)
118-
(cdr dap-tooltip-bounds)
119-
'(mouse-face))
120-
;; restore the selection
121-
(when (region-active-p)
122-
(let ((bounds dap-tooltip-bounds))
123-
(run-with-idle-timer
124-
0.0
125-
nil
126-
(lambda ()
127-
(let ((point (point)))
128-
(push-mark (car bounds) t t)
129-
(goto-char (cdr bounds))
130-
(unless (= point (point))
131-
(exchange-point-and-mark)))))))
132-
(setq dap-tooltip-bounds nil)))
134+
135+
(when dap-mouse--hide-timer
136+
(cancel-timer dap-mouse--hide-timer))
137+
(when (dap-mouse--hide-popup?)
138+
(setq
139+
dap-mouse--hide-timer
140+
(run-at-time
141+
dap-mouse-popup-timeout nil
142+
(lambda ()
143+
(when (dap-mouse--hide-popup?)
144+
(posframe-hide dap-mouse-buffer)
145+
(when dap-tooltip-bounds
146+
(remove-text-properties (car dap-tooltip-bounds)
147+
(cdr dap-tooltip-bounds)
148+
'(mouse-face))
149+
;; restore the selection
150+
(when (region-active-p)
151+
(let ((bounds dap-tooltip-bounds))
152+
(run-with-idle-timer
153+
0.0
154+
nil
155+
(lambda ()
156+
(let ((point (point)))
157+
(push-mark (car bounds) t t)
158+
(goto-char (cdr bounds))
159+
(unless (= point (point))
160+
(exchange-point-and-mark)))))))
161+
(setq dap-tooltip-bounds nil))
162+
163+
(setq dap-mouse--hide-timer nil)
164+
(remove-hook 'post-command-hook #'dap-tooltip-post-tooltip)))))))
133165

134166
(defun dap-tooltip-tips (event)
135167
"Show tip for identifier or selection under the mouse.
@@ -149,25 +181,38 @@ This function must return nil if it doesn't handle EVENT."
149181
dap-tooltip-mode
150182
mouse-point)
151183
(-when-let* ((active-frame-id (-some->> debug-session
152-
dap--debug-session-active-frame
153-
(gethash "id")))
184+
dap--debug-session-active-frame
185+
(gethash "id")))
154186
(bounds (dap-tooltip-thing-bounds mouse-point))
155187
((start . end) bounds)
156-
(expression (buffer-substring start end)))
188+
(expression (s-trim (buffer-substring start end))))
157189
(setq dap-tooltip-bounds bounds)
158190
(dap--send-message
159191
(dap--make-request "evaluate"
160192
(list :expression expression
161193
:frameId active-frame-id))
162-
(-lambda ((&hash "message" "body" (&hash? "result")))
194+
(-lambda ((&hash "message" "body" (var &as &hash? "result")))
163195
(when (= request-id dap-tooltip--request)
164196
(if result
165197
(progn
166198
(add-text-properties start end
167199
'(mouse-face dap-mouse-eval-thing-face))
168-
(tooltip-show result
169-
(or dap-tooltip-echo-area tooltip-use-echo-area
170-
(not tooltip-mode)))
200+
(apply #'posframe-show
201+
(with-current-buffer (get-buffer-create dap-mouse-buffer)
202+
(lsp-treemacs-render
203+
(-let [(&hash "result" "variablesReference" variables-reference) var]
204+
`((:key ,expression
205+
:label ,result
206+
:icon dap-field
207+
:children ,(dap-ui-render-variables
208+
debug-session
209+
variables-reference nil))))
210+
""
211+
nil
212+
(buffer-name)))
213+
:position start
214+
:accept-focus t
215+
dap-mouse-posframe-properties)
171216
(add-hook 'post-command-hook 'dap-tooltip-post-tooltip))
172217
(message message))))
173218
debug-session))))

dap-ui.el

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,13 @@ number - expand N levels."
171171
((not (dap--session-running debug-session)) 'dap-ui-sessions-terminated-face)
172172
(t 'dap-ui-sessions-running-face)))
173173

174-
(defun dap-ui--make-overlay (beg end tooltip-text visuals &optional mouse-face buf)
174+
(defun dap-ui--make-overlay (beg end visuals &optional mouse-face buf)
175175
"Allocate a DAP UI overlay in range BEG and END.
176176
TOOLTIP-TEXT, VISUALS, MOUSE-FACE will be used for the overlay.
177177
BUF is the active buffer."
178178
(let ((ov (make-overlay beg end buf t t)))
179179
(overlay-put ov 'face (plist-get visuals :face))
180180
(overlay-put ov 'mouse-face mouse-face)
181-
(overlay-put ov 'help-echo tooltip-text)
182181
(overlay-put ov 'dap-ui-overlay t)
183182
(overlay-put ov 'priority (plist-get visuals :priority))
184183
(let ((char (plist-get visuals :char)))
@@ -192,7 +191,7 @@ BUF is the active buffer."
192191
(plist-get visuals :fringe)))))))
193192
ov))
194193

195-
(defun dap-ui--make-overlay-at (file point msg visuals)
194+
(defun dap-ui--make-overlay-at (file point visuals)
196195
"Create an overlay highlighting the given POINT in FILE.
197196
VISUALS and MSG will be used for the overlay."
198197
(-when-let (buf (find-buffer-visiting file))
@@ -201,7 +200,7 @@ VISUALS and MSG will be used for the overlay."
201200
(when (integer-or-marker-p point)
202201
(save-excursion
203202
(goto-char point)
204-
(dap-ui--make-overlay (point-at-bol) (point-at-eol) msg visuals nil buf))))))
203+
(dap-ui--make-overlay (point-at-bol) (point-at-eol) visuals nil buf))))))
205204

206205
(defvar-local dap-ui--breakpoint-overlays nil)
207206

@@ -236,7 +235,6 @@ DEBUG-SESSION the new breakpoints for FILE-NAME."
236235
(-map (-lambda ((bp . remote-bp))
237236
(push (dap-ui--make-overlay-at buffer-file-name
238237
(dap-breakpoint-get-point bp)
239-
"Breakpoint"
240238
(dap-ui--breakpoint-visuals bp remote-bp))
241239
dap-ui--breakpoint-overlays))
242240
(-zip-fill
@@ -261,7 +259,6 @@ DEBUG-SESSION the new breakpoints for FILE-NAME."
261259
(setq-local dap-ui--cursor-overlay
262260
(dap-ui--make-overlay-at
263261
file point
264-
"Debug Marker"
265262
(list :face 'dap-ui-marker-face
266263
:char ">"
267264
:bitmap 'right-triangle
@@ -785,7 +782,7 @@ DEBUG-SESSION is the debug session triggering the event."
785782
'face 'font-lock-variable-name-face)
786783
": "
787784
value)
788-
:icon variable
785+
:icon dap-variable
789786
:value ,value
790787
:session ,debug-session
791788
:variables-reference ,variables-reference
@@ -811,7 +808,7 @@ DEBUG-SESSION is the debug session triggering the event."
811808
(-map (-lambda ((&hash "name" "variablesReference" variables-reference))
812809
(list :key name
813810
:label name
814-
:icon 'scope
811+
:icon 'dap-scope
815812
:children (-partial #'dap-ui-render-variables
816813
(dap--cur-session)
817814
variables-reference)))
@@ -1065,7 +1062,7 @@ DEBUG-SESSION is the debug session triggering the event."
10651062
(s-join "\n"))
10661063
"Breakpoint"))))
10671064
(list :key label
1068-
:icon 'breakpoint
1065+
:icon 'dap-breakpoint
10691066
:icon-literal (propertize
10701067
""
10711068
'face (if (and remote-bp (gethash "verified" remote-bp))

0 commit comments

Comments
 (0)