3737(require  'goto-addr )
3838(require  'markdown-mode )
3939(require  'cl-lib )
40+ (require  'posframe )
4041
4142(when  (featurep  'xwidget-internal )
4243  (require  'xwidget ))
@@ -144,29 +145,14 @@ Only the `background' is used in this face."
144145  :group  'lsp-ui-doc )
145146
146147(defvar  lsp-ui-doc-frame-parameters 
147-   '((left .  -1 )
148-     (no-focus-on-map .  t )
149-     (min-width  .  0 )
150-     (width  .  0 )
151-     (min-height  .  0 )
152-     (height  .  0 )
153-     (internal-border-width .  1 )
148+   '((no-focus-on-map .  t )
154149    (vertical-scroll-bars .  nil )
155150    (horizontal-scroll-bars .  nil )
156-     (right-fringe .  0 )
157-     (menu-bar-lines .  0 )
158-     (tool-bar-lines .  0 )
159-     (line-spacing  .  0 )
160-     (unsplittable .  t )
161-     (undecorated .  t )
162-     (top .  -1 )
163-     (visibility .  nil )
164151    (mouse-wheel-frame .  nil )
165-     (no-other-frame  .  t )
152+     (no-accept-focus  .  nil )
166153    (inhibit-double-buffering .  t )
167-     (drag-internal-border .  t )
168-     (no-special-glyphs .  t )
169-     (desktop-dont-save .  t ))
154+     (cursor-type  .  box)
155+     (drag-internal-border .  t ))
170156  " Frame parameters used to create the frame." 
171157
172158(defvar  lsp-ui-doc-render-function  nil 
@@ -365,10 +351,7 @@ We don't extract the string that `lps-line' is already displaying."
365351  (when  (overlayp  lsp-ui-doc--inline-ov)
366352    (delete-overlay  lsp-ui-doc--inline-ov))
367353  (when  (lsp-ui-doc--get-frame)
368-     (unless  lsp-ui-doc-use-webkit
369-       (lsp-ui-doc--with-buffer
370-        (erase-buffer )))
371-     (make-frame-invisible  (lsp-ui-doc--get-frame))))
354+     (posframe-hide (lsp-ui-doc--make-buffer-name))))
372355
373356(defun  lsp-ui-doc--buffer-width  ()
374357  " Calcul the max width of the buffer." 
@@ -403,19 +386,6 @@ We don't extract the string that `lps-line' is already displaying."
403386    (xwidget-resize (lsp-ui-doc--webkit-get-xwidget) offset-width offset-height))
404387  (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame)))
405388
406- (defun  lsp-ui-doc--resize-buffer  ()
407-   " If the buffer's width is larger than the current frame, resize it." 
408-   (if  lsp-ui-doc-use-webkit
409-       (lsp-ui-doc--webkit-execute-script
410-        " [document.querySelector('#lsp-ui-webkit').offsetWidth, document.querySelector('#lsp-ui-webkit').offsetHeight];" 
411-        'lsp-ui-doc--webkit-resize-callback )
412- 
413-     (let*  ((frame-width  (frame-width ))
414-            (fill-column  (min  lsp-ui-doc-max-width (-  frame-width 5 ))))
415-       (when  (>  (lsp-ui-doc--buffer-width) (min  lsp-ui-doc-max-width frame-width))
416-         (lsp-ui-doc--with-buffer
417-          (fill-region  (point-min ) (point-max )))))))
418- 
419389(defun  lsp-ui-doc--mv-at-point  (frame  width  height  start-x  start-y )
420390  " Move FRAME to be where the point is.
421391WIDTH is the child frame width. 
@@ -459,12 +429,11 @@ FRAME just below the symbol at point."
459429    (if  (eq  lsp-ui-doc-position 'at-point )
460430        (lsp-ui-doc--mv-at-point frame width height left top)
461431      (set-frame-position  frame
462-                           (max  (-  frame-right width 10  ( frame-char-width ))  10 )
432+                           (max  (-  frame-right width )  0 )
463433                          (pcase  lsp-ui-doc-position
464-                             ('top  ( +   top  10 ) )
434+                             ('top  top)
465435                            ('bottom  (-  (lsp-ui-doc--line-height 'mode-line )
466-                                         height
467-                                         10 )))))))
436+                                         height)))))))
468437
469438(defun  lsp-ui-doc--visit-file  (filename )
470439  " Visit FILENAME in the parent frame." 
@@ -495,26 +464,31 @@ FN is the function to call on click."
495464        (lsp-ui-doc--put-click (match-beginning  0 ) (match-end  0 )
496465                               'browse-url-at-mouse )))))
497466
498- (defun  lsp-ui-doc--render-buffer  (string  symbol )
499-   " Set the buffer with STRING." 
467+ (defvar  lsp-ui-doc--render-string  nil 
468+   " The string to render in the documentation popup." 
469+ (defvar  lsp-ui-doc--render-symbol  nil 
470+   " The symbol to render documentation for." 
471+ 
472+ (defun  lsp-ui-doc--render-buffer  ()
473+   " Set the buffer with `lsp-ui-doc--render-string' ." 
500474  (lsp-ui-doc--with-buffer
501475   (if  lsp-ui-doc-use-webkit
502476       (progn 
503477         (lsp-ui-doc--webkit-execute-script
504478          (format 
505479           " renderMarkdown('%s', '%s');" 
506-            symbol
507-            (url-hexify-string  string))
480+            lsp-ui-doc--render- symbol
481+            (url-hexify-string  lsp-ui-doc--render- string))
508482          'lsp-ui-doc--webkit-resize-callback ))
509483     (erase-buffer )
510484     (let  ((inline-p (lsp-ui-doc--inline-p)))
511485       (insert  (concat  (unless  inline-p (propertize  " \n " 'face  '(:height  0.2 )))
512-                        (s-trim string)
486+                        (s-trim lsp-ui-doc--render- string)
513487                       (unless  inline-p (propertize  " \n\n " 'face  '(:height  0.3 ))))))
514488     (lsp-ui-doc--make-clickable-link))
515489   (setq-local  face-remapping-alist `((header-line  lsp-ui-doc-header)))
516490   (setq-local  window-min-height 1 )
517-    (setq  header-line-format (when  lsp-ui-doc-header (concat  "  " 
491+    (setq  header-line-format (when  lsp-ui-doc-header (concat  "  " lsp-ui-doc--render- symbol))
518492         mode-line-format nil 
519493         cursor-type nil )))
520494
@@ -619,49 +593,66 @@ HEIGHT is the documentation number of lines."
619593(defun  lsp-ui-doc--inline-p  ()
620594  " Return non-nil when the documentation should be display without a child frame." 
621595  (or  (not  lsp-ui-doc-use-childframe)
622-       (not  (display-graphic -p
596+       (not  (posframe-workable -p))
623597      (not  (fboundp  'display-buffer-in-child-frame ))))
624598
625599(defun  lsp-ui-doc--display  (symbol  string )
626600  " Display the documentation." 
601+   (setq  lsp-ui-doc--render-symbol symbol
602+         lsp-ui-doc--render-string string)
627603  (when  (and  lsp-ui-doc-use-webkit (not  (featurep  'xwidget-internal )))
628604    (setq  lsp-ui-doc-use-webkit nil ))
629605  (if  (or  (null  string) (string-empty-p  string))
630606      (lsp-ui-doc--hide-frame)
631-     (lsp-ui-doc--render-buffer string symbol )
607+     (lsp-ui-doc--render-buffer)
632608    (if  (lsp-ui-doc--inline-p)
633609        (lsp-ui-doc--inline)
634-       (unless  (lsp-ui-doc--get-frame)
610+       (when  (or  (not  lsp-ui-doc-use-webkit)
611+                 (not  (lsp-ui-doc--get-frame)))
635612        (lsp-ui-doc--set-frame (lsp-ui-doc--make-frame)))
636-       (unless  lsp-ui-doc-use-webkit
637-         (lsp-ui-doc--resize-buffer)
638-         (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame)))
639613      (unless  (frame-visible-p  (lsp-ui-doc--get-frame))
640614        (make-frame-visible  (lsp-ui-doc--get-frame))))))
641615
616+ (defun  lsp-ui-doc--posframe-poshandler-point-top-left-corner  (info )
617+   " Place the posframe at the top-left corner of the point without covering the
618+ point. 
619+ 
620+ The structure of INFO is defined in the documentation of `posframe-show' ."  
621+   (let*  ((frame (plist-get  info :posframe ))
622+          (height (frame-pixel-height  frame)))
623+     (posframe-poshandler-point-bottom-left-corner info (-  height))))
624+ 
642625(defun  lsp-ui-doc--make-frame  ()
643626  " Create the child frame and return it." 
644627  (lsp-ui-doc--delete-frame)
645-   (let*  ((after-make-frame-functions  nil )
646-          (before-make-frame-hook  nil )
647-          (name-buffer (lsp-ui-doc--make-buffer-name))
648-          (buffer (get-buffer  name-buffer))
649-          (params (append  lsp-ui-doc-frame-parameters
650-                          `((name .  " " 
651-                            (default-minibuffer-frame  .  ,(selected-frame ))
652-                            (minibuffer .  ,(minibuffer-window ))
653-                            (left-fringe .  ,(frame-char-width ))
654-                            (background-color .  ,(face-background  'lsp-ui-doc-background  nil  t )))))
655-          (window (display-buffer-in-child-frame 
656-                   buffer
657-                   `((child-frame-parameters .  , params
658-          (frame (window-frame  window)))
628+   (let*  ((before-make-frame-hook  nil )
629+         (buffer-name  (lsp-ui-doc--make-buffer-name))
630+         (buffer (get-buffer-create  buffer-name))
631+         (params (append  lsp-ui-doc-frame-parameters
632+                         `((name .  " " 
633+                           (default-minibuffer-frame  .  ,(selected-frame ))
634+                           (minibuffer .  ,(minibuffer-window )))))
635+         (position  (pcase  (list  lsp-ui-doc-position lsp-ui-doc-alignment)
636+                     ('(top frame) #'posframe-poshandler-frame-top-right-corner  )
637+                     ('(top window) #'posframe-poshandler-window-top-right-corner  )
638+                     ('(bottom frame) #'posframe-poshandler-frame-bottom-right-corner  )
639+                     ('(bottom window) #'posframe-poshandler-window-bottom-right-corner  )
640+                     ('(at-point frame) #'lsp-ui-doc--posframe-poshandler-point-top-left-corner  )
641+                     ('(at-point window) #'lsp-ui-doc--posframe-poshandler-point-top-left-corner  )))
642+         (frame (posframe-show buffer
643+                               :width  lsp-ui-doc-max-width
644+                               :height  lsp-ui-doc-max-height
645+                               :poshandler  position
646+                               :internal-border-width  1 
647+                               :internal-border-color  lsp-ui-doc-border
648+                               :left-fringe  t 
649+                               :right-fringe  t 
650+                               :background-color  (face-background  'lsp-ui-doc-background  nil  t )
651+                               :override-parameters  params))
652+         (window (frame-root-window  frame)))
659653    (with-current-buffer  buffer
660-       (lsp-ui-doc-frame-mode 1 ))
661-     (set-frame-parameter  nil  'lsp-ui-doc-buffer  buffer)
662-     (set-window-dedicated-p  window t )
663-     (redirect-frame-focus  frame (frame-parent  frame))
664-     (set-face-background  'internal-border  lsp-ui-doc-border frame)
654+       (lsp-ui-doc-frame-mode 1 )
655+       (visual-line-mode  1 ))
665656    (set-face-background  'fringe  nil  frame)
666657    (run-hook-with-args  'lsp-ui-doc-frame-hook  frame window)
667658    (when  lsp-ui-doc-use-webkit
@@ -670,6 +661,8 @@ HEIGHT is the documentation number of lines."
670661          (interactive )
671662
672663          (let  ((xwidget-event-type (nth  1  last-input-event)))
664+             (when  (eq  xwidget-event-type 'load-changed )
665+               (lsp-ui-doc--render-buffer))
673666            ; ; (when (eq xwidget-event-type 'load-changed)
674667            ; ;   (lsp-ui-doc--move-frame (lsp-ui-doc--get-frame)))
675668
@@ -727,7 +720,7 @@ BUFFER is the buffer where the request has been made."
727720(defun  lsp-ui-doc--delete-frame  ()
728721  " Delete the child frame if it exists." 
729722  (-when-let (frame (lsp-ui-doc--get-frame))
730-     (delete-frame  frame )
723+     (posframe- delete-frame (lsp-ui-doc--make-buffer-name) )
731724    (lsp-ui-doc--set-frame nil )))
732725
733726(defun  lsp-ui-doc--visible-p  ()
@@ -766,6 +759,27 @@ before, or if the new window is the minibuffer."
766759    (and  (buffer-live-p  it) it)
767760    (kill-buffer  it)))
768761
762+ (define-minor-mode  lsp-ui-doc-frame-mode
763+   " Marker mode to add additional key bind for lsp-ui-doc-frame." 
764+   :init-value  nil 
765+   :lighter  " " 
766+   :group  lsp-ui-doc
767+   :keymap  `(([?q ] .  lsp-ui-doc-unfocus-frame)))
768+ 
769+ (defun  lsp-ui-doc-focus-frame  ()
770+   " Focus into lsp-ui-doc-frame." 
771+   (interactive )
772+   (when  (lsp-ui-doc--frame-visible-p)
773+     (lsp-ui-doc--with-buffer
774+      (setq  cursor-type t ))
775+     (select-frame-set-input-focus  (lsp-ui-doc--get-frame))))
776+ 
777+ (defun  lsp-ui-doc-unfocus-frame  ()
778+   " Unfocus from lsp-ui-doc-frame." 
779+   (interactive )
780+   (when-let  ((frame (frame-parent  (lsp-ui-doc--get-frame))))
781+     (select-frame-set-input-focus  frame)))
782+ 
769783(define-minor-mode  lsp-ui-doc-mode
770784  " Minor mode for showing hover information in child frame." 
771785  :init-value  nil 
@@ -783,11 +797,17 @@ before, or if the new window is the minibuffer."
783797        (cl-callf  copy-tree  frameset-filter-alist)
784798        (push  '(lsp-ui-doc-frame .  :never ) frameset-filter-alist)))
785799    (add-hook  'post-command-hook  'lsp-ui-doc--make-request  nil  t )
786-     (add-hook  'delete-frame-functions  'lsp-ui-doc--on-delete  nil  t ))
800+     (add-hook  'delete-frame-functions  'lsp-ui-doc--on-delete  nil  t )
801+     (advice-add  #'posframe--redirect-posframe-focus  
802+                 :before-until  (lambda  (&rest  _ )
803+                                 lsp-ui-doc-frame-mode)
804+                 '((name .  lsp-ui-doc--dont-redirect-posframe))))
787805   (t 
788806    (lsp-ui-doc-hide)
789807    (remove-hook  'post-command-hook  'lsp-ui-doc--make-request  t )
790-     (remove-hook  'delete-frame-functions  'lsp-ui-doc--on-delete  t ))))
808+     (remove-hook  'delete-frame-functions  'lsp-ui-doc--on-delete  t )
809+     (advice-remove  #'posframe--redirect-posframe-focus  
810+                    'lsp-ui-doc--dont-redirect-posframe ))))
791811
792812(defun  lsp-ui-doc-enable  (enable )
793813  " Enable/disable ‘lsp-ui-doc-mode’.
@@ -825,26 +845,5 @@ It is supposed to be called from `lsp-ui--toggle'"
825845    (cancel-timer  lsp-ui-doc--unfocus-frame-timer))
826846  (add-hook  'post-command-hook  'lsp-ui-doc--glance-hide-frame ))
827847
828- (define-minor-mode  lsp-ui-doc-frame-mode
829-   " Marker mode to add additional key bind for lsp-ui-doc-frame." 
830-   :init-value  nil 
831-   :lighter  " " 
832-   :group  lsp-ui-doc
833-   :keymap  `(([?q ] .  lsp-ui-doc-unfocus-frame)))
834- 
835- (defun  lsp-ui-doc-focus-frame  ()
836-   " Focus into lsp-ui-doc-frame." 
837-   (interactive )
838-   (when  (lsp-ui-doc--frame-visible-p)
839-     (lsp-ui-doc--with-buffer
840-      (setq  cursor-type t ))
841-     (select-frame-set-input-focus  (lsp-ui-doc--get-frame))))
842- 
843- (defun  lsp-ui-doc-unfocus-frame  ()
844-   " Unfocus from lsp-ui-doc-frame." 
845-   (interactive )
846-   (when-let  ((frame (frame-parent  (lsp-ui-doc--get-frame))))
847-     (select-frame-set-input-focus  frame)))
848- 
849848(provide  'lsp-ui-doc )
850849; ;; lsp-ui-doc.el ends here
0 commit comments