diff options
| author | Martin Rudalics | 2021-05-12 09:44:02 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2021-05-12 09:44:02 +0200 |
| commit | b41f39d22cdb921fe88311f4fd113cbb9c2f0c76 (patch) | |
| tree | 6bdb2ec7ead4dace5a00914a12b2b90e3a7921f9 /src | |
| parent | 47070ed39eda524d334e5f82dc7f4a50b8d3252c (diff) | |
| download | emacs-b41f39d22cdb921fe88311f4fd113cbb9c2f0c76.tar.gz emacs-b41f39d22cdb921fe88311f4fd113cbb9c2f0c76.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/frame.c | 13 | ||||
| -rw-r--r-- | src/frame.h | 6 | ||||
| -rw-r--r-- | src/nsfns.m | 1 | ||||
| -rw-r--r-- | src/w32fns.c | 2 | ||||
| -rw-r--r-- | src/xfns.c | 20 | ||||
| -rw-r--r-- | src/xterm.c | 16 |
6 files changed, 52 insertions, 6 deletions
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) | |||
| 971 | f->no_accept_focus = false; | 971 | f->no_accept_focus = false; |
| 972 | f->z_group = z_group_none; | 972 | f->z_group = z_group_none; |
| 973 | f->tooltip = false; | 973 | f->tooltip = false; |
| 974 | f->was_invisible = false; | ||
| 974 | f->child_frame_border_width = -1; | 975 | f->child_frame_border_width = -1; |
| 975 | f->last_tab_bar_item = -1; | 976 | f->last_tab_bar_item = -1; |
| 976 | #ifndef HAVE_EXT_TOOL_BAR | 977 | #ifndef HAVE_EXT_TOOL_BAR |
| @@ -5855,7 +5856,18 @@ selected frame. This is useful when `make-pointer-invisible' is set. */) | |||
| 5855 | return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt; | 5856 | return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt; |
| 5856 | } | 5857 | } |
| 5857 | 5858 | ||
| 5859 | DEFUN ("frame--set-was-invisible", Fframe__set_was_invisible, | ||
| 5860 | Sframe__set_was_invisible, 2, 2, 0, | ||
| 5861 | doc: /* Set FRAME's was-invisible flag if WAS-INVISIBLE is non-nil. | ||
| 5862 | This function is for internal use only. */) | ||
| 5863 | (Lisp_Object frame, Lisp_Object was_invisible) | ||
| 5864 | { | ||
| 5865 | struct frame *f = decode_live_frame (frame); | ||
| 5858 | 5866 | ||
| 5867 | f->was_invisible = !NILP (was_invisible); | ||
| 5868 | |||
| 5869 | return f->was_invisible ? Qt : Qnil; | ||
| 5870 | } | ||
| 5859 | 5871 | ||
| 5860 | /*********************************************************************** | 5872 | /*********************************************************************** |
| 5861 | Multimonitor data | 5873 | Multimonitor data |
| @@ -6495,6 +6507,7 @@ iconify the top level frame instead. */); | |||
| 6495 | defsubr (&Sframe_position); | 6507 | defsubr (&Sframe_position); |
| 6496 | defsubr (&Sset_frame_position); | 6508 | defsubr (&Sset_frame_position); |
| 6497 | defsubr (&Sframe_pointer_visible_p); | 6509 | defsubr (&Sframe_pointer_visible_p); |
| 6510 | defsubr (&Sframe__set_was_invisible); | ||
| 6498 | defsubr (&Sframe_window_state_change); | 6511 | defsubr (&Sframe_window_state_change); |
| 6499 | defsubr (&Sset_frame_window_state_change); | 6512 | defsubr (&Sset_frame_window_state_change); |
| 6500 | defsubr (&Sframe_scale_factor); | 6513 | 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 | |||
| 456 | /* True when new_width or new_height were set by change_frame_size, | 456 | /* True when new_width or new_height were set by change_frame_size, |
| 457 | false when they were set by adjust_frame_size internally or not | 457 | false when they were set by adjust_frame_size internally or not |
| 458 | set. */ | 458 | set. */ |
| 459 | bool_bf new_size_p; | 459 | bool_bf new_size_p : 1; |
| 460 | |||
| 461 | /* True when frame was invisible before first MapNotify event. Used | ||
| 462 | in X builds only. */ | ||
| 463 | bool_bf was_invisible : 1; | ||
| 460 | 464 | ||
| 461 | /* Bitfield area ends here. */ | 465 | /* Bitfield area ends here. */ |
| 462 | 466 | ||
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, | |||
| 1404 | else | 1404 | else |
| 1405 | { | 1405 | { |
| 1406 | /* Must have been Qnil. */ | 1406 | /* Must have been Qnil. */ |
| 1407 | f->was_invisible = true; | ||
| 1407 | } | 1408 | } |
| 1408 | } | 1409 | } |
| 1409 | 1410 | ||
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, | |||
| 6107 | 6107 | ||
| 6108 | if (!NILP (visibility)) | 6108 | if (!NILP (visibility)) |
| 6109 | w32_make_frame_visible (f); | 6109 | w32_make_frame_visible (f); |
| 6110 | else | ||
| 6111 | f->was_invisible = true; | ||
| 6110 | } | 6112 | } |
| 6111 | 6113 | ||
| 6112 | store_frame_param (f, Qvisibility, visibility); | 6114 | 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. */) | |||
| 4127 | cannot control visibility, so don't try. */ | 4127 | cannot control visibility, so don't try. */ |
| 4128 | if (!f->output_data.x->explicit_parent) | 4128 | if (!f->output_data.x->explicit_parent) |
| 4129 | { | 4129 | { |
| 4130 | /* When called from `x-create-frame-with-faces' visibility is | ||
| 4131 | always explicitly nil. */ | ||
| 4130 | Lisp_Object visibility | 4132 | Lisp_Object visibility |
| 4131 | = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, | 4133 | = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, |
| 4132 | RES_TYPE_SYMBOL); | 4134 | RES_TYPE_SYMBOL); |
| 4135 | Lisp_Object height | ||
| 4136 | = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); | ||
| 4137 | Lisp_Object width | ||
| 4138 | = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); | ||
| 4133 | 4139 | ||
| 4134 | if (EQ (visibility, Qicon)) | 4140 | if (EQ (visibility, Qicon)) |
| 4135 | x_iconify_frame (f); | 4141 | { |
| 4142 | f->was_invisible = true; | ||
| 4143 | x_iconify_frame (f); | ||
| 4144 | } | ||
| 4136 | else | 4145 | else |
| 4137 | { | 4146 | { |
| 4138 | if (EQ (visibility, Qunbound)) | 4147 | if (EQ (visibility, Qunbound)) |
| @@ -4140,8 +4149,17 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4140 | 4149 | ||
| 4141 | if (!NILP (visibility)) | 4150 | if (!NILP (visibility)) |
| 4142 | x_make_frame_visible (f); | 4151 | x_make_frame_visible (f); |
| 4152 | else | ||
| 4153 | f->was_invisible = true; | ||
| 4143 | } | 4154 | } |
| 4144 | 4155 | ||
| 4156 | /* Leave f->was_invisible true only if height or width were | ||
| 4157 | specified too. This takes effect only when we are not called | ||
| 4158 | from `x-create-frame-with-faces' (see above comment). */ | ||
| 4159 | f->was_invisible | ||
| 4160 | = (f->was_invisible | ||
| 4161 | && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); | ||
| 4162 | |||
| 4145 | store_frame_param (f, Qvisibility, visibility); | 4163 | store_frame_param (f, Qvisibility, visibility); |
| 4146 | } | 4164 | } |
| 4147 | 4165 | ||
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, | |||
| 8181 | #if defined USE_GTK && defined HAVE_GTK3 | 8181 | #if defined USE_GTK && defined HAVE_GTK3 |
| 8182 | /* If GTK3 wants to impose some old size here (Bug#24526), | 8182 | /* If GTK3 wants to impose some old size here (Bug#24526), |
| 8183 | tell it that the current size is what we want. */ | 8183 | tell it that the current size is what we want. */ |
| 8184 | xg_frame_set_char_size | 8184 | if (f->was_invisible) |
| 8185 | (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); | 8185 | { |
| 8186 | xg_frame_set_char_size | ||
| 8187 | (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); | ||
| 8188 | f->was_invisible = false; | ||
| 8189 | } | ||
| 8186 | #endif | 8190 | #endif |
| 8187 | XSETFRAME (inev.ie.frame_or_window, f); | 8191 | XSETFRAME (inev.ie.frame_or_window, f); |
| 8188 | } | 8192 | } |
| @@ -8443,8 +8447,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8443 | #if defined USE_GTK && defined HAVE_GTK3 | 8447 | #if defined USE_GTK && defined HAVE_GTK3 |
| 8444 | /* If GTK3 wants to impose some old size here (Bug#24526), | 8448 | /* If GTK3 wants to impose some old size here (Bug#24526), |
| 8445 | tell it that the current size is what we want. */ | 8449 | tell it that the current size is what we want. */ |
| 8446 | xg_frame_set_char_size | 8450 | if (f->was_invisible) |
| 8447 | (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); | 8451 | { |
| 8452 | xg_frame_set_char_size | ||
| 8453 | (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); | ||
| 8454 | f->was_invisible = false; | ||
| 8455 | } | ||
| 8448 | #endif | 8456 | #endif |
| 8449 | f->output_data.x->has_been_visible = true; | 8457 | f->output_data.x->has_been_visible = true; |
| 8450 | } | 8458 | } |