* Resize mini windows
@ 2019-03-07 13:46 martin rudalics
2019-03-11 9:14 ` martin rudalics
0 siblings, 1 reply; 2+ messages in thread
From: martin rudalics @ 2019-03-07 13:46 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 557 bytes --]
The attached patch does the following:
- Move some of the minibuffer resize code from xdisp.c to window.c and
provide a common subroutine for automatic and manual resizing there.
- Remove the PIXELWISE argument from some of these functions since
resizing minibuffer windows never rounds.
- Provide a new option called 'resize-mini-frames' which allows to
automatically resize minibuffer-only frames according to the size of
text they display.
If there are no objections, I intend to install in a few days.
Thanks for your attention, martin
[-- Attachment #2: resize_mini_windows.diff --]
[-- Type: text/plain, Size: 16567 bytes --]
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 44ce292..9b9a46b 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -314,7 +314,13 @@ minibuffer-prompt-properties--setter
(other :tag "hidden by keypress" 1))
"22.1")
(make-pointer-invisible mouse boolean "23.2")
- (menu-bar-mode frames boolean nil
+ (resize-mini-frames
+ frames (choice
+ (const :tag "Never" nil)
+ (const :tag "Use 'fit-frame-to-buffer'" t)
+ (function :tag "User-defined function"))
+ "27.1")
+ (menu-bar-mode frames boolean nil
;; FIXME?
;; :initialize custom-initialize-default
:set custom-set-minor-mode)
diff --git a/lisp/window.el b/lisp/window.el
index 39f4fa1..90a2d0f 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2753,7 +2753,7 @@ window--resize-mini-window
;; Sanitize DELTA.
(cond
((<= (+ height delta) 0)
- (setq delta (- (frame-char-height (window-frame window)) height)))
+ (setq delta (- (frame-char-height frame) height)))
((> delta min-delta)
(setq delta min-delta)))
@@ -3381,6 +3381,12 @@ window--resize-root-window-vertically
pixel-delta
(/ pixel-delta (frame-char-height frame)))))
+(defun window--resize-mini-frame (frame)
+ "Resize minibuffer-only frame FRAME."
+ (if (functionp resize-mini-frames)
+ (funcall resize-mini-frames frame)
+ (fit-frame-to-buffer frame nil nil nil nil 'vertically)))
+
(defun window--sanitize-window-sizes (horizontal)
"Assert that all windows on selected frame are large enough.
If necessary and possible, make sure that every window on frame
diff --git a/src/frame.c b/src/frame.c
index 1219569..a194c48 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -6045,6 +6045,19 @@ either customize it (see the info node `Easy Customization')
This variable is local to the current terminal and cannot be buffer-local. */);
+ DEFVAR_LISP ("resize-mini-frames", resize_mini_frames,
+ doc: /* Non-nil means resize minibuffer-only frames automatically.
+If this is nil, do not resize minibuffer-only frames automatically.
+
+If this is a function, call that function with the minibuffer-only
+frame that shall be resized as sole argument. The buffer of the root
+window of that frame is the buffer whose text will be eventually shown
+in the minibuffer window.
+
+Any other non-nil value means to resize minibuffer-only frames by
+calling `fit-frame-to-buffer' with the ONLY argument 'vertically'. */);
+ resize_mini_frames = Qnil;
+
DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
doc: /* Non-nil if window system changes focus when you move the mouse.
You should set this variable to tell Emacs how your window manager
diff --git a/src/window.c b/src/window.c
index 8543cbf..3754220 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5134,118 +5134,111 @@ SIDE t (or `right') specifies that the new window shall be located on
Resizing Mini-Windows
***********************************************************************/
-/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
- can. */
+/**
+ * resize_mini_window_apply:
+ *
+ * Assign new window sizes after resizing a mini window W by DELTA
+ * pixels. No error checking performed.
+ */
+static void
+resize_mini_window_apply (struct window *w, int delta)
+{
+ struct frame *f = XFRAME (w->frame);
+ Lisp_Object root = FRAME_ROOT_WINDOW (f);
+ struct window *r = XWINDOW (root);
+
+ block_input ();
+ w->pixel_height = w->pixel_height + delta;
+ w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
+
+ window_resize_apply (r, false);
+
+ w->pixel_top = r->pixel_top + r->pixel_height;
+ w->top_line = r->top_line + r->total_lines;
+
+ /* Enforce full redisplay of the frame. */
+ /* FIXME: Shouldn't some of the caller do it? */
+ fset_redisplay (f);
+ adjust_frame_glyphs (f);
+ unblock_input ();
+}
+
+/**
+ * grow_mini_window:
+ *
+ * Grow mini-window W by DELTA pixels. If DELTA is negative, this may
+ * shrink the minibuffer window to the minimum height to display one
+ * line of text.
+ */
void
-grow_mini_window (struct window *w, int delta, bool pixelwise)
+grow_mini_window (struct window *w, int delta)
{
struct frame *f = XFRAME (w->frame);
- struct window *r;
- Lisp_Object root, height;
- int line_height, pixel_height;
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
+ int min_height = FRAME_LINE_HEIGHT (f);
eassert (MINI_WINDOW_P (w));
- eassert (delta >= 0);
- if (delta > 0)
- {
- root = FRAME_ROOT_WINDOW (f);
- r = XWINDOW (root);
- height = call3 (Qwindow__resize_root_window_vertically,
- root, make_fixnum (- delta), pixelwise ? Qt : Qnil);
- if (FIXNUMP (height) && window_resize_check (r, false))
- {
- block_input ();
- window_resize_apply (r, false);
+ if (old_height + delta < min_height)
+ /* Never shrink mini-window to less than its minimum
+ height. */
+ delta = old_height > min_height ? min_height - old_height : 0;
- if (pixelwise)
- {
- pixel_height = min (-XFIXNUM (height), INT_MAX - w->pixel_height);
- line_height = pixel_height / FRAME_LINE_HEIGHT (f);
- }
- else
- {
- line_height = min (-XFIXNUM (height),
- ((INT_MAX - w->pixel_height)
- / FRAME_LINE_HEIGHT (f)));
- pixel_height = line_height * FRAME_LINE_HEIGHT (f);
- }
+ if (delta != 0)
+ {
+ Lisp_Object root = FRAME_ROOT_WINDOW (f);
+ struct window *r = XWINDOW (root);
+ Lisp_Object grow;
- /* Grow the mini-window. */
- w->pixel_top = r->pixel_top + r->pixel_height;
- w->top_line = r->top_line + r->total_lines;
- /* Make sure the mini-window has always at least one line. */
- w->pixel_height = max (w->pixel_height + pixel_height,
- FRAME_LINE_HEIGHT (f));
- w->total_lines = max (w->total_lines + line_height, 1);
-
- /* Enforce full redisplay of the frame. */
- /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
- fset_redisplay (f);
- adjust_frame_glyphs (f);
- unblock_input ();
- }
- else
- error ("Failed to grow minibuffer window");
+ FRAME_WINDOWS_FROZEN (f) = true;
+ grow = call3 (Qwindow__resize_root_window_vertically,
+ root, make_fixnum (- delta), Qt);
+ if (FIXNUMP (grow) && window_resize_check (r, false))
+ resize_mini_window_apply (w, -XFIXNUM (grow));
}
}
-/* Shrink mini-window W to one line. */
+/**
+ * shrink_mini_window:
+ *
+ * Shrink mini-window W to the minimum height needed to display one
+ * line of text.
+ */
void
-shrink_mini_window (struct window *w, bool pixelwise)
+shrink_mini_window (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- struct window *r;
- Lisp_Object root, delta;
- EMACS_INT height, unit;
+ int delta = WINDOW_PIXEL_HEIGHT (w) - FRAME_LINE_HEIGHT (f);
eassert (MINI_WINDOW_P (w));
- height = pixelwise ? w->pixel_height : w->total_lines;
- unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
- if (height > unit)
+ if (delta > 0)
{
- root = FRAME_ROOT_WINDOW (f);
- r = XWINDOW (root);
- delta = call3 (Qwindow__resize_root_window_vertically,
- root, make_fixnum (height - unit),
- pixelwise ? Qt : Qnil);
- if (FIXNUMP (delta) && window_resize_check (r, false))
- {
- block_input ();
- window_resize_apply (r, false);
-
- /* Shrink the mini-window. */
- w->top_line = r->top_line + r->total_lines;
- w->total_lines = 1;
- w->pixel_top = r->pixel_top + r->pixel_height;
- w->pixel_height = FRAME_LINE_HEIGHT (f);
- /* Enforce full redisplay of the frame. */
- /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
- fset_redisplay (f);
- adjust_frame_glyphs (f);
- unblock_input ();
- }
- /* If the above failed for whatever strange reason we must make a
- one window frame here. The same routine will be needed when
- shrinking the frame (and probably when making the initial
- *scratch* window). For the moment leave things as they are. */
- else
- error ("Failed to shrink minibuffer window");
+ Lisp_Object root = FRAME_ROOT_WINDOW (f);
+ struct window *r = XWINDOW (root);
+ Lisp_Object grow;
+
+ FRAME_WINDOWS_FROZEN (f) = false;
+ grow = call3 (Qwindow__resize_root_window_vertically,
+ root, make_fixnum (delta), Qt);
+
+ if (FIXNUMP (grow) && window_resize_check (r, false))
+ resize_mini_window_apply (w, -XFIXNUM (grow));
}
}
-DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
- doc: /* Resize minibuffer window WINDOW. */)
+DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal,
+ Sresize_mini_window_internal, 1, 1, 0,
+ doc: /* Resize mini window WINDOW. */)
(Lisp_Object window)
{
struct window *w = XWINDOW (window);
struct window *r;
struct frame *f;
- int height;
+ int old_height, delta;
- CHECK_WINDOW (window);
+ CHECK_LIVE_WINDOW (window);
f = XFRAME (w->frame);
if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
@@ -5254,26 +5247,18 @@ SIDE t (or `right') specifies that the new window shall be located on
error ("Cannot resize a minibuffer-only frame");
r = XWINDOW (FRAME_ROOT_WINDOW (f));
- height = r->pixel_height + w->pixel_height;
+ old_height = r->pixel_height + w->pixel_height;
+ delta = XFIXNUM (w->new_pixel) - w->pixel_height;
if (window_resize_check (r, false)
&& XFIXNUM (w->new_pixel) > 0
- && height == XFIXNUM (r->new_pixel) + XFIXNUM (w->new_pixel))
+ && old_height == XFIXNUM (r->new_pixel) + XFIXNUM (w->new_pixel))
{
- block_input ();
- window_resize_apply (r, false);
-
- w->pixel_height = XFIXNAT (w->new_pixel);
- w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
- w->pixel_top = r->pixel_top + r->pixel_height;
- w->top_line = r->top_line + r->total_lines;
+ resize_mini_window_apply (w, delta);
- fset_redisplay (f);
- adjust_frame_glyphs (f);
- unblock_input ();
return Qt;
}
else
- error ("Failed to resize minibuffer window");
+ error ("Cannot resize mini window");
}
\f
/* Mark window cursors off for all windows in the window tree rooted
@@ -8012,6 +7997,7 @@ static void init_window_once_for_pdumper (void)
DEFSYM (Qwindow__resize_root_window, "window--resize-root-window");
DEFSYM (Qwindow__resize_root_window_vertically,
"window--resize-root-window-vertically");
+ DEFSYM (Qwindow__resize_mini_frame, "window--resize-mini-frame");
DEFSYM (Qwindow__sanitize_window_sizes, "window--sanitize-window-sizes");
DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
DEFSYM (Qsafe, "safe");
diff --git a/src/window.h b/src/window.h
index d816bb1..b450173 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1063,8 +1063,8 @@ extern Lisp_Object window_from_coordinates (struct frame *, int, int,
extern void resize_frame_windows (struct frame *, int, bool, bool);
extern void restore_window_configuration (Lisp_Object);
extern void delete_all_child_windows (Lisp_Object);
-extern void grow_mini_window (struct window *, int, bool);
-extern void shrink_mini_window (struct window *, bool);
+extern void grow_mini_window (struct window *, int);
+extern void shrink_mini_window (struct window *);
extern int window_relative_x_coord (struct window *, enum window_part, int);
void run_window_change_functions (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index 6ceb5c9..953cf7f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11259,15 +11259,10 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
resize_mini_window (struct window *w, bool exact_p)
{
struct frame *f = XFRAME (w->frame);
- bool window_height_changed_p = false;
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
eassert (MINI_WINDOW_P (w));
- /* By default, start display at the beginning. */
- set_marker_both (w->start, w->contents,
- BUF_BEGV (XBUFFER (w->contents)),
- BUF_BEGV_BYTE (XBUFFER (w->contents)));
-
/* Don't resize windows while redisplaying a window; it would
confuse redisplay functions when the size of the window they are
displaying changes from under them. Such a resizing can happen,
@@ -11278,19 +11273,30 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
return false;
/* Nil means don't try to resize. */
- if (NILP (Vresize_mini_windows)
+ if ((NILP (Vresize_mini_windows)
+ && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
|| (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
return false;
- if (!FRAME_MINIBUF_ONLY_P (f))
+ /* By default, start display at the beginning. */
+ set_marker_both (w->start, w->contents,
+ BUF_BEGV (XBUFFER (w->contents)),
+ BUF_BEGV_BYTE (XBUFFER (w->contents)));
+
+ if (FRAME_MINIBUF_ONLY_P (f))
+ {
+ if (!NILP (resize_mini_frames))
+ safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
+ }
+ else
{
struct it it;
- int total_height = (WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)))
- + WINDOW_PIXEL_HEIGHT (w));
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
int unit = FRAME_LINE_HEIGHT (f);
int height, max_height;
struct text_pos start;
struct buffer *old_current_buffer = NULL;
+ int windows_height = FRAME_WINDOWS_HEIGHT (f);
if (current_buffer != XBUFFER (w->contents))
{
@@ -11302,14 +11308,14 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
/* Compute the max. number of lines specified by the user. */
if (FLOATP (Vmax_mini_window_height))
- max_height = XFLOAT_DATA (Vmax_mini_window_height) * total_height;
+ max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
else if (FIXNUMP (Vmax_mini_window_height))
max_height = XFIXNUM (Vmax_mini_window_height) * unit;
else
- max_height = total_height / 4;
+ max_height = windows_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = clip_to_bounds (unit, max_height, total_height);
+ max_height = clip_to_bounds (unit, max_height, windows_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
@@ -11335,63 +11341,27 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
}
else
SET_TEXT_POS (start, BEGV, BEGV_BYTE);
+
SET_MARKER_FROM_TEXT_POS (w->start, start);
if (EQ (Vresize_mini_windows, Qgrow_only))
{
/* Let it grow only, until we display an empty message, in which
case the window shrinks again. */
- if (height > WINDOW_PIXEL_HEIGHT (w))
- {
- int old_height = WINDOW_PIXEL_HEIGHT (w);
-
- FRAME_WINDOWS_FROZEN (f) = true;
- grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), true);
- window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
- }
- else if (height < WINDOW_PIXEL_HEIGHT (w)
- && (exact_p || BEGV == ZV))
- {
- int old_height = WINDOW_PIXEL_HEIGHT (w);
-
- FRAME_WINDOWS_FROZEN (f) = false;
- shrink_mini_window (w, true);
- window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
- }
- }
- else
- {
- /* Always resize to exact size needed. */
- if (height > WINDOW_PIXEL_HEIGHT (w))
- {
- int old_height = WINDOW_PIXEL_HEIGHT (w);
-
- FRAME_WINDOWS_FROZEN (f) = true;
- grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), true);
- window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
- }
- else if (height < WINDOW_PIXEL_HEIGHT (w))
- {
- int old_height = WINDOW_PIXEL_HEIGHT (w);
-
- FRAME_WINDOWS_FROZEN (f) = false;
- shrink_mini_window (w, true);
-
- if (height)
- {
- FRAME_WINDOWS_FROZEN (f) = true;
- grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), true);
- }
-
- window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
- }
+ if (height > old_height)
+ grow_mini_window (w, height - old_height);
+ else if (height < old_height && (exact_p || BEGV == ZV))
+ shrink_mini_window (w);
}
+ else if (height != old_height)
+ /* Always resize to exact size needed. */
+ grow_mini_window (w, height - old_height);
if (old_current_buffer)
set_buffer_internal (old_current_buffer);
}
- return window_height_changed_p;
+ return WINDOW_PIXEL_HEIGHT (w) != old_height;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: Resize mini windows
2019-03-07 13:46 Resize mini windows martin rudalics
@ 2019-03-11 9:14 ` martin rudalics
0 siblings, 0 replies; 2+ messages in thread
From: martin rudalics @ 2019-03-11 9:14 UTC (permalink / raw)
To: emacs-devel
> If there are no objections, I intend to install in a few days.
Installed now.
martin
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-03-11 9:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-03-07 13:46 Resize mini windows martin rudalics
2019-03-11 9:14 ` martin rudalics
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.