diff --git a/lisp/faces.el b/lisp/faces.el index 68bfbbae38..9969140f0c 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -2118,7 +2118,23 @@ x-create-frame-with-faces (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 738bfe9a5c..15988a6c30 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 @@ -5907,7 +5908,18 @@ DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p, 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 @@ -6547,6 +6559,7 @@ focus (where a frame immediately loses focus when it's left by the mouse 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 744b95e1e0..75a0b184c1 100644 --- a/src/frame.h +++ b/src/frame.h @@ -456,7 +456,11 @@ #define EMACS_FRAME_H /* 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 1f281f75fd..d14f7b51ea 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1404,6 +1404,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side. else { /* Must have been Qnil. */ + f->was_invisible = true; } } diff --git a/src/w32fns.c b/src/w32fns.c index 66baeaecbd..e5edd62abb 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 782e0a483c..e46616e6d6 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4127,12 +4127,21 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 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 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 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 9edaed9a34..a663a0f184 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; }