From 0e2b123a4ef600f5b337972a7bb61c1fc4b7d0cd Mon Sep 17 00:00:00 2001 From: Andrii Kolomoiets Date: Thu, 11 Feb 2021 10:09:41 +0100 Subject: Use frame monitor in frame_float * src/frame.c (frame_float): Use frame monitor attributes instead of attributes of the main monitor (bug#46406). --- src/frame.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index 635fc945604..a62347c1fb2 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3890,7 +3890,7 @@ frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what, Lisp_Object frame; XSETFRAME (frame, f); - monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame)); + monitor_attributes = call1 (Qframe_monitor_attributes, frame); if (NILP (monitor_attributes)) { /* No monitor attributes available. */ @@ -5890,7 +5890,7 @@ syms_of_frame (void) DEFSYM (Qframep, "framep"); DEFSYM (Qframe_live_p, "frame-live-p"); DEFSYM (Qframe_windows_min_size, "frame-windows-min-size"); - DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list"); + DEFSYM (Qframe_monitor_attributes, "frame-monitor-attributes"); DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total"); DEFSYM (Qexplicit_name, "explicit-name"); DEFSYM (Qheight, "height"); -- cgit v1.2.3 From ef122bf45d8ab7f8ec31612ac39fc521039ae19a Mon Sep 17 00:00:00 2001 From: Daniel Martín Date: Tue, 16 Mar 2021 01:29:28 +0100 Subject: Add minibuffer input support to commands that set the frame size * lisp/frame.el (set-frame-property--interactive): Internal function to produce the interactive form of `set-frame-width' and `set-frame-height'. Offer the current size as default. (Bug#9970) * src/frame.c (Fset_frame_height): Modify to call `set-frame-property--interactive'. (Fset_frame_width): Modify to call `set-frame-property--interactive'. * doc/lispref/frames.texi (Frame Size): Update the manuals. * etc/NEWS: Advertise the change (bug#9970). --- doc/lispref/frames.texi | 12 ++++++------ etc/NEWS | 4 ++++ lisp/frame.el | 8 ++++++++ src/frame.c | 4 ++-- 4 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/frame.c') diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index f4316b753d8..cd2ff8f3b31 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -1120,9 +1120,9 @@ The optional fourth argument @var{pixelwise} non-@code{nil} means that refuse to truly honor the request if it does not increase/decrease the frame height to a multiple of its character height. -When used interactively, this command will set the height of the -currently selected frame to the number of lines specified by the -numeric prefix. +When used interactively, this command will ask the user for the number +of lines to set the height of the currently selected frame. You can +also provide this value with a numeric prefix. @end defun @defun set-frame-width frame width &optional pretend pixelwise @@ -1136,9 +1136,9 @@ The optional fourth argument @var{pixelwise} non-@code{nil} means that refuse to fully honor the request if it does not increase/decrease the frame width to a multiple of its character width. -When used interactively, this command will set the width of the -currently selected frame to the number of columns specified by the -numeric prefix. +When used interactively, this command will ask the user for the number +of columns to set the width of the currently selected frame. You can +also provide this value with a numeric prefix. @end defun None of these three functions will make a frame smaller than needed to diff --git a/etc/NEWS b/etc/NEWS index 18b1252bcae..6fe98dbc123 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -253,6 +253,10 @@ commands. The new keystrokes are 'C-x x g' ('revert-buffer'), ('clone-buffer'), 'C-x x i' ('insert-buffer') and 'C-x x t' ('toggle-truncate-lines'). +--- +** Commands 'set-frame-width' and 'set-frame-height' can now get their +input using the minibuffer. + * Editing Changes in Emacs 28.1 diff --git a/lisp/frame.el b/lisp/frame.el index ce4de83b8c5..409ce0563b5 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2733,6 +2733,14 @@ See also `toggle-frame-maximized'." (make-obsolete-variable 'window-system-version "it does not give useful information." "24.3") +(defun set-frame-property--interactive (prompt number) + "Get a value for `set-frame-width' or `set-frame-height', prompting with PROMPT. +Offer NUMBER as default value, if it is a natural number." + (if (and current-prefix-arg (not (consp current-prefix-arg))) + (list (selected-frame) (prefix-numeric-value current-prefix-arg)) + (let ((default (and (natnump number) number))) + (list (selected-frame) (read-number prompt (list default (point))))))) + ;; Variables whose change of value should trigger redisplay of the ;; current buffer. ;; To test whether a given variable needs to be added to this list, diff --git a/src/frame.c b/src/frame.c index a62347c1fb2..cfdf3b61938 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3595,7 +3595,7 @@ check_frame_pixels (Lisp_Object size, Lisp_Object pixelwise, int item_size) } DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, - "(list (selected-frame) (prefix-numeric-value current-prefix-arg))", + "(set-frame-property--interactive \"Frame height: \" (frame-height))", doc: /* Set text height of frame FRAME to HEIGHT lines. Optional third arg PRETEND non-nil means that redisplay should use HEIGHT lines but that the idea of the actual height of the frame should @@ -3620,7 +3620,7 @@ If FRAME is nil, it defaults to the selected frame. */) } DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, - "(list (selected-frame) (prefix-numeric-value current-prefix-arg))", + "(set-frame-property--interactive \"Frame width: \" (frame-width))", doc: /* Set text width of frame FRAME to WIDTH columns. Optional third arg PRETEND non-nil means that redisplay should use WIDTH columns but that the idea of the actual width of the frame should not -- cgit v1.2.3 From 7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sun, 21 Mar 2021 16:54:31 +0000 Subject: Prevent open minibuffers getting lost when their frame gets deleted This happened with minibuffer-follows-selected-frame set to t. * doc/emacs/mini.texi (Basic Minibuffer): State where a command's action takes place when a minibuffer's frame has been deleted. * lisp/window.el (window--before-delete-windows, record-window-buffer): Take into account that minibuffers are now recorded on w->prev_buffers field. * src/fns.c (merge_c): New version of `merge' taking a C function, rather than a Lisp function as the comparison function. * src/frame.c (do_switch_frame): Pass arguments sf and for_deletion to move_minibuffers_onnto_frame. * src/lisp.h (top level): Declare merge_c and move_minibuffers_onto_selected_frame. * src/minibuf.c (MB_frame): New Lisp_Object recording the minibuffer's frame. (choose_minibuf_frame): Remove all code except that which sets minibuf_window to the current frame's minibuffer. (minibuffer_ent_greater): New comparison function, passed to merge_c. (zip_minibuffer_stacks): New function. (move_minibuffers_onto_frame): Renamed from `move_minibuffer_onto_frame' given two arguments, the old frame and for_deletion, and simplified. Minibuffers are now stacked in the mini-window's ->prev_buffers field. (read_minibuf): Several detailed amendments. (exp_MB_frame): New Lisp_Object, the expired minibuffer's frame. (read_minibuf_unwind): Search for the expired minibuffer's frame, rather than taking it from (unreliable) variables. Switch temporarily to this frame for tidying up operations. (minibuffer_unwind): New function which pops a stacked minibuffer. (syms_of_minibuf): Call staticpro for the two new Lisp variables. * src/window.c (Fset_window_configuration): Don't record minibuffers with record-window-buffer. * src/xdisp.c (gui_consider_frame_title): Remove redundant Fselect_window, which caused an unwanted frame switch. Amend the arguments to format_mode_line_unwind_data to match. --- doc/emacs/mini.texi | 4 +- lisp/window.el | 5 +- src/fns.c | 46 +++++++++ src/frame.c | 2 +- src/lisp.h | 3 +- src/minibuf.c | 292 +++++++++++++++++++++++++++++++++------------------- src/window.c | 3 +- src/xdisp.c | 3 +- 8 files changed, 242 insertions(+), 116 deletions(-) (limited to 'src/frame.c') diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi index 9c1b9757593..d0865c5d0bd 100644 --- a/doc/emacs/mini.texi +++ b/doc/emacs/mini.texi @@ -82,7 +82,9 @@ after a recursive minibuffer has been opened in the current command (@pxref{Recursive Mini,,, elisp}). This option is mainly to retain (approximately) the behavior prior to Emacs 28.1. Note that the effect of the command, when you finally finish using the minibuffer, -always takes place in the frame where you first opened it. +always takes place in the frame where you first opened it. The sole +exception is that when that frame no longer exists, the action takes +place in the currently selected frame. @node Minibuffer File @section Minibuffers for File Names diff --git a/lisp/window.el b/lisp/window.el index cfd9876ed05..f27631bb86a 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -4158,7 +4158,7 @@ returned by `window-start' and `window-point' respectively. This function is called only if `switch-to-buffer-preserve-window-point' evaluates non-nil." - (dolist (win (window-list)) + (dolist (win (window-list nil 'no-minibuf)) (let* ((buf (window-buffer (or window win))) (start (window-start win)) (pos (window-point win)) @@ -4416,7 +4416,8 @@ WINDOW must be a live window and defaults to the selected one." window (assq-delete-all buffer (window-prev-buffers window)))) ;; Don't record insignificant buffers. - (unless (eq (aref (buffer-name buffer) 0) ?\s) + (when (or (not (eq (aref (buffer-name buffer) 0) ?\s)) + (minibufferp buffer)) ;; Add an entry for buffer to WINDOW's previous buffers. (with-current-buffer buffer (let ((start (window-start window)) diff --git a/src/fns.c b/src/fns.c index 766e767e123..2cd59c83d91 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2279,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) } } +Lisp_Object +merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, Lisp_Object)) +{ + Lisp_Object l1 = org_l1; + Lisp_Object l2 = org_l2; + Lisp_Object tail = Qnil; + Lisp_Object value = Qnil; + + while (1) + { + if (NILP (l1)) + { + if (NILP (tail)) + return l2; + Fsetcdr (tail, l2); + return value; + } + if (NILP (l2)) + { + if (NILP (tail)) + return l1; + Fsetcdr (tail, l1); + return value; + } + + Lisp_Object tem; + if (less (Fcar (l1), Fcar (l2))) + { + tem = l1; + l1 = Fcdr (l1); + org_l1 = l1; + } + else + { + tem = l2; + l2 = Fcdr (l2); + org_l2 = l2; + } + if (NILP (tail)) + value = tem; + else + Fsetcdr (tail, tem); + tail = tem; + } +} + /* This does not check for quits. That is safe since it must terminate. */ diff --git a/src/frame.c b/src/frame.c index cfdf3b61938..66ae4943ba2 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1487,7 +1487,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor #endif internal_last_event_frame = Qnil; - move_minibuffer_onto_frame (); + move_minibuffers_onto_frame (sf, for_deletion); return frame; } diff --git a/src/lisp.h b/src/lisp.h index b95f389b890..c67c8b08573 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3610,6 +3610,7 @@ extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object, extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); +extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, Lisp_Object)); extern Lisp_Object do_yes_or_no_p (Lisp_Object); extern int string_version_cmp (Lisp_Object, Lisp_Object); extern Lisp_Object concat2 (Lisp_Object, Lisp_Object); @@ -4348,7 +4349,7 @@ extern void clear_regexp_cache (void); extern Lisp_Object Vminibuffer_list; extern Lisp_Object last_minibuf_string; -extern void move_minibuffer_onto_frame (void); +extern void move_minibuffers_onto_frame (struct frame *, bool); extern bool is_minibuffer (EMACS_INT, Lisp_Object); extern EMACS_INT this_minibuffer_depth (Lisp_Object); extern EMACS_INT minibuf_level; diff --git a/src/minibuf.c b/src/minibuf.c index 4b1f4b1ff72..d58924ae520 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -59,6 +59,12 @@ Lisp_Object last_minibuf_string; static Lisp_Object minibuf_prompt; +/* The frame containinug the most recently opened Minibuffer. This is + used only when `minibuffer-follows-selected-frame' is neither nil + nor t. */ + +static Lisp_Object MB_frame; + /* Width of current mini-buffer prompt. Only set after display_line of the line that contains the prompt. */ @@ -67,6 +73,7 @@ static ptrdiff_t minibuf_prompt_width; static Lisp_Object nth_minibuffer (EMACS_INT depth); static EMACS_INT minibuf_c_loop_level (EMACS_INT depth); static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth); +static bool live_minibuffer_p (Lisp_Object); /* Return TRUE when a frame switch causes a minibuffer on the old @@ -78,6 +85,7 @@ minibuf_follows_frame (void) Qt); } +#if 0 /* Return TRUE when a minibuffer always remains on the frame where it was first invoked. */ static bool @@ -85,6 +93,7 @@ minibuf_stays_put (void) { return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame)); } +#endif /* Return TRUE when opening a (recursive) minibuffer causes minibuffers on other frames to move to the selected frame. */ @@ -112,84 +121,85 @@ choose_minibuf_frame (void) emacs_abort (); minibuf_window = sf->minibuffer_window; - /* If we've still got another minibuffer open, use its mini-window - instead. */ - if (minibuf_level > 1 && minibuf_stays_put ()) - { - Lisp_Object buffer = get_minibuffer (minibuf_level); - Lisp_Object tail, frame; - - FOR_EACH_FRAME (tail, frame) - if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents, - buffer)) - { - minibuf_window = XFRAME (frame)->minibuffer_window; - break; - } - } } +} - if (minibuf_moves_frame_when_opened () - && FRAMEP (selected_frame) - && FRAME_LIVE_P (XFRAME (selected_frame))) - /* Make sure no other frame has a minibuffer as its selected window, - because the text would not be displayed in it, and that would be - confusing. Only allow the selected frame to do this, - and that only if the minibuffer is active. */ - { - Lisp_Object tail, frame; - struct frame *of; - - FOR_EACH_FRAME (tail, frame) - if (!EQ (frame, selected_frame) - && minibuf_level > 1 - /* The frame's minibuffer can be on a different frame. */ - && ! EQ (XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame, - selected_frame)) - { - if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of)))) - Fset_frame_selected_window (frame, Fframe_first_window (frame), - Qnil); - - if (!EQ (XWINDOW (of->minibuffer_window)->contents, - nth_minibuffer (0))) - set_window_buffer (of->minibuffer_window, - nth_minibuffer (0), 0, 0); - } - } +/* If ENT1 has a higher minibuffer index than ENT2, return true. More +precisely, compare the buffer components of each window->prev_buffers +entry. */ +static bool +minibuffer_ent_greater (Lisp_Object ent1, Lisp_Object ent2) +{ + return this_minibuffer_depth (Fcar (ent1)) + > this_minibuffer_depth (Fcar (ent2)) ; } -/* If `minibuffer_follows_selected_frame' is t and we have a - minibuffer, move it from its current frame to the selected frame. - This function is intended to be called from `do_switch_frame' in - frame.c. */ -void move_minibuffer_onto_frame (void) +/* Move the ordered "stack" of minibuffers from SOURCE_WINDOW to + DEST_WINDOW, interleaving those minibuffers with any in DEST_WINDOW + to produce an ordered combination. The ordering is by minibuffer + depth. A stack of minibuffers consists of the minibuffer currently + in DEST/SOURCE_WINDOW together with any recorded in the + ->prev_buffers field of the struct window. */ +static void +zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window) { - if (!minibuf_level) - return; - if (!minibuf_follows_frame ()) - return; - if (FRAMEP (selected_frame) - && FRAME_LIVE_P (XFRAME (selected_frame)) - && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window)) + struct window *dw = XWINDOW (dest_window); + struct window *sw = XWINDOW (source_window); + Lisp_Object acc; + Lisp_Object d_ent; /* Entry from dw->prev_buffers */ + + if (!live_minibuffer_p (dw->contents) + && NILP (dw->prev_buffers)) { - EMACS_INT i; - struct frame *sf = XFRAME (selected_frame); - Lisp_Object old_frame = XWINDOW (minibuf_window)->frame; - struct frame *of = XFRAME (old_frame); + set_window_buffer (dest_window, sw->contents, 0, 0); + Fset_window_start (dest_window, Fwindow_start (source_window), Qnil); + Fset_window_point (dest_window, Fwindow_point (source_window)); + dw->prev_buffers = sw->prev_buffers; + set_window_buffer (source_window, get_minibuffer (0), 0, 0); + sw->prev_buffers = Qnil; + return; + } - /* Stack up all the (recursively) open minibuffers on the selected - mini_window. */ - for (i = 1; i <= minibuf_level; i++) - set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0); - minibuf_window = sf->minibuffer_window; - if (of != sf) - { - Lisp_Object temp = get_minibuffer (0); + if (live_minibuffer_p (dw->contents)) + call1 (Qrecord_window_buffer, dest_window); + if (live_minibuffer_p (sw->contents)) + call1 (Qrecord_window_buffer, source_window); - set_window_buffer (of->minibuffer_window, temp, 0, 0); - set_minibuffer_mode (temp, 0); - } + acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater); + + if (!NILP (acc)) + { + d_ent = Fcar (acc); + acc = Fcdr (acc); + set_window_buffer (dest_window, Fcar (d_ent), 0, 0); + Fset_window_start (dest_window, Fcar (Fcdr (d_ent)), Qnil); + Fset_window_point (dest_window, Fcar (Fcdr (Fcdr (d_ent)))); + } + dw->prev_buffers = acc; + sw->prev_buffers = Qnil; + set_window_buffer (source_window, get_minibuffer (0), 0, 0); +} + +/* If `minibuffer_follows_selected_frame' is t, or we're about to + delete a frame which potentially "contains" minibuffers, move them + from the old frame to the selected frame. This function is + intended to be called from `do_switch_frame' in frame.c. OF is the + old frame, FOR_DELETION is true if OF is about to be deleted. */ +void +move_minibuffers_onto_frame (struct frame *of, bool for_deletion) +{ + struct frame *f = XFRAME (selected_frame); + + minibuf_window = f->minibuffer_window; + if (!(minibuf_level + && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of)))) + return; + if (FRAME_LIVE_P (f) + && !EQ (f->minibuffer_window, of->minibuffer_window)) + { + zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); + if (for_deletion && XFRAME (MB_frame) != of) + MB_frame = selected_frame; } } @@ -221,6 +231,7 @@ without invoking the usual minibuffer commands. */) /* Actual minibuffer invocation. */ static void read_minibuf_unwind (void); +static void minibuffer_unwind (void); static void run_exit_minibuf_hook (void); @@ -544,7 +555,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, Lisp_Object histval; Lisp_Object empty_minibuf; - Lisp_Object dummy, frame; specbind (Qminibuffer_default, defalt); specbind (Qinhibit_read_only, Qnil); @@ -626,17 +636,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window)); if (minibuf_level > 1 + && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame, + MB_frame) && minibuf_moves_frame_when_opened () - && (!minibuf_follows_frame () - || (!EQ (mini_frame, selected_frame)))) + && (!minibuf_follows_frame ())) { - EMACS_INT i; + struct frame *of = XFRAME (MB_frame); - /* Stack up the existing minibuffers on the current mini-window */ - for (i = 1; i < minibuf_level; i++) - set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0); + zip_minibuffer_stacks (minibuf_window, of->minibuffer_window); + /* MB_frame's minibuffer can be on a different frame. */ + if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of)))) + Fset_frame_selected_window (MB_frame, + Fframe_first_window (MB_frame), Qnil); } + MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame; + if (live_minibuffer_p (XWINDOW (minibuf_window)->contents)) + call1 (Qrecord_window_buffer, minibuf_window); + record_unwind_protect_void (minibuffer_unwind); record_unwind_protect (restore_window_configuration, Fcons (Qt, Fcurrent_window_configuration (Qnil))); @@ -771,23 +788,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, empty_minibuf = get_minibuffer (0); set_minibuffer_mode (empty_minibuf, 0); - FOR_EACH_FRAME (dummy, frame) - { - Lisp_Object root_window = Fframe_root_window (frame); - Lisp_Object mini_window = XWINDOW (root_window)->next; - Lisp_Object buffer; - - if (!NILP (mini_window) && !EQ (mini_window, minibuf_window) - && !NILP (Fwindow_minibuffer_p (mini_window))) - { - buffer = XWINDOW (mini_window)->contents; - if (!live_minibuffer_p (buffer)) - /* Use set_window_buffer instead of Fset_window_buffer (see - discussion of bug#11984, bug#12025, bug#12026). */ - set_window_buffer (mini_window, empty_minibuf, 0, 0); - } - } - /* Display this minibuffer in the proper window. */ /* Use set_window_buffer instead of Fset_window_buffer (see discussion of bug#11984, bug#12025, bug#12026). */ @@ -908,7 +908,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, unbind_to (count, Qnil); /* Switch the frame back to the calling frame. */ - if (!EQ (selected_frame, calling_frame) + if ((!EQ (selected_frame, calling_frame) + || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame, + calling_frame)) && FRAMEP (calling_frame) && FRAME_LIVE_P (XFRAME (calling_frame))) call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil); @@ -1026,6 +1028,14 @@ run_exit_minibuf_hook (void) safe_run_hooks (Qminibuffer_exit_hook); } +/* This variable records the expired minibuffer's frame between the + calls of `read_minibuf_unwind' and `minibuffer_unwind'. It should + be used only by these two functions. Note that the same search + method for the MB's frame won't always work in `minibuffer_unwind' + because the intervening `restore-window-configuration' will have + changed the buffer in the mini-window. */ +static Lisp_Object exp_MB_frame; + /* This function is called on exiting minibuffer, whether normally or not, and it restores the current window, buffer, etc. */ @@ -1036,6 +1046,28 @@ read_minibuf_unwind (void) Lisp_Object calling_frame; Lisp_Object calling_window; Lisp_Object future_mini_window; + Lisp_Object saved_selected_frame = selected_frame; + Lisp_Object window, frames; + struct window *w; + struct frame *f; + + /* Locate the expired minibuffer. */ + FOR_EACH_FRAME (frames, exp_MB_frame) + { + f = XFRAME (exp_MB_frame); + window = f->minibuffer_window; + w = XWINDOW (window); + if (EQ (w->frame, exp_MB_frame) + && EQ (w->contents, nth_minibuffer (minibuf_level))) + goto found; + } + return; /* expired minibuffer not found. Maybe we should output an + error, here. */ + + found: + if (!EQ (exp_MB_frame, saved_selected_frame)) + do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets + minibuff_window */ /* To keep things predictable, in case it matters, let's be in the minibuffer when we reset the relevant variables. Don't depend on @@ -1127,20 +1159,61 @@ read_minibuf_unwind (void) away from the expired minibuffer window, both in the current minibuffer's frame and the original calling frame. */ choose_minibuf_frame (); - if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame)) - { - Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil); - /* PREV can be on a different frame when we have a minibuffer only - frame, the other frame's minibuffer window is MINIBUF_WINDOW, - and its "focus window" is also MINIBUF_WINDOW. */ - if (!EQ (prev, minibuf_window) - && EQ (WINDOW_FRAME (XWINDOW (prev)), - WINDOW_FRAME (XWINDOW (minibuf_window)))) - Fset_frame_selected_window (selected_frame, prev, Qnil); - } - else - Fset_frame_selected_window (calling_frame, calling_window, Qnil); + if (NILP (XWINDOW (minibuf_window)->prev_buffers)) + { + if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame)) + { + Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil); + /* PREV can be on a different frame when we have a minibuffer only + frame, the other frame's minibuffer window is MINIBUF_WINDOW, + and its "focus window" is also MINIBUF_WINDOW. */ + if (!EQ (prev, minibuf_window) + && EQ (WINDOW_FRAME (XWINDOW (prev)), + WINDOW_FRAME (XWINDOW (minibuf_window)))) + Fset_frame_selected_window (selected_frame, prev, Qnil); + } + else + Fset_frame_selected_window (calling_frame, calling_window, Qnil); + } + + /* Restore the selected frame. */ + if (!EQ (exp_MB_frame, saved_selected_frame)) + do_switch_frame (saved_selected_frame, 0, 0, Qt); +} + +/* Replace the expired minibuffer in frame exp_MB_frame with the next less + nested minibuffer in that frame, if any. Otherwise, replace it + with the null minibuffer. MINIBUF_WINDOW is not changed. */ +static void +minibuffer_unwind (void) +{ + struct frame *f; + struct window *w; + Lisp_Object window; + Lisp_Object entry; + + f = XFRAME (exp_MB_frame); + window = f->minibuffer_window; + w = XWINDOW (window); + if (FRAME_LIVE_P (f)) + { + /* minibuf_window = sf->minibuffer_window; */ + if (!NILP (w->prev_buffers)) + { + entry = Fcar (w->prev_buffers); + w->prev_buffers = Fcdr (w->prev_buffers); + set_window_buffer (window, Fcar (entry), 0, 0); + Fset_window_start (window, Fcar (Fcdr (entry)), Qnil); + Fset_window_point (window, Fcar (Fcdr (Fcdr (entry)))); + /* set-window-configuration may/will have unselected the + mini-window as the selected window. Restore it. */ + Fset_frame_selected_window (exp_MB_frame, window, Qnil); + } + else + set_window_buffer (window, nth_minibuffer (0), 0, 0); + } } + void @@ -2213,6 +2286,9 @@ syms_of_minibuf (void) { staticpro (&minibuf_prompt); staticpro (&minibuf_save_list); + staticpro (&MB_frame); + MB_frame = Qnil; + staticpro (&exp_MB_frame); DEFSYM (Qminibuffer_follows_selected_frame, "minibuffer-follows-selected-frame"); diff --git a/src/window.c b/src/window.c index eb16e2a4338..4d5c7e763ec 100644 --- a/src/window.c +++ b/src/window.c @@ -6958,7 +6958,8 @@ the return value is nil. Otherwise the value is t. */) if (BUFFERP (w->contents) && !EQ (w->contents, p->buffer) - && BUFFER_LIVE_P (XBUFFER (p->buffer))) + && BUFFER_LIVE_P (XBUFFER (p->buffer)) + && (NILP (Fminibufferp (p->buffer, Qnil)))) /* If a window we restore gets another buffer, record the window's old buffer. */ call1 (Qrecord_window_buffer, window); diff --git a/src/xdisp.c b/src/xdisp.c index cc0a689ba32..a405d51f803 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12650,9 +12650,8 @@ gui_consider_frame_title (Lisp_Object frame) mode_line_noprop_buf; then display the title. */ record_unwind_protect (unwind_format_mode_line, format_mode_line_unwind_data - (f, current_buffer, selected_window, false)); + (NULL, current_buffer, Qnil, false)); - Fselect_window (f->selected_window, Qt); set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents)); fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; -- cgit v1.2.3 From 4e1f92feb3a861f93b7a285715d03be930b41b91 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Wed, 24 Mar 2021 22:50:03 +0000 Subject: Implement frame-scale-factor * src/frame.c (Fframe_scale_factor): New function. (syms_of_frame): Add frame-scale-factor. * src/frame.h: Add FRAME_SCALE_FACTOR. * src/image.c: Move FRAME_SCALE_FACTOR to frame.h. --- src/frame.c | 12 ++++++++++++ src/frame.h | 7 +++++++ src/image.c | 8 -------- 3 files changed, 19 insertions(+), 8 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index 66ae4943ba2..784a079bffe 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3744,6 +3744,17 @@ window state change flag is reset. */) return (FRAME_WINDOW_STATE_CHANGE (f) = !NILP (arg)) ? Qt : Qnil; } +DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor, + 0, 1, 0, + doc: /* Return FRAMEs scale factor. +The scale factor is the amount a logical pixel size must be multiplied +to find the real number of pixels. */) + (Lisp_Object frame) +{ + struct frame *f = decode_live_frame (frame); + + return (make_float (FRAME_SCALE_FACTOR (f))); +} /*********************************************************************** Frame Parameters @@ -6457,6 +6468,7 @@ iconify the top level frame instead. */); defsubr (&Sframe_pointer_visible_p); defsubr (&Sframe_window_state_change); defsubr (&Sset_frame_window_state_change); + defsubr (&Sframe_scale_factor); #ifdef HAVE_WINDOW_SYSTEM defsubr (&Sx_get_resource); diff --git a/src/frame.h b/src/frame.h index 9ddcb4c6810..9963112036f 100644 --- a/src/frame.h +++ b/src/frame.h @@ -907,6 +907,13 @@ default_pixels_per_inch_y (void) (WINDOWP (f->minibuffer_window) \ && XFRAME (XWINDOW (f->minibuffer_window)->frame) == f) +/* Scale factor of frame F. */ +#if defined HAVE_NS +# define FRAME_SCALE_FACTOR(f) (FRAME_NS_P (f) ? ns_frame_scale_factor (f) : 1) +#else +# define FRAME_SCALE_FACTOR(f) 1; +#endif + /* Pixel width of frame F. */ #define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width) diff --git a/src/image.c b/src/image.c index b85418c690d..774b7e14ea9 100644 --- a/src/image.c +++ b/src/image.c @@ -135,14 +135,6 @@ typedef struct ns_bitmap_record Bitmap_Record; # define COLOR_TABLE_SUPPORT 1 #endif -#ifdef HAVE_RSVG -#if defined HAVE_NS -# define FRAME_SCALE_FACTOR(f) ns_frame_scale_factor (f) -#else -# define FRAME_SCALE_FACTOR(f) 1; -#endif -#endif - static void image_disable_image (struct frame *, struct image *); static void image_edge_detection (struct frame *, struct image *, Lisp_Object, Lisp_Object); -- cgit v1.2.3 From 69158a19956656c52208cbe8c11134eeed8ca867 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 4 Apr 2021 09:41:44 +0300 Subject: Fix recent changes regarding frame-scale-factor * src/frame.c (Fframe_scale_factor): Make more robust and avoid compiler warning while at that. Doc fix. --- src/frame.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index 784a079bffe..bbdc3b55992 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3747,13 +3747,13 @@ window state change flag is reset. */) DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor, 0, 1, 0, doc: /* Return FRAMEs scale factor. -The scale factor is the amount a logical pixel size must be multiplied -to find the real number of pixels. */) +The scale factor is the amount by which a logical pixel size must be +multiplied to find the real number of pixels. */) (Lisp_Object frame) { struct frame *f = decode_live_frame (frame); - return (make_float (FRAME_SCALE_FACTOR (f))); + return (make_float (f ? FRAME_SCALE_FACTOR (f) : 1)); } /*********************************************************************** -- cgit v1.2.3 From ef6df9ec8f7f4a5d7ab15f21e870ba21f99872d5 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Tue, 13 Apr 2021 18:07:26 +0200 Subject: Improve docstring of 'frame-scale-factor' * src/frame.c (Fframe_scale_factor): Explain what happens when the FRAME argument is nil. --- src/frame.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index bbdc3b55992..028a45afeb7 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3747,6 +3747,7 @@ window state change flag is reset. */) DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor, 0, 1, 0, doc: /* Return FRAMEs scale factor. +If FRAME is omitted or nil, the selected frame is used. The scale factor is the amount by which a logical pixel size must be multiplied to find the real number of pixels. */) (Lisp_Object frame) -- cgit v1.2.3 From 5819f4fb0a9337fab4c32dac557a02ec6497bce5 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sun, 18 Apr 2021 09:51:32 +0200 Subject: Avoid selecting tooltip windows and frames (Bug#47207) * src/frame.c (do_switch_frame): Don't switch to a tooltip frame. (Fselect_frame): Do not select a tooltip frame. * src/w32fns.c (Fx_show_tip): * src/xfns.c (Fx_show_tip): Set the tooltip window's `no-other-window' parameter so `other-window' will skip it. * src/window.c (select_window): Do not select a tooltip window. (candidate_window_p): Make sure MINIBUF is live. (decode_next_window_args): Make sure that W's frame's minibuffer window is live before including it. (Qno_other_window): New symbol. --- src/frame.c | 15 +++++++++++++-- src/w32fns.c | 2 ++ src/window.c | 36 +++++++++++++++++++++++------------- src/xfns.c | 2 ++ 4 files changed, 40 insertions(+), 15 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index 028a45afeb7..097cd555c64 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1384,7 +1384,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor especially when deleting the initial frame during startup. */ CHECK_FRAME (frame); f = XFRAME (frame); - if (!FRAME_LIVE_P (f)) + /* Silently ignore dead and tooltip frames (Bug#47207). */ + if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f)) return Qnil; else if (f == sf) return frame; @@ -1508,7 +1509,16 @@ redisplay will display FRAME. This function returns FRAME, or nil if FRAME has been deleted. */) (Lisp_Object frame, Lisp_Object norecord) { - return do_switch_frame (frame, 1, 0, norecord); + struct frame *f; + + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + + if (FRAME_TOOLTIP_P (f)) + /* Do not select a tooltip frame (Bug#47207). */ + error ("Cannot select a tooltip frame"); + else + return do_switch_frame (frame, 1, 0, norecord); } DEFUN ("handle-switch-frame", Fhandle_switch_frame, @@ -1523,6 +1533,7 @@ necessarily represent user-visible input focus. */) /* Preserve prefix arg that the command loop just cleared. */ kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); run_hook (Qmouse_leave_buffer_hook); + return do_switch_frame (event, 0, 0, Qnil); } diff --git a/src/w32fns.c b/src/w32fns.c index 9db367bfafe..c07f32ab0cc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -7434,6 +7434,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, set_window_buffer (window, tip_buf, false, false); w = XWINDOW (window); w->pseudo_window_p = true; + /* Try to avoid that `other-window' select us (Bug#47207). */ + Fset_window_parameter (window, Qno_other_window, Qt); /* Set up the frame's root window. Note: The following code does not try to size the window or its frame correctly. Its only purpose is diff --git a/src/window.c b/src/window.c index 7c238a33fcb..9a49032ba8a 100644 --- a/src/window.c +++ b/src/window.c @@ -504,10 +504,18 @@ select_window (Lisp_Object window, Lisp_Object norecord, { struct window *w; struct frame *sf; + Lisp_Object frame; + struct frame *f; CHECK_LIVE_WINDOW (window); w = XWINDOW (window); + frame = WINDOW_FRAME (w); + f = XFRAME (frame); + + if (FRAME_TOOLTIP_P (f)) + /* Do not select a tooltip window (Bug#47207). */ + error ("Cannot select a tooltip window"); /* Make the selected window's buffer current. */ Fset_buffer (w->contents); @@ -528,14 +536,14 @@ select_window (Lisp_Object window, Lisp_Object norecord, redisplay_other_windows (); sf = SELECTED_FRAME (); - if (XFRAME (WINDOW_FRAME (w)) != sf) + if (f != sf) { - fset_selected_window (XFRAME (WINDOW_FRAME (w)), window); + fset_selected_window (f, window); /* Use this rather than Fhandle_switch_frame so that FRAME_FOCUS_FRAME is moved appropriately as we move around in the state where a minibuffer in a separate frame is active. */ - Fselect_frame (WINDOW_FRAME (w), norecord); + Fselect_frame (frame, norecord); /* Fselect_frame called us back so we've done all the work already. */ eassert (EQ (window, selected_window)); return window; @@ -2596,7 +2604,7 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, candidate_p = false; else if (MINI_WINDOW_P (w) && (EQ (minibuf, Qlambda) - || (WINDOWP (minibuf) && !EQ (minibuf, window)))) + || (WINDOW_LIVE_P (minibuf) && !EQ (minibuf, window)))) { /* If MINIBUF is `lambda' don't consider any mini-windows. If it is a window, consider only that one. */ @@ -2659,12 +2667,12 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window; XSETWINDOW (*window, w); - /* MINIBUF nil may or may not include minibuffers. Decide if it - does. */ - if (NILP (*minibuf)) - *minibuf = this_minibuffer_depth (XWINDOW (miniwin)->contents) - ? miniwin - : Qlambda; + /* MINIBUF nil may or may not include minibuffer windows. Decide if + it does. But first make sure that this frame's minibuffer window + is live (Bug#47207). */ + if (WINDOW_LIVE_P (miniwin) && NILP (*minibuf)) + *minibuf = (this_minibuffer_depth (XWINDOW (miniwin)->contents) + ? miniwin : Qlambda); else if (!EQ (*minibuf, Qt)) *minibuf = Qlambda; @@ -2675,9 +2683,10 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object /* ALL_FRAMES nil doesn't specify which frames to include. */ if (NILP (*all_frames)) *all_frames - = (!EQ (*minibuf, Qlambda) - ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame)) - : Qnil); + /* Once more make sure that this frame's minibuffer window is live + before including it (Bug#47207). */ + = ((WINDOW_LIVE_P (miniwin) && !EQ (*minibuf, Qlambda)) + ? miniwin : Qnil); else if (EQ (*all_frames, Qvisible)) ; else if (EQ (*all_frames, make_fixnum (0))) @@ -8232,6 +8241,7 @@ syms_of_window (void) DEFSYM (Qmode_line_format, "mode-line-format"); DEFSYM (Qheader_line_format, "header-line-format"); DEFSYM (Qtab_line_format, "tab-line-format"); + DEFSYM (Qno_other_window, "no-other-window"); DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, doc: /* Non-nil means call as function to display a help buffer. diff --git a/src/xfns.c b/src/xfns.c index 0507dc8f61d..f120653ee7b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7076,6 +7076,8 @@ Text larger than the specified size is clipped. */) set_window_buffer (window, tip_buf, false, false); w = XWINDOW (window); w->pseudo_window_p = true; + /* Try to avoid that `other-window' select us (Bug#47207). */ + Fset_window_parameter (window, Qno_other_window, Qt); /* Set up the frame's root window. Note: The following code does not try to size the window or its frame correctly. Its only purpose is -- cgit v1.2.3 From a190b4cfd8b6f42a91678ac7292e1cceccd168e7 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Tue, 27 Apr 2021 09:53:42 +0200 Subject: Major rewrite of adjust_frame_size Have adjust_frame_size pass native frame sizes to backends instead of text sizes. Expand frame size history management. Drop PIXELWISE argument from change_frame_size and convert native to text sizes only when calling adjust_frame_size. Use convention in arguments that -1 instead of 0 means that no size change is required. When adjusting frame sizes pick up delayed size changes (Bug#46827). * lisp/frame.el (frame-notice-user-settings, make-frame): Don't set frame size history. (frame--size-history): Rewrite doc-string. Handle new formats of `frame-size-history' entries. * src/dispextern.h (delayed_size_change): Extern it. (change_frame_size): Drop last argument from extern. * src/dispnew.c (delayed_size_change): Make it global. (handle_window_change_signal): Reformat. Drop last argument from change_frame_size call. (do_pending_window_change, init_display_interactive): Drop last argument from change_frame_size call. (change_frame_size_1): NEW_WIDTH and NEW_HEIGHT now specify native sizes. Drop last argument PIXELWISE. Queue a change when it either differs from F's current pixel sizes or F's previously queued sizes. Inject frame_size_history_extra call when queuing. Adopt convention that for queued sizes -1 means that no size change is required. Convert from native to text sizes when calling adjust_frame_size. (change_frame_size): Drop last argument PIXELWISE and drop it also in change_frame_size_1 calls. * src/frame.c (frame_size_history_add): Remove. (frame_inhibit_resize): Remove call to frame_size_history_add. (set_menu_bar_lines, set_tab_bar_lines): Simplify. Drop last argument from change_frame_size call. (frame_windows_min_size): No more static. (keep_ratio): Minor rewrite using macros. (frame_size_history_adjust, frame_size_history_plain) (frame_size_history_extra): New functions. (adjust_frame_size): Major rewrite. Adopt new convention that negative values for new sizes mean no change. Pick up delayed size changes from F's new_width and new_height slots (Bug#46827). Call set_window_size_hook with native instead of text sizes. Do not sanitize window sizes any more. Call frame_size_history_adjust instead of frame_size_history_add. Always set F's resized_p slot to true. (make_frame): Initialize new_width and new_height slots to -1. Simplify setup of initial sizes and an adjust_frame_size call. (Fframe_parameters): Drop processing F's new_pixelwise slot. (check_frame_pixels): Reorder to make declarations appear first. (Fset_frame_height, Fset_frame_width, Fset_frame_size): Pass explicit width and height values to adjust_frame_size instead of -1. (gui_set_frame_parameters): Minor rewrite making sure that explicit sizes and the corresponding parameter are passed to adjust_frame_size. Remove frame_size_history_add call. (gui_figure_window_size): Drop last two arguments. Simplify assignment of initial size. Set new_height and new_width slots to -1. Use adjust_frame_size to set sizes instead of returning them to caller. (syms_of_frame): Drop symbols used by frame size history; these are now built on-the-fly. Also drop some menu bar related symbols in favor of Qmenu_bar_lines. * src/frame.h (struct frame): Remove new_pixelwise. (SET_FRAME_COLS, SET_FRAME_LINES, SET_FRAME_WIDTH) (SET_FRAME_HEIGHT): Remove macros. (frame_size_history_add): Remove externs. (frame_windows_min_size, frame_size_history_plain) (frame_size_history_extra): Add externs. (FRAME_WINDOWS_WIDTH, FRAME_WINDOWS_HEIGHT): Rename to FRAME_INNER_WIDTH and FRAME_INNER_HEIGHT. (gui_figure_window_size): Drop last two arguments from extern. * src/gtkutil.c (xg_frame_resized): Rename arguments to WIDTH and HEIGHT. Consult delayed_size_change to handle case where WIDTH and HEIGHT do not match F's new_width and new_height values. Call change_frame_size with native sizes and without PIXELWISE argument. Instead of frame_size_history_add call frame_size_history_extra. (xg_frame_set_char_size): WIDTH and HEIGHT are native sizes now; fix adjust_frame_size call accordingly. Instead of frame_size_history_add call frame_size_history_extra. (style_changed_cb): Call xg_frame_set_char_size with native instead of text sizes. (tb_size_cb): Remove frame_size_history_add call. Call adjust_frame_size with INHIBIT 5. (free_frame_tool_bar, xg_change_toolbar_position): Remove frame_size_history_add call. (update_frame_tool_bar): Call adjust_frame_size with INHIBIT 2 and let it handle frame_inhibit_implied_resize and fullheight/-width. Remove frame_size_history_add call. * src/keyboard.c (Fsuspend_emacs): Call change_frame_size with native sizes. * src/nsfns.m (ns_set_tool_bar_lines): Call adjust_frame_size with INHIBIT 2 and let it handle frame_inhibit_implied_resize and fullheight/-width. Remove frame_size_history_add call. (Fx_create_frame): Drop two last arguments in gui_figure_window_size call. Do not SET_FRAME_WIDTH and SET_FRAME_HEIGHT, the adjust_frame_size in gui_figure_window_size did that already. * src/nsterm.m (ns_set_window_size): Drop PIXELWISE argument and its processing; WIDTH and HEIGHT represent native pixel sizes now. Call change_frame_size with native sizes. Remove call to frame_size_history_add. ([EmacsView viewDidResize:]): Call change_frame_size with native sizes. * src/term.c (Fresume_tty): Call change_frame_size with native sizes. * src/termhooks.h (*set_window_size_hook): Drop last argument PIXELWISE. * src/w32fns.c (w32_change_tab_bar_height) (w32_change_tool_bar_height): Fix handling of these in the initial phase before they have been resized at least once. (Fx_create_frame, w32_create_tip_frame): Drop two last arguments in gui_figure_window_size call. Do not SET_FRAME_WIDTH and SET_FRAME_HEIGHT (or SET_FRAME_COLS and SET_FRAME_LINES), the adjust_frame_size in gui_figure_window_size did that already. * src/w32inevt.c (resize_event, maybe_generate_resize_event): Pass native sizes to change_frame_size. * src/w32term.c (w32_read_socket): When WM_WINDOWPOSCHANGED pass native sizes to change_frame_size. (w32_new_font): Recalculate FRAME_TAB_BAR_HEIGHT. Simplify code. (w32fullscreen_hook): Call change_frame_size with native sizes. (w32_set_window_size): Drop argument PIXELWISE and its processing; WIDTH and HEIGHT are native sizes now. Remove frame_size_history_add calls. Pass native sizes to change_frame_size. * src/widget.c (set_frame_size): Set width and height of widget directly. Call frame_size_history_plain instead of frame_size_history_add. (update_from_various_frame_slots): Call frame_size_history_extra. (EmacsFrameRealize): Call frame_size_history_plain. (EmacsFrameResize): Call change_frame_size with native sizes. Call frame_size_history_extra instead of frame_size_history_add. (EmacsFrameSetCharSize): Call frame_size_history_extra. Drop PIXELWISE argument in x_set_window_size call and specify pixels. (pixel_to_text_size): Remove function. * src/xdisp.c (resize_mini_window): Replace FRAME_WINDOWS_HEIGHT with FRAME_INNER_HEIGHT. (redisplay_tab_bar): Don't set tab_bar_redisplayed when we did not redisplay it. (redisplay_tool_bar): Don't call it for external tool bar. Don't set tool_bar_redisplayed when we did not redisplay it. (redisplay_window): When the tool bar is external call update_frame_tool_bar directly. * src/xfns.c (x_set_menu_bar_lines): Call adjust_frame_size only if number of menu bar lines changed and fix 6th argument. (x_change_tab_bar_height, x_change_tool_bar_height): Fix handling of these in the initial phase before they have been resized at least once. (Fx_create_frame, x_create_tip_frame): Drop two last arguments in gui_figure_window_size call. Do not SET_FRAME_WIDTH and SET_FRAME_HEIGHT (or SET_FRAME_COLS and SET_FRAME_LINES), the adjust_frame_size in gui_figure_window_size did that already. * src/xmenu.c (update_frame_menubar): Fix 6th arg of adjust_frame_size call. (free_frame_menubar): For Motif frames fix fullscreen and `frame-inhibit-implied-resize' handling. Fix 6th arg of adjust_frame_size calls. * src/xterm.c (x_net_wm_state): Remove call to frame_size_history_add. (handle_one_xevent): For PropertyNotify and UnmapNotify events add frame_size_history_plain calls. For MapNotify and ConfigureNotify events add a frame_size_history_extra call. For ConfigureNotify events also handle delayed size changes and call change_frame_size with native sizes. (x_new_font): Recalculate FRAME_TAB_BAR_HEIGHT. Simplify code. (x_handle_net_wm_state): Remove frame_size_history_add call. (x_check_fullscreen): Remove frame_size_history_add call. Call change_frame_size with native height. (x_set_window_size_1): WIDTH and HEIGHT are now native. Remove some frame_size_history_add calls and add frame_size_history_extra calls instead. If the frame is not visible call adjust_frame_size directly instead of calling change_frame_size. (x_set_window_size): Drop PIXELWISE argument. WIDTH and HEIGHT represent native sizes now. (x_make_frame_visible, x_make_frame_invisible): Call frame_size_history_plain. * src/xterm.h (x_set_window_size): Drop last argument from extern declaration. --- lisp/frame.el | 121 ++++++--- src/dispextern.h | 4 +- src/dispnew.c | 120 +++++---- src/frame.c | 732 ++++++++++++++++++++++++++++++------------------------- src/frame.h | 213 ++++++---------- src/gtkutil.c | 158 +++++------- src/keyboard.c | 5 +- src/nsfns.m | 26 +- src/nsterm.m | 41 +--- src/term.c | 4 +- src/termhooks.h | 2 +- src/w32fns.c | 100 +++----- src/w32inevt.c | 12 +- src/w32term.c | 156 ++++-------- src/widget.c | 75 +++--- src/xdisp.c | 29 +-- src/xfns.c | 135 ++++------ src/xmenu.c | 32 ++- src/xterm.c | 260 ++++++++------------ src/xterm.h | 2 +- 20 files changed, 1000 insertions(+), 1227 deletions(-) (limited to 'src/frame.c') diff --git a/lisp/frame.el b/lisp/frame.el index bca160175a5..aff1d479eca 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -615,15 +615,6 @@ there (in decreasing order of priority)." (face-set-after-frame-default frame-initial-frame) (setq newparms (delq new-bg newparms))) - (when (numberp (car frame-size-history)) - (setq frame-size-history - (cons (1- (car frame-size-history)) - (cons - (list frame-initial-frame - "FRAME-NOTICE-USER" - nil newparms) - (cdr frame-size-history))))) - (modify-frame-parameters frame-initial-frame newparms))))) ;; Restore the original buffer. @@ -926,12 +917,6 @@ the new frame according to its own rules." (let ((val (frame-parameter oldframe param))) (when val (set-frame-parameter frame param val))))) - (when (numberp (car frame-size-history)) - (setq frame-size-history - (cons (1- (car frame-size-history)) - (cons (list frame "MAKE-FRAME") - (cdr frame-size-history))))) - ;; We can run `window-configuration-change-hook' for this frame now. (frame-after-make-frame frame t) (run-hook-with-args 'after-make-frame-functions frame) @@ -1695,26 +1680,104 @@ and width values are in pixels. (defun frame--size-history (&optional frame) "Print history of resize operations for FRAME. -Print prettified version of `frame-size-history' into a buffer -called *frame-size-history*. Optional argument FRAME denotes the -frame whose history will be printed. FRAME defaults to the -selected frame." +This function dumps a prettified version of `frame-size-history' +into a buffer called *frame-size-history*. The optional argument +FRAME denotes the frame whose history will be dumped; it defaults +to the selected frame. + +Storing information about resize operations is off by default. +If you set the variable `frame-size-history' like this + +(setq frame-size-history '(100)) + +then Emacs will save information about the next 100 significant +operations affecting any frame's size in that variable. This +function prints the entries for FRAME stored in that variable in +a more legible way. + +All lines start with an indication of the requested action. An +entry like `menu-bar-lines' or `scroll-bar-width' indicates that +a change of the corresponding frame parameter or Lisp variable +was requested. An entry like gui_figure_window_size indicates +that that C function was executed, an entry like ConfigureNotify +indicates that that event was received. + +In long entries, a number in parentheses displays the INHIBIT +parameter passed to the C function adjust_frame_size. Such +entries may also display changes of frame rectangles in a form +like R=n1xn2~>n3xn4 where R denotes the rectangle type (TS for +text, NS for native and IS for inner frame rectangle sizes, all +in pixels, TC for text rectangle sizes in frame columns and +lines), n1 and n2 denote the old width and height and n3 and n4 +the new width and height in the according units. MS stands for +the minimum inner frame size in pixels, IH and IV, if present, +indicate that resizing horizontally and/or vertically was +inhibited (either by `frame-inhibit-implied-resize' or because of +the frame's fullscreen state). + +Shorter entries represent C functions that process width and +height changes of the native rectangle where PS stands for the +frame's present pixel width and height, XS for a requested pixel +width and height and DS for some earlier requested but so far +delayed pixel width and height. + +Very short entries represent calls of C functions that do not +directly ask for size changes but may indirectly affect the size +of frames like calls to map a frame or change its visibility." (let ((history (reverse frame-size-history)) - entry) + entry item) (setq frame (window-normalize-frame frame)) (with-current-buffer (get-buffer-create "*frame-size-history*") (erase-buffer) (insert (format "Frame size history of %s\n" frame)) (while (consp (setq entry (pop history))) - (when (eq (car entry) frame) - (pop entry) - (insert (format "%s" (pop entry))) - (move-to-column 24 t) - (while entry - (insert (format " %s" (pop entry)))) - (insert "\n"))) - (unless frame-size-history - (insert "Frame size history is nil.\n"))))) + (setq item (car entry)) + (cond + ((not (consp item)) + ;; An item added quickly for debugging purposes. + (insert (format "%s\n" entry))) + ((and (eq (nth 0 item) frame) (= (nth 1 item) 1)) + ;; Length 1 is a "plain event". + (insert (format "%s\n" (nth 2 item)))) + ((and (eq (nth 0 item) frame) (= (nth 1 item) 2)) + ;; Length 2 is an "extra" item. + (insert (format "%s" (nth 2 item))) + (setq item (nth 0 (cdr entry))) + (insert (format ", PS=%sx%s" (nth 0 item) (nth 1 item))) + (when (or (>= (nth 2 item) 0) (>= (nth 3 item) 0)) + (insert (format ", XS=%sx%s" (nth 2 item) (nth 3 item)))) + (setq item (nth 1 (cdr entry))) + (when (or (>= (nth 0 item) 0) (>= (nth 1 item) 0)) + (insert (format ", DS=%sx%s" (nth 0 item) (nth 1 item)))) + (insert "\n")) + ((and (eq (nth 0 item) frame) (= (nth 1 item) 5)) + ;; Length 5 is an `adjust-frame-size' item. + (insert (format "%s (%s)" (nth 3 item) (nth 2 item))) + (setq item (nth 0 (cdr entry))) + (unless (and (= (nth 0 item) (nth 2 item)) + (= (nth 1 item) (nth 3 item))) + (insert (format ", TS=%sx%s~>%sx%s" + (nth 0 item) (nth 1 item) (nth 2 item) (nth 3 item)))) + (setq item (nth 1 (cdr entry))) + (unless (and (= (nth 0 item) (nth 2 item)) + (= (nth 1 item) (nth 3 item))) + (insert (format ", TC=%sx%s~>%sx%s" + (nth 0 item) (nth 1 item) (nth 2 item) (nth 3 item)))) + (setq item (nth 2 (cdr entry))) + (unless (and (= (nth 0 item) (nth 2 item)) + (= (nth 1 item) (nth 3 item))) + (insert (format ", NS=%sx%s~>%sx%s" + (nth 0 item) (nth 1 item) (nth 2 item) (nth 3 item)))) + (setq item (nth 3 (cdr entry))) + (unless (and (= (nth 0 item) (nth 2 item)) + (= (nth 1 item) (nth 3 item))) + (insert (format ", IS=%sx%s~>%sx%s" + (nth 0 item) (nth 1 item) (nth 2 item) (nth 3 item)))) + (setq item (nth 4 (cdr entry))) + (insert (format ", MS=%sx%s" (nth 0 item) (nth 1 item))) + (when (nth 2 item) (insert " IH")) + (when (nth 3 item) (insert " IV")) + (insert "\n"))))))) (declare-function x-frame-edges "xfns.c" (&optional frame type)) (declare-function w32-frame-edges "w32fns.c" (&optional frame type)) diff --git a/src/dispextern.h b/src/dispextern.h index a2ebd04f235..213032d4de8 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1262,7 +1262,7 @@ extern struct glyph space_glyph; /* True means last display completed. False means it was preempted. */ extern bool display_completed; - +extern bool delayed_size_change; /************************************************************************ @@ -3641,7 +3641,7 @@ extern void gui_update_window_begin (struct window *); extern void gui_update_window_end (struct window *, bool, bool); #endif void do_pending_window_change (bool); -void change_frame_size (struct frame *, int, int, bool, bool, bool, bool); +void change_frame_size (struct frame *, int, int, bool, bool, bool); void init_display (void); void syms_of_display (void); extern void spec_glyph_lookup_face (struct window *, GLYPH *); diff --git a/src/dispnew.c b/src/dispnew.c index f613f7b6568..b3f7be67e0f 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -102,7 +102,7 @@ bool display_completed; /* True means SIGWINCH happened when not safe. */ -static bool delayed_size_change; +bool delayed_size_change; /* A glyph for a space. */ @@ -5770,32 +5770,34 @@ handle_window_change_signal (int sig) termcap-controlled terminal, but we can't decide which. Therefore, we resize the frames corresponding to each tty. */ - for (tty = tty_list; tty; tty = tty->next) { + for (tty = tty_list; tty; tty = tty->next) + { + if (! tty->term_initted) + continue; - if (! tty->term_initted) - continue; + /* Suspended tty frames have tty->input == NULL avoid trying to + use it. */ + if (!tty->input) + continue; - /* Suspended tty frames have tty->input == NULL avoid trying to - use it. */ - if (!tty->input) - continue; + get_tty_size (fileno (tty->input), &width, &height); - get_tty_size (fileno (tty->input), &width, &height); + if (width > 5 && height > 2) + { + Lisp_Object tail, frame; - if (width > 5 && height > 2) { - Lisp_Object tail, frame; + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); - FOR_EACH_FRAME (tail, frame) - if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty) - /* Record the new sizes, but don't reallocate the data - structures now. Let that be done later outside of the - signal handler. */ - change_frame_size (XFRAME (frame), width, - height - FRAME_MENU_BAR_LINES (XFRAME (frame)) - - FRAME_TAB_BAR_LINES (XFRAME (frame)), - 0, 1, 0, 0); + if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty) + /* Record the new sizes, but don't reallocate the data + structures now. Let that be done later outside of the + signal handler. */ + change_frame_size (f, width, height, false, true, false); + } + } } - } } static void @@ -5821,15 +5823,17 @@ do_pending_window_change (bool safe) { Lisp_Object tail, frame; - delayed_size_change = 0; + delayed_size_change = false; FOR_EACH_FRAME (tail, frame) { struct frame *f = XFRAME (frame); - if (f->new_height != 0 || f->new_width != 0) + /* Negative new_width or new_height values mean no change is + required (a native size can never drop below zero). */ + if (f->new_height >= 0 || f->new_width >= 0) change_frame_size (f, f->new_width, f->new_height, - 0, 0, safe, f->new_pixelwise); + false, false, safe); } } } @@ -5837,47 +5841,43 @@ do_pending_window_change (bool safe) static void change_frame_size_1 (struct frame *f, int new_width, int new_height, - bool pretend, bool delay, bool safe, bool pixelwise) + bool pretend, bool delay, bool safe) { - /* If we can't deal with the change now, queue it for later. */ if (delay || (redisplaying_p && !safe)) { + if (CONSP (frame_size_history) + && ((new_width != f->new_width + || new_height != f->new_height + || new_width != FRAME_PIXEL_WIDTH (f) + || new_height != FRAME_PIXEL_HEIGHT (f)))) + frame_size_history_extra + (f, build_string ("change_frame_size_1, delayed"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + new_width, new_height, f->new_width, f->new_height); + + /* We can't deal with the change now, queue it for later. */ f->new_width = new_width; f->new_height = new_height; - f->new_pixelwise = pixelwise; - delayed_size_change = 1; + delayed_size_change = true; } else { - /* This size-change overrides any pending one for this frame. */ - f->new_height = 0; - f->new_width = 0; - f->new_pixelwise = 0; - - /* If an argument is zero, set it to the current value. */ - if (pixelwise) - { - new_width = (new_width <= 0) ? FRAME_TEXT_WIDTH (f) : new_width; - new_height = (new_height <= 0) ? FRAME_TEXT_HEIGHT (f) : new_height; - } - else - { - new_width = (((new_width <= 0) ? FRAME_COLS (f) : new_width) - * FRAME_COLUMN_WIDTH (f)); - new_height = (((new_height <= 0) ? FRAME_LINES (f) : new_height) - * FRAME_LINE_HEIGHT (f)); - } - - /* Adjust frame size but make sure set_window_size_hook does not - get called. */ - adjust_frame_size (f, new_width, new_height, 5, pretend, - Qchange_frame_size); + /* Storing -1 in the new_width/new_height slots means that no size + change is pending. Native sizes are always non-negative. */ + f->new_height = -1; + f->new_width = -1; + /* adjust_frame_size wants its arguments in terms of text_width + and text_height, so convert them here. For pathologically + small frames, the resulting values may be negative though. */ + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, new_width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_height), 5, + pretend, Qchange_frame_size); } } -/* Change text height/width of frame F. Values may be given as zero to - indicate that no change is needed. +/* Change native height/width of frame F to NEW_WIDTH/NEW_HEIGHT pixels. + Values may be given as -1 to indicate that no change is needed. If DELAY, assume we're being called from a signal handler, and queue the change for later - perhaps the next redisplay. Since this tries @@ -5887,7 +5887,7 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height, change frame sizes while a redisplay is in progress. */ void change_frame_size (struct frame *f, int new_width, int new_height, - bool pretend, bool delay, bool safe, bool pixelwise) + bool pretend, bool delay, bool safe) { Lisp_Object tail, frame; @@ -5897,13 +5897,12 @@ change_frame_size (struct frame *f, int new_width, int new_height, size affects all frames. Termcap now supports multiple ttys. */ FOR_EACH_FRAME (tail, frame) - if (! FRAME_WINDOW_P (XFRAME (frame))) + if (!FRAME_WINDOW_P (XFRAME (frame))) change_frame_size_1 (XFRAME (frame), new_width, new_height, - pretend, delay, safe, pixelwise); + pretend, delay, safe); } else - change_frame_size_1 (f, new_width, new_height, pretend, delay, safe, - pixelwise); + change_frame_size_1 (f, new_width, new_height, pretend, delay, safe); } /*********************************************************************** @@ -6492,9 +6491,8 @@ init_display_interactive (void) t->display_info.tty->top_frame = selected_frame; change_frame_size (XFRAME (selected_frame), FrameCols (t->display_info.tty), - FrameRows (t->display_info.tty) - - FRAME_MENU_BAR_LINES (f) - - FRAME_TAB_BAR_LINES (f), 0, 0, 1, 0); + FrameRows (t->display_info.tty), + false, false, true); /* Delete the initial terminal. */ if (--initial_terminal->reference_count == 0 diff --git a/src/frame.c b/src/frame.c index 097cd555c64..4129a70aa5f 100644 --- a/src/frame.c +++ b/src/frame.c @@ -150,29 +150,6 @@ get_frame_param (struct frame *frame, Lisp_Object prop) } -void -frame_size_history_add (struct frame *f, Lisp_Object fun_symbol, - int width, int height, Lisp_Object rest) -{ - Lisp_Object frame; - - XSETFRAME (frame, f); - if (CONSP (frame_size_history) - && FIXNUMP (XCAR (frame_size_history)) - && 0 < XFIXNUM (XCAR (frame_size_history))) - frame_size_history = - Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1), - Fcons (list4 - (frame, fun_symbol, - ((width > 0) - ? list4i (FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), - width, height) - : Qnil), - rest), - XCDR (frame_size_history))); -} - - /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen state of frame F would be affected by a vertical (horizontal if HORIZONTAL is true) resize. PARAMETER is the symbol of the frame @@ -193,78 +170,54 @@ frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) : ((horizontal && f->inhibit_horizontal_resize) || (!horizontal && f->inhibit_vertical_resize))); - if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f)) - frame_size_history_add - (f, Qframe_inhibit_resize, 0, 0, - list5 (horizontal ? Qt : Qnil, parameter, - f->after_make_frame ? Qt : Qnil, - frame_inhibit_implied_resize, - fullscreen)); return inhibit; } + +/** Set menu bar lines for a TTY frame. */ static void set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { - int nlines; int olines = FRAME_MENU_BAR_LINES (f); + int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0; /* Right now, menu bars don't work properly in minibuf-only frames; most of the commands try to apply themselves to the minibuffer frame itself, and get an error because you can't switch buffers in or split the minibuffer window. */ - if (FRAME_MINIBUF_ONLY_P (f)) - return; - - if (TYPE_RANGED_FIXNUMP (int, value)) - nlines = XFIXNUM (value); - else - nlines = 0; - - if (nlines != olines) + if (!FRAME_MINIBUF_ONLY_P (f) && nlines != olines) { windows_or_buffers_changed = 14; - FRAME_MENU_BAR_LINES (f) = nlines; - FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - change_frame_size (f, FRAME_COLS (f), - FRAME_LINES (f) + olines - nlines, - 0, 1, 0, 0); + FRAME_MENU_BAR_LINES (f) = FRAME_MENU_BAR_HEIGHT (f) = nlines; + change_frame_size (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + false, true, false); } } + +/** Set tab bar lines for a TTY frame. */ static void set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { - int nlines; int olines = FRAME_TAB_BAR_LINES (f); + int nlines = TYPE_RANGED_FIXNUMP (int, value) ? XFIXNUM (value) : 0; /* Right now, tab bars don't work properly in minibuf-only frames; most of the commands try to apply themselves to the minibuffer frame itself, and get an error because you can't switch buffers in or split the minibuffer window. */ - if (FRAME_MINIBUF_ONLY_P (f)) - return; - - if (TYPE_RANGED_FIXNUMP (int, value)) - nlines = XFIXNUM (value); - else - nlines = 0; - - if (nlines != olines) + if (!FRAME_MINIBUF_ONLY_P (f) && nlines != olines) { windows_or_buffers_changed = 14; - FRAME_TAB_BAR_LINES (f) = nlines; - FRAME_TAB_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - change_frame_size (f, FRAME_COLS (f), - FRAME_LINES (f) + olines - nlines, - 0, 1, 0, 0); + FRAME_TAB_BAR_LINES (f) = FRAME_TAB_BAR_HEIGHT (f) = nlines; + change_frame_size (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + false, true, false); } } Lisp_Object Vframe_list; - DEFUN ("framep", Fframep, Sframep, 1, 1, 0, doc: /* Return non-nil if OBJECT is a frame. Value is: @@ -366,14 +319,15 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size, * * If `frame-windows-min-size' is called, it will make sure that the * return value accommodates all windows of FRAME respecting the values - * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil). - * With IGNORE non-nil the values of these variables are ignored. + * of `window-min-height' (`window-min-width' if HORIZONTAL is + * non-nil) and `window-safe-min-height' (`window-safe-min-width') + * according to IGNORE (see `window-min-size'). * * In either case, never return a value less than 1. For TTY frames, * additionally limit the minimum frame height to a value large enough - * to support the menu bar, the mode line, and the echo area. + * to support menu bar, tab bar, mode line and echo area. */ -static int +int frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise) { @@ -405,6 +359,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, else retval = XFIXNUM (call4 (Qframe_windows_min_size, frame, horizontal, ignore, pixelwise)); + /* Don't allow too small height of text-mode frames, or else cm.c might abort in cmcheckmagic. */ if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal)) @@ -413,6 +368,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, + FRAME_TAB_BAR_LINES (f) + FRAME_WANTS_MODELINE_P (f) + 2); /* one text line and one echo-area line */ + if (retval < min_height) retval = min_height; } @@ -474,9 +430,10 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height, if (CONSP (keep_ratio) && (NILP (Fcar (keep_ratio)) || EQ (Fcar (keep_ratio), Qheight_only)) - && p->pixel_width - f->pixel_width < pos_x) + && FRAME_PIXEL_WIDTH (p) - FRAME_PIXEL_WIDTH (f) < pos_x) { - int p_f_width = p->pixel_width - f->pixel_width; + int p_f_width + = FRAME_PIXEL_WIDTH (p) - FRAME_PIXEL_WIDTH (f); if (p_f_width <= 0) pos_x = 0; @@ -496,14 +453,15 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height, if (CONSP (keep_ratio) && (NILP (Fcar (keep_ratio)) || EQ (Fcar (keep_ratio), Qwidth_only)) - && p->pixel_height - f->pixel_height < pos_y) + && FRAME_PIXEL_HEIGHT (p) - FRAME_PIXEL_HEIGHT (f) < pos_y) /* When positional adjustment was requested and the width of F should remain unaltered, try to constrain F to its parent. This means that when the parent frame is enlarged later the child's original position won't get restored. */ { - int p_f_height = p->pixel_height - f->pixel_height; + int p_f_height + = FRAME_PIXEL_HEIGHT (p) - FRAME_PIXEL_HEIGHT (f); if (p_f_height <= 0) pos_y = 0; @@ -523,60 +481,143 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height, if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only)) pixel_width = -1; else - { - pixel_width = (int)(f->pixel_width * width_factor + 0.5); - pixel_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width); - } + pixel_width + = (int)(FRAME_PIXEL_WIDTH (f) * width_factor + 0.5); if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only)) pixel_height = -1; else - { - pixel_height = (int)(f->pixel_height * height_factor + 0.5); - pixel_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height); - } + pixel_height + = (int)(FRAME_PIXEL_HEIGHT (f) * height_factor + 0.5); - adjust_frame_size (f, pixel_width, pixel_height, 1, 0, - Qkeep_ratio); + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height), 1, + false, Qkeep_ratio); } } } #endif +static void +frame_size_history_adjust (struct frame *f, int inhibit, Lisp_Object parameter, + int old_text_width, int old_text_height, + int new_text_width, int new_text_height, + int old_text_cols, int old_text_lines, + int new_text_cols, int new_text_lines, + int old_native_width, int old_native_height, + int new_native_width, int new_native_height, + int old_inner_width, int old_inner_height, + int new_inner_width, int new_inner_height, + int min_inner_width, int min_inner_height, + bool inhibit_horizontal, bool inhibit_vertical) +{ + Lisp_Object frame; + + XSETFRAME (frame, f); + if (CONSP (frame_size_history) + && FIXNUMP (XCAR (frame_size_history)) + && 0 < XFIXNUM (XCAR (frame_size_history))) + frame_size_history = + Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1), + Fcons (Fcons (list4 (frame, make_fixnum (5), + make_fixnum (inhibit), parameter), + list5 (list4i (old_text_width, old_text_height, + new_text_width, new_text_height), + list4i (old_text_cols, old_text_lines, + new_text_cols, new_text_lines), + list4i (old_native_width, old_native_height, + new_native_width, new_native_height), + list4i (old_inner_width, old_inner_height, + new_inner_width, new_inner_height), + list4 (make_fixnum (min_inner_width), + make_fixnum (min_inner_height), + inhibit_horizontal ? Qt : Qnil, + inhibit_vertical ? Qt : Qnil))), + XCDR (frame_size_history))); +} + + +void +frame_size_history_plain (struct frame *f, Lisp_Object parameter) +{ + Lisp_Object frame; + + XSETFRAME (frame, f); + if (CONSP (frame_size_history) + && FIXNUMP (XCAR (frame_size_history)) + && 0 < XFIXNUM (XCAR (frame_size_history))) + frame_size_history = + Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1), + Fcons (Fcons (list3 (frame, make_fixnum (1), parameter), Qt), + XCDR (frame_size_history))); +} + + +void +frame_size_history_extra (struct frame *f, Lisp_Object parameter, + int pixel_width, int pixel_height, + int extra_width, int extra_height, + int delayed_width, int delayed_height) +{ + Lisp_Object frame; + + XSETFRAME (frame, f); + if (CONSP (frame_size_history) + && FIXNUMP (XCAR (frame_size_history)) + && 0 < XFIXNUM (XCAR (frame_size_history))) + frame_size_history = + Fcons (make_fixnum (XFIXNUM (XCAR (frame_size_history)) - 1), + Fcons (Fcons (list3 (frame, make_fixnum (2), parameter), + list2 (list4i (pixel_width, pixel_height, + extra_width, extra_height), + list2i (delayed_width, delayed_height))), + XCDR (frame_size_history))); +} + + /** * adjust_frame_size: * - * Adjust size of frame F. NEW_WIDTH and NEW_HEIGHT specify the new - * text size of F in pixels. A value of -1 means no change is requested - * for that direction (but the frame may still have to be resized to - * accommodate windows with their minimum sizes). This can either issue - * a request to resize the frame externally (via set_window_size_hook), to - * resize the frame internally (via resize_frame_windows) or do nothing - * at all. + * Adjust size of frame F. NEW_TEXT_WIDTH and NEW_TEXT_HEIGHT specify + * the new text size of F in pixels. When INHIBIT equals 2, 3 or 4, a + * value of -1 means to leave the text size of F unchanged and adjust, + * if necessary and possible, F's native size accordingly. When INHIBIT + * equals 0, 1 or 5, a negative value means that the frame has been (or + * should be) made pathologically small which usually means that parts + * of the frame's windows may not be entirely visible. * - * The argument INHIBIT can assume the following values: + * The effect of calling this function can be to either issue a request + * to resize the frame externally (via set_window_size_hook), to resize + * the frame internally (via resize_frame_windows) or to do nothing. + * + * The argument INHIBIT controls whether set_window_size_hook may be + * called and can assume the following values: * * 0 means to unconditionally call set_window_size_hook even if sizes * apparently do not change. Fx_create_frame uses this to pass the * initial size to the window manager. * - * 1 means to call set_window_size_hook if the native frame size really - * changes. Fset_frame_size, Fset_frame_height, ... use this. + * 1 means to call set_window_size_hook if the native frame size should + * change. Fset_frame_size and friends and width and height parameter + * changes use this. * * 2 means to call set_window_size_hook provided frame_inhibit_resize - * allows it. The menu and tool bar code use this ("3" won't work - * here in general because menu and tool bar are often not counted in - * the frame's text height). + * allows it. The code updating external menu and tool bars uses this + * to keep the height of the native frame unaltered when one of these + * bars is added or removed. This means that Emacs has to work + * against the window manager which usually tries to keep the combined + * height (native frame plus bar) unaltered. * - * 3 means call set_window_size_hook if window minimum sizes must be - * preserved or frame_inhibit_resize allows it. - * gui_set_left_fringe, gui_set_scroll_bar_width, gui_new_font - * ... use (or should use) this. + * 3 means to call set_window_size_hook if window minimum sizes must be + * preserved or frame_inhibit_resize allows it. This is the default + * for parameters accounted for in a frame's text size like fringes, + * scroll bars, internal border, tab bar, internal tool and menu bars. + * It's also used when the frame's default font changes. * - * 4 means call set_window_size_hook only if window minimum sizes must - * be preserved. x_set_right_divider_width, x_set_border_width and - * the code responsible for wrapping the tool bar use this. + * 4 means to call set_window_size_hook only if window minimum sizes + * must be preserved. The code for setting up window dividers and + * that responsible for wrapping the (internal) tool bar use this. * * 5 means to never call set_window_size_hook. change_frame_size uses * this. @@ -588,146 +629,172 @@ keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height, * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the * symbol of the parameter changed (like `menu-bar-lines', `font', ...). * This is passed on to frame_inhibit_resize to let the latter decide on - * a case-by-case basis whether the frame may be resized externally. + * a case-by-case basis whether set_window_size_hook should be called. */ void -adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, - bool pretend, Lisp_Object parameter) +adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, + int inhibit, bool pretend, Lisp_Object parameter) { int unit_width = FRAME_COLUMN_WIDTH (f); int unit_height = FRAME_LINE_HEIGHT (f); - int old_pixel_width = FRAME_PIXEL_WIDTH (f); - int old_pixel_height = FRAME_PIXEL_HEIGHT (f); - int old_cols = FRAME_COLS (f); - int old_lines = FRAME_LINES (f); - int new_pixel_width, new_pixel_height; - /* The following two values are calculated from the old frame pixel - sizes and any "new" settings for tool bar, menu bar and internal - borders. We do it this way to detect whether we have to call - set_window_size_hook as consequence of the new settings. */ - int windows_width = FRAME_WINDOWS_WIDTH (f); - int windows_height = FRAME_WINDOWS_HEIGHT (f); - int min_windows_width, min_windows_height; - /* These are a bit tedious, maybe we should use a macro. */ + int old_native_width = FRAME_PIXEL_WIDTH (f); + int old_native_height = FRAME_PIXEL_HEIGHT (f); + int new_native_width, new_native_height; + /* The desired minimum inner width and height of the frame calculated + via 'frame-windows-min-size'. */ + int min_inner_width, min_inner_height; + /* Get the "old" inner width, height and position of F via its root + window and the minibuffer window. We cannot use FRAME_INNER_WIDTH + and FRAME_INNER_HEIGHT here since the internal border and the top + margin may have been already set to new values. */ struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); - int old_windows_width = WINDOW_PIXEL_WIDTH (r); - int old_windows_height + int old_inner_width = WINDOW_PIXEL_WIDTH (r); + int old_inner_height = (WINDOW_PIXEL_HEIGHT (r) + ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f))) : 0)); - int new_windows_width, new_windows_height; + int new_inner_width, new_inner_height; + int old_text_cols = FRAME_COLS (f); + int old_text_lines = FRAME_LINES (f); + int new_text_cols, new_text_lines; int old_text_width = FRAME_TEXT_WIDTH (f); int old_text_height = FRAME_TEXT_HEIGHT (f); - /* If a size is < 0 use the old value. */ - int new_text_width = (new_width >= 0) ? new_width : old_text_width; - int new_text_height = (new_height >= 0) ? new_height : old_text_height; - int new_cols, new_lines; bool inhibit_horizontal, inhibit_vertical; Lisp_Object frame; XSETFRAME (frame, f); - frame_size_history_add - (f, Qadjust_frame_size_1, new_text_width, new_text_height, - list2 (parameter, make_fixnum (inhibit))); - - /* The following two values are calculated from the old window body - sizes and any "new" settings for scroll bars, dividers, fringes and - margins (though the latter should have been processed already). */ - min_windows_width - = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt); - min_windows_height - = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt); + min_inner_width + = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qsafe : Qnil, Qt); + min_inner_height + = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qsafe : Qnil, Qt); if (inhibit >= 2 && inhibit <= 4) /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay within the limits and either resizing is inhibited or INHIBIT equals 4. */ { - inhibit_horizontal = (windows_width >= min_windows_width + if (new_text_width == -1) + new_text_width = FRAME_TEXT_WIDTH (f); + if (new_text_height == -1) + new_text_height = FRAME_TEXT_HEIGHT (f); + + inhibit_horizontal = (FRAME_INNER_WIDTH (f) >= min_inner_width && (inhibit == 4 || frame_inhibit_resize (f, true, parameter))); - inhibit_vertical = (windows_height >= min_windows_height + inhibit_vertical = (FRAME_INNER_HEIGHT (f) >= min_inner_height && (inhibit == 4 || frame_inhibit_resize (f, false, parameter))); } else - /* Otherwise inhibit if INHIBIT equals 5. */ + /* Otherwise inhibit if INHIBIT equals 5. If we wanted to overrule + the WM do that here (could lead to some sort of eternal fight + with the WM). */ inhibit_horizontal = inhibit_vertical = inhibit == 5; - new_pixel_width = ((inhibit_horizontal && (inhibit < 5)) - ? old_pixel_width - : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width), - min_windows_width - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); - new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f); - new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width); - new_cols = new_text_width / unit_width; - - new_pixel_height = ((inhibit_vertical && (inhibit < 5)) - ? old_pixel_height - : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height), - min_windows_height - + FRAME_TOP_MARGIN_HEIGHT (f) + new_native_width = ((inhibit_horizontal && inhibit < 5) + ? old_native_width + : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width), + min_inner_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); - new_windows_height = (new_pixel_height - - FRAME_TOP_MARGIN_HEIGHT (f) - - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height); - new_lines = new_text_height / unit_height; + new_inner_width = new_native_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f); + new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_native_width); + new_text_cols = new_text_width / unit_width; + + new_native_height = ((inhibit_vertical && inhibit < 5) + ? old_native_height + : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height), + min_inner_height + + FRAME_TOP_MARGIN_HEIGHT (f) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); + new_inner_height = (new_native_height + - FRAME_TOP_MARGIN_HEIGHT (f) + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_native_height); + new_text_lines = new_text_height / unit_height; -#ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f) && f->can_set_window_size && ((!inhibit_horizontal - && (new_pixel_width != old_pixel_width + && (new_native_width != old_native_width || inhibit == 0 || inhibit == 2)) || (!inhibit_vertical - && (new_pixel_height != old_pixel_height + && (new_native_height != old_native_height || inhibit == 0 || inhibit == 2)))) - /* We are either allowed to change the frame size or the minimum - sizes request such a change. Do not care for fixing minimum - sizes here, we do that eventually when we're called from - change_frame_size. */ { /* Make sure we respect fullheight and fullwidth. */ if (inhibit_horizontal) - new_text_width = old_text_width; + new_native_width = old_native_width; else if (inhibit_vertical) - new_text_height = old_text_height; + new_native_height = old_native_height; + + if (inhibit == 2 && f->new_width > 0 && f->new_height > 0) + /* For implied resizes with inhibit 2 (external menu and tool + bar) pick up any new sizes the display engine has not + processed yet. Otherwsie, we would request the old sizes + which will make this request appear as a request to set new + sizes and have the WM react accordingly which is not TRT. */ + { + /* But don't that for the external menu bar on Motif. + Otherwise, switching off the menu bar will shrink the frame + and switching it on will not enlarge it. */ +#ifdef USE_MOTIF + if (!EQ (parameter, Qmenu_bar_lines)) +#endif + { + new_native_width = f->new_width; + new_native_height = f->new_height; + } + } - frame_size_history_add - (f, Qadjust_frame_size_2, new_text_width, new_text_height, - list2 (inhibit_horizontal ? Qt : Qnil, - inhibit_vertical ? Qt : Qnil)); + if (CONSP (frame_size_history)) + frame_size_history_adjust (f, inhibit, parameter, + old_text_width, old_text_height, + new_text_width, new_text_height, + old_text_cols, old_text_lines, + new_text_cols, new_text_lines, + old_native_width, old_native_height, + new_native_width, new_native_height, + old_inner_width, old_inner_height, + new_inner_width, new_inner_height, + min_inner_width, min_inner_height, + inhibit_horizontal, inhibit_vertical); if (FRAME_TERMINAL (f)->set_window_size_hook) FRAME_TERMINAL (f)->set_window_size_hook - (f, 0, new_text_width, new_text_height, 1); + (f, 0, new_native_width, new_native_height); f->resized_p = true; return; } -#endif + + if (CONSP (frame_size_history)) + frame_size_history_adjust (f, inhibit, parameter, + old_text_width, old_text_height, + new_text_width, new_text_height, + old_text_cols, old_text_lines, + new_text_cols, new_text_lines, + old_native_width, old_native_height, + new_native_width, new_native_height, + old_inner_width, old_inner_height, + new_inner_width, new_inner_height, + min_inner_width, min_inner_height, + inhibit_horizontal, inhibit_vertical); if ((XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f)) && new_text_width == old_text_width && new_text_height == old_text_height - && new_windows_width == old_windows_width - && new_windows_height == old_windows_height - && new_pixel_width == old_pixel_width - && new_pixel_height == old_pixel_height - && new_cols == old_cols - && new_lines == old_lines) - /* No change. Sanitize window sizes and return. */ - { - sanitize_window_sizes (Qt); - sanitize_window_sizes (Qnil); - - return; - } + && new_inner_width == old_inner_width + && new_inner_height == old_inner_height + /* We might be able to drop these but some doubts remain. */ + && new_native_width == old_native_width + && new_native_height == old_native_height + && new_text_cols == old_text_cols + && new_text_lines == old_text_lines) + /* No change. */ + return; block_input (); @@ -736,69 +803,67 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, our video hardware. Try to find the smallest size greater or equal to the requested dimensions, while accounting for the fact that the menu-bar lines are not counted in the frame height. */ - int dos_new_lines = new_lines + FRAME_TOP_MARGIN (f); - dos_set_window_size (&dos_new_lines, &new_cols); - new_lines = dos_new_lines - FRAME_TOP_MARGIN (f); + int dos_new_text_lines = new_text_lines + FRAME_TOP_MARGIN (f); + + dos_set_window_size (&dos_new_text_lines, &new_text_cols); + new_text_lines = dos_new_text_lines - FRAME_TOP_MARGIN (f); #endif - if (new_windows_width != old_windows_width) + if (new_inner_width != old_inner_width) { - resize_frame_windows (f, new_windows_width, true); + resize_frame_windows (f, new_inner_width, true); /* MSDOS frames cannot PRETEND, as they change frame size by manipulating video hardware. */ if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) - FrameCols (FRAME_TTY (f)) = new_cols; + FrameCols (FRAME_TTY (f)) = new_text_cols; #if defined (HAVE_WINDOW_SYSTEM) if (WINDOWP (f->tab_bar_window)) { - XWINDOW (f->tab_bar_window)->pixel_width = new_windows_width; + XWINDOW (f->tab_bar_window)->pixel_width = new_inner_width; XWINDOW (f->tab_bar_window)->total_cols - = new_windows_width / unit_width; + = new_inner_width / unit_width; } #endif #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) if (WINDOWP (f->tool_bar_window)) { - XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width; + XWINDOW (f->tool_bar_window)->pixel_width = new_inner_width; XWINDOW (f->tool_bar_window)->total_cols - = new_windows_width / unit_width; + = new_inner_width / unit_width; } #endif } - else if (new_cols != old_cols) + else if (new_text_cols != old_text_cols) call2 (Qwindow__pixel_to_total, frame, Qt); - if (new_windows_height != old_windows_height + if (new_inner_height != old_inner_height /* When the top margin has changed we have to recalculate the top edges of all windows. No such calculation is necessary for the left edges. */ || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f)) { - resize_frame_windows (f, new_windows_height, false); + resize_frame_windows (f, new_inner_height, false); /* MSDOS frames cannot PRETEND, as they change frame size by manipulating video hardware. */ if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) - FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f); + FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f); } - else if (new_lines != old_lines) + else if (new_text_lines != old_text_lines) call2 (Qwindow__pixel_to_total, frame, Qnil); - frame_size_history_add - (f, Qadjust_frame_size_3, new_text_width, new_text_height, - list4i (old_pixel_width, old_pixel_height, - new_pixel_width, new_pixel_height)); - /* Assign new sizes. */ + FRAME_COLS (f) = new_text_cols; + FRAME_LINES (f) = new_text_lines; FRAME_TEXT_WIDTH (f) = new_text_width; FRAME_TEXT_HEIGHT (f) = new_text_height; - FRAME_PIXEL_WIDTH (f) = new_pixel_width; - FRAME_PIXEL_HEIGHT (f) = new_pixel_height; - SET_FRAME_COLS (f, new_cols); - SET_FRAME_LINES (f, new_lines); + FRAME_PIXEL_WIDTH (f) = new_native_width; + FRAME_PIXEL_HEIGHT (f) = new_native_height; + FRAME_TOTAL_COLS (f) = FRAME_PIXEL_WIDTH (f) / FRAME_COLUMN_WIDTH (f); + FRAME_TOTAL_LINES (f) = FRAME_PIXEL_HEIGHT (f) / FRAME_LINE_HEIGHT (f); { struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); @@ -812,18 +877,18 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, w->cursor.vpos = w->cursor.y = 0; } - /* Sanitize window sizes. */ - sanitize_window_sizes (Qt); - sanitize_window_sizes (Qnil); - adjust_frame_glyphs (f); calculate_costs (f); SET_FRAME_GARBAGED (f); + /* We now say here that F was resized instead of using the old + condition below. Some resizing must have taken place and if it was + only shifting the root window's position (paranoia?). */ + f->resized_p = true; - /* A frame was "resized" if one of its pixelsizes changed, even if its - X window wasn't resized at all. */ - f->resized_p = (new_pixel_width != old_pixel_width - || new_pixel_height != old_pixel_height); +/** /\* A frame was "resized" if its native size changed, even if its X **/ +/** window wasn't resized at all. *\/ **/ +/** f->resized_p = (new_native_width != old_native_width **/ +/** || new_native_height != old_native_height); **/ unblock_input (); @@ -834,8 +899,8 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, FOR_EACH_FRAME (frames, frame1) if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f) - keep_ratio (XFRAME (frame1), f, old_pixel_width, old_pixel_height, - new_pixel_width, new_pixel_height); + keep_ratio (XFRAME (frame1), f, old_native_width, old_native_height, + new_native_width, new_native_height); } #endif } @@ -884,6 +949,8 @@ make_frame (bool mini_p) f->tool_bar_resized = false; f->column_width = 1; /* !FRAME_WINDOW_P value. */ f->line_height = 1; /* !FRAME_WINDOW_P value. */ + f->new_width = -1; + f->new_height = -1; #ifdef HAVE_WINDOW_SYSTEM f->vertical_scroll_bar_type = vertical_scroll_bar_none; f->horizontal_scroll_bars = false; @@ -932,17 +999,14 @@ make_frame (bool mini_p) wset_frame (rw, frame); - /* 80/25 is arbitrary, - just so that there is "something there." + /* 80/25 is arbitrary, just so that there is "something there." Correct size will be set up later with adjust_frame_size. */ + FRAME_COLS (f) = FRAME_TOTAL_COLS (f) = rw->total_cols = 80; + FRAME_TEXT_WIDTH (f) = FRAME_PIXEL_WIDTH (f) = rw->pixel_width + = 80 * FRAME_COLUMN_WIDTH (f); + FRAME_LINES (f) = FRAME_TOTAL_LINES (f) = 25; + FRAME_TEXT_HEIGHT (f) = FRAME_PIXEL_HEIGHT (f) = 25 * FRAME_LINE_HEIGHT (f); - SET_FRAME_COLS (f, 80); - SET_FRAME_LINES (f, 25); - SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f)); - SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f)); - - rw->total_cols = FRAME_COLS (f); - rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f); rw->total_lines = FRAME_LINES (f) - (mini_p ? 1 : 0); rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f); @@ -1316,8 +1380,8 @@ affects all frames on the same terminal device. */) { int width, height; get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); - adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f) - - FRAME_TAB_BAR_LINES (f), + /* With INHIBIT 5 pass correct text height to adjust_frame_size. */ + adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f), 5, 0, Qterminal_frame); } @@ -3220,21 +3284,23 @@ If FRAME is omitted or nil, return information on the currently selected frame. : FRAME_W32_P (f) ? "w32term" :"tty")); } + store_in_alist (&alist, Qname, f->name); - height = (f->new_height - ? (f->new_pixelwise - ? (f->new_height / FRAME_LINE_HEIGHT (f)) - : f->new_height) + /* It's questionable whether here we should report the value of + f->new_height (and f->new_width below) but we've done that in the + past, so let's keep it. Note that a value of -1 for either of + these means that no new size was requested. */ + height = (f->new_height >= 0 + ? f->new_height / FRAME_LINE_HEIGHT (f) : FRAME_LINES (f)); store_in_alist (&alist, Qheight, make_fixnum (height)); - width = (f->new_width - ? (f->new_pixelwise - ? (f->new_width / FRAME_COLUMN_WIDTH (f)) - : f->new_width) - : FRAME_COLS (f)); + width = (f->new_width >= 0 + ? f->new_width / FRAME_COLUMN_WIDTH (f) + : FRAME_COLS(f)); store_in_alist (&alist, Qwidth, make_fixnum (width)); - store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil)); - store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil)); + + store_in_alist (&alist, Qmodeline, FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil); + store_in_alist (&alist, Qunsplittable, FRAME_NO_SPLIT_P (f) ? Qt : Qnil); store_in_alist (&alist, Qbuffer_list, f->buffer_list); store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list); @@ -3247,6 +3313,7 @@ If FRAME is omitted or nil, return information on the currently selected frame. { /* This ought to be correct in f->param_alist for an X frame. */ Lisp_Object lines; + XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f)); store_in_alist (&alist, Qmenu_bar_lines, lines); XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f)); @@ -3593,15 +3660,18 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt static int check_frame_pixels (Lisp_Object size, Lisp_Object pixelwise, int item_size) { + intmax_t sz; + int pixel_size; /* size * item_size */ + CHECK_INTEGER (size); if (!NILP (pixelwise)) item_size = 1; - intmax_t sz; - int pixel_size; /* size * item_size */ - if (! integer_to_intmax (size, &sz) + + if (!integer_to_intmax (size, &sz) || INT_MULTIPLY_WRAPV (sz, item_size, &pixel_size)) args_out_of_range_3 (size, make_int (INT_MIN / item_size), make_int (INT_MAX / item_size)); + return pixel_size; } @@ -3624,9 +3694,13 @@ If FRAME is nil, it defaults to the selected frame. */) (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise) { struct frame *f = decode_live_frame (frame); - int pixel_height = check_frame_pixels (height, pixelwise, - FRAME_LINE_HEIGHT (f)); - adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight); + int text_height + = check_frame_pixels (height, pixelwise, FRAME_LINE_HEIGHT (f)); + + /* With INHIBIT 1 pass correct text width to adjust_frame_size. */ + adjust_frame_size + (f, FRAME_TEXT_WIDTH (f), text_height, 1, !NILP (pretend), Qheight); + return Qnil; } @@ -3649,9 +3723,13 @@ If FRAME is nil, it defaults to the selected frame. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise) { struct frame *f = decode_live_frame (frame); - int pixel_width = check_frame_pixels (width, pixelwise, - FRAME_COLUMN_WIDTH (f)); - adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth); + int text_width + = check_frame_pixels (width, pixelwise, FRAME_COLUMN_WIDTH (f)); + + /* With INHIBIT 1 pass correct text height to adjust_frame_size. */ + adjust_frame_size + (f, text_width, FRAME_TEXT_HEIGHT (f), 1, !NILP (pretend), Qwidth); + return Qnil; } @@ -3667,11 +3745,14 @@ If FRAME is nil, it defaults to the selected frame. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise) { struct frame *f = decode_live_frame (frame); - int pixel_width = check_frame_pixels (width, pixelwise, - FRAME_COLUMN_WIDTH (f)); - int pixel_height = check_frame_pixels (height, pixelwise, - FRAME_LINE_HEIGHT (f)); - adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize); + int text_width + = check_frame_pixels (width, pixelwise, FRAME_COLUMN_WIDTH (f)); + int text_height + = check_frame_pixels (height, pixelwise, FRAME_LINE_HEIGHT (f)); + + /* PRETEND is always false here. */ + adjust_frame_size (f, text_width, text_height, 1, false, Qsize); + return Qnil; } @@ -4035,11 +4116,9 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) { Lisp_Object tail, frame; - - /* If both of these parameters are present, it's more efficient to - set them both at once. So we wait until we've looked at the - entire list before we set them. */ - int width = -1, height = -1; /* -1 denotes they were not changed. */ + /* Neither of these values should be used. */ + int width = -1, height = -1; + bool width_change = false, height_change = false; /* Same here. */ Lisp_Object left, top; @@ -4117,6 +4196,8 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) if (EQ (prop, Qwidth)) { + width_change = true; + if (RANGED_FIXNUMP (0, val, INT_MAX)) width = XFIXNAT (val) * FRAME_COLUMN_WIDTH (f) ; else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) @@ -4125,9 +4206,13 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) else if (FLOATP (val)) width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done, &outer_done, -1); + else + width_change = false; } else if (EQ (prop, Qheight)) { + height_change = true; + if (RANGED_FIXNUMP (0, val, INT_MAX)) height = XFIXNAT (val) * FRAME_LINE_HEIGHT (f); else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) @@ -4136,6 +4221,8 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) else if (FLOATP (val)) height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done, &outer_done, -1); + else + height_change = false; } else if (EQ (prop, Qtop)) top = val; @@ -4204,23 +4291,28 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) XSETINT (icon_top, 0); } - /* Don't set these parameters unless they've been explicitly - specified. The window might be mapped or resized while we're in - this function, and we don't want to override that unless the lisp - code has asked for it. - - Don't set these parameters unless they actually differ from the - window's current parameters; the window may not actually exist - yet. */ - if ((width != -1 && width != FRAME_TEXT_WIDTH (f)) - || (height != -1 && height != FRAME_TEXT_HEIGHT (f))) - /* We could consider checking f->after_make_frame here, but I - don't have the faintest idea why the following is needed at - all. With the old setting it can get a Heisenbug when - EmacsFrameResize intermittently provokes a delayed - change_frame_size in the middle of adjust_frame_size. */ - /** || (f->can_set_window_size && (f->new_height || f->new_width))) **/ - adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters); + if (width_change || height_change) + { + Lisp_Object parameter; + + if (width_change) + { + if (height_change) + parameter = Qsize; + else + { + height = FRAME_TEXT_HEIGHT (f); + parameter = Qwidth; + } + } + else + { + width = FRAME_TEXT_WIDTH (f); + parameter = Qheight; + } + + adjust_frame_size (f, width, height, 1, 0, parameter); + } if ((!NILP (left) || !NILP (top)) && ! (left_no_change && top_no_change) @@ -4293,9 +4385,6 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) { Lisp_Object old_value = get_frame_param (f, Qfullscreen); - frame_size_history_add - (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen)); - store_frame_param (f, Qfullscreen, fullscreen); if (!EQ (fullscreen, old_value)) gui_set_fullscreen (f, fullscreen, old_value); @@ -5504,25 +5593,16 @@ On Nextstep, this just calls `ns-parse-geometry'. */) This function does not make the coordinates positive. */ -#define DEFAULT_ROWS 36 -#define DEFAULT_COLS 80 - long gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, - bool toolbar_p, int *x_width, int *x_height) + bool toolbar_p) { Lisp_Object height, width, user_size, top, left, user_position; long window_prompting = 0; Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); int parent_done = -1, outer_done = -1; - - /* Default values if we fall through. - Actually, if that happens we should get - window manager prompting. */ - SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f)); - SET_FRAME_COLS (f, DEFAULT_COLS); - SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f)); - SET_FRAME_LINES (f, DEFAULT_ROWS); + int text_width = 80 * FRAME_COLUMN_WIDTH (f); + int text_height = 36 * FRAME_LINE_HEIGHT (f); /* Window managers expect that if program-specified positions are not (0,0), they're intentional, not defaults. */ @@ -5537,8 +5617,12 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, if (tabbar_p && FRAME_TAB_BAR_LINES (f)) { if (frame_default_tab_bar_height) + /* A default tab bar height was already set by the display code + for some other frame, use that. */ FRAME_TAB_BAR_HEIGHT (f) = frame_default_tab_bar_height; else + /* Calculate the height from various other settings. For some + reason, these are usually off by 2 hence of no use. */ { int margin, relief; @@ -5591,7 +5675,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, /* Ensure that earlier new_width and new_height settings won't override what we specify below. */ - f->new_width = f->new_height = 0; + f->new_width = f->new_height = -1; height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); @@ -5605,9 +5689,8 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, if ((XFIXNUM (XCDR (width)) < 0 || XFIXNUM (XCDR (width)) > INT_MAX)) xsignal1 (Qargs_out_of_range, XCDR (width)); - SET_FRAME_WIDTH (f, XFIXNUM (XCDR (width))); + text_width = XFIXNUM (XCDR (width)); f->inhibit_horizontal_resize = true; - *x_width = XFIXNUM (XCDR (width)); } else if (FLOATP (width)) { @@ -5621,7 +5704,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, &parent_done, &outer_done, -1); if (new_width > -1) - SET_FRAME_WIDTH (f, new_width); + text_width = new_width; } } else @@ -5630,7 +5713,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, if ((XFIXNUM (width) < 0 || XFIXNUM (width) > INT_MAX)) xsignal1 (Qargs_out_of_range, width); - SET_FRAME_WIDTH (f, XFIXNUM (width) * FRAME_COLUMN_WIDTH (f)); + text_width = XFIXNUM (width) * FRAME_COLUMN_WIDTH (f); } } @@ -5642,9 +5725,8 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, if ((XFIXNUM (XCDR (height)) < 0 || XFIXNUM (XCDR (height)) > INT_MAX)) xsignal1 (Qargs_out_of_range, XCDR (height)); - SET_FRAME_HEIGHT (f, XFIXNUM (XCDR (height))); + text_height = XFIXNUM (XCDR (height)); f->inhibit_vertical_resize = true; - *x_height = XFIXNUM (XCDR (height)); } else if (FLOATP (height)) { @@ -5658,7 +5740,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, &parent_done, &outer_done, -1); if (new_height > -1) - SET_FRAME_HEIGHT (f, new_height); + text_height = new_height; } } else @@ -5667,7 +5749,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, if ((XFIXNUM (height) < 0) || (XFIXNUM (height) > INT_MAX)) xsignal1 (Qargs_out_of_range, height); - SET_FRAME_HEIGHT (f, XFIXNUM (height) * FRAME_LINE_HEIGHT (f)); + text_height = XFIXNUM (height) * FRAME_LINE_HEIGHT (f); } } @@ -5679,6 +5761,9 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, window_prompting |= PSize; } + adjust_frame_size (f, text_width, text_height, 5, false, + Qgui_figure_window_size); + top = gui_display_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER); left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0, @@ -5986,39 +6071,17 @@ syms_of_frame (void) DEFSYM (Qtab_bar_size, "tab-bar-size"); DEFSYM (Qtool_bar_external, "tool-bar-external"); DEFSYM (Qtool_bar_size, "tool-bar-size"); - /* The following are used for frame_size_history. */ - DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1"); - DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2"); - DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3"); - DEFSYM (Qx_set_frame_parameters, "x-set-frame-parameters"); - DEFSYM (QEmacsFrameResize, "EmacsFrameResize"); - DEFSYM (Qset_frame_size, "set-frame-size"); - DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize"); - DEFSYM (Qx_set_fullscreen, "x-set-fullscreen"); - DEFSYM (Qx_check_fullscreen, "x-check-fullscreen"); - DEFSYM (Qxg_frame_resized, "xg-frame-resized"); - DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1"); - DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2"); - DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3"); - DEFSYM (Qxg_frame_set_char_size_4, "xg-frame-set-char-size-4"); - DEFSYM (Qx_set_window_size_1, "x-set-window-size-1"); - DEFSYM (Qx_set_window_size_2, "x-set-window-size-2"); - DEFSYM (Qx_set_window_size_3, "x-set-window-size-3"); - DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position"); - DEFSYM (Qx_net_wm_state, "x-net-wm-state"); - DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state"); - DEFSYM (Qtb_size_cb, "tb-size-cb"); - DEFSYM (Qupdate_frame_tab_bar, "update-frame-tab-bar"); - DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar"); - DEFSYM (Qfree_frame_tab_bar, "free-frame-tab-bar"); - DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar"); - DEFSYM (Qx_set_menu_bar_lines, "x-set-menu-bar-lines"); - DEFSYM (Qchange_frame_size, "change-frame-size"); - DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size"); - DEFSYM (Qset_window_configuration, "set-window-configuration"); - DEFSYM (Qx_create_frame_1, "x-create-frame-1"); - DEFSYM (Qx_create_frame_2, "x-create-frame-2"); - DEFSYM (Qterminal_frame, "terminal-frame"); + /* The following are passed to adjust_frame_size. */ + DEFSYM (Qx_set_menu_bar_lines, "x_set_menu_bar_lines"); + DEFSYM (Qchange_frame_size, "change_frame_size"); + DEFSYM (Qxg_frame_set_char_size, "xg_frame_set_char_size"); + DEFSYM (Qx_set_window_size_1, "x_set_window_size_1"); + DEFSYM (Qset_window_configuration, "set_window_configuration"); + DEFSYM (Qx_create_frame_1, "x_create_frame_1"); + DEFSYM (Qx_create_frame_2, "x_create_frame_2"); + DEFSYM (Qgui_figure_window_size, "gui_figure_window_size"); + DEFSYM (Qtip_frame, "tip_frame"); + DEFSYM (Qterminal_frame, "terminal_frame"); #ifdef HAVE_NS DEFSYM (Qns_parse_geometry, "ns-parse-geometry"); @@ -6047,9 +6110,7 @@ syms_of_frame (void) DEFSYM (Qleft_fringe, "left-fringe"); DEFSYM (Qline_spacing, "line-spacing"); DEFSYM (Qmenu_bar_lines, "menu-bar-lines"); - DEFSYM (Qupdate_frame_menubar, "update-frame-menubar"); - DEFSYM (Qfree_frame_menubar_1, "free-frame-menubar-1"); - DEFSYM (Qfree_frame_menubar_2, "free-frame-menubar-2"); + DEFSYM (Qtab_bar_lines, "tab-bar-lines"); DEFSYM (Qmouse_color, "mouse-color"); DEFSYM (Qname, "name"); DEFSYM (Qright_divider_width, "right-divider-width"); @@ -6061,7 +6122,6 @@ syms_of_frame (void) DEFSYM (Qscroll_bar_width, "scroll-bar-width"); DEFSYM (Qsticky, "sticky"); DEFSYM (Qtitle, "title"); - DEFSYM (Qtab_bar_lines, "tab-bar-lines"); DEFSYM (Qtool_bar_lines, "tool-bar-lines"); DEFSYM (Qtool_bar_position, "tool-bar-position"); DEFSYM (Qunsplittable, "unsplittable"); diff --git a/src/frame.h b/src/frame.h index 0fd95e4dd3c..19ee6ac10e7 100644 --- a/src/frame.h +++ b/src/frame.h @@ -256,8 +256,8 @@ struct frame be used for output. */ bool_bf glyphs_initialized_p : 1; - /* Set to true in change_frame_size when size of frame changed - Clear the frame in clear_garbaged_frames if set. */ + /* Set to true in adjust_frame_size when one of the frame's sizes + changed. Clear the frame in clear_garbaged_frames if set. */ bool_bf resized_p : 1; /* Set to true if the default face for the frame has been @@ -415,10 +415,6 @@ struct frame bool_bf no_special_glyphs : 1; #endif /* HAVE_WINDOW_SYSTEM */ - /* Whether new_height and new_width shall be interpreted - in pixels. */ - bool_bf new_pixelwise : 1; - /* True means set_window_size_hook requests can be processed for this frame. */ bool_bf can_set_window_size : 1; @@ -426,11 +422,23 @@ struct frame /* Set to true after this frame was made by `make-frame'. */ bool_bf after_make_frame : 1; - /* Whether the tab bar height change should be taken into account. */ + /* Two sticky flags, that are both false when a frame is created. + 'display_tab_bar' sets the former to true the first time it + displays the tab bar. When the former is true, the next call of + 'x_change_tab_bar_height' and associates sets the latter true and + tries to adjust the frame height in a way that the now valid pixel + height of the tab bar is taken into account by the frame's native + height. */ bool_bf tab_bar_redisplayed : 1; bool_bf tab_bar_resized : 1; - /* Whether the tool bar height change should be taken into account. */ + /* Two sticky flags, that are both false when a frame is created. + 'redisplay_tool_bar' sets the former to true the first time it + displays the tool bar. When the former is true, the next call of + 'x_change_tool_bar_height' and associates sets the latter true and + tries to adjust the frame height in a way that the now valid pixel + height of the tool bar is taken into account by the frame's native + height. */ bool_bf tool_bar_redisplayed : 1; bool_bf tool_bar_resized : 1; @@ -461,7 +469,7 @@ struct frame last time run_window_change_functions was called on it. */ ptrdiff_t number_of_windows; - /* Number of lines (rounded up) of tab bar. REMOVE THIS */ + /* Number of frame lines (rounded up) of tab bar. */ int tab_bar_lines; /* Height of frame internal tab bar in pixels. */ @@ -470,7 +478,7 @@ struct frame int n_tab_bar_rows; int n_tab_bar_items; - /* Number of lines (rounded up) of tool bar. REMOVE THIS */ + /* Number of frame lines (rounded up) of tool bar. */ int tool_bar_lines; /* Height of frame internal tool bar in pixels. */ @@ -492,39 +500,24 @@ struct frame /* Cost of deleting n lines on this frame. */ int *delete_n_lines_cost; - /* Text width of this frame (excluding fringes, vertical scroll bar - and internal border widths) and text height (excluding menu bar, - tool bar, horizontal scroll bar and internal border widths) in - units of canonical characters. */ + /* Text width and height of this frame in (and maybe rounded to) frame + columns and lines. */ int text_cols, text_lines; - - /* Total width of this frame (including fringes, vertical scroll bar - and internal border widths) and total height (including menu bar, - tool bar, horizontal scroll bar and internal border widths) in - units of canonical characters. */ - int total_cols, total_lines; - - /* Text width of this frame (excluding fringes, vertical scroll bar - and internal border widths) and text height (excluding menu bar, - tool bar, horizontal scroll bar and internal border widths) in - pixels. */ + /* Text width and height of this frame in pixels. */ int text_width, text_height; - /* New text height and width for pending size change. 0 if no change - pending. These values represent pixels or canonical character units - according to the value of new_pixelwise and correlate to the - text width/height of the frame. */ + /* Native width of this frame in (and maybe rounded to) frame columns + and lines. */ + int total_cols, total_lines; + /* Native width and height of this frame in pixels. */ + int pixel_width, pixel_height; + /* New native width and height of this frame for pending size change, + in pixels. -1 if no change pending. */ int new_width, new_height; /* Pixel position of the frame window (x and y offsets in root window). */ int left_pos, top_pos; - /* Total width of this frame (including fringes, vertical scroll bar - and internal border widths) and total height (including internal - menu and tool bars, horizontal scroll bar and internal border - widths) in pixels. */ - int pixel_width, pixel_height; - /* This is the gravity value for the specified window position. */ int win_gravity; @@ -848,7 +841,6 @@ default_pixels_per_inch_y (void) /* FRAME_WINDOW_P tests whether the frame is a graphical window system frame. */ - #ifdef HAVE_X_WINDOWS #define FRAME_WINDOW_P(f) FRAME_X_P (f) #endif @@ -914,45 +906,36 @@ default_pixels_per_inch_y (void) # define FRAME_SCALE_FACTOR(f) 1 #endif -/* Pixel width of frame F. */ +/* Native width and height of frame F, in pixels and frame + columns/lines. */ #define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width) - -/* Pixel height of frame F. */ #define FRAME_PIXEL_HEIGHT(f) ((f)->pixel_height) +#define FRAME_TOTAL_COLS(f) ((f)->total_cols) +#define FRAME_TOTAL_LINES(f) ((f)->total_lines) -/* Width of frame F, measured in canonical character columns, - not including scroll bars if any. */ -#define FRAME_COLS(f) (f)->text_cols - -/* Height of frame F, measured in canonical lines, including - non-toolkit menu bar and non-toolkit tool bar lines. */ -#define FRAME_LINES(f) (f)->text_lines - -/* Width of frame F, measured in pixels not including the width for - fringes, scroll bar, and internal borders. */ +/* Text width and height of frame F, in pixels and frame + columns/lines. */ #define FRAME_TEXT_WIDTH(f) (f)->text_width - -/* Height of frame F, measured in pixels not including the height - for scroll bar and internal borders. */ #define FRAME_TEXT_HEIGHT(f) (f)->text_height +#define FRAME_COLS(f) ((f)->text_cols) +#define FRAME_LINES(f) ((f)->text_lines) -/* Number of lines of frame F used for menu bar. - This is relevant on terminal frames and on - X Windows when not using the X toolkit. - These lines are counted in FRAME_LINES. */ -#define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines +/* True if this frame should display an external menu bar. */ +#ifdef HAVE_EXT_MENU_BAR +#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar +#else +#define FRAME_EXTERNAL_MENU_BAR(f) false +#endif -/* Pixel height of frame F's menu bar. */ +/* Size of frame F's internal menu bar in frame lines and pixels. */ +#define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines #define FRAME_MENU_BAR_HEIGHT(f) (f)->menu_bar_height -/* Number of lines of frame F used for the tab-bar. */ +/* Size of frame F's tab bar in frame lines and pixels. */ #define FRAME_TAB_BAR_LINES(f) (f)->tab_bar_lines - -/* Pixel height of frame F's tab-bar. */ #define FRAME_TAB_BAR_HEIGHT(f) (f)->tab_bar_height -/* True if this frame should display a tool bar - in a way that does not use any text lines. */ +/* True if this frame should display an external tool bar. */ #ifdef HAVE_EXT_TOOL_BAR #define FRAME_EXTERNAL_TOOL_BAR(f) (f)->external_tool_bar #else @@ -966,27 +949,21 @@ default_pixels_per_inch_y (void) #define FRAME_TOOL_BAR_POSITION(f) ((void) (f), Qtop) #endif -/* Number of lines of frame F used for the tool-bar. */ +/* Size of frame F's internal tool bar in frame lines and pixels. */ #define FRAME_TOOL_BAR_LINES(f) (f)->tool_bar_lines - -/* Pixel height of frame F's tool-bar. */ #define FRAME_TOOL_BAR_HEIGHT(f) (f)->tool_bar_height -/* Lines above the top-most window in frame F. */ -#define FRAME_TOP_MARGIN(F) \ - (FRAME_MENU_BAR_LINES (F) + FRAME_TAB_BAR_LINES (F) + FRAME_TOOL_BAR_LINES (F)) +/* Height of frame F's top margin in frame lines. */ +#define FRAME_TOP_MARGIN(F) \ + (FRAME_MENU_BAR_LINES (F) \ + + FRAME_TAB_BAR_LINES (F) \ + + FRAME_TOOL_BAR_LINES (F)) /* Pixel height of frame F's top margin. */ -#define FRAME_TOP_MARGIN_HEIGHT(F) \ - (FRAME_MENU_BAR_HEIGHT (F) + FRAME_TAB_BAR_HEIGHT (F) + FRAME_TOOL_BAR_HEIGHT (F)) - -/* True if this frame should display a menu bar - in a way that does not use any text lines. */ -#ifdef HAVE_EXT_MENU_BAR -#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar -#else -#define FRAME_EXTERNAL_MENU_BAR(f) false -#endif +#define FRAME_TOP_MARGIN_HEIGHT(F) \ + (FRAME_MENU_BAR_HEIGHT (F) \ + + FRAME_TAB_BAR_HEIGHT (F) \ + + FRAME_TOOL_BAR_HEIGHT (F)) /* True if frame F is currently visible. */ #define FRAME_VISIBLE_P(f) (f)->visible @@ -1183,48 +1160,6 @@ default_pixels_per_inch_y (void) ? FRAME_CONFIG_SCROLL_BAR_LINES (f) \ : 0) -/* Total width of frame F, in columns (characters), - including the width used by scroll bars if any. */ -#define FRAME_TOTAL_COLS(f) ((f)->total_cols) - -/* Total height of frame F, in lines (characters), - including the height used by scroll bars if any. */ -#define FRAME_TOTAL_LINES(f) ((f)->total_lines) - -/* Set the character widths of frame F. WIDTH specifies a nominal - character text width. */ -#define SET_FRAME_COLS(f, width) \ - ((f)->text_cols = (width), \ - (f)->total_cols = ((width) \ - + FRAME_SCROLL_BAR_COLS (f) \ - + FRAME_FRINGE_COLS (f))) - -/* Set the character heights of frame F. HEIGHT specifies a nominal - character text height. */ -#define SET_FRAME_LINES(f, height) \ - ((f)->text_lines = (height), \ - (f)->total_lines = ((height) \ - + FRAME_TOP_MARGIN (f) \ - + FRAME_SCROLL_BAR_LINES (f))) - -/* Set the widths of frame F. WIDTH specifies a nominal pixel text - width. */ -#define SET_FRAME_WIDTH(f, width) \ - ((f)->text_width = (width), \ - (f)->pixel_width = ((width) \ - + FRAME_SCROLL_BAR_AREA_WIDTH (f) \ - + FRAME_TOTAL_FRINGE_WIDTH (f) \ - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))) - -/* Set the heights of frame F. HEIGHT specifies a nominal pixel text - height. */ -#define SET_FRAME_HEIGHT(f, height) \ - ((f)->text_height = (height), \ - (f)->pixel_height = ((height) \ - + FRAME_TOP_MARGIN_HEIGHT (f) \ - + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))) - /* Maximum + 1 legitimate value for FRAME_CURSOR_X. */ #define FRAME_CURSOR_X_LIMIT(f) \ (FRAME_COLS (f) + FRAME_LEFT_SCROLL_BAR_COLS (f)) @@ -1245,7 +1180,6 @@ default_pixels_per_inch_y (void) #define FRAME_BACKGROUND_PIXEL(f) ((f)->background_pixel) /* Return a pointer to the face cache of frame F. */ - #define FRAME_FACE_CACHE(F) (F)->face_cache /* Return the size of message_buf of the frame F. We multiply the @@ -1271,15 +1205,13 @@ default_pixels_per_inch_y (void) This macro is a holdover from a time when multiple frames weren't always supported. An alternate definition of the macro would expand to something which executes the statement once. */ - -#define FOR_EACH_FRAME(list_var, frame_var) \ - for ((list_var) = Vframe_list; \ - (CONSP (list_var) \ +#define FOR_EACH_FRAME(list_var, frame_var) \ + for ((list_var) = Vframe_list; \ + (CONSP (list_var) \ && (frame_var = XCAR (list_var), true)); \ list_var = XCDR (list_var)) /* Reflect mouse movement when a complete frame update is performed. */ - #define FRAME_MOUSE_UPDATE(frame) \ do { \ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (frame); \ @@ -1294,8 +1226,7 @@ default_pixels_per_inch_y (void) } while (false) /* Handy macro to construct an argument to Fmodify_frame_parameters. */ - -#define AUTO_FRAME_ARG(name, parameter, value) \ +#define AUTO_FRAME_ARG(name, parameter, value) \ AUTO_LIST1 (name, AUTO_CONS_EXPR (parameter, value)) /* False means there are no visible garbaged frames. */ @@ -1305,7 +1236,6 @@ extern bool frame_garbaged; We call redisplay_other_windows to make sure the frame gets redisplayed if some changes were applied to it while it wasn't visible (and hence wasn't redisplayed). */ - INLINE void SET_FRAME_VISIBLE (struct frame *f, int v) { @@ -1320,9 +1250,8 @@ SET_FRAME_VISIBLE (struct frame *f, int v) f->visible = v; } -/* Set iconify of frame F. */ - -#define SET_FRAME_ICONIFIED(f, i) \ +/* Set iconified status of frame F. */ +#define SET_FRAME_ICONIFIED(f, i) \ (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i)) extern Lisp_Object selected_frame; @@ -1369,11 +1298,14 @@ extern void frame_make_pointer_invisible (struct frame *); extern void frame_make_pointer_visible (struct frame *); extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object); -extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object); -extern void frame_size_history_add (struct frame *f, Lisp_Object fun_symbol, - int width, int height, Lisp_Object rest); +extern void adjust_frame_size (struct frame *, int, int, int, bool, + Lisp_Object); extern Lisp_Object mouse_position (bool); - +extern int frame_windows_min_size (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object); +extern void frame_size_history_plain (struct frame *, Lisp_Object); +extern void frame_size_history_extra (struct frame *, Lisp_Object, + int, int, int, int, int, int); extern Lisp_Object Vframe_list; /* Value is a pointer to the selected frame. If the selected frame @@ -1652,12 +1584,11 @@ IMAGE_OPT_FROM_ID (struct frame *f, int id) - FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) -/* Return the width/height reserved for the windows of frame F. */ -#define FRAME_WINDOWS_WIDTH(f) \ +#define FRAME_INNER_WIDTH(f) \ (FRAME_PIXEL_WIDTH (f) \ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) -#define FRAME_WINDOWS_HEIGHT(f) \ +#define FRAME_INNER_HEIGHT(f) \ (FRAME_PIXEL_HEIGHT (f) \ - FRAME_TOP_MARGIN_HEIGHT (f) \ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) @@ -1701,7 +1632,7 @@ extern void gui_set_horizontal_scroll_bars (struct frame *, Lisp_Object, Lisp_Ob extern void gui_set_scroll_bar_width (struct frame *, Lisp_Object, Lisp_Object); extern void gui_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object); -extern long gui_figure_window_size (struct frame *, Lisp_Object, bool, bool, int *, int *); +extern long gui_figure_window_size (struct frame *, Lisp_Object, bool, bool); extern void gui_set_alpha (struct frame *, Lisp_Object, Lisp_Object); extern void gui_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object); diff --git a/src/gtkutil.c b/src/gtkutil.c index 4634c35dd4c..4ad172bb486 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -910,70 +910,58 @@ xg_set_geometry (struct frame *f) } } -/* Function to handle resize of our frame. As we have a Gtk+ tool bar - and a Gtk+ menu bar, we get resize events for the edit part of the - frame only. We let Gtk+ deal with the Gtk+ parts. - F is the frame to resize. - PIXELWIDTH, PIXELHEIGHT is the new size in pixels. */ - +/** Function to handle resize of native frame F to WIDTH and HEIGHT + pixels after we got a ConfigureNotify event. */ void -xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) +xg_frame_resized (struct frame *f, int width, int height) { - int width, height; - - if (pixelwidth == -1 && pixelheight == -1) + /* Ignore case where size of native rectangle didn't change. */ + if (width != FRAME_PIXEL_WIDTH (f) || height != FRAME_PIXEL_HEIGHT (f) + || (delayed_size_change + && (width != f->new_width || height != f->new_height))) { - if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f))) - gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)), - 0, 0, &pixelwidth, &pixelheight); - else - return; - } + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("xg_frame_resized, changed"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + delayed_size_change ? f->new_width : -1, + delayed_size_change ? f->new_height : -1); - width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth); - height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight); - - frame_size_history_add - (f, Qxg_frame_resized, width, height, Qnil); - - if (width != FRAME_TEXT_WIDTH (f) - || height != FRAME_TEXT_HEIGHT (f) - || pixelwidth != FRAME_PIXEL_WIDTH (f) - || pixelheight != FRAME_PIXEL_HEIGHT (f)) - { FRAME_RIF (f)->clear_under_internal_border (f); - change_frame_size (f, width, height, 0, 1, 0, 1); + change_frame_size (f, width, height, false, true, false); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } + else if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("xg_frame_resized, unchanged"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + delayed_size_change ? f->new_width : -1, + delayed_size_change ? f->new_height : -1); + } /** Resize the outer window of frame F. WIDTH and HEIGHT are the new - pixel sizes of F's text area. */ + native pixel sizes of F. */ void xg_frame_set_char_size (struct frame *f, int width, int height) { - int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); gint gwidth, gheight; - int totalheight - = pixelheight + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); - int totalwidth = pixelwidth + FRAME_TOOLBAR_WIDTH (f); + int outer_height + = height + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); + int outer_width = width + FRAME_TOOLBAR_WIDTH (f); bool was_visible = false; bool hide_child_frame; - if (FRAME_PIXEL_HEIGHT (f) == 0) - return; - gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), &gwidth, &gheight); /* Do this before resize, as we don't know yet if we will be resized. */ FRAME_RIF (f)->clear_under_internal_border (f); - totalheight /= xg_get_scale (f); - totalwidth /= xg_get_scale (f); + outer_height /= xg_get_scale (f); + outer_width /= xg_get_scale (f); x_wm_set_size_hint (f, 0, 0); @@ -986,35 +974,19 @@ xg_frame_set_char_size (struct frame *f, int width, int height) manager will abolish it. At least the respective size should remain unchanged but giving the frame back its normal size will be broken ... */ - if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f)) - { - frame_size_history_add - (f, Qxg_frame_set_char_size_1, width, height, - list2i (gheight, totalheight)); - - gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - gwidth, totalheight); - } - else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f)) - { - frame_size_history_add - (f, Qxg_frame_set_char_size_2, width, height, - list2i (gwidth, totalwidth)); - - gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - totalwidth, gheight); - } + if (EQ (fullscreen, Qfullwidth) && width == FRAME_PIXEL_WIDTH (f)) + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + gwidth, outer_height); + else if (EQ (fullscreen, Qfullheight) && height == FRAME_PIXEL_HEIGHT (f)) + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + outer_width, gheight); else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)) { was_visible = true; hide_child_frame = EQ (x_gtk_resize_child_frames, Qhide); - if (totalwidth != gwidth || totalheight != gheight) + if (outer_width != gwidth || outer_height != gheight) { - frame_size_history_add - (f, Qxg_frame_set_char_size_4, width, height, - list2i (totalwidth, totalheight)); - if (hide_child_frame) { block_input (); @@ -1023,7 +995,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height) } gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - totalwidth, totalheight); + outer_width, outer_height); if (hide_child_frame) { @@ -1037,11 +1009,8 @@ xg_frame_set_char_size (struct frame *f, int width, int height) } else { - frame_size_history_add - (f, Qxg_frame_set_char_size_3, width, height, - list2i (totalwidth, totalheight)); gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - totalwidth, totalheight); + outer_width, outer_height); fullscreen = Qnil; } @@ -1062,6 +1031,12 @@ xg_frame_set_char_size (struct frame *f, int width, int height) gdk_flush (); x_wait_for_event (f, ConfigureNotify); + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("xg_frame_set_char_size, visible"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + f->new_width, f->new_height); + if (!NILP (fullscreen)) /* Try to restore fullscreen state. */ { @@ -1070,8 +1045,17 @@ xg_frame_set_char_size (struct frame *f, int width, int height) } } else - adjust_frame_size (f, width, height, 5, 0, Qxg_frame_set_char_size); - + { + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("xg_frame_set_char_size, invisible"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + f->new_width, f->new_height); + + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), + 5, 0, Qxg_frame_set_char_size); + } } /* Handle height/width changes (i.e. add/remove/move menu/toolbar). @@ -1186,7 +1170,8 @@ style_changed_cb (GObject *go, { FRAME_TERMINAL (f)->set_scroll_bar_default_width_hook (f); FRAME_TERMINAL (f)->set_scroll_bar_default_height_hook (f); - xg_frame_set_char_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f)); + xg_frame_set_char_size (f, FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f)); } } } @@ -4589,10 +4574,7 @@ tb_size_cb (GtkWidget *widget, struct frame *f = user_data; if (xg_update_tool_bar_sizes (f)) - { - frame_size_history_add (f, Qtb_size_cb, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, 5, 0, Qtool_bar_lines); - } + adjust_frame_size (f, -1, -1, 2, false, Qtool_bar_lines); } /* Create a tool bar for frame F. */ @@ -5219,23 +5201,10 @@ update_frame_tool_bar (struct frame *f) xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f)); gtk_widget_show_all (x->toolbar_widget); if (xg_update_tool_bar_sizes (f)) - { - int inhibit - = ((f->after_make_frame - && !f->tool_bar_resized - && (EQ (frame_inhibit_implied_resize, Qt) - || (CONSP (frame_inhibit_implied_resize) - && !NILP (Fmemq (Qtool_bar_lines, - frame_inhibit_implied_resize)))) - /* This will probably fail to DTRT in the - fullheight/-width cases. */ - && NILP (get_frame_param (f, Qfullscreen))) - ? 0 - : 2); - - frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines); - } + /* It's not entirely clear whether here we want a treatment + similar to that for frames with internal tool bar. */ + adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); + f->tool_bar_resized = f->tool_bar_redisplayed; } @@ -5284,7 +5253,6 @@ free_frame_tool_bar (struct frame *f) NULL); } - frame_size_history_add (f, Qfree_frame_tool_bar, 0, 0, Qnil); adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); unblock_input (); @@ -5316,11 +5284,7 @@ xg_change_toolbar_position (struct frame *f, Lisp_Object pos) g_object_unref (top_widget); if (xg_update_tool_bar_sizes (f)) - { - frame_size_history_add (f, Qxg_change_toolbar_position, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); - } - + adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); unblock_input (); } diff --git a/src/keyboard.c b/src/keyboard.c index e9236fee1aa..47b5e590245 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -10665,10 +10665,7 @@ On such systems, Emacs starts a subshell instead of suspending. */) with a window system; but suspend should be disabled in that case. */ get_tty_size (fileno (CURTTY ()->input), &width, &height); if (width != old_width || height != old_height) - change_frame_size (SELECTED_FRAME (), width, - height - FRAME_MENU_BAR_LINES (SELECTED_FRAME ()) - - FRAME_TAB_BAR_LINES (SELECTED_FRAME ()), - 0, 0, 0, 0); + change_frame_size (SELECTED_FRAME (), width, height, false, false, false); run_hook (intern ("suspend-resume-hook")); diff --git a/src/nsfns.m b/src/nsfns.m index 5c4cc915e7c..054777aa66f 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -669,21 +669,9 @@ ns_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } { - int inhibit - = ((f->after_make_frame - && !f->tool_bar_resized - && (EQ (frame_inhibit_implied_resize, Qt) - || (CONSP (frame_inhibit_implied_resize) - && !NILP (Fmemq (Qtool_bar_lines, - frame_inhibit_implied_resize)))) - && NILP (get_frame_param (f, Qfullscreen))) - ? 0 - : 2); - NSTRACE_MSG ("inhibit:%d", inhibit); - frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines); + adjust_frame_size (f, -1, -1, 2, false, Qtool_bar_lines); } } @@ -1332,8 +1320,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, RES_TYPE_STRING); parms = get_geometry_from_preferences (dpyinfo, parms); - window_prompting = gui_figure_window_size (f, parms, false, true, - &x_width, &x_height); + window_prompting = gui_figure_window_size (f, parms, false, true); tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); @@ -1400,13 +1387,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, /* Allow set_window_size_hook, now. */ f->can_set_window_size = true; - if (x_width > 0) - SET_FRAME_WIDTH (f, x_width); - if (x_height > 0) - SET_FRAME_HEIGHT (f, x_height); - - adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1, - Qx_create_frame_2); + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qx_create_frame_2); if (! f->output_data.ns->explicit_parent) { diff --git a/src/nsterm.m b/src/nsterm.m index a6501100ca9..b135e359f5d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1876,10 +1876,9 @@ static void ns_set_window_size (struct frame *f, bool change_gravity, int width, - int height, - bool pixelwise) + int height) /* -------------------------------------------------------------------------- - Adjust window pixel size based on given character grid size + Adjust window pixel size based on native sizes WIDTH and HEIGHT. Impl is a bit more complex than other terms, need to do some internal clipping. -------------------------------------------------------------------------- */ @@ -1887,7 +1886,6 @@ ns_set_window_size (struct frame *f, EmacsView *view = FRAME_NS_VIEW (f); NSWindow *window = [view window]; NSRect wr = [window frame]; - int pixelwidth, pixelheight; int orig_height = wr.size.height; NSTRACE ("ns_set_window_size"); @@ -1896,24 +1894,13 @@ ns_set_window_size (struct frame *f, return; NSTRACE_RECT ("current", wr); - NSTRACE_MSG ("Width:%d Height:%d Pixelwise:%d", width, height, pixelwise); + NSTRACE_MSG ("Width:%d Height:%d", width, height); NSTRACE_MSG ("Font %d x %d", FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); block_input (); - if (pixelwise) - { - pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); - } - else - { - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); - } - - wr.size.width = pixelwidth + f->border_width; - wr.size.height = pixelheight; + wr.size.width = width + f->border_width; + wr.size.height = height; if (! [view isFullscreen]) wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); @@ -1926,21 +1913,10 @@ ns_set_window_size (struct frame *f, else wr.origin.y += orig_height - wr.size.height; - frame_size_history_add - (f, Qx_set_window_size_1, width, height, - list5 (Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)), - Fcons (make_fixnum (wr.size.width), make_fixnum (wr.size.height)), - make_fixnum (f->border_width), - make_fixnum (FRAME_NS_TITLEBAR_HEIGHT (f)), - make_fixnum (FRAME_TOOLBAR_HEIGHT (f)))); - /* Usually it seems safe to delay changing the frame size, but when a series of actions are taken with no redisplay between them then we can end up using old values so don't delay here. */ - change_frame_size (f, - FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth), - FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight), - 0, NO, 0, 1); + change_frame_size (f, width, height, false, NO, false); [window setFrame:wr display:NO]; @@ -7359,10 +7335,7 @@ not_in_argv (NSString *arg) changes size, as Emacs may already know about the change. Unfortunately there doesn't seem to be a bullet-proof method of determining whether we need to call it or not. */ - change_frame_size (emacsframe, - FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww), - FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh), - 0, YES, 0, 1); + change_frame_size (emacsframe, neww, newh, false, YES, false); SET_FRAME_GARBAGED (emacsframe); cancel_mouse_face (emacsframe); diff --git a/src/term.c b/src/term.c index 1059b0669a7..c995a4499cf 100644 --- a/src/term.c +++ b/src/term.c @@ -2356,9 +2356,7 @@ frame's terminal). */) was suspended. */ get_tty_size (fileno (t->display_info.tty->input), &width, &height); if (width != old_width || height != old_height) - change_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f) - - FRAME_TAB_BAR_LINES (f), - 0, 0, 0, 0); + change_frame_size (f, width, height, false, false, false); SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); } diff --git a/src/termhooks.h b/src/termhooks.h index 3800679e803..1d3cdc8fe8d 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -583,7 +583,7 @@ struct terminal window gravity for this size change and subsequent size changes. Otherwise we leave the window gravity unchanged. */ void (*set_window_size_hook) (struct frame *f, bool change_gravity, - int width, int height, bool pixelwise); + int width, int height); /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, to really change the position, and 0 when calling from diff --git a/src/w32fns.c b/src/w32fns.c index c07f32ab0cc..66baeaecbdb 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1701,7 +1701,7 @@ w32_change_tab_bar_height (struct frame *f, int height) int unit = FRAME_LINE_HEIGHT (f); int old_height = FRAME_TAB_BAR_HEIGHT (f); int lines = (height + unit - 1) / unit; - Lisp_Object fullscreen; + Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); /* Make sure we redisplay all windows in this frame. */ fset_redisplay (f); @@ -1728,25 +1728,21 @@ w32_change_tab_bar_height (struct frame *f, int height) if ((height < old_height) && WINDOWP (f->tab_bar_window)) clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix); - /* Recalculate tabbar height. */ - f->n_tab_bar_rows = 0; - if (old_height == 0 - && (!f->after_make_frame - || NILP (frame_inhibit_implied_resize) - || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize))))) - f->tab_bar_redisplayed = f->tab_bar_resized = false; - - adjust_frame_size (f, -1, -1, - ((!f->tab_bar_resized - && (NILP (fullscreen = - get_frame_param (f, Qfullscreen)) - || EQ (fullscreen, Qfullwidth))) ? 1 - : (old_height == 0 || height == 0) ? 2 - : 4), - false, Qtab_bar_lines); - - f->tab_bar_resized = f->tab_bar_redisplayed; + if (!f->tab_bar_resized) + { + /* As long as tab_bar_resized is false, effectively try to change + F's native height. */ + if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth)) + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 1, false, Qtab_bar_lines); + else + adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines); + + f->tab_bar_resized = f->tab_bar_redisplayed; + } + else + /* Any other change may leave the native size of F alone. */ + adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines); /* adjust_frame_size might not have done anything, garbage frame here. */ @@ -1790,7 +1786,7 @@ w32_change_tool_bar_height (struct frame *f, int height) int unit = FRAME_LINE_HEIGHT (f); int old_height = FRAME_TOOL_BAR_HEIGHT (f); int lines = (height + unit - 1) / unit; - Lisp_Object fullscreen; + Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); /* Make sure we redisplay all windows in this frame. */ windows_or_buffers_changed = 23; @@ -1811,25 +1807,21 @@ w32_change_tool_bar_height (struct frame *f, int height) if ((height < old_height) && WINDOWP (f->tool_bar_window)) clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); - /* Recalculate toolbar height. */ - f->n_tool_bar_rows = 0; - if (old_height == 0 - && (!f->after_make_frame - || NILP (frame_inhibit_implied_resize) - || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize))))) - f->tool_bar_redisplayed = f->tool_bar_resized = false; - - adjust_frame_size (f, -1, -1, - ((!f->tool_bar_resized - && (NILP (fullscreen = - get_frame_param (f, Qfullscreen)) - || EQ (fullscreen, Qfullwidth))) ? 1 - : (old_height == 0 || height == 0) ? 2 - : 4), - false, Qtool_bar_lines); - - f->tool_bar_resized = f->tool_bar_redisplayed; + if (!f->tool_bar_resized) + { + /* As long as tool_bar_resized is false, effectively try to change + F's native height. */ + if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth)) + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 1, false, Qtool_bar_lines); + else + adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines); + + f->tool_bar_resized = f->tool_bar_redisplayed; + } + else + /* Any other change may leave the native size of F alone. */ + adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines); /* adjust_frame_size might not have done anything, garbage frame here. */ @@ -5718,7 +5710,6 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, struct w32_display_info *dpyinfo = NULL; Lisp_Object parent, parent_frame; struct kboard *kb; - int x_width = 0, x_height = 0; if (!FRAME_W32_P (SELECTED_FRAME ()) && !FRAME_INITIAL_P (SELECTED_FRAME ())) @@ -6045,8 +6036,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor; - window_prompting = gui_figure_window_size (f, parameters, true, true, - &x_width, &x_height); + window_prompting = gui_figure_window_size (f, parameters, true, true); tem = gui_display_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); @@ -6081,11 +6071,6 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, /* Allow set_window_size_hook, now. */ f->can_set_window_size = true; - if (x_width > 0) - SET_FRAME_WIDTH (f, x_width); - if (x_height > 0) - SET_FRAME_HEIGHT (f, x_height); - /* Tell the server what size and position, etc, we want, and how badly we want them. This should be done after we have the menu bar so that its size can be taken into account. */ @@ -6093,8 +6078,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, w32_wm_set_size_hint (f, window_prompting, false); unblock_input (); - adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true, - Qx_create_frame_2); + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qx_create_frame_2); /* Process fullscreen parameter here in the hope that normalizing a fullheight/fullwidth frame will produce the size set by the last @@ -6888,11 +6873,9 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) struct frame *f; Lisp_Object frame; Lisp_Object name; - int width, height; ptrdiff_t count = SPECPDL_INDEX (); struct kboard *kb; bool face_change_before = face_change; - int x_width = 0, x_height = 0; /* Use this general default value to start with until we know if this frame has a specified name. */ @@ -7013,7 +6996,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.w32->explicit_parent = false; - gui_figure_window_size (f, parms, true, true, &x_width, &x_height); + gui_figure_window_size (f, parms, true, true); /* No fringes on tip frame. */ f->fringe_cols = 0; @@ -7039,15 +7022,6 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) gui_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); - /* Dimensions, especially FRAME_LINES (f), must be done via - change_frame_size. Change will not be effected unless different - from the current FRAME_LINES (f). */ - width = FRAME_COLS (f); - height = FRAME_LINES (f); - SET_FRAME_COLS (f, 0); - SET_FRAME_LINES (f, 0); - adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), - height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame); /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); @@ -7088,6 +7062,8 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) visible won't work. */ Vframe_list = Fcons (frame, Vframe_list); f->can_set_window_size = true; + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qtip_frame); /* Setting attributes of faces of the tooltip frame from resources and similar will set face_change, which leads to the diff --git a/src/w32inevt.c b/src/w32inevt.c index 1a80a001974..1255072b7f3 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -608,9 +608,7 @@ resize_event (WINDOW_BUFFER_SIZE_RECORD *event) { struct frame *f = get_frame (); - change_frame_size (f, event->dwSize.X, event->dwSize.Y - - FRAME_MENU_BAR_LINES (f) - - FRAME_TAB_BAR_LINES (f), 0, 1, 0, 0); + change_frame_size (f, event->dwSize.X, event->dwSize.Y, false, true, false); SET_FRAME_GARBAGED (f); } @@ -624,11 +622,9 @@ maybe_generate_resize_event (void) /* It is okay to call this unconditionally, since it will do nothing if the size hasn't actually changed. */ - change_frame_size (f, - 1 + info.srWindow.Right - info.srWindow.Left, - 1 + info.srWindow.Bottom - info.srWindow.Top - - FRAME_MENU_BAR_LINES (f) - - FRAME_TAB_BAR_LINES (f), 0, 1, 0, 0); + change_frame_size (f, 1 + info.srWindow.Right - info.srWindow.Left, + 1 + info.srWindow.Bottom - info.srWindow.Top, + false, true, false); } #if HAVE_W32NOTIFY diff --git a/src/w32term.c b/src/w32term.c index 361cf33c024..4f910296ecc 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5352,7 +5352,7 @@ w32_read_socket (struct terminal *terminal, if (f) { RECT rect; - int /* rows, columns, */ width, height, text_width, text_height; + int /* rows, columns, */ width, height; if (GetClientRect (msg.msg.hwnd, &rect) /* GetClientRect evidently returns (0, 0, 0, 0) if @@ -5365,23 +5365,11 @@ w32_read_socket (struct terminal *terminal, { height = rect.bottom - rect.top; width = rect.right - rect.left; - text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width); - text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height); - /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */ - /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */ - - /* TODO: Clip size to the screen dimensions. */ - - /* Even if the number of character rows and columns - has not changed, the font size may have changed, - so we need to check the pixel dimensions as well. */ - if (width != FRAME_PIXEL_WIDTH (f) - || height != FRAME_PIXEL_HEIGHT (f) - || text_width != FRAME_TEXT_WIDTH (f) - || text_height != FRAME_TEXT_HEIGHT (f)) + || height != FRAME_PIXEL_HEIGHT (f)) { - change_frame_size (f, text_width, text_height, 0, 1, 0, 1); + change_frame_size + (f, width, height, false, true, false); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); f->win_gravity = NorthWestGravity; @@ -5565,7 +5553,7 @@ w32_read_socket (struct terminal *terminal, if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED) { RECT rect; - int /* rows, columns, */ width, height, text_width, text_height; + int /* rows, columns, */ width, height; if (GetClientRect (msg.msg.hwnd, &rect) /* GetClientRect evidently returns (0, 0, 0, 0) if @@ -5578,23 +5566,12 @@ w32_read_socket (struct terminal *terminal, { height = rect.bottom - rect.top; width = rect.right - rect.left; - text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width); - text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height); - /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */ - /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */ - - /* TODO: Clip size to the screen dimensions. */ - - /* Even if the number of character rows and columns - has not changed, the font size may have changed, - so we need to check the pixel dimensions as well. */ if (width != FRAME_PIXEL_WIDTH (f) - || height != FRAME_PIXEL_HEIGHT (f) - || text_width != FRAME_TEXT_WIDTH (f) - || text_height != FRAME_TEXT_HEIGHT (f)) + || height != FRAME_PIXEL_HEIGHT (f)) { - change_frame_size (f, text_width, text_height, 0, 1, 0, 1); + change_frame_size + (f, width, height, false, true, false); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); f->win_gravity = NorthWestGravity; @@ -6267,17 +6244,15 @@ w32_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit; } - /* Now make the frame display the given font. */ - if (FRAME_NATIVE_WINDOW (f) != 0) - { - /* Don't change the size of a tip frame; there's no point in - doing it because it's done in Fx_show_tip, and it leads to - problems because the tip frame has no widget. */ - if (!FRAME_TOOLTIP_P (f)) - adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, - false, Qfont); - } + FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); + +/* Don't change the size of a tip frame; there's no point in + doing it because it's done in Fx_show_tip, and it leads to + problems because the tip frame has no widget. */ + if (FRAME_NATIVE_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f)) + adjust_frame_size + (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); /* X version sets font of input methods here also. */ @@ -6490,7 +6465,8 @@ w32fullscreen_hook (struct frame *f) ShowWindow (hwnd, SW_SHOWNORMAL); else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED) { - if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH + if (prev_fsmode == FULLSCREEN_BOTH + || prev_fsmode == FULLSCREEN_WIDTH || prev_fsmode == FULLSCREEN_HEIGHT) /* Make window normal since otherwise the subsequent maximization might fail in some cases. */ @@ -6499,52 +6475,31 @@ w32fullscreen_hook (struct frame *f) } else if (f->want_fullscreen == FULLSCREEN_BOTH) { - int menu_bar_height = GetSystemMetrics (SM_CYMENU); - - w32_fullscreen_rect (hwnd, f->want_fullscreen, - FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect); + w32_fullscreen_rect + (hwnd, f->want_fullscreen, + FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect); if (!FRAME_UNDECORATED (f)) SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOOWNERZORDER | SWP_FRAMECHANGED); change_frame_size - (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, rect.right - rect.left), - FRAME_PIXEL_TO_TEXT_HEIGHT (f, (rect.bottom - rect.top - - menu_bar_height)), - 0, 1, 0, 1); + (f, rect.right - rect.left, rect.bottom - rect.top, + false, true, false); } else { ShowWindow (hwnd, SW_SHOWNORMAL); - w32_fullscreen_rect (hwnd, f->want_fullscreen, - FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect); + w32_fullscreen_rect + (hwnd, f->want_fullscreen, + FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect); SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0); - if (f->want_fullscreen == FULLSCREEN_WIDTH) - { - int border_width = GetSystemMetrics (SM_CXFRAME); - - change_frame_size - (f, (FRAME_PIXEL_TO_TEXT_WIDTH - (f, rect.right - rect.left - 2 * border_width)), - 0, 0, 1, 0, 1); - } - else - { - int border_height = GetSystemMetrics (SM_CYFRAME); - /* Won't work for wrapped menu bar. */ - int menu_bar_height = GetSystemMetrics (SM_CYMENU); - int title_height = GetSystemMetrics (SM_CYCAPTION); - - change_frame_size - (f, 0, (FRAME_PIXEL_TO_TEXT_HEIGHT - (f, rect.bottom - rect.top - 2 * border_height - - title_height - menu_bar_height)), - 0, 1, 0, 1); - } - } + change_frame_size + (f, rect.right - rect.left, rect.bottom - rect.top, + false, true, false); + } f->want_fullscreen = FULLSCREEN_NONE; unblock_input (); @@ -6559,16 +6514,14 @@ w32fullscreen_hook (struct frame *f) f->want_fullscreen |= FULLSCREEN_WAIT; } -/* Call this to change the size of frame F's native window. - If CHANGE_GRAVITY, change to top-left-corner window gravity - for this size change and subsequent size changes. - Otherwise we leave the window gravity unchanged. */ - +/* Change the size of frame F's Windows window to WIDTH and HEIGHT + pixels. If CHANGE_GRAVITY, change to top-left-corner window gravity + for this size change and subsequent size changes. Otherwise leave + the window gravity unchanged. */ static void w32_set_window_size (struct frame *f, bool change_gravity, - int width, int height, bool pixelwise) + int width, int height) { - int pixelwidth, pixelheight; Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); RECT rect; MENUBARINFO info; @@ -6584,17 +6537,6 @@ w32_set_window_size (struct frame *f, bool change_gravity, GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info); menu_bar_height = info.rcBar.bottom - info.rcBar.top; - if (pixelwise) - { - pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); - } - else - { - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); - } - if (w32_add_wrapped_menu_bar_lines) { /* When the menu bar wraps sending a SetWindowPos shrinks the @@ -6610,15 +6552,15 @@ w32_set_window_size (struct frame *f, bool change_gravity, if ((default_menu_bar_height > 0) && (menu_bar_height > default_menu_bar_height) && ((menu_bar_height % default_menu_bar_height) == 0)) - pixelheight = pixelheight + menu_bar_height - default_menu_bar_height; + height = height + menu_bar_height - default_menu_bar_height; } f->win_gravity = NorthWestGravity; w32_wm_set_size_hint (f, (long) 0, false); rect.left = rect.top = 0; - rect.right = pixelwidth; - rect.bottom = pixelheight; + rect.right = width; + rect.bottom = height; AdjustWindowRect (&rect, f->output_data.w32->dwStyle, menu_bar_height > 0); @@ -6636,7 +6578,7 @@ w32_set_window_size (struct frame *f, bool change_gravity, { rect.left = window_rect.left; rect.right = window_rect.right; - pixelwidth = 0; + width = -1; } if (EQ (fullscreen, Qmaximized) || EQ (fullscreen, Qfullboth) @@ -6644,19 +6586,12 @@ w32_set_window_size (struct frame *f, bool change_gravity, { rect.top = window_rect.top; rect.bottom = window_rect.bottom; - pixelheight = 0; + height = -1; } } - if (pixelwidth > 0 || pixelheight > 0) + if (width > 0 || height > 0) { - frame_size_history_add - (f, Qx_set_window_size_1, width, height, - list2 (Fcons (make_fixnum (pixelwidth), - make_fixnum (pixelheight)), - Fcons (make_fixnum (rect.right - rect.left), - make_fixnum (rect.bottom - rect.top)))); - if (!FRAME_PARENT_FRAME (f)) my_set_window_pos (FRAME_W32_WINDOW (f), NULL, 0, 0, @@ -6670,12 +6605,7 @@ w32_set_window_size (struct frame *f, bool change_gravity, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOACTIVATE); - change_frame_size (f, - ((pixelwidth == 0) - ? 0 : FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth)), - ((pixelheight == 0) - ? 0 : FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)), - 0, 1, 0, 1); + change_frame_size (f, width, height, false, true, false); SET_FRAME_GARBAGED (f); /* If cursor was outside the new size, mark it as off. */ diff --git a/src/widget.c b/src/widget.c index 43f0307b4e0..dd43fd1c466 100644 --- a/src/widget.c +++ b/src/widget.c @@ -168,14 +168,6 @@ pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height); } -static void -pixel_to_text_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *text_width, int *text_height) -{ - struct frame *f = ew->emacs_frame.frame; - *text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, (int) pixel_width); - *text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, (int) pixel_height); -} - static void char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height) { @@ -257,27 +249,14 @@ set_frame_size (EmacsFrame ew) */ - /* Hairily merged geometry */ struct frame *f = ew->emacs_frame.frame; - int w = FRAME_COLS (f); - int h = FRAME_LINES (f); - Widget wmshell = get_wm_shell ((Widget) ew); - Dimension pixel_width, pixel_height; - /* Each Emacs shell is now independent and top-level. */ - - if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort (); - - char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height); - ew->core.width = (frame_resize_pixelwise - ? FRAME_PIXEL_WIDTH (f) - : pixel_width); - ew->core.height = (frame_resize_pixelwise - ? FRAME_PIXEL_HEIGHT (f) - : pixel_height); - - frame_size_history_add - (f, Qset_frame_size, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), - list2i (ew->core.width, ew->core.height)); + + ew->core.width = FRAME_PIXEL_WIDTH (f); + ew->core.height = FRAME_PIXEL_HEIGHT (f); + + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("set_frame_size")); } static void @@ -350,6 +329,13 @@ update_from_various_frame_slots (EmacsFrame ew) ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f); ew->emacs_frame.cursor_color = x->cursor_pixel; ew->core.border_pixel = x->border_pixel; + + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("update_from_various_frame_slots"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + ew->core.width, ew->core.height, + f->new_width, f->new_height); } static void @@ -381,6 +367,7 @@ static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs) { EmacsFrame ew = (EmacsFrame) widget; + struct frame *f = ew->emacs_frame.frame; /* This used to contain SubstructureRedirectMask, but this turns out to be a problem with XIM on Solaris, and events from that mask @@ -394,6 +381,11 @@ EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs /* Some ConfigureNotify events does not end up in EmacsFrameResize so make sure we get them all. Seen with xfcwm4 for example. */ XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL); + + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("EmacsFrameRealize")); + update_wm_hints (ew); } @@ -408,18 +400,15 @@ EmacsFrameResize (Widget widget) { EmacsFrame ew = (EmacsFrame) widget; struct frame *f = ew->emacs_frame.frame; - int width, height; - - pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height); - frame_size_history_add - (f, QEmacsFrameResize, width, height, - list5 (make_fixnum (ew->core.width), make_fixnum (ew->core.height), - make_fixnum (FRAME_TOP_MARGIN_HEIGHT (f)), - make_fixnum (FRAME_SCROLL_BAR_AREA_HEIGHT (f)), - make_fixnum (2 * FRAME_INTERNAL_BORDER_WIDTH (f)))); + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("EmacsFrameResize"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + ew->core.width, ew->core.height, + f->new_width, f->new_height); - change_frame_size (f, width, height, 0, 1, 0, 1); + change_frame_size (f, ew->core.width, ew->core.height, false, true, false); update_wm_hints (ew); update_various_frame_slots (ew); @@ -463,9 +452,17 @@ EmacsFrameSetCharSize (Widget widget, int columns, int rows) EmacsFrame ew = (EmacsFrame) widget; struct frame *f = ew->emacs_frame.frame; + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("EmacsFrameSetCharSize"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + columns, rows, + f->new_width, f->new_height); + if (!frame_inhibit_resize (f, 0, Qfont) && !frame_inhibit_resize (f, 1, Qfont)) - x_set_window_size (f, 0, columns, rows, 0); + x_set_window_size (f, 0, columns * FRAME_COLUMN_WIDTH (f), + rows * FRAME_LINE_HEIGHT (f)); } diff --git a/src/xdisp.c b/src/xdisp.c index 7a89089958f..23b4ba5c39c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -11860,7 +11860,7 @@ resize_mini_window (struct window *w, bool exact_p) int height, max_height; struct text_pos start; struct buffer *old_current_buffer = NULL; - int windows_height = FRAME_WINDOWS_HEIGHT (f); + int windows_height = FRAME_INNER_HEIGHT (f); if (current_buffer != XBUFFER (w->contents)) { @@ -13477,8 +13477,6 @@ PIXELWISE non-nil means return the height of the tab bar in pixels. */) static bool redisplay_tab_bar (struct frame *f) { - f->tab_bar_redisplayed = true; - struct window *w; struct it it; struct glyph_row *row; @@ -13492,6 +13490,8 @@ redisplay_tab_bar (struct frame *f) WINDOW_TOTAL_LINES (w) == 0)) return false; + f->tab_bar_redisplayed = true; + /* Set up an iterator for the tab-bar window. */ init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID); it.first_visible_x = 0; @@ -14402,21 +14402,13 @@ PIXELWISE non-nil means return the height of the tool bar in pixels. */) return make_fixnum (height); } +#ifndef HAVE_EXT_TOOL_BAR -/* Display the tool-bar of frame F. Value is true if tool-bar's - height should be changed. */ +/* Display the internal tool-bar of frame F. Value is true if + tool-bar's height should be changed. */ static bool redisplay_tool_bar (struct frame *f) { - f->tool_bar_redisplayed = true; -#ifdef HAVE_EXT_TOOL_BAR - - if (FRAME_EXTERNAL_TOOL_BAR (f)) - update_frame_tool_bar (f); - return false; - -#else /* ! (HAVE_EXT_TOOL_BAR) */ - struct window *w; struct it it; struct glyph_row *row; @@ -14430,6 +14422,8 @@ redisplay_tool_bar (struct frame *f) WINDOW_TOTAL_LINES (w) == 0)) return false; + f->tool_bar_redisplayed = true; + /* Set up an iterator for the tool-bar window. */ init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID); it.first_visible_x = 0; @@ -14565,13 +14559,10 @@ redisplay_tool_bar (struct frame *f) } f->minimize_tool_bar_window_p = false; - return false; -#endif /* HAVE_EXT_TOOL_BAR */ + return false; } -#ifndef HAVE_EXT_TOOL_BAR - /* Get information about the tool-bar item which is displayed in GLYPH on frame F. Return in *PROP_IDX the index where tool-bar item properties start in F->tool_bar_items. Value is false if @@ -19334,7 +19325,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) #ifdef HAVE_EXT_TOOL_BAR if (FRAME_EXTERNAL_TOOL_BAR (f)) - redisplay_tool_bar (f); + update_frame_tool_bar (f); #else if (WINDOWP (f->tool_bar_window) && (FRAME_TOOL_BAR_LINES (f) > 0 diff --git a/src/xfns.c b/src/xfns.c index f120653ee7b..2c95065d3ea 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1563,7 +1563,6 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) #else /* not USE_X_TOOLKIT && not USE_GTK */ FRAME_MENU_BAR_LINES (f) = nlines; FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines); if (FRAME_X_WINDOW (f)) x_clear_under_internal_border (f); @@ -1577,6 +1576,8 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) int width = FRAME_PIXEL_WIDTH (f); int y; + adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines); + /* height can be zero here. */ if (FRAME_X_WINDOW (f) && height > 0 && width > 0) { @@ -1637,7 +1638,7 @@ x_change_tab_bar_height (struct frame *f, int height) int unit = FRAME_LINE_HEIGHT (f); int old_height = FRAME_TAB_BAR_HEIGHT (f); int lines = (height + unit - 1) / unit; - Lisp_Object fullscreen; + Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); /* Make sure we redisplay all windows in this frame. */ fset_redisplay (f); @@ -1645,16 +1646,8 @@ x_change_tab_bar_height (struct frame *f, int height) /* Recalculate tab bar and frame text sizes. */ FRAME_TAB_BAR_HEIGHT (f) = height; FRAME_TAB_BAR_LINES (f) = lines; - /* Store the `tab-bar-lines' and `height' frame parameters. */ store_frame_param (f, Qtab_bar_lines, make_fixnum (lines)); - store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f))); - - /* We also have to make sure that the internal border at the top of - the frame, below the menu bar or tab bar, is redrawn when the - tab bar disappears. This is so because the internal border is - below the tab bar if one is displayed, but is below the menu bar - if there isn't a tab bar. The tab bar draws into the area - below the menu bar. */ + if (FRAME_X_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0) { clear_frame (f); @@ -1664,25 +1657,21 @@ x_change_tab_bar_height (struct frame *f, int height) if ((height < old_height) && WINDOWP (f->tab_bar_window)) clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix); - /* Recalculate tabbar height. */ - f->n_tab_bar_rows = 0; - if (old_height == 0 - && (!f->after_make_frame - || NILP (frame_inhibit_implied_resize) - || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize))))) - f->tab_bar_redisplayed = f->tab_bar_resized = false; - - adjust_frame_size (f, -1, -1, - ((!f->tab_bar_resized - && (NILP (fullscreen = - get_frame_param (f, Qfullscreen)) - || EQ (fullscreen, Qfullwidth))) ? 1 - : (old_height == 0 || height == 0) ? 2 - : 4), - false, Qtab_bar_lines); - - f->tab_bar_resized = f->tab_bar_redisplayed; + if (!f->tab_bar_resized) + { + /* As long as tab_bar_resized is false, effectively try to change + F's native height. */ + if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth)) + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 1, false, Qtab_bar_lines); + else + adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines); + + f->tab_bar_resized = f->tab_bar_redisplayed; + } + else + /* Any other change may leave the native size of F alone. */ + adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines); /* adjust_frame_size might not have done anything, garbage frame here. */ @@ -1743,24 +1732,15 @@ x_change_tool_bar_height (struct frame *f, int height) int unit = FRAME_LINE_HEIGHT (f); int old_height = FRAME_TOOL_BAR_HEIGHT (f); int lines = (height + unit - 1) / unit; - Lisp_Object fullscreen; + Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); /* Make sure we redisplay all windows in this frame. */ fset_redisplay (f); - /* Recalculate tool bar and frame text sizes. */ FRAME_TOOL_BAR_HEIGHT (f) = height; FRAME_TOOL_BAR_LINES (f) = lines; - /* Store the `tool-bar-lines' and `height' frame parameters. */ store_frame_param (f, Qtool_bar_lines, make_fixnum (lines)); - store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f))); - - /* We also have to make sure that the internal border at the top of - the frame, below the menu bar or tool bar, is redrawn when the - tool bar disappears. This is so because the internal border is - below the tool bar if one is displayed, but is below the menu bar - if there isn't a tool bar. The tool bar draws into the area - below the menu bar. */ + if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0) { clear_frame (f); @@ -1770,25 +1750,21 @@ x_change_tool_bar_height (struct frame *f, int height) if ((height < old_height) && WINDOWP (f->tool_bar_window)) clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); - /* Recalculate toolbar height. */ - f->n_tool_bar_rows = 0; - if (old_height == 0 - && (!f->after_make_frame - || NILP (frame_inhibit_implied_resize) - || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize))))) - f->tool_bar_redisplayed = f->tool_bar_resized = false; - - adjust_frame_size (f, -1, -1, - ((!f->tool_bar_resized - && (NILP (fullscreen = - get_frame_param (f, Qfullscreen)) - || EQ (fullscreen, Qfullwidth))) ? 1 - : (old_height == 0 || height == 0) ? 2 - : 4), - false, Qtool_bar_lines); - - f->tool_bar_resized = f->tool_bar_redisplayed; + if (!f->tool_bar_resized) + { + /* As long as tool_bar_resized is false, effectively try to change + F's native height. */ + if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth)) + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 1, false, Qtool_bar_lines); + else + adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines); + + f->tool_bar_resized = f->tool_bar_redisplayed; + } + else + /* Any other change may leave the native size of F alone. */ + adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines); /* adjust_frame_size might not have done anything, garbage frame here. */ @@ -3687,7 +3663,6 @@ This function is an internal primitive--use `make-frame' instead. */) struct x_display_info *dpyinfo = NULL; Lisp_Object parent, parent_frame; struct kboard *kb; - int x_width = 0, x_height = 0; parms = Fcopy_alist (parms); @@ -3999,18 +3974,6 @@ This function is an internal primitive--use `make-frame' instead. */) init_iterator with a null face cache, which should not happen. */ init_frame_faces (f); - /* We have to call adjust_frame_size here since otherwise - x_set_tool_bar_lines will already work with the character sizes - installed by init_frame_faces while the frame's pixel size is still - calculated from a character size of 1 and we subsequently hit the - (height >= 0) assertion in window_box_height. - - The non-pixelwise code apparently worked around this because it - had one frame line vs one toolbar line which left us with a zero - root window height which was obviously wrong as well ... - - Also process `min-width' and `min-height' parameters right here - because `frame-windows-min-size' needs them. */ tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER); if (FIXNUMP (tem)) @@ -4019,6 +3982,7 @@ This function is an internal primitive--use `make-frame' instead. */) RES_TYPE_NUMBER); if (FIXNUMP (tem)) store_frame_param (f, Qmin_height, tem); + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, Qx_create_frame_1); @@ -4055,8 +4019,7 @@ This function is an internal primitive--use `make-frame' instead. */) RES_TYPE_BOOLEAN); /* Compute the size of the X window. */ - window_prompting = gui_figure_window_size (f, parms, true, true, - &x_width, &x_height); + window_prompting = gui_figure_window_size (f, parms, true, true); tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); @@ -4140,11 +4103,6 @@ This function is an internal primitive--use `make-frame' instead. */) /* Consider frame official, now. */ f->can_set_window_size = true; - if (x_width > 0) - SET_FRAME_WIDTH (f, x_width); - if (x_height > 0) - SET_FRAME_HEIGHT (f, x_height); - /* Tell the server what size and position, etc, we want, and how badly we want them. This should be done after we have the menu bar so that its size can be taken into account. */ @@ -6291,10 +6249,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) struct frame *f; Lisp_Object frame; Lisp_Object name; - int width, height; ptrdiff_t count = SPECPDL_INDEX (); bool face_change_before = face_change; - int x_width = 0, x_height = 0; if (!dpyinfo->terminal->name) error ("Terminal is not live, can't create new frames on it"); @@ -6418,7 +6374,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), "borderWidth", "BorderWidth", RES_TYPE_NUMBER); - /* This defaults to 2 in order to match xterm. We recognize either + /* This defaults to 1 in order to match xterm. We recognize either internalBorderWidth or internalBorder (which is what xterm calls it). */ if (NILP (Fassq (Qinternal_border_width, parms))) @@ -6466,7 +6422,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) "inhibitDoubleBuffering", "InhibitDoubleBuffering", RES_TYPE_BOOLEAN); - gui_figure_window_size (f, parms, false, false, &x_width, &x_height); + gui_figure_window_size (f, parms, false, false); { XSetWindowAttributes attrs; @@ -6518,15 +6474,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) gui_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); - /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. - Change will not be effected unless different from the current - FRAME_LINES (f). */ - width = FRAME_COLS (f); - height = FRAME_LINES (f); - SET_FRAME_COLS (f, 0); - SET_FRAME_LINES (f, 0); - change_frame_size (f, width, height, true, false, false, false); - /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) { @@ -6588,6 +6535,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) visible won't work. */ Vframe_list = Fcons (frame, Vframe_list); f->can_set_window_size = true; + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qtip_frame); /* Setting attributes of faces of the tooltip frame from resources and similar will set face_change, which leads to the clearing of diff --git a/src/xmenu.c b/src/xmenu.c index a83fffbf1ce..a6762236bc4 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -641,7 +641,7 @@ update_frame_menubar (struct frame *f) lw_refigure_widget (x->column_widget, True); /* Force the pane widget to resize itself. */ - adjust_frame_size (f, -1, -1, 2, false, Qupdate_frame_menubar); + adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines); unblock_input (); #endif /* USE_GTK */ } @@ -1044,6 +1044,7 @@ free_frame_menubar (struct frame *f) /* Motif automatically shrinks the frame in lw_destroy_all_widgets. If we want to preserve the old height, calculate it now so we can restore it below. */ + int old_width = FRAME_TEXT_WIDTH (f); int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); #endif @@ -1077,26 +1078,43 @@ free_frame_menubar (struct frame *f) lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id); f->output_data.x->menubar_widget = NULL; + /* When double-buffering is enabled and the frame shall not be + resized either because resizing is inhibited or the frame is + fullheight, some (usually harmless) display artifacts like a + doubled mode line may show up. Sometimes the configuration + gets messed up in a more serious fashion though and you may + have to resize the frame to get it back in a normal state. */ if (f->output_data.x->widget) { #ifdef USE_MOTIF XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL); if (x1 == 0 && y1 == 0) XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL); - if (frame_inhibit_resize (f, false, Qmenu_bar_lines)) - adjust_frame_size (f, -1, old_height, 1, false, Qfree_frame_menubar_1); + /* When resizing is inhibited and a normal Motif frame is not + fullheight, we have to explicitly request its old sizes + here since otherwise turning off the menu bar will shrink + the frame but turning them on again will not resize it + back. For a fullheight frame we let the window manager + deal with this problem. */ + if (frame_inhibit_resize (f, false, Qmenu_bar_lines) + && !EQ (get_frame_param (f, Qfullscreen), Qfullheight)) + adjust_frame_size (f, old_width, old_height, 1, false, + Qmenu_bar_lines); else - adjust_frame_size (f, -1, -1, 2, false, Qfree_frame_menubar_1); + adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines); #else - adjust_frame_size (f, -1, -1, 2, false, Qfree_frame_menubar_1); + adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines); #endif /* USE_MOTIF */ } else { #ifdef USE_MOTIF if (WINDOWP (FRAME_ROOT_WINDOW (f)) - && frame_inhibit_resize (f, false, Qmenu_bar_lines)) - adjust_frame_size (f, -1, old_height, 1, false, Qfree_frame_menubar_2); + /* See comment above. */ + && frame_inhibit_resize (f, false, Qmenu_bar_lines) + && !EQ (get_frame_param (f, Qfullscreen), Qfullheight)) + adjust_frame_size (f, old_width, old_height, 1, false, + Qmenu_bar_lines); #endif } diff --git a/src/xterm.c b/src/xterm.c index 11de287aecc..5049f72ca63 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7833,10 +7833,6 @@ x_net_wm_state (struct frame *f, Window window) break; } - frame_size_history_add - (f, Qx_net_wm_state, 0, 0, - list2 (get_frame_param (f, Qfullscreen), lval)); - store_frame_param (f, Qfullscreen, lval); /** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ } @@ -8167,19 +8163,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state) { bool not_hidden = x_handle_net_wm_state (f, &event->xproperty); + if (not_hidden && FRAME_ICONIFIED_P (f)) { + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("PropertyNotify, not hidden & iconified")); + /* Gnome shell does not iconify us when C-z is pressed. It hides the frame. So if our state says we aren't hidden anymore, treat it as deiconified. */ SET_FRAME_VISIBLE (f, 1); SET_FRAME_ICONIFIED (f, false); + f->output_data.x->has_been_visible = true; inev.ie.kind = DEICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } - else if (! not_hidden && ! FRAME_ICONIFIED_P (f)) + else if (!not_hidden && !FRAME_ICONIFIED_P (f)) { + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("PropertyNotify, hidden & not iconified")); + SET_FRAME_VISIBLE (f, 0); SET_FRAME_ICONIFIED (f, true); inev.ie.kind = ICONIFY_EVENT; @@ -8357,10 +8363,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, and that way, we know the window is not iconified now. */ if (visible || FRAME_ICONIFIED_P (f)) { + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("UnmapNotify, visible | iconified")); + SET_FRAME_ICONIFIED (f, true); - inev.ie.kind = ICONIFY_EVENT; + inev.ie.kind = ICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } + else if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("UnmapNotify, not visible & not iconified")); } goto OTHER; @@ -8372,8 +8385,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f) { bool iconified = FRAME_ICONIFIED_P (f); - - /* Check if fullscreen was specified before we where mapped the + int value; + bool sticky; + bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky); + + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, + iconified + ? (not_hidden + ? build_string ("MapNotify, not hidden & iconified") + : build_string ("MapNotify, hidden & iconified")) + : (not_hidden + ? build_string ("MapNotify, not hidden & not iconified") + : build_string ("MapNotify, hidden & not iconified")), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + -1, -1, f->new_width, f->new_height); + + /* Check if fullscreen was specified before we where mapped the first time, i.e. from the command line. */ if (!f->output_data.x->has_been_visible) { @@ -8974,7 +9003,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, || !(configureEvent.xconfigure.width <= 1 && configureEvent.xconfigure.height <= 1))) { - block_input (); + + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("ConfigureNotify"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + configureEvent.xconfigure.width, + configureEvent.xconfigure.height, + f->new_width, f->new_height); + + block_input (); if (FRAME_X_DOUBLE_BUFFERED_P (f)) font_drop_xrender_surfaces (f); unblock_input (); @@ -9015,24 +9053,28 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifndef USE_X_TOOLKIT #ifndef USE_GTK - int width = - FRAME_PIXEL_TO_TEXT_WIDTH (f, configureEvent.xconfigure.width); - int height = - FRAME_PIXEL_TO_TEXT_HEIGHT (f, configureEvent.xconfigure.height); + int width = configureEvent.xconfigure.width; + int height = configureEvent.xconfigure.height; + + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("ConfigureNotify"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), + width, height, f->new_width, f->new_height); - /* In the toolkit version, change_frame_size + /* In the toolkit version, change_frame_size is called by the code that handles resizing of the EmacsFrame widget. */ /* Even if the number of character rows and columns has not changed, the font size may have changed, so we need to check the pixel dimensions as well. */ - if (width != FRAME_TEXT_WIDTH (f) - || height != FRAME_TEXT_HEIGHT (f) - || configureEvent.xconfigure.width != FRAME_PIXEL_WIDTH (f) - || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f)) + if (width != FRAME_PIXEL_WIDTH (f) + || height != FRAME_PIXEL_HEIGHT (f) + || (delayed_size_change + && (width != f->new_width || height != f->new_height))) { - change_frame_size (f, width, height, false, true, false, true); + change_frame_size (f, width, height, false, true, false); x_clear_under_internal_border (f); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); @@ -10217,11 +10259,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) { struct font *font = XFONT_OBJECT (font_object); int unit, font_ascent, font_descent; -#ifndef USE_X_TOOLKIT - int old_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f); - int old_tab_bar_height = FRAME_TAB_BAR_HEIGHT (f); - Lisp_Object fullscreen; -#endif if (fontset < 0) fontset = fontset_from_font (font_object); @@ -10239,8 +10276,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) #ifndef USE_X_TOOLKIT FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); - FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); #endif + /* We could use a more elaborate calculation here. */ + FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); /* Compute character columns occupied by scrollbar. @@ -10253,34 +10291,14 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) else FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit; - if (FRAME_X_WINDOW (f) != 0) - { - /* Don't change the size of a tip frame; there's no point in - doing it because it's done in Fx_show_tip, and it leads to - problems because the tip frame has no widget. */ - if (!FRAME_TOOLTIP_P (f)) - { - adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, - false, Qfont); -#ifndef USE_X_TOOLKIT - if ((FRAME_MENU_BAR_HEIGHT (f) != old_menu_bar_height - || FRAME_TAB_BAR_HEIGHT (f) != old_tab_bar_height) - && !f->after_make_frame - && (EQ (frame_inhibit_implied_resize, Qt) - || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qfont, frame_inhibit_implied_resize)))) - && (NILP (fullscreen = get_frame_param (f, Qfullscreen)) - || EQ (fullscreen, Qfullwidth))) - /* If the menu/tab bar height changes, try to keep text height - constant. */ - adjust_frame_size - (f, -1, FRAME_TEXT_HEIGHT (f) + FRAME_MENU_BAR_HEIGHT (f) - + FRAME_TAB_BAR_HEIGHT (f) - - old_menu_bar_height - old_tab_bar_height, 1, false, Qfont); -#endif /* USE_X_TOOLKIT */ - } - } + + /* Don't change the size of a tip frame; there's no point in doing it + because it's done in Fx_show_tip, and it leads to problems because + the tip frame has no widget. */ + if (FRAME_X_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f)) + adjust_frame_size + (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); #ifdef HAVE_X_I18N if (FRAME_XIC (f) @@ -11164,10 +11182,6 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event) break; } - frame_size_history_add - (f, Qx_handle_net_wm_state, 0, 0, - list2 (get_frame_param (f, Qfullscreen), lval)); - store_frame_param (f, Qfullscreen, lval); store_frame_param (f, Qsticky, sticky ? Qt : Qnil); @@ -11222,9 +11236,6 @@ x_check_fullscreen (struct frame *f) emacs_abort (); } - frame_size_history_add - (f, Qx_check_fullscreen, width, height, Qnil); - x_wm_set_size_hint (f, 0, false); XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), @@ -11234,8 +11245,7 @@ x_check_fullscreen (struct frame *f) x_wait_for_event (f, ConfigureNotify); else { - change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f), - false, true, false, true); + change_frame_size (f, width, height, false, true, false); x_sync (f); } } @@ -11389,57 +11399,12 @@ static void x_set_window_size_1 (struct frame *f, bool change_gravity, int width, int height) { - int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); - int old_width = FRAME_PIXEL_WIDTH (f); - int old_height = FRAME_PIXEL_HEIGHT (f); - Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); - if (change_gravity) f->win_gravity = NorthWestGravity; x_wm_set_size_hint (f, 0, false); - /* When the frame is fullheight and we only want to change the width - or it is fullwidth and we only want to change the height we should - be able to preserve the fullscreen property. However, due to the - fact that we have to send a resize request anyway, the window - manager will abolish it. At least the respective size should - remain unchanged but giving the frame back its normal size will - be broken ... */ - if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f)) - { - frame_size_history_add - (f, Qx_set_window_size_1, width, height, - list2i (old_height, pixelheight + FRAME_MENUBAR_HEIGHT (f))); - - XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f)); - } - else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f)) - { - frame_size_history_add - (f, Qx_set_window_size_2, width, height, - list2i (old_width, pixelwidth)); - - XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - pixelwidth, old_height); - } - - else - { - frame_size_history_add - (f, Qx_set_window_size_3, width, height, - list3i (pixelwidth + FRAME_TOOLBAR_WIDTH (f), - (pixelheight + FRAME_TOOLBAR_HEIGHT (f) - + FRAME_MENUBAR_HEIGHT (f)), - FRAME_MENUBAR_HEIGHT (f))); - - XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f)); - fullscreen = Qnil; - } - - + XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + width, height + FRAME_MENUBAR_HEIGHT (f)); /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to receive in the ConfigureNotify event; if we get what we asked @@ -11468,66 +11433,42 @@ x_set_window_size_1 (struct frame *f, bool change_gravity, { x_wait_for_event (f, ConfigureNotify); - if (!NILP (fullscreen)) - /* Try to restore fullscreen state. */ - { - store_frame_param (f, Qfullscreen, fullscreen); - gui_set_fullscreen (f, fullscreen, fullscreen); - } + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("x_set_window_size_1, visible"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + f->new_width, f->new_height); } else { - change_frame_size (f, width, height, false, true, false, true); + if (CONSP (frame_size_history)) + frame_size_history_extra + (f, build_string ("x_set_window_size_1, invisible"), + FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, + f->new_width, f->new_height); + + /* Call adjust_frame_size right away as with GTK. It might be + tempting to clear out f->new_width and f->new_height here. */ + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), + 5, 0, Qx_set_window_size_1); + x_sync (f); } } -/* Call this to change the size of frame F's x-window. - If CHANGE_GRAVITY, change to top-left-corner window gravity - for this size change and subsequent size changes. - Otherwise we leave the window gravity unchanged. */ +/* Change the size of frame F's X window to WIDTH and HEIGHT pixels. If + CHANGE_GRAVITY, change to top-left-corner window gravity for this + size change and subsequent size changes. Otherwise we leave the + window gravity unchanged. */ void x_set_window_size (struct frame *f, bool change_gravity, - int width, int height, bool pixelwise) + int width, int height) { block_input (); - /* The following breaks our calculations. If it's really needed, - think of something else. */ -#if false - if (!FRAME_TOOLTIP_P (f)) - { - int text_width, text_height; - - /* When the frame is maximized/fullscreen or running under for - example Xmonad, x_set_window_size_1 will be a no-op. - In that case, the right thing to do is extend rows/width to - the current frame size. We do that first if x_set_window_size_1 - turns out to not be a no-op (there is no way to know). - The size will be adjusted again if the frame gets a - ConfigureNotify event as a result of x_set_window_size. */ - int pixelh = FRAME_PIXEL_HEIGHT (f); -#ifdef USE_X_TOOLKIT - /* The menu bar is not part of text lines. The tool bar - is however. */ - pixelh -= FRAME_MENUBAR_HEIGHT (f); -#endif - text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f)); - text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh); - - change_frame_size (f, text_width, text_height, false, true, false, true); - } -#endif - - /* Pixelize width and height, if necessary. */ - if (! pixelwise) - { - width = width * FRAME_COLUMN_WIDTH (f); - height = height * FRAME_LINE_HEIGHT (f); - } - #ifdef USE_GTK if (FRAME_GTK_WIDGET (f)) xg_frame_set_char_size (f, width, height); @@ -11880,6 +11821,11 @@ x_make_frame_visible (struct frame *f) poll_for_input_1 (); poll_suppress_count = old_poll_suppress_count; #endif + + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("x_make_frame_visible")); + if (! FRAME_VISIBLE_P (f)) x_wait_for_event (f, MapNotify); } @@ -11937,6 +11883,10 @@ x_make_frame_invisible (struct frame *f) SET_FRAME_VISIBLE (f, 0); SET_FRAME_ICONIFIED (f, false); + if (CONSP (frame_size_history)) + frame_size_history_plain + (f, build_string ("x_make_frame_invisible")); + unblock_input (); } diff --git a/src/xterm.h b/src/xterm.h index ebc42b7dd55..de6ea50385d 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1079,7 +1079,7 @@ extern bool x_had_errors_p (Display *); extern void x_uncatch_errors (void); extern void x_uncatch_errors_after_check (void); extern void x_clear_errors (Display *); -extern void x_set_window_size (struct frame *f, bool, int, int, bool); +extern void x_set_window_size (struct frame *f, bool, int, int); extern void x_make_frame_visible (struct frame *f); extern void x_make_frame_invisible (struct frame *f); extern void x_iconify_frame (struct frame *f); -- cgit v1.2.3 From 8a4081c396a47aa7593a6c25b1bad8a2b8b157b7 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sun, 2 May 2021 10:33:22 +0200 Subject: Make adjust_frame_size set up frame's new_width/_height too (Bug#17120) The purpose of this change is to have implied frame size changes pick up sizes requested by previous explicit size changes not only after they have been confirmed by the WM but already when they are initially passed to adjust_frame_size (Bug#17120). * src/dispextern.h (delayed_size_change): Remove extern. * src/dispnew.c (delayed_size_change): Make static again. (do_pending_window_change): Call change_frame_size only if F's new_size_p flag is set. (change_frame_size_1): Set/reset F's new_size_p flag * src/frame.c (adjust_frame_size): Remove extra inhibit_horizontal/_vertical checks. Improve the implied resizes check with INHIBIT equals 2. Set F's new_width and new_height and reset F's new_size_p flag when we run set_window_size_hook with INHIBIT 0 or 1. * src/frame.h (struct frame): New bit slot new_size_p. * src/gtkutil.c (xg_frame_resized): Use F's new_size_p flag instead of delayed_size_change to decide whether to call change_frame_size. (xg_frame_set_char_size): Call frame_size_history_extra before waiting for the ConfigureNotify event. * src/xterm.c (handle_one_xevent): Use F's new_size_p flag instead of delayed_size_change to decide whether to call change_frame_size. --- src/dispextern.h | 2 -- src/dispnew.c | 15 ++++++++++----- src/frame.c | 22 ++++++++++++++++------ src/frame.h | 5 +++++ src/gtkutil.c | 26 ++++++++++++++------------ src/xterm.c | 5 +++-- 6 files changed, 48 insertions(+), 27 deletions(-) (limited to 'src/frame.c') diff --git a/src/dispextern.h b/src/dispextern.h index 213032d4de8..33fcaa4c078 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1262,8 +1262,6 @@ extern struct glyph space_glyph; /* True means last display completed. False means it was preempted. */ extern bool display_completed; -extern bool delayed_size_change; - /************************************************************************ Glyph Strings diff --git a/src/dispnew.c b/src/dispnew.c index b3f7be67e0f..1378c34e984 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -102,7 +102,7 @@ bool display_completed; /* True means SIGWINCH happened when not safe. */ -bool delayed_size_change; +static bool delayed_size_change; /* A glyph for a space. */ @@ -5815,7 +5815,6 @@ deliver_window_change_signal (int sig) void do_pending_window_change (bool safe) { - /* If window change signal handler should have run before, run it now. */ if (redisplaying_p && !safe) return; @@ -5830,8 +5829,11 @@ do_pending_window_change (bool safe) struct frame *f = XFRAME (frame); /* Negative new_width or new_height values mean no change is - required (a native size can never drop below zero). */ - if (f->new_height >= 0 || f->new_width >= 0) + required (a native size can never drop below zero). If + new_size_p is not set, this means the size change was + requested by adjust_frame_size but has not been honored by + the window manager yet. */ + if (f->new_size_p && (f->new_height >= 0 || f->new_width >= 0)) change_frame_size (f, f->new_width, f->new_height, false, false, safe); } @@ -5858,14 +5860,17 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height, /* We can't deal with the change now, queue it for later. */ f->new_width = new_width; f->new_height = new_height; + f->new_size_p = true; delayed_size_change = true; } else { /* Storing -1 in the new_width/new_height slots means that no size - change is pending. Native sizes are always non-negative. */ + change is pending. Native sizes are always non-negative. + Reset the new_size_p slot as well. */ f->new_height = -1; f->new_width = -1; + f->new_size_p = false; /* adjust_frame_size wants its arguments in terms of text_width and text_height, so convert them here. For pathologically small frames, the resulting values may be negative though. */ diff --git a/src/frame.c b/src/frame.c index 4129a70aa5f..32110512e95 100644 --- a/src/frame.c +++ b/src/frame.c @@ -619,12 +619,8 @@ frame_size_history_extra (struct frame *f, Lisp_Object parameter, * must be preserved. The code for setting up window dividers and * that responsible for wrapping the (internal) tool bar use this. * - * 5 means to never call set_window_size_hook. change_frame_size uses - * this. - * - * Note that even when set_window_size_hook is not called, individual - * windows may have to be resized (via `window--sanitize-window-sizes') - * in order to support minimum size constraints. + * 5 means to never call set_window_size_hook. Usually this means to + * call resize_frame_windows. change_frame_size uses this. * * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the * symbol of the parameter changed (like `menu-bar-lines', `font', ...). @@ -716,6 +712,9 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, if (FRAME_WINDOW_P (f) && f->can_set_window_size + /* For inhibit == 1 call the window_size_hook only if a native + size changes. For inhibit == 0 or inhibit == 2 always call + it. */ && ((!inhibit_horizontal && (new_native_width != old_native_width || inhibit == 0 || inhibit == 2)) @@ -761,6 +760,17 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, min_inner_width, min_inner_height, inhibit_horizontal, inhibit_vertical); + if (inhibit == 0 || inhibit == 1) + { + f->new_width = new_native_width; + f->new_height = new_native_height; + /* Resetting f->new_size_p is controversial: It might cause + do_pending_window_change drop a previous request and we are + in troubles when the window manager does not honor the + request we issue here. */ + f->new_size_p = false; + } + if (FRAME_TERMINAL (f)->set_window_size_hook) FRAME_TERMINAL (f)->set_window_size_hook (f, 0, new_native_width, new_native_height); diff --git a/src/frame.h b/src/frame.h index 19ee6ac10e7..744b95e1e04 100644 --- a/src/frame.h +++ b/src/frame.h @@ -453,6 +453,11 @@ struct frame frame is in the process of being redisplayed. */ bool_bf inhibit_clear_image_cache : 1; + /* True when new_width or new_height were set by change_frame_size, + false when they were set by adjust_frame_size internally or not + set. */ + bool_bf new_size_p; + /* Bitfield area ends here. */ /* This frame's change stamp, set the last time window change diff --git a/src/gtkutil.c b/src/gtkutil.c index 4ad172bb486..ba506faf356 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -916,16 +916,18 @@ void xg_frame_resized (struct frame *f, int width, int height) { /* Ignore case where size of native rectangle didn't change. */ - if (width != FRAME_PIXEL_WIDTH (f) || height != FRAME_PIXEL_HEIGHT (f) - || (delayed_size_change - && (width != f->new_width || height != f->new_height))) + if (width != FRAME_PIXEL_WIDTH (f) + || height != FRAME_PIXEL_HEIGHT (f) + || (f->new_size_p + && ((f->new_width >= 0 && width != f->new_width) + || (f->new_height >= 0 && height != f->new_height)))) { if (CONSP (frame_size_history)) frame_size_history_extra (f, build_string ("xg_frame_resized, changed"), FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, - delayed_size_change ? f->new_width : -1, - delayed_size_change ? f->new_height : -1); + f->new_size_p ? f->new_width : -1, + f->new_size_p ? f->new_height : -1); FRAME_RIF (f)->clear_under_internal_border (f); change_frame_size (f, width, height, false, true, false); @@ -936,8 +938,8 @@ xg_frame_resized (struct frame *f, int width, int height) frame_size_history_extra (f, build_string ("xg_frame_resized, unchanged"), FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, - delayed_size_change ? f->new_width : -1, - delayed_size_change ? f->new_height : -1); + f->new_size_p ? f->new_width : -1, + f->new_size_p ? f->new_height : -1); } @@ -1026,17 +1028,17 @@ xg_frame_set_char_size (struct frame *f, int width, int height) the frame is mapped again we will (hopefully) get the correct size. */ if (FRAME_VISIBLE_P (f) && !was_visible) { - /* Must call this to flush out events */ - (void)gtk_events_pending (); - gdk_flush (); - x_wait_for_event (f, ConfigureNotify); - if (CONSP (frame_size_history)) frame_size_history_extra (f, build_string ("xg_frame_set_char_size, visible"), FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height, f->new_width, f->new_height); + /* Must call this to flush out events */ + (void)gtk_events_pending (); + gdk_flush (); + x_wait_for_event (f, ConfigureNotify); + if (!NILP (fullscreen)) /* Try to restore fullscreen state. */ { diff --git a/src/xterm.c b/src/xterm.c index 5049f72ca63..189e3a47eea 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9071,8 +9071,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, to check the pixel dimensions as well. */ if (width != FRAME_PIXEL_WIDTH (f) || height != FRAME_PIXEL_HEIGHT (f) - || (delayed_size_change - && (width != f->new_width || height != f->new_height))) + || (f->new_size_p + && ((f->new_width >= 0 && width != f->new_width) + || (f->new_height >= 0 && height != f->new_height)))) { change_frame_size (f, width, height, false, true, false); x_clear_under_internal_border (f); -- cgit v1.2.3 From 30d974bf5c02a1367291fbb6fa17a182bb7974b7 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sun, 2 May 2021 17:44:01 +0200 Subject: Add two changes announced but not included in previous commit * src/frame.c (adjust_frame_size): Remove extra inhibit_horizontal/_vertical checks. Improve the implied resize check when INHIBIT equals 2. --- src/frame.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index 32110512e95..d884a6d8b96 100644 --- a/src/frame.c +++ b/src/frame.c @@ -722,29 +722,25 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, && (new_native_height != old_native_height || inhibit == 0 || inhibit == 2)))) { - /* Make sure we respect fullheight and fullwidth. */ - if (inhibit_horizontal) - new_native_width = old_native_width; - else if (inhibit_vertical) - new_native_height = old_native_height; - - if (inhibit == 2 && f->new_width > 0 && f->new_height > 0) + if (inhibit == 2 +#ifdef USE_MOTIF + && !EQ (parameter, Qmenu_bar_lines) +#endif + && (f->new_width >= 0 || f->new_height >= 0)) /* For implied resizes with inhibit 2 (external menu and tool bar) pick up any new sizes the display engine has not processed yet. Otherwsie, we would request the old sizes which will make this request appear as a request to set new - sizes and have the WM react accordingly which is not TRT. */ + sizes and have the WM react accordingly which is not TRT. + + We don't that for the external menu bar on Motif. + Otherwise, switching off the menu bar will shrink the frame + and switching it on will not enlarge it. */ { - /* But don't that for the external menu bar on Motif. - Otherwise, switching off the menu bar will shrink the frame - and switching it on will not enlarge it. */ -#ifdef USE_MOTIF - if (!EQ (parameter, Qmenu_bar_lines)) -#endif - { - new_native_width = f->new_width; - new_native_height = f->new_height; - } + if (f->new_width >= 0) + new_native_width = f->new_width; + if (f->new_height >= 0) + new_native_height = f->new_height; } if (CONSP (frame_size_history)) -- cgit v1.2.3 From e9baa733b8cac00e008cb834abc8712c8c00beed Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Wed, 5 May 2021 18:36:00 +0200 Subject: Fix setting of 'width' and 'height' frame parameters * src/frame.c (Fframe_parameters): Fix bogus setting of 'height' and 'width' parameters. --- src/frame.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index d884a6d8b96..738bfe9a5c8 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3295,12 +3295,15 @@ If FRAME is omitted or nil, return information on the currently selected frame. /* It's questionable whether here we should report the value of f->new_height (and f->new_width below) but we've done that in the past, so let's keep it. Note that a value of -1 for either of - these means that no new size was requested. */ - height = (f->new_height >= 0 + these means that no new size was requested. + + But check f->new_size before to make sure that f->new_height and + f->new_width are not ones requested by adjust_frame_size. */ + height = ((f->new_size_p && f->new_height >= 0) ? f->new_height / FRAME_LINE_HEIGHT (f) : FRAME_LINES (f)); store_in_alist (&alist, Qheight, make_fixnum (height)); - width = (f->new_width >= 0 + width = ((f->new_size_p && f->new_width >= 0) ? f->new_width / FRAME_COLUMN_WIDTH (f) : FRAME_COLS(f)); store_in_alist (&alist, Qwidth, make_fixnum (width)); -- cgit v1.2.3 From c873d16af61ae9b956c6dd6d9e50ebad2bb7666e Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 6 May 2021 10:48:14 +0000 Subject: Fix wrong handling of minibuffers when frames get iconified/made invisible This should fix bug #47766. * lisp/window.el (window-deletable-p): Add a quote where it was missing from minibuffer-follows-selected-frame. * src/frame.c (check_minibuf_window): Delete the function. (delete_frame): In place of calling check_minibuf_window, call move_minibuffers_onto_frame, possibly to move minibuffers onto the new current frame. (Fmake_frame_invisible, Ficonify_frame): Remove calls to check_minibuf_window. * src/minibuf.c (Factive_minibuffer_window): Search the frames for the active minibuffer rather than just assuming minibuf_window has been correctly updated. --- lisp/window.el | 2 +- src/frame.c | 62 +++++----------------------------------------------------- src/minibuf.c | 18 ++++++++++++++++- 3 files changed, 23 insertions(+), 59 deletions(-) (limited to 'src/frame.c') diff --git a/lisp/window.el b/lisp/window.el index cf5752113d5..bba4992ca24 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -4117,7 +4117,7 @@ frame can be safely deleted." (let ((minibuf (active-minibuffer-window))) (and minibuf (eq frame (window-frame minibuf)) (not (eq (default-toplevel-value - minibuffer-follows-selected-frame) + 'minibuffer-follows-selected-frame) t))))) 'frame)) ((window-minibuffer-p window) diff --git a/src/frame.c b/src/frame.c index 738bfe9a5c8..cb9d4f52109 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1929,52 +1929,6 @@ other_frames (struct frame *f, bool invisible, bool force) return false; } -/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer - window. Preferably use the selected frame's minibuffer window - instead. If the selected frame doesn't have one, get some other - frame's minibuffer window. SELECT non-zero means select the new - minibuffer window. */ -static void -check_minibuf_window (Lisp_Object frame, int select) -{ - struct frame *f = decode_live_frame (frame); - - XSETFRAME (frame, f); - - if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window)) - { - Lisp_Object frames, this, window = make_fixnum (0); - - if (!EQ (frame, selected_frame) - && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame))) - window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame)); - else - FOR_EACH_FRAME (frames, this) - { - if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this))) - { - window = FRAME_MINIBUF_WINDOW (XFRAME (this)); - break; - } - } - - /* Don't abort if no window was found (Bug#15247). */ - if (WINDOWP (window)) - { - /* Use set_window_buffer instead of Fset_window_buffer (see - discussion of bug#11984, bug#12025, bug#12026). */ - set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0); - minibuf_window = window; - - /* SELECT non-zero usually means that FRAME's minibuffer - window was selected; select the new one. */ - if (select) - Fselect_window (minibuf_window, Qnil); - } - } -} - - /** * delete_frame: * @@ -1989,7 +1943,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) struct frame *sf; struct kboard *kb; Lisp_Object frames, frame1; - int minibuffer_selected, is_tooltip_frame; + int is_tooltip_frame; bool nochild = !FRAME_PARENT_FRAME (f); Lisp_Object minibuffer_child_frame = Qnil; @@ -2097,7 +2051,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) /* At this point, we are committed to deleting the frame. There is no more chance for errors to prevent it. */ - minibuffer_selected = EQ (minibuf_window, selected_window); sf = SELECTED_FRAME (); /* Don't let the frame remain selected. */ if (f == sf) @@ -2155,9 +2108,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force) do_switch_frame (frame1, 0, 1, Qnil); sf = SELECTED_FRAME (); } - - /* Don't allow minibuf_window to remain on a deleted frame. */ - check_minibuf_window (frame, minibuffer_selected); + else + /* Ensure any minibuffers on FRAME are moved onto the selected + frame. */ + move_minibuffers_onto_frame (f, true); /* Don't let echo_area_window to remain on a deleted frame. */ if (EQ (f->minibuffer_window, echo_area_window)) @@ -2788,9 +2742,6 @@ displayed in the terminal. */) if (NILP (force) && !other_frames (f, true, false)) error ("Attempt to make invisible the sole visible or iconified frame"); - /* Don't allow minibuf_window to remain on an invisible frame. */ - check_minibuf_window (frame, EQ (minibuf_window, selected_window)); - if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->frame_visible_invisible_hook) FRAME_TERMINAL (f)->frame_visible_invisible_hook (f, false); @@ -2833,9 +2784,6 @@ for how to proceed. */) } #endif /* HAVE_WINDOW_SYSTEM */ - /* Don't allow minibuf_window to remain on an iconified frame. */ - check_minibuf_window (frame, EQ (minibuf_window, selected_window)); - if (FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->iconify_frame_hook) FRAME_TERMINAL (f)->iconify_frame_hook (f); diff --git a/src/minibuf.c b/src/minibuf.c index c4482d7f1ee..bc7d4393985 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -212,7 +212,23 @@ DEFUN ("active-minibuffer-window", Factive_minibuffer_window, doc: /* Return the currently active minibuffer window, or nil if none. */) (void) { - return minibuf_level ? minibuf_window : Qnil; + Lisp_Object frames, frame; + struct frame *f; + Lisp_Object innermost_MB; + + if (!minibuf_level) + return Qnil; + + innermost_MB = nth_minibuffer (minibuf_level); + FOR_EACH_FRAME (frames, frame) + { + f = XFRAME (frame); + if (FRAME_LIVE_P (f) + && WINDOW_LIVE_P (f->minibuffer_window) + && EQ (XWINDOW (f->minibuffer_window)->contents, innermost_MB)) + return f->minibuffer_window; + } + return minibuf_window; /* "Can't happen." */ } DEFUN ("set-minibuffer-window", Fset_minibuffer_window, -- cgit v1.2.3 From b41f39d22cdb921fe88311f4fd113cbb9c2f0c76 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Wed, 12 May 2021 09:44:02 +0200 Subject: Handle Bug#24526 without breaking Emacs on tiling WMs (Bug#48268) Since tiling window managers may react allergically to resize requests immediately following MapNotify events on X, make sure that such requests are issued only when a new frame should not become visible and a size has been explicitly requested for it. * lisp/faces.el (x-create-frame-with-faces): Mark frame as 'was-invisible' if it should be initially invisible or iconified and has its size specified explicitly. * src/frame.c (make_frame): Initialize new frame's was_invisible flag. (Fframe__set_was_invisible): New internal function. * src/frame.h (struct frame): Specify size of new_size_p slot. New flag was_invisible. * src/w32fns.c (Fx_create_frame) * src/nsfns.m (Fx_create_frame) * src/xfns.c (Fx_create_frame): Set new frame's was_invisible flag. * src/xterm.c (handle_one_xevent): Call xg_frame_set_char_size after a PropertyNotify or MapNotify event only if F's was_invisible flag was set. --- lisp/faces.el | 18 +++++++++++++++++- src/frame.c | 13 +++++++++++++ src/frame.h | 6 +++++- src/nsfns.m | 1 + src/w32fns.c | 2 ++ src/xfns.c | 20 +++++++++++++++++++- src/xterm.c | 16 ++++++++++++---- 7 files changed, 69 insertions(+), 7 deletions(-) (limited to 'src/frame.c') diff --git a/lisp/faces.el b/lisp/faces.el index 68bfbbae384..9969140f0ca 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -2118,7 +2118,23 @@ the X resource \"reverseVideo\" is present, handle that." (x-handle-reverse-video frame parameters) (frame-set-background-mode frame t) (face-set-after-frame-default frame parameters) - (if (null visibility-spec) + ;; Mark frame as 'was-invisible' when it was created as + ;; invisible or iconified and PARAMETERS contains either a + ;; width or height specification. This should be sufficient + ;; to handle Bug#24526 (where a frame is initially iconified + ;; to allow manipulating its size in a non-obtrusive way) and + ;; avoid that a tiling window manager for GTK3 gets a resize + ;; request it cannot handle (Bug#48268). The 'was-invisible' + ;; flag is eventually processed in xterm.c after we receive a + ;; MapNotify event; non-X builds ignore it. + (frame--set-was-invisible + frame + (and visibility-spec + (memq (cdr visibility-spec) '(nil icon)) + (or (assq 'width parameters) + (assq 'height parameters)))) + + (if (null visibility-spec) (make-frame-visible frame) (modify-frame-parameters frame (list visibility-spec))) (setq success t)) diff --git a/src/frame.c b/src/frame.c index cb9d4f52109..e3d65dd28f3 100644 --- a/src/frame.c +++ b/src/frame.c @@ -971,6 +971,7 @@ make_frame (bool mini_p) f->no_accept_focus = false; f->z_group = z_group_none; f->tooltip = false; + f->was_invisible = false; f->child_frame_border_width = -1; f->last_tab_bar_item = -1; #ifndef HAVE_EXT_TOOL_BAR @@ -5855,7 +5856,18 @@ selected frame. This is useful when `make-pointer-invisible' is set. */) return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt; } +DEFUN ("frame--set-was-invisible", Fframe__set_was_invisible, + Sframe__set_was_invisible, 2, 2, 0, + doc: /* Set FRAME's was-invisible flag if WAS-INVISIBLE is non-nil. +This function is for internal use only. */) + (Lisp_Object frame, Lisp_Object was_invisible) +{ + struct frame *f = decode_live_frame (frame); + f->was_invisible = !NILP (was_invisible); + + return f->was_invisible ? Qt : Qnil; +} /*********************************************************************** Multimonitor data @@ -6495,6 +6507,7 @@ iconify the top level frame instead. */); defsubr (&Sframe_position); defsubr (&Sset_frame_position); defsubr (&Sframe_pointer_visible_p); + defsubr (&Sframe__set_was_invisible); defsubr (&Sframe_window_state_change); defsubr (&Sset_frame_window_state_change); defsubr (&Sframe_scale_factor); diff --git a/src/frame.h b/src/frame.h index 744b95e1e04..75a0b184c19 100644 --- a/src/frame.h +++ b/src/frame.h @@ -456,7 +456,11 @@ struct frame /* True when new_width or new_height were set by change_frame_size, false when they were set by adjust_frame_size internally or not set. */ - bool_bf new_size_p; + bool_bf new_size_p : 1; + + /* True when frame was invisible before first MapNotify event. Used + in X builds only. */ + bool_bf was_invisible : 1; /* Bitfield area ends here. */ diff --git a/src/nsfns.m b/src/nsfns.m index 1f281f75fd4..d14f7b51eaf 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1404,6 +1404,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, else { /* Must have been Qnil. */ + f->was_invisible = true; } } diff --git a/src/w32fns.c b/src/w32fns.c index 66baeaecbdb..e5edd62abbc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -6107,6 +6107,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, if (!NILP (visibility)) w32_make_frame_visible (f); + else + f->was_invisible = true; } store_frame_param (f, Qvisibility, visibility); diff --git a/src/xfns.c b/src/xfns.c index 782e0a483c4..e46616e6d66 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4127,12 +4127,21 @@ This function is an internal primitive--use `make-frame' instead. */) cannot control visibility, so don't try. */ if (!f->output_data.x->explicit_parent) { + /* When called from `x-create-frame-with-faces' visibility is + always explicitly nil. */ Lisp_Object visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); + Lisp_Object height + = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); + Lisp_Object width + = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); if (EQ (visibility, Qicon)) - x_iconify_frame (f); + { + f->was_invisible = true; + x_iconify_frame (f); + } else { if (EQ (visibility, Qunbound)) @@ -4140,8 +4149,17 @@ This function is an internal primitive--use `make-frame' instead. */) if (!NILP (visibility)) x_make_frame_visible (f); + else + f->was_invisible = true; } + /* Leave f->was_invisible true only if height or width were + specified too. This takes effect only when we are not called + from `x-create-frame-with-faces' (see above comment). */ + f->was_invisible + = (f->was_invisible + && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); + store_frame_param (f, Qvisibility, visibility); } diff --git a/src/xterm.c b/src/xterm.c index 9edaed9a34b..a663a0f1844 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8181,8 +8181,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, #if defined USE_GTK && defined HAVE_GTK3 /* If GTK3 wants to impose some old size here (Bug#24526), tell it that the current size is what we want. */ - xg_frame_set_char_size - (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); + if (f->was_invisible) + { + xg_frame_set_char_size + (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); + f->was_invisible = false; + } #endif XSETFRAME (inev.ie.frame_or_window, f); } @@ -8443,8 +8447,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, #if defined USE_GTK && defined HAVE_GTK3 /* If GTK3 wants to impose some old size here (Bug#24526), tell it that the current size is what we want. */ - xg_frame_set_char_size - (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); + if (f->was_invisible) + { + xg_frame_set_char_size + (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); + f->was_invisible = false; + } #endif f->output_data.x->has_been_visible = true; } -- cgit v1.2.3 From 2ee5ce208f212ed658cf2125ef6bc24a435dda50 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Mon, 31 May 2021 16:24:11 +0000 Subject: Make frames record when their selected window was the mini-window When a frame in this state is selected again by Fselect_frame (but not by Fselect_window), the mini-window rather than the frame's currently selected window, is chosen for selection, should there still be an active minibuffer in it. This fixes bug #48674. * src/frame.h (struct frame): Add new boolean field select_mini_window_flag. * src/frame.c (make_frame): Initialize select_mini_window_flag to false. (do_switch_frame): Set the new flag appropriately for the old frame, and process the new frame's setting of this flag, before setting it to false. * src/window.c (select_window): Set f->select_mini_window_flag to false. (Fset_frame_selected_window, Fdelete_other_windows_internal) (Fdelete_window_internal): Add comments clarifying that there is no clearing of f->select_mini_window_flag in these functions. --- src/frame.c | 12 +++++++++++- src/frame.h | 5 +++++ src/window.c | 10 ++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c index e3d65dd28f3..623e4ba2cde 100644 --- a/src/frame.c +++ b/src/frame.c @@ -982,6 +982,7 @@ make_frame (bool mini_p) f->ns_transparent_titlebar = false; #endif #endif + f->select_mini_window_flag = false; /* This one should never be zero. */ f->change_stamp = 1; root_window = make_window (); @@ -1542,7 +1543,17 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor tty->top_frame = frame; } + sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); + selected_frame = frame; + + move_minibuffers_onto_frame (sf, for_deletion); + + if (f->select_mini_window_flag + && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) + f->selected_window = f->minibuffer_window; + f->select_mini_window_flag = false; + if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) last_nonminibuf_frame = XFRAME (selected_frame); @@ -1559,7 +1570,6 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor #endif internal_last_event_frame = Qnil; - move_minibuffers_onto_frame (sf, for_deletion); return frame; } diff --git a/src/frame.h b/src/frame.h index 75a0b184c19..cad3df5ae10 100644 --- a/src/frame.h +++ b/src/frame.h @@ -462,6 +462,11 @@ struct frame in X builds only. */ bool_bf was_invisible : 1; + /* True when the frame isn't selected, and selecting it in the + future should select the mini-window rather than the currently + selected window in the frame, assuming there is still an active + minibuffer in that mini-window. */ + bool_bf select_mini_window_flag : 1; /* Bitfield area ends here. */ /* This frame's change stamp, set the last time window change diff --git a/src/window.c b/src/window.c index 9961c54161d..2d98ae5f156 100644 --- a/src/window.c +++ b/src/window.c @@ -468,6 +468,7 @@ Return WINDOW. */) else { fset_selected_window (XFRAME (frame), window); + /* Don't clear FRAME's select_mini_window_flag here. */ return window; } } @@ -517,6 +518,9 @@ select_window (Lisp_Object window, Lisp_Object norecord, /* Do not select a tooltip window (Bug#47207). */ error ("Cannot select a tooltip window"); + /* We deinitely want to select WINDOW, not the mini-window. */ + f->select_mini_window_flag = false; + /* Make the selected window's buffer current. */ Fset_buffer (w->contents); @@ -3242,6 +3246,9 @@ window-start value is reasonable when this function is called. */) if (EQ (selected_frame, w->frame)) Fselect_window (window, Qnil); else + /* Do not clear f->select_mini_window_flag here. If the + last selected window on F was an active minibuffer, we + want to return to it on a later Fselect_frame. */ fset_selected_window (f, window); } } @@ -5153,6 +5160,9 @@ Signal an error when WINDOW is the only window on its frame. */) if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) Fselect_window (new_selected_window, Qt); else + /* Do not clear f->select_mini_window_flag here. If the + last selected window on F was an active minibuffer, we + want to return to it on a later Fselect_frame. */ fset_selected_window (f, new_selected_window); unblock_input (); -- cgit v1.2.3 From e3b8ddd5005903465ec86823559a2e884c7b13f2 Mon Sep 17 00:00:00 2001 From: Jashank Jeremy Date: Wed, 21 Jul 2021 16:01:03 +0200 Subject: Speed up by storing frame faces in hash tables instead of alists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * src/frame.h (struct frame): Add face_hash_table, remove face_alist. (fset_face_hash_table): New function. (fset_face_alist): Remove. * src/frame.c (make_frame): Initialize f->face_hash_table. (Fmake_terminal_frame): Update to work with hash tables instead of alists. * src/xfaces.c (lface_from_face_name_no_resolve): (Finternal_make_lisp_face): (update_face_from_frame_parameter): Update to work with hash tables instead of alists. (Fframe_face_hash_table): New function. (Fframe_face_alist): Move to faces.el as frame-face-alist. (syms_of_xfaces): Add frame_face_hash_table. * lisp/progmodes/elisp-mode.el (elisp--eval-defun-1): * lisp/frame.el (frame-set-background-mode): Update to work with hash tables instead of alists. * lisp/faces.el (face-new-frame-defaults): Mark obsolete. (face-list): Update to use face--new-frame-defaults. (frame-face-alist): Moved here from src/xfaces.c. (x-create-frame-with-faces): Update to handle subtle semantic change to how frame faces propagate, which otherwise breaks frame creation with reverse video enabled (bug#41200). Reworked from a patch by Clément Pit-Claudel . --- lisp/custom.el | 2 +- lisp/faces.el | 26 ++++++++++++-- lisp/frame.el | 2 +- lisp/progmodes/elisp-mode.el | 3 +- src/frame.c | 20 +++++++---- src/frame.h | 8 ++--- src/xfaces.c | 83 +++++++++++++++++++++++--------------------- 7 files changed, 86 insertions(+), 58 deletions(-) (limited to 'src/frame.c') diff --git a/lisp/custom.el b/lisp/custom.el index 1db3f4fd394..f392bd8d369 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -926,7 +926,7 @@ See `custom-known-themes' for a list of known themes." ;; the value to a fake theme, `changed'. If the theme is ;; later disabled, we use this to bring back the old value. ;; - ;; For faces, we just use `face-new-frame-defaults' to + ;; For faces, we just use `face--new-frame-defaults' to ;; recompute when the theme is disabled. (when (and (eq prop 'theme-value) (boundp symbol)) diff --git a/lisp/faces.el b/lisp/faces.el index af2f37df967..4bb3a2b00fc 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -176,10 +176,28 @@ REGISTRY, ALTERNATIVE1, ALTERNATIVE2, and etc." ;;; Creation, copying. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(make-obsolete-variable 'face-new-frame-defaults + "use `face--new-frame-defaults' or `face-alist' instead." "28.1") + +(defun frame-face-alist (&optional frame) + "Return an alist of frame-local faces defined on FRAME. +This alist is a copy of the contents of `frame--face-hash-table'. +For internal use only." + (declare (obsolete frame--face-hash-table "28.1")) + (let (faces) + (maphash (lambda (face spec) + (let ((face-id (car (gethash face face--new-frame-defaults)))) + (push `(,face-id ,face . ,spec) faces))) + (frame--face-hash-table frame)) + (mapcar #'cdr (sort faces (lambda (f1 f2) (< (car f1) (car f2))))))) (defun face-list () "Return a list of all defined faces." - (mapcar #'car face-new-frame-defaults)) + (let (faces) + (maphash (lambda (face spec) + (push `(,(car spec) . ,face) faces)) + face--new-frame-defaults) + (mapcar #'cdr (sort faces (lambda (f1 f2) (< (car f1) (car f2))))))) (defun make-face (face) "Define a new face with name FACE, a symbol. @@ -2115,6 +2133,8 @@ the X resource \"reverseVideo\" is present, handle that." (unwind-protect (progn (x-setup-function-keys frame) + (dolist (face (nreverse (face-list))) + (face-spec-recalc face frame)) (x-handle-reverse-video frame parameters) (frame-set-background-mode frame t) (face-set-after-frame-default frame parameters) @@ -2145,7 +2165,7 @@ the X resource \"reverseVideo\" is present, handle that." (defun face-set-after-frame-default (frame &optional parameters) "Initialize the frame-local faces of FRAME. Calculate the face definitions using the face specs, custom theme -settings, X resources, and `face-new-frame-defaults'. +settings, X resources, and `face--new-frame-defaults'. Finally, apply any relevant face attributes found amongst the frame parameters in PARAMETERS." ;; The `reverse' is so that `default' goes first. @@ -2154,7 +2174,7 @@ frame parameters in PARAMETERS." (progn ;; Initialize faces from face spec and custom theme. (face-spec-recalc face frame) - ;; Apply attributes specified by face-new-frame-defaults + ;; Apply attributes specified by face--new-frame-defaults (internal-merge-in-global-face face frame)) ;; Don't let invalid specs prevent frame creation. (error nil))) diff --git a/lisp/frame.el b/lisp/frame.el index 378d7c8e5ba..9b3d120598b 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1231,7 +1231,7 @@ face specs for the new background mode." ;; during startup with -rv on the command ;; line for the initial frame, because frames ;; are not recorded in the pdump file. - (assq face (frame-face-alist frame)) + (gethash face (frame--face-hash-table)) (face-spec-match-p face (face-user-default-spec face) frame))) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index a56c7093e79..7ed2d3d08cc 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1325,8 +1325,7 @@ Reinitialize the face according to the `defface' specification." ((eq (car form) 'custom-declare-face) ;; Reset the face. (let ((face-symbol (eval (nth 1 form) lexical-binding))) - (setq face-new-frame-defaults - (assq-delete-all face-symbol face-new-frame-defaults)) + (remhash face-symbol face--new-frame-defaults) (put face-symbol 'face-defface-spec nil) (put face-symbol 'face-override-spec nil)) form) diff --git a/src/frame.c b/src/frame.c index 623e4ba2cde..b105268d423 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1018,6 +1018,10 @@ make_frame (bool mini_p) rw->total_lines = FRAME_LINES (f) - (mini_p ? 1 : 0); rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f); + fset_face_hash_table + (f, make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE, + DEFAULT_REHASH_THRESHOLD, Qnil, false)); + if (mini_p) { mw->top_line = rw->total_lines; @@ -1326,7 +1330,7 @@ affects all frames on the same terminal device. */) { struct frame *f; struct terminal *t = NULL; - Lisp_Object frame, tem; + Lisp_Object frame; struct frame *sf = SELECTED_FRAME (); #ifdef MSDOS @@ -1408,14 +1412,16 @@ affects all frames on the same terminal device. */) store_in_alist (&parms, Qminibuffer, Qt); Fmodify_frame_parameters (frame, parms); - /* Make the frame face alist be frame-specific, so that each + /* Make the frame face hash be frame-specific, so that each frame could change its face definitions independently. */ - fset_face_alist (f, Fcopy_alist (sf->face_alist)); - /* Simple Fcopy_alist isn't enough, because we need the contents of - the vectors which are the CDRs of associations in face_alist to + fset_face_hash_table (f, Fcopy_hash_table (sf->face_hash_table)); + /* Simple copy_hash_table isn't enough, because we need the contents of + the vectors which are the values in face_hash_table to be copied as well. */ - for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem)) - XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem)))); + ptrdiff_t idx = 0; + struct Lisp_Hash_Table *table = XHASH_TABLE (f->face_hash_table); + for (idx = 0; idx < table->count; ++idx) + set_hash_value_slot (table, idx, Fcopy_sequence (HASH_VALUE (table, idx))); f->can_set_window_size = true; f->after_make_frame = true; diff --git a/src/frame.h b/src/frame.h index cad3df5ae10..a8ad011889d 100644 --- a/src/frame.h +++ b/src/frame.h @@ -158,8 +158,8 @@ struct frame There are four additional elements of nil at the end, to terminate. */ Lisp_Object menu_bar_items; - /* Alist of elements (FACE-NAME . FACE-VECTOR-DATA). */ - Lisp_Object face_alist; + /* Hash table of FACE-NAME keys and FACE-VECTOR-DATA values. */ + Lisp_Object face_hash_table; /* A vector that records the entire structure of this frame's menu bar. For the format of the data, see extensive comments in xmenu.c. @@ -672,9 +672,9 @@ fset_condemned_scroll_bars (struct frame *f, Lisp_Object val) f->condemned_scroll_bars = val; } INLINE void -fset_face_alist (struct frame *f, Lisp_Object val) +fset_face_hash_table (struct frame *f, Lisp_Object val) { - f->face_alist = val; + f->face_hash_table = val; } #if defined (HAVE_WINDOW_SYSTEM) INLINE void diff --git a/src/xfaces.c b/src/xfaces.c index fed7b3336a2..207f0d6a36e 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -95,9 +95,10 @@ along with GNU Emacs. If not, see . */ with the symbol `face' in slot 0, and a slot for each of the face attributes mentioned above. - There is also a global face alist `Vface_new_frame_defaults'. Face - definitions from this list are used to initialize faces of newly - created frames. + There is also a global face map `Vface_new_frame_defaults', + containing conses of (FACE_ID . FACE_DEFINITION). Face definitions + from this table are used to initialize faces of newly created + frames. A face doesn't have to specify all attributes. Those not specified have a value of `unspecified'. Faces specifying all attributes but @@ -1965,13 +1966,11 @@ lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name, Lisp_Object lface; if (f) - lface = assq_no_quit (face_name, f->face_alist); + lface = Fgethash (face_name, f->face_hash_table, Qnil); else - lface = assq_no_quit (face_name, Vface_new_frame_defaults); + lface = CDR (Fgethash (face_name, Vface_new_frame_defaults, Qnil)); - if (CONSP (lface)) - lface = XCDR (lface); - else if (signal_p) + if (signal_p && NILP (lface)) signal_error ("Invalid face", face_name); check_lface (lface); @@ -2870,11 +2869,6 @@ Value is a vector of face attributes. */) /* Add a global definition if there is none. */ if (NILP (global_lface)) { - global_lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified); - ASET (global_lface, 0, Qface); - Vface_new_frame_defaults = Fcons (Fcons (face, global_lface), - Vface_new_frame_defaults); - /* Assign the new Lisp face a unique ID. The mapping from Lisp face id to Lisp face is given by the vector lface_id_to_name. The mapping from Lisp face to Lisp face id is given by the @@ -2884,9 +2878,14 @@ Value is a vector of face attributes. */) xpalloc (lface_id_to_name, &lface_id_to_name_size, 1, MAX_FACE_ID, sizeof *lface_id_to_name); + Lisp_Object face_id = make_fixnum (next_lface_id); lface_id_to_name[next_lface_id] = face; - Fput (face, Qface, make_fixnum (next_lface_id)); + Fput (face, Qface, face_id); ++next_lface_id; + + global_lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified); + ASET (global_lface, 0, Qface); + Fputhash (face, Fcons (face_id, global_lface), Vface_new_frame_defaults); } else if (f == NULL) for (i = 1; i < LFACE_VECTOR_SIZE; ++i) @@ -2899,7 +2898,7 @@ Value is a vector of face attributes. */) { lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified); ASET (lface, 0, Qface); - fset_face_alist (f, Fcons (Fcons (face, lface), f->face_alist)); + Fputhash (face, lface, f->face_hash_table); } else for (i = 1; i < LFACE_VECTOR_SIZE; ++i) @@ -3060,7 +3059,7 @@ FRAME 0 means change the face on all frames, and change the default f = NULL; lface = lface_from_face_name (NULL, face, true); - /* When updating face-new-frame-defaults, we put :ignore-defface + /* When updating face--new-frame-defaults, we put :ignore-defface where the caller wants `unspecified'. This forces the frame defaults to ignore the defface value. Otherwise, the defface will take effect, which is generally not what is intended. @@ -3645,7 +3644,7 @@ update_face_from_frame_parameter (struct frame *f, Lisp_Object param, /* If there are no faces yet, give up. This is the case when called from Fx_create_frame, and we do the necessary things later in face-set-after-frame-defaults. */ - if (NILP (f->face_alist)) + if (XFIXNAT (Fhash_table_count (f->face_hash_table)) == 0) return; if (EQ (param, Qforeground_color)) @@ -4311,14 +4310,13 @@ If FRAME is omitted or nil, use the selected frame. */) return i == LFACE_VECTOR_SIZE ? Qt : Qnil; } - -DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, +DEFUN ("frame--face-hash-table", Fframe_face_hash_table, Sframe_face_hash_table, 0, 1, 0, - doc: /* Return an alist of frame-local faces defined on FRAME. + doc: /* Return a hash table of frame-local faces defined on FRAME. For internal use only. */) (Lisp_Object frame) { - return decode_live_frame (frame)->face_alist; + return decode_live_frame (frame)->face_hash_table; } @@ -6835,30 +6833,32 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources, #ifdef HAVE_PDUMPER /* All the faces defined during loadup are recorded in - face-new-frame-defaults, with the last face first in the list. We - need to set next_lface_id to the next face ID number, so that any - new faces defined in this session will have face IDs different from - those defined during loadup. We also need to set up the - lface_id_to_name[] array for the faces that were defined during - loadup. */ + face-new-frame-defaults. We need to set next_lface_id to the next + face ID number, so that any new faces defined in this session will + have face IDs different from those defined during loadup. We also + need to set up the lface_id_to_name[] array for the faces that were + defined during loadup. */ void init_xfaces (void) { - if (CONSP (Vface_new_frame_defaults)) + int nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults)); + if (nfaces > 0) { /* Allocate the lface_id_to_name[] array. */ - lface_id_to_name_size = next_lface_id = - XFIXNAT (Flength (Vface_new_frame_defaults)); + lface_id_to_name_size = next_lface_id = nfaces; lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name); /* Store the faces. */ - Lisp_Object tail; - int i = next_lface_id - 1; - for (tail = Vface_new_frame_defaults; CONSP (tail); tail = XCDR (tail)) + struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults); + for (ptrdiff_t idx = 0; idx < nfaces; ++idx) { - Lisp_Object lface = XCAR (tail); - eassert (i >= 0); - lface_id_to_name[i--] = XCAR (lface); + Lisp_Object lface = HASH_KEY (table, idx); + Lisp_Object face_id = CAR (HASH_VALUE (table, idx)); + if (FIXNATP (face_id)) { + int id = XFIXNAT (face_id); + eassert (id >= 0); + lface_id_to_name[id] = lface; + } } } face_attr_sym[0] = Qface; @@ -7014,7 +7014,7 @@ syms_of_xfaces (void) defsubr (&Sinternal_copy_lisp_face); defsubr (&Sinternal_merge_in_global_face); defsubr (&Sface_font); - defsubr (&Sframe_face_alist); + defsubr (&Sframe_face_hash_table); defsubr (&Sdisplay_supports_face_attributes_p); defsubr (&Scolor_distance); defsubr (&Sinternal_set_font_selection_order); @@ -7038,9 +7038,12 @@ This variable is intended for use only by code that evaluates the "specifity" of a face specification and should be let-bound only for this purpose. */); - DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults, - doc: /* List of global face definitions (for internal use only.) */); - Vface_new_frame_defaults = Qnil; + DEFVAR_LISP ("face--new-frame-defaults", Vface_new_frame_defaults, + doc: /* Hash table of global face definitions (for internal use only.) */); + Vface_new_frame_defaults = + /* 33 entries is enough to fit all basic faces */ + make_hash_table (hashtest_eq, 33, DEFAULT_REHASH_SIZE, + DEFAULT_REHASH_THRESHOLD, Qnil, false); DEFVAR_LISP ("face-default-stipple", Vface_default_stipple, doc: /* Default stipple pattern used on monochrome displays. -- cgit v1.2.3