When using the popwin mode, I notice that the pop-up window always appears at the bottom of the entire frame. For example, given the frame contains two windows, divided vertically, and I am editing the left one

+            |            +   
+  Editting  |            +   
+   window   |            +   
+            |            +   
+            |            +   

When performing some task, for example, compiling the editting file, the pop-up window in popwin mode will appear as follow:

+  Editting  |            +   
+   window   |            +   
+            |            +   
+         pop-win         +   

I find out that it's is a waste of space that the pop-up window occupies and the other window is shrunk, consequently.

So, I would like to ask if popwin mode can be configured to appear as follow?

+  Editting  |            +   
+   window   |            +   
+            |            +   
++++++++++++++            +
+   pop-win  |            +   

Thank you very much for spending your time to read my question. Any helps is much appreciated.

1 Answer 1


Popwin doesn't have a customizable way to achieve what you ask for, but we can hack it by overriding the function popwin:popup-buffer. Essentially, we replace the call to popwin:create-popup-window with code that displays the popup buffer in a new split:

(let* ((orig-window (selected-window))
      (new-window (split-window orig-window nil 'below)))
  (set-window-buffer new-window buffer)
  (list orig-window new-window nil))

This piece of code returns a "master window", which is the original window, a "popup window", which is the window used for the popup buffer, and a "window map", which is nil. In the original version, popwin:create-popup-window calls popwin:replicate-window-config and returns the result as the "window map". In turn, popwin:replicate-window-config returns nil if the frame has more than one window (maybe a bug), otherwise it returns some other value.

This answer is more a proof-of-concept than a polished solution, but of course you can improve on it if you find it necessary.

(defun* popwin:popup-buffer (buffer
                            (width popwin:popup-window-width)
                            (height popwin:popup-window-height)
                            (position popwin:popup-window-position)
  "Show BUFFER in a popup window and return the popup window. If
NOSELECT is non-nil, the popup window will not be selected. If
STICK is non-nil, the popup window will be stuck. If TAIL is
non-nil, the popup window will show the last contents. Calling
`popwin:popup-buffer' during `popwin:popup-buffer' is allowed. In
that case, the buffer of the popup window will be replaced with
  (interactive "BPopup buffer:\n")
  (setq buffer (get-buffer buffer))
  (run-hooks 'popwin:before-popup-hook)
  (multiple-value-bind (context context-stack)
      (popwin:find-context-for-buffer buffer :valid-only t)
    (if context
          (popwin:use-context context)
          (setq popwin:context-stack context-stack))
      (let ((win-outline (car (popwin:window-config-tree))))
        (destructuring-bind (master-win popup-win win-map)
            (let ((size (if (popwin:position-horizontal-p position) width height))
                  (adjust popwin:adjust-other-windows))
              ;; (popwin:create-popup-window size position adjust)       ; <-- original line
              (let* ((orig-window (selected-window))                     ; <-- modifications
                    (new-window (split-window orig-window nil 'below)))  ; <--
                (set-window-buffer new-window buffer)                    ; <--
                (list orig-window new-window nil))                       ; <--
          (setq popwin:popup-window popup-win
                popwin:master-window master-win
                popwin:window-outline win-outline
                popwin:window-map win-map
                popwin:window-config nil
                popwin:selected-window (selected-window)))
        (popwin:update-window-reference 'popwin:context-stack :recursive t)
      (with-selected-window popwin:popup-window
        (popwin:switch-to-buffer buffer)
        (when tail
          (set-window-point popwin:popup-window (point-max))
          (recenter -2)))
      (setq popwin:popup-buffer buffer
            popwin:popup-last-config (list buffer
                                          :width width :height height :position position
                                          :noselect noselect :dedicated dedicated
                                          :stick stick :tail tail)
            popwin:popup-window-dedicated-p dedicated
            popwin:popup-window-stuck-p stick)))
  (if noselect
      (setq popwin:focus-window popwin:selected-window)
    (setq popwin:focus-window popwin:popup-window)
    (select-window popwin:popup-window))
  (run-hooks 'popwin:after-popup-hook)
  • It's so nice that you gave a so detailed answer. It's even so wonderful that your answer works nicely! Thank you very much! This is definitely an awesome feature that popwin lacks, in my opinion.
    – Trung Ta
    Commented Oct 11, 2016 at 10:50
  • I make a small modification to adjust the popup-window-height according to the customization of popwin mode: (let* ((popup-win-height (- popwin:popup-window-height)) (orig-window (selected-window)) (new-window (split-window orig-window popup-win-height 'below))) (set-window-buffer new-window buffer) (list orig-window new-window nil))
    – Trung Ta
    Commented Oct 11, 2016 at 11:14
  • Sorry, the code inserted in my comment above is kind of ugly since all of the new-line characters are trimmed
    – Trung Ta
    Commented Oct 11, 2016 at 11:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.