14

Often, I my windows get automatically split until I arbitrarily decide that the current frame does not have enough real-estate for them all. When this occurs, I manually delete a window, create a frame, and switch to that deleted window. How can I write an elisp function that does this?

I tried:

(defun pop-window-into-frame ()
  (interactive)
  (delete-window)
  (make-frame-command)
  (switch-to-prev-buffer))

But for some reason this doesn't do what I think it should.

PythonNut
  • 10,243
  • 2
  • 29
  • 75

2 Answers2

16

Try this instead:

(defun my-turn-current-window-into-frame ()
  (interactive)
  (let ((buffer (current-buffer)))
    (unless (one-window-p)
      (delete-window))
    (display-buffer-pop-up-frame buffer nil)))
PythonNut
  • 10,243
  • 2
  • 29
  • 75
wasamasa
  • 21,803
  • 1
  • 65
  • 97
  • 1
    Another thing I didn't know I wanted until someone else wrote it. Cool. – glucas Jan 07 '15 at 15:19
  • Nice! +1 for being concise. – PythonNut Jan 07 '15 at 16:43
  • In terms of (minimal) performance impact - would it make a difference if the let and unless forms are swapped? – Matthias Jan 11 '15 at 09:08
  • @Matthias I'm not sure whether the inversion would make sense at this point, the reason I'm binding the current buffer is because deleting the window might change the notion of the current buffer. The only way I see around it would make the code more complicated by checking whether there's only one window, if yes let-binding the current buffer, deleting and popping it, if no just displaying the current buffer in a new frame. The loss of clarity isn't worth it for the miniscule performance change IMHO. – wasamasa Jan 11 '15 at 13:08
  • @wasamasa sorry for not beeing precise. I had in mind (unless (one-window-p) (let ... – Matthias Jan 30 '15 at 21:06
5
;; Inspired from `mouse-tear-off-window'.
(defun tear-off-window ()
  "Create a new frame displaying buffer of selected window.
    If window is not the only one in frame, then delete it.
    Otherwise, this command effectively clones the frame and window."
  (interactive)
  (let ((owin  (selected-window))
        (buf   (window-buffer))
        (fr    (make-frame)))
    (select-frame fr)
    (switch-to-buffer buf)
    (save-window-excursion 
      (select-window owin)
      (unless (one-window-p) (delete-window owin)))))

This command, as well as the following, which does nothing if the selected window is alone in its frame, are available in library frame-cmds.el.

(defun tear-off-window-if-not-alone ()
  "Move selected window to a new frame, unless it is alone in its frame.
If it is alone, do nothing.  Otherwise, delete it and create a new
frame showing the same buffer."
  (interactive)
  (if (one-window-p 'NOMINI)
      (message "Sole window in frame")
    (tear-off-window)))
Drew
  • 75,699
  • 9
  • 109
  • 225
  • This didn't give focus to the new frame here (gnome3.28). Adding `(select-frame-set-input-focus fr)` at the end worked. – olejorgenb Mar 29 '18 at 10:26
  • @olejorgenb: Yes, whether a newly created frame gets the input focus can depend on your window manager. So yes, you might need to add `select-frame-set-input-focus`. In MS Windows, for instance, it does get the focus, so that's not needed. Also, the command description does not say that the frame becomes focused. If that's wanted then a different command can be created that calls this and then focuses the frame. – Drew Mar 29 '18 at 15:43