]> git.eshelyaron.com Git - emacs.git/commitdiff
Handle Bug#24526 without breaking Emacs on tiling WMs (Bug#48268)
authorMartin Rudalics <rudalics@gmx.at>
Wed, 12 May 2021 07:44:02 +0000 (09:44 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Wed, 12 May 2021 07:44:02 +0000 (09:44 +0200)
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
src/frame.c
src/frame.h
src/nsfns.m
src/w32fns.c
src/xfns.c
src/xterm.c

index 68bfbbae384a032ab6d8ea8e4855271d4c79f882..9969140f0ca7338fdf9f64376192fa0bba9cafa1 100644 (file)
@@ -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))
index cb9d4f52109db14f26329642b8ac46d7b3f45995..e3d65dd28f36ef2af1fa2de07232fca29729e69b 100644 (file)
@@ -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;
+}
 \f
 /***********************************************************************
                        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);
index 744b95e1e04e2a1845221a7f470968a600b0dfc0..75a0b184c19bd24ea9f44ad389bf44f7f835b609 100644 (file)
@@ -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.  */
 
index 1f281f75fd4aecc5f06355132b6981ebf2c6bffa..d14f7b51eaff3ae22133b8511f4fee93a7569380 100644 (file)
@@ -1404,6 +1404,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
       else
         {
          /* Must have been Qnil.  */
+         f->was_invisible = true;
         }
     }
 
index 66baeaecbdb8f707ccc46b6954160977d1232dfc..e5edd62abbc47b99a4315caa53056ab19ddb86d0 100644 (file)
@@ -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);
index 782e0a483c4f6a0b7703be36f9eb662d594c234f..e46616e6d66b72055a822ce0762f3de14d45b986 100644 (file)
@@ -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);
     }
 
index 9edaed9a34bd53be428bdaf7a6c02ee829be571a..a663a0f1844cb78403ad2d13178b3eabeebe4463 100644 (file)
@@ -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;
            }