mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
Try to resize or resize-and-move child frames in one update
This pertains to X11 toolkit builds. Other ports (including PGTK) seem to have mostly atomic window updates already. * src/xterm.c (x_set_window_size_1): Resize the Xt widget eagerly, so the next redraw is not clipped. Update the "desired" Cairo surface dimensions. Skip waiting for next XEvent. Do all that for child frames only. Update old comments (bug#80662). (x_set_window_size_and_position_1): Same. Also clear the widget's cached position coordinates (we don't keep them up to date). (x_set_window_size, x_set_window_size_and_position): Skip redrawing the border on child frames, it will happen during redisplay anyway. * src/gtkutil.c (xg_frame_set_size_and_position): On child frames, resize the GTK widget hierarchy immediately. Update the "desired" Cairo surface dimensions. Skip waiting for events. * src/widget.c (EmacsFrameResize): When resize should be a no-op, exit early (minor optimization). (EmacsFrameExpose): Redraw the border on the last Expose event. * src/xdisp.c (clear_garbaged_frames): Don't redraw borders here. * src/xfns.c (x_window): Undo the previous change in bit_gravity in the no-toolkit build. StaticGravity works the best for it thanks to no nesting in window configuration.
This commit is contained in:
parent
da4ab3d738
commit
a6a3b32208
5 changed files with 74 additions and 30 deletions
|
|
@ -1421,6 +1421,16 @@ xg_frame_set_size_and_position (struct frame *f, int width, int height)
|
|||
|
||||
#ifndef HAVE_PGTK
|
||||
gdk_window_move_resize (gwin, x, y, outer_width, outer_height);
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
/* Resize all inner widgets and Cairo surface right away so the
|
||||
next redisplay drawing isn't clipped to the old size. */
|
||||
GtkAllocation alloc = {0, 0, outer_width, outer_height};
|
||||
gtk_widget_size_allocate (FRAME_GTK_OUTER_WIDGET (f), &alloc);
|
||||
#ifdef USE_CAIRO
|
||||
x_cr_update_surface_desired_size (f, width, height);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (FRAME_GTK_OUTER_WIDGET (f))
|
||||
gdk_window_move_resize (gwin, x, y, outer_width, outer_height);
|
||||
|
|
@ -1432,7 +1442,11 @@ xg_frame_set_size_and_position (struct frame *f, int width, int height)
|
|||
SET_FRAME_GARBAGED (f);
|
||||
cancel_mouse_face (f);
|
||||
|
||||
if (FRAME_VISIBLE_P (f))
|
||||
/* For child frames, don't wait for events — that would flush the X
|
||||
buffer and might show outdated contents in the frame. Same for
|
||||
invisible frames: this way is faster and x_make_frame_visible will
|
||||
wait for event anyway. */
|
||||
if (FRAME_VISIBLE_P (f) && !FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
/* Must call this to flush out events */
|
||||
(void)gtk_events_pending ();
|
||||
|
|
|
|||
|
|
@ -428,6 +428,10 @@ EmacsFrameResize (Widget widget)
|
|||
ew->core.width, ew->core.height,
|
||||
f->new_width, f->new_height);
|
||||
|
||||
if (FRAME_PIXEL_WIDTH (f) == ew->core.width
|
||||
&& FRAME_PIXEL_HEIGHT (f) == ew->core.height)
|
||||
return;
|
||||
|
||||
change_frame_size (f, ew->core.width, ew->core.height,
|
||||
false, true, false);
|
||||
|
||||
|
|
@ -495,6 +499,8 @@ EmacsFrameExpose (Widget widget, XEvent *event, Region region)
|
|||
|
||||
expose_frame (f, event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
if (event->xexpose.count == 0)
|
||||
x_clear_under_internal_border (f);
|
||||
flush_frame (f);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13661,11 +13661,6 @@ clear_garbaged_frames (void)
|
|||
if (is_tty_frame (f))
|
||||
current_matrices_cleared = true;
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (FRAME_WINDOW_P (f)
|
||||
&& FRAME_RIF (f)->clear_under_internal_border)
|
||||
FRAME_RIF (f)->clear_under_internal_border (f);
|
||||
#endif
|
||||
fset_redisplay (f);
|
||||
f->garbaged = false;
|
||||
f->resized_p = false;
|
||||
|
|
|
|||
|
|
@ -4483,7 +4483,7 @@ x_window (struct frame *f)
|
|||
|
||||
attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
|
||||
attributes.border_pixel = f->output_data.x->border_pixel;
|
||||
attributes.bit_gravity = NorthWestGravity;
|
||||
attributes.bit_gravity = StaticGravity;
|
||||
attributes.backing_store = NotUseful;
|
||||
attributes.save_under = True;
|
||||
attributes.event_mask = STANDARD_EVENT_SET;
|
||||
|
|
|
|||
75
src/xterm.c
75
src/xterm.c
|
|
@ -28484,6 +28484,19 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
|
|||
f->win_gravity = NorthWestGravity;
|
||||
x_wm_set_size_hint (f, 0, false);
|
||||
|
||||
#ifdef USE_X_TOOLKIT
|
||||
if (FRAME_PARENT_FRAME (f) && f->output_data.x->widget)
|
||||
{
|
||||
/* Resize all inner widgets and Cairo surface right away so the
|
||||
next redisplay drawing isn't clipped to the old size. */
|
||||
XtResizeWidget (f->output_data.x->widget,
|
||||
width, height + FRAME_MENUBAR_HEIGHT (f), 0);
|
||||
#ifdef USE_CAIRO
|
||||
x_cr_update_surface_desired_size (f, width, height);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
width, height + FRAME_MENUBAR_HEIGHT (f));
|
||||
|
||||
|
|
@ -28499,30 +28512,25 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
|
|||
if (!NILP (Vx_lax_frame_positioning))
|
||||
return;
|
||||
|
||||
/* Now, strictly speaking, we can't be sure that this is accurate,
|
||||
/* Now, strictly speaking, we can't be sure that this is final,
|
||||
but the window manager will get around to dealing with the size
|
||||
change request eventually, and we'll hear how it went when the
|
||||
ConfigureNotify event gets here.
|
||||
|
||||
We could just not bother storing any of this information here,
|
||||
and let the ConfigureNotify event set everything up, but that
|
||||
might be kind of confusing to the Lisp code, since size changes
|
||||
wouldn't be reported in the frame parameters until some random
|
||||
point in the future when the ConfigureNotify event arrives.
|
||||
|
||||
Pass true for DELAY since we can't run Lisp code inside of
|
||||
a BLOCK_INPUT. */
|
||||
|
||||
/* But the ConfigureNotify may in fact never arrive, and then this is
|
||||
not right if the frame is visible. Instead wait (with timeout)
|
||||
for the ConfigureNotify. */
|
||||
if (FRAME_VISIBLE_P (f))
|
||||
We could just let the ConfigureNotify update everything, but
|
||||
waiting creates an implicit X flush which might flicker with
|
||||
outdated contents in the frame. For child frames, the window
|
||||
manager is not a concern and it's better to finish quickly. */
|
||||
if (FRAME_VISIBLE_P (f) && !FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
/* The event may create delayed size change (delayed because we
|
||||
can't run Lisp code inside of a BLOCK_INPUT) which will be
|
||||
applied right after by do_pending_window_change. */
|
||||
x_wait_for_event (f, ConfigureNotify);
|
||||
|
||||
if (CONSP (frame_size_history))
|
||||
frame_size_history_extra
|
||||
(f, build_string ("x_set_window_size_1, visible"),
|
||||
(f, build_string ("x_set_window_size_1, waited for event"),
|
||||
FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
|
||||
f->new_width, f->new_height);
|
||||
}
|
||||
|
|
@ -28530,7 +28538,7 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
|
|||
{
|
||||
if (CONSP (frame_size_history))
|
||||
frame_size_history_extra
|
||||
(f, build_string ("x_set_window_size_1, invisible"),
|
||||
(f, build_string ("x_set_window_size_1, not waited for event"),
|
||||
FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
|
||||
f->new_width, f->new_height);
|
||||
|
||||
|
|
@ -28561,7 +28569,8 @@ x_set_window_size (struct frame *f, bool change_gravity,
|
|||
x_set_window_size_1 (f, change_gravity, width, height);
|
||||
#else /* not USE_GTK */
|
||||
x_set_window_size_1 (f, change_gravity, width, height);
|
||||
x_clear_under_internal_border (f);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
x_clear_under_internal_border (f);
|
||||
#endif /* not USE_GTK */
|
||||
|
||||
/* If cursor was outside the new size, mark it as off. */
|
||||
|
|
@ -28586,16 +28595,35 @@ x_set_window_size_and_position_1 (struct frame *f, int width, int height)
|
|||
|
||||
x_wm_set_size_hint (f, 0, false);
|
||||
|
||||
XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
x, y, width, height + FRAME_MENUBAR_HEIGHT (f));
|
||||
#ifdef USE_X_TOOLKIT
|
||||
if (FRAME_PARENT_FRAME (f) && f->output_data.x->widget)
|
||||
{
|
||||
/* Clear widget's position coordinates because it only sends
|
||||
changed values with its XConfigureWindow command. And these
|
||||
are likely outdated because XtDispatchEvent does not save them.
|
||||
The alternative would be to always use XtMoveWidget instead of
|
||||
XMoveWindow. */
|
||||
f->output_data.x->widget->core.x = -1;
|
||||
f->output_data.x->widget->core.y = -1;
|
||||
/* Resize all inner widgets and Cairo surface right away so the
|
||||
next redisplay drawing isn't clipped to the old size. */
|
||||
XtConfigureWidget (f->output_data.x->widget,
|
||||
x, y, width, height + FRAME_MENUBAR_HEIGHT (f), 0);
|
||||
#ifdef USE_CAIRO
|
||||
x_cr_update_surface_desired_size (f, width, height);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
x, y, width, height + FRAME_MENUBAR_HEIGHT (f));
|
||||
|
||||
SET_FRAME_GARBAGED (f);
|
||||
|
||||
if (FRAME_VISIBLE_P (f))
|
||||
/* Same as x_set_window_size_1. */
|
||||
if (FRAME_VISIBLE_P (f) && !FRAME_PARENT_FRAME (f))
|
||||
x_wait_for_event (f, ConfigureNotify);
|
||||
else
|
||||
/* 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);
|
||||
|
|
@ -28615,7 +28643,8 @@ x_set_window_size_and_position (struct frame *f, int width, int height)
|
|||
x_set_window_size_and_position_1 (f, width, height);
|
||||
#endif /* USE_GTK */
|
||||
|
||||
x_clear_under_internal_border (f);
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
x_clear_under_internal_border (f);
|
||||
|
||||
/* If cursor was outside the new size, mark it as off. */
|
||||
mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
|
||||
|
|
|
|||
Loading…
Reference in a new issue