From 2c4e7a99cc161ed4ee246a698792feeff26d7b91 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sun, 2 Nov 2025 09:24:05 +0100 Subject: [PATCH] Handle resizing of fullscreen frames more consistently (Bug#79704) * src/frame.c (adjust_frame_size): Honor new option 'alter-fullscreen-frames'. (syms_of_frame) : New option to maintain consistent state when attempting to resize fullscreen frames. Default to 'inhibit' for NS builds because these resized the frame while leaving the 'fullscreen' parameter alone (Bug#79704). (syms_of_frame) : Define symbol. * lisp/cus-start.el (standard): Add customization options for 'alter-fullscreen-frames' * doc/lispref/frames.texi (Frame Size): Describe new option 'alter-fullscreen-frames'. * etc/NEWS: Call out new option 'alter-fullscreen-frames'. --- doc/lispref/frames.texi | 31 +++++++++++++++++++++++++++++ etc/NEWS | 10 ++++++++++ lisp/cus-start.el | 6 ++++++ src/frame.c | 44 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 740ea43a90f..c053d8c5543 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -1234,6 +1234,37 @@ bottom corner of the frame. The parameters @code{min-width} and @code{min-height} (@pxref{Size Parameters}) can be used to obtain a similar behavior when changing the frame size from within Emacs. +When a frame is in a fullscreen state (@pxref{Size Parameters}), +requests to change the frame size via one of these functions may be +supported or refused either by Emacs itself or by the window manager. +The following variable provides more control of the resulting behavior. + +@cindex altering the size of fullscreen frames +@cindex resizing fullscreen frames +@defopt alter-fullscreen-frames +This options controls how to handle requests to alter fullscreen frames. +Emacs consults it when asked to resize a fullscreen frame via functions +like @code{set-frame-size} or when setting the @code{width} or +@code{height} parameter of a frame. The following values are provided: + +@table @code +@item nil +This will forward the resize request to the window manager and leave it +to the latter how to proceed. + +@item t +This will first reset the fullscreen status and then forward the resize +request on to the window manager. + +@item inhibit +This will reject the resize request and leave the fullscreen status +unchanged. +@end table + +The default is @code{inhibit} on NS builds and @code{nil} everywhere +else. +@end defopt + @cindex tracking frame size changes The abnormal hook @code{window-size-change-functions} (@pxref{Window Hooks}) tracks all changes of the inner size of a frame including those diff --git a/etc/NEWS b/etc/NEWS index 1a8f941ca1e..63ea0b5a11f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -444,6 +444,16 @@ This will inhibit implied resizing while a new frame is made and can be useful on tiling window managers where the initial frame size should be specified by external means. ++++ +*** New option 'alter-fullscreen-frames'. +This option is useful to maintain a consistent state when attempting to +resize fullscreen frames. It defaults to 'inhibit' on NS builds which +means that a fullscreen frame would not change size. It defaults to nil +everywhere else which means that the window manager is supposed to +either resize the frame and change the fullscreen status accordingly or +keep the frame size unchanged. The value t means to first reset the +fullscreen status and then resize the frame. + --- *** Frames can now be renamed to F on text terminals. Unlike with other frame names, an attempt to rename to F throws diff --git a/lisp/cus-start.el b/lisp/cus-start.el index e49d1552c08..c4ab23bec61 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -347,6 +347,12 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of ;; :initialize custom-initialize-default :set custom-set-minor-mode) (frame-resize-pixelwise frames boolean "24.4") + (alter-fullscreen-frames frames + (choice + (const :tag "Forward request to window manager" nil) + (const :tag "Reset fullscreen status first" t) + (const :tag "Inhibit altering fullscreen frames" inhibit)) + "31.1") (frame-inhibit-implied-resize frames (choice (const :tag "Never" nil) diff --git a/src/frame.c b/src/frame.c index 01e21d323ae..d426fa6f1da 100644 --- a/src/frame.c +++ b/src/frame.c @@ -786,6 +786,26 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, min_inner_height = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qsafe : Qnil, Qt); + if (inhibit == 1 && !NILP (alter_fullscreen_frames)) + { + Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); + + if ((new_text_width != old_text_width + && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight)) + || (new_text_height != old_text_height + && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth))) + + { + if (EQ (alter_fullscreen_frames, Qt)) + /* Reset fullscreen status and proceed. */ + Fmodify_frame_parameters + (frame, Fcons (Fcons (Qfullscreen, Qnil), Qnil)); + else if (EQ (alter_fullscreen_frames, Qinhibit)) + /* Do nothing and return. */ + return; + } + } + 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 @@ -7102,6 +7122,7 @@ syms_of_frame (void) DEFSYM (Quse_frame_synchronization, "use-frame-synchronization"); DEFSYM (Qfont_parameter, "font-parameter"); DEFSYM (Qforce, "force"); + DEFSYM (Qinhibit, "inhibit"); for (int i = 0; i < ARRAYELTS (frame_parms); i++) { @@ -7487,6 +7508,29 @@ allow `make-frame' to show the current buffer even if its hidden. */); frame_internal_parameters = list3 (Qname, Qparent_id, Qwindow_id); #endif + DEFVAR_LISP ("alter-fullscreen-frames", alter_fullscreen_frames, + doc: /* How to handle requests to alter fullscreen frames. +Emacs consults this option when asked to resize a fullscreen frame via +functions like 'set-frame-size' or when setting the 'width' or 'height' +parameter of a frame. The following values are provided: + +- nil means to forward the resize request to the window manager and + leave it to the latter how to proceed. + +- t means to first reset the fullscreen status and then forward the + request to the window manager. + +- 'inhibit' means to reject the resize request and leave the fullscreen + status unchanged. + +The default is 'inhibit' on NS builds and nil everywhere else. */); + +#if defined (NS_IMPL_COCOA) + alter_fullscreen_frames = Qinhibit; +#else + alter_fullscreen_frames = Qnil; +#endif + defsubr (&Sframep); defsubr (&Sframe_live_p); defsubr (&Swindow_system);