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 #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 * 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. * the user. In practice this means XDG toplevel and XWayland windows.

View file

@ -29,9 +29,6 @@
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
#endif #endif
#define LAB_FALLBACK_WIDTH 640
#define LAB_FALLBACK_HEIGHT 480
struct view * struct view *
view_from_wlr_surface(struct wlr_surface *surface) view_from_wlr_surface(struct wlr_surface *surface)
{ {
@ -827,8 +824,8 @@ adjust_floating_geometry(struct view *view, struct wlr_box *geometry,
void void
view_set_fallback_natural_geometry(struct view *view) view_set_fallback_natural_geometry(struct view *view)
{ {
view->natural_geometry.width = LAB_FALLBACK_WIDTH; view->natural_geometry.width = VIEW_FALLBACK_WIDTH;
view->natural_geometry.height = LAB_FALLBACK_HEIGHT; view->natural_geometry.height = VIEW_FALLBACK_HEIGHT;
view_compute_centered_position(view, NULL, view_compute_centered_position(view, NULL,
view->natural_geometry.width, view->natural_geometry.width,
view->natural_geometry.height, view->natural_geometry.height,
@ -836,9 +833,6 @@ view_set_fallback_natural_geometry(struct view *view)
&view->natural_geometry.y); &view->natural_geometry.y);
} }
#undef LAB_FALLBACK_WIDTH
#undef LAB_FALLBACK_HEIGHT
void void
view_store_natural_geometry(struct view *view) 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_serial = 0;
view->pending_configure_timeout = NULL; view->pending_configure_timeout = NULL;
/* bool empty_pending = wlr_box_empty(&view->pending);
* We do not use view_impl_apply_geometry() here since in the timeout if (empty_pending || view->pending.x != view->current.x
* case we prefer to always put the top-left corner of the view at the || view->pending.y != view->current.y) {
* desired position rather than anchoring some other edge or corner /*
*/ * This is a pending move + resize and the client is
bool moved = view->current.x != view->pending.x * taking too long to respond to the resize. Apply the
|| view->current.y != view->pending.y; * move now (while keeping the current size) so that the
view->current.x = view->pending.x; * desktop doesn't appear unresponsive.
view->current.y = view->pending.y; *
if (moved) { * 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); view_moved(view);
} }