> Please try with more buffers than initial 2 (*scratch* and *Messages*), > e.g. with *info* (just `C-h i'), I get > > 1 ... current: *scratch* ... window-buffer: *scratch* ... which is something you probably don't even want - it comes from 'get-buffer-create' when making the *info* buffer ... > 2 ... current: *scratch* ... window-buffer: *info* > > which is in an inconsistent state, ... not really - look at the backtrace: foo() run-hooks(buffer-list-update-hook) record-window-buffer(#) set-window-buffer(# #) window--display-buffer(# # reuse ((inhibit-same-window))) display-buffer-same-window(# ((inhibit-same-window))) display-buffer(# (display-buffer-same-window (inhibit-same-window))) pop-to-buffer("*info*" (display-buffer-same-window (inhibit-same-window)) nil) pop-to-buffer-same-window("*info*") info(nil nil) funcall-interactively(info nil nil) call-interactively(info nil nil) command-execute(info) 'pop-to-buffer' can "reasonably" select the window and thus implicitly make its buffer current only _after_ the buffer has been displayed via 'display-buffer-same-window'. I say reasonably because we could make the buffer current earlier but this doesn't strike me as a very good idea. It would constitute an incompatible change in the internal behavior of 'pop-to-buffer'. > and after typing `q' the hook is called 3 times > > 3 ... current: *scratch* ... window-buffer: *scratch* > 4 ... current: *scratch* ... window-buffer: *scratch* > 5 ... current: *scratch* ... window-buffer: *scratch* Look at the backtraces: 3 ... current: *scratch* ... window-buffer: *scratch* run-hooks(buffer-list-update-hook) record-window-buffer(#) set-window-buffer(# #) set-window-buffer-start-and-point(# # 1 #) quit-restore-window(nil bury) quit-window() Info-exit() funcall-interactively(Info-exit) call-interactively(Info-exit nil nil) command-execute(Info-exit) This one comes from replacing the *info* buffer with *scratch* in the window. 4 ... current: *scratch* ... window-buffer: *scratch* run-hooks(buffer-list-update-hook) select-window(#) quit-restore-window(nil bury) quit-window() Info-exit() funcall-interactively(Info-exit) call-interactively(Info-exit nil nil) command-execute(Info-exit) This one comes from selecting that window. 5 ... current: *scratch* ... window-buffer: *scratch* run-hooks(buffer-list-update-hook) bury-buffer-internal(#) quit-restore-window(nil bury) quit-window() Info-exit() funcall-interactively(Info-exit) call-interactively(Info-exit nil nil) command-execute(Info-exit) And this one comes from burying the *info* buffer. What should we do instead? > And there is the workflow how to break the correct order > of `C-x C-x ': > > 1. Create *info* buffer: `C-h i' and quit `q' > 2. Split windows `C-x 2' or `C-x 3' (both windows display *scratch*) > 3. Check that `C-x C-x ' correctly returns to the original > buffer *scratch* in the first window. > 4. After `C-x o' in another window `C-x C-x ' > doesn't return to the original buffer *scratch*. > It displays *info*. Evidently, this comment for 'record-window-buffer' ;; The following function is called by `set-window-buffer' _before_ it ;; replaces the buffer of the argument window with the new buffer. had its purpose. Please try the attached patch. Thanks, martin