Package: emacs;
Reported by: joaotavora <at> gmail.com (João Távora)
Date: Fri, 13 Oct 2017 16:08:02 UTC
Severity: minor
Tags: patch
Found in version 26.0.90
Done: joaotavora <at> gmail.com (João Távora)
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: joaotavora <at> gmail.com (João Távora) To: Dmitry Gutov <dgutov <at> yandex.ru> Cc: 28814 <at> debbugs.gnu.org Subject: bug#28814: [BUMP, PATCH] (26.0.90; When *xref* window is needed, original window-switching intent is lost ) Date: Mon, 23 Oct 2017 09:23:05 +0100
[Message part 1 (text/plain, inline)]
Dmitry Gutov <dgutov <at> yandex.ru> writes: > You are working on something that I agree is a real problem, but doing > this would effectively revert commit > 5698947ff9335cf150c73cca257a5e7e5951b045, which was based on a > previous discussion (see the link in the commit message), and in > particular, would bring back "disappearing *xref* buffer problem", as > Eli put it. > [...] > > I have a rough idea on how to fix the situation, but nothing even > close to an implementation. > Thanks for the pointer. After I read that discussion I will probably ask you about that. >> emacs -Q >> C-x 3 [split-window-right] >> C-x 2 [split-window-below] >> M-. xref-backend-definitions RET [xref-find-definitions] >> C-n [next-line] >> RET [xref-goto-xref] >> >> Expected the definition to be found in the original window where I >> pressed M-. but instead it was found in another. Another case: >> >> emacs -Q >> C-x 4 . xref-backend-definitions RET [xref-find-definitions-other-window] >> C-n >> RET >> >> Expected the definition to be found in some other window, different from >> the one I pressed M-. on. Instead went to the same one. > > With your patches applied, this example pops a new frame for me if I > press 'n' instead of 'C-n'. This is not hugely important in the light > of the larger problems above, but demonstrated difficulties with > window management when we try to pretend that the xref buffer "was > never there". You are absolutely right (and you don't have to tell me how hairy window-management code is). This particular problem, which I had also noticed, slipped through. I have a fix attached as a patch. The cause of this problem is that split-window-sensibly refuses to split a window whose dimensions are below those of split-height-threshold and split-width-threshold. The reason you don't see frames popping up every time you do C-x 4 b on a small frame is that this function contains a safety net for these cases: if the window to be split is the only one available in the frame, it disregards the dimension threshholds and splits anyway. The attached window.el patch is a correct way to generalize this to account for dedicated windows. If this is not accepted this local fix in xref.el will also work fine. @@ -504,7 +504,8 @@ xref--show-location (t (save-selected-window (xref--with-dedicated-window - (xref--show-pos-in-buf marker buf)))))) + (let ((split-height-threshold 0)) + (xref--show-pos-in-buf marker buf))))))) (user-error (message (error-message-string err))))) (defun xref-show-location-at-point () >> Also, in both >> situations, expected the window configuration to be the same as if I had >> searched for, say xref-backend-functions. >> >> This is fixed by the patches that I reattach after minor tweaks. The >> general idea is to have the *xref*, whose sudden appearance is hard to >> predict, obtrude as little as possible on the user's window >> configuration.p > > If we don't bring back the "disappearing *xref* buffer problem", > *xref* has to stay obtrusive. Do you think the rest of your patch will > make sense with that change? I see and I will try to answer. I proposed two patches previously: * a first one to fix the non-determinism of window popping/selecting behaviour; * a second one to make the *xref* buffer less obstrusive. * (now there is the third one that fixes the frame-popping glitch) IIUC it is the second one that clashes with "the dissapearing *xref* problem" that I have yet to read up on. If we don't come up with a solution for that, I would be OK with a solution that leaves it unsolved but adds some customization point (hook) for the user to put this behaviour in. João
[0003-Allow-split-window-sensibly-to-split-threshold-in-fu.patch (text/x-diff, inline)]
From 47480926f328db5d840ba518125e0866d29f8665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= <joaotavora <at> gmail.com> Date: Mon, 23 Oct 2017 09:05:32 +0100 Subject: [PATCH 3/3] Allow split-window-sensibly to split threshold in further edge case As a fallback, and to avoid creating a frame, split-window-sensibly would previously disregard split-height-threshold if the window to be split is the frame's root window. This change slightly expands on that: it disregards the threshold if the window to be split is the frame's only usable window (it is either the only one, as before, or all the other windows are dedicated to some buffer and thus cannot be touched). * lisp/window.el (split-height-threshold): Adjust doc to match split-window-sensibly. (split-window-sensibly): Also disregard threshold if all other windows are dedicated. --- lisp/window.el | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lisp/window.el b/lisp/window.el index 5ba9a305f9..21271944c0 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -6449,8 +6449,9 @@ split-height-threshold vertically only if it has at least this many lines. If this is nil, `split-window-sensibly' is not allowed to split a window vertically. If, however, a window is the only window on its -frame, `split-window-sensibly' may split it vertically -disregarding the value of this variable." +frame, or all the other ones are dedicated, +`split-window-sensibly' may split it vertically disregarding the +value of this variable." :type '(choice (const nil) (integer :tag "lines")) :version "23.1" :group 'windows) @@ -6557,15 +6558,25 @@ split-window-sensibly ;; Split window horizontally. (with-selected-window window (split-window-right))) - (and (eq window (frame-root-window (window-frame window))) - (not (window-minibuffer-p window)) - ;; If WINDOW is the only window on its frame and is not the - ;; minibuffer window, try to split it vertically disregarding - ;; the value of `split-height-threshold'. - (let ((split-height-threshold 0)) - (when (window-splittable-p window) - (with-selected-window window - (split-window-below)))))))) + (and + (let ((frame (window-frame window))) + (or + (eq window (frame-root-window frame)) + (let ((windows (delete window (window-list frame))) + w) + (while (and (setq w (pop windows)) + (window-dedicated-p w))) + (not windows)))) + (not (window-minibuffer-p window)) + ;; If WINDOW is the only usable window on its frame (it is + ;; the only one or,not being the only one, all the other ones + ;; are dedicated) and is not the minibuffer window, try to + ;; split it vertically disregarding the value of + ;; `split-height-threshold'. + (let ((split-height-threshold 0)) + (when (window-splittable-p window) + (with-selected-window window + (split-window-below)))))))) (defun window--try-to-split-window (window &optional alist) "Try to split WINDOW. -- 2.14.2
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.