xdg: try to handle slow un-maximize with empty natural geometry better

In the case of an initially-maximized view which is taking a long time
to un-maximize (seen for example with Thunderbird on slow machines), we
may end up in handle_configure_timeout() with an empty pending geometry.
In that case we have no great options (we can't center the view since we
don't know the un-maximized size yet), so set a fallback position.

v2: check wlr_box_empty() before comparing pending and current

Fixes: #2191
This commit is contained in:
John Lindgren 2024-10-01 10:16:29 -04:00 committed by Johan Malm
parent 915d638f8a
commit 452f45cd3d
3 changed files with 41 additions and 18 deletions

View file

@ -13,6 +13,16 @@
#define LAB_MIN_VIEW_HEIGHT 60
/*
* Fallback view geometry used in some cases where a better position
* and/or size can't be determined. Try to avoid using these except as
* a last resort.
*/
#define VIEW_FALLBACK_X 100
#define VIEW_FALLBACK_Y 100
#define VIEW_FALLBACK_WIDTH 640
#define VIEW_FALLBACK_HEIGHT 480
/*
* In labwc, a view is a container for surfaces which can be moved around by
* the user. In practice this means XDG toplevel and XWayland windows.

View file

@ -29,9 +29,6 @@
#include <wlr/xwayland.h>
#endif
#define LAB_FALLBACK_WIDTH 640
#define LAB_FALLBACK_HEIGHT 480
struct view *
view_from_wlr_surface(struct wlr_surface *surface)
{
@ -827,8 +824,8 @@ adjust_floating_geometry(struct view *view, struct wlr_box *geometry,
void
view_set_fallback_natural_geometry(struct view *view)
{
view->natural_geometry.width = LAB_FALLBACK_WIDTH;
view->natural_geometry.height = LAB_FALLBACK_HEIGHT;
view->natural_geometry.width = VIEW_FALLBACK_WIDTH;
view->natural_geometry.height = VIEW_FALLBACK_HEIGHT;
view_compute_centered_position(view, NULL,
view->natural_geometry.width,
view->natural_geometry.height,
@ -836,9 +833,6 @@ view_set_fallback_natural_geometry(struct view *view)
&view->natural_geometry.y);
}
#undef LAB_FALLBACK_WIDTH
#undef LAB_FALLBACK_HEIGHT
void
view_store_natural_geometry(struct view *view)
{

View file

@ -251,16 +251,35 @@ handle_configure_timeout(void *data)
view->pending_configure_serial = 0;
view->pending_configure_timeout = NULL;
/*
* We do not use view_impl_apply_geometry() here since in the timeout
* case we prefer to always put the top-left corner of the view at the
* desired position rather than anchoring some other edge or corner
*/
bool moved = view->current.x != view->pending.x
|| view->current.y != view->pending.y;
view->current.x = view->pending.x;
view->current.y = view->pending.y;
if (moved) {
bool empty_pending = wlr_box_empty(&view->pending);
if (empty_pending || view->pending.x != view->current.x
|| view->pending.y != view->current.y) {
/*
* This is a pending move + resize and the client is
* taking too long to respond to the resize. Apply the
* move now (while keeping the current size) so that the
* desktop doesn't appear unresponsive.
*
* We do not use view_impl_apply_geometry() here since
* in this case we prefer to always put the top-left
* corner of the view at the desired position rather
* than anchoring some other edge or corner.
*
* Corner case: we may get here with an empty pending
* geometry in the case of an initially-maximized view
* which is taking a long time to un-maximize (seen for
* example with Thunderbird on slow machines). In that
* case we have no great options (we can't center the
* view since we don't know the un-maximized size yet),
* so set a fallback position.
*/
if (empty_pending) {
wlr_log(WLR_INFO, "using fallback position");
view->pending.x = VIEW_FALLBACK_X;
view->pending.y = VIEW_FALLBACK_Y;
}
view->current.x = view->pending.x;
view->current.y = view->pending.y;
view_moved(view);
}