* Please note: only xdg-shell-toplevel-view and xwayland-view view_impl
* functions should call these functions.
*/
+struct view;
void view_impl_move_to_front(struct view *view);
void view_impl_map(struct view *view);
+/*
+ * Updates view geometry at commit based on current position/size,
+ * pending move/resize, and committed surface size. The computed
+ * position may not match pending.x/y exactly in some cases.
+ */
+void view_impl_apply_geometry(struct view *view, int w, int h);
+
#endif /* __LABWC_VIEW_IMPL_COMMON_H */
view_update_title(view);
view_update_app_id(view);
}
+
+static bool
+resizing_edge(struct view *view, uint32_t edge)
+{
+ struct server *server = view->server;
+ return server->input_mode == LAB_INPUT_STATE_RESIZE
+ && server->grabbed_view == view
+ && (server->resize_edges & edge);
+}
+
+void
+view_impl_apply_geometry(struct view *view, int w, int h)
+{
+ struct wlr_box *current = &view->current;
+ struct wlr_box *pending = &view->pending;
+ struct wlr_box old = *current;
+
+ /*
+ * Anchor right edge if resizing via left edge.
+ *
+ * Note that answering the question "are we resizing?" is a bit
+ * tricky. The most obvious method is to look at the server
+ * flags; but that method will not account for any late commits
+ * that occur after the mouse button is released, as the client
+ * catches up with pending configure requests. So as a fallback,
+ * we resort to a geometry-based heuristic -- also not 100%
+ * reliable on its own. The combination of the two methods
+ * should catch 99% of resize cases that we care about.
+ */
+ bool resizing_left_edge = resizing_edge(view, WLR_EDGE_LEFT);
+ if (resizing_left_edge || (current->x != pending->x
+ && current->x + current->width ==
+ pending->x + pending->width)) {
+ current->x = pending->x + pending->width - w;
+ } else {
+ current->x = pending->x;
+ }
+
+ /* Anchor bottom edge if resizing via top edge */
+ bool resizing_top_edge = resizing_edge(view, WLR_EDGE_TOP);
+ if (resizing_top_edge || (current->y != pending->y
+ && current->y + current->height ==
+ pending->y + pending->height)) {
+ current->y = pending->y + pending->height - h;
+ } else {
+ current->y = pending->y;
+ }
+
+ current->width = w;
+ current->height = h;
+
+ if (!wlr_box_equal(current, &old)) {
+ view_moved(view);
+ }
+}
wlr_xdg_surface_get_geometry(xdg_surface, &size);
struct wlr_box *current = &view->current;
- struct wlr_box *pending = &view->pending;
- bool update_required = false;
-
- if (current->width != size.width || current->height != size.height) {
- update_required = true;
- current->width = size.width;
- current->height = size.height;
- }
+ bool update_required = current->width != size.width
+ || current->height != size.height;
uint32_t serial = view->pending_configure_serial;
if (serial > 0 && serial >= xdg_surface->current.configure_serial) {
- if (current->x != pending->x) {
- update_required = true;
- current->x = pending->x + pending->width - size.width;
- }
- if (current->y != pending->y) {
- update_required = true;
- current->y = pending->y + pending->height - size.height;
- }
+ update_required = true;
if (serial == xdg_surface->current.configure_serial) {
view->pending_configure_serial = 0;
}
}
if (update_required) {
- view_moved(view);
+ view_impl_apply_geometry(view, size.width, size.height);
}
}
/* Must receive commit signal before accessing surface->current* */
struct wlr_surface_state *state = &view->surface->current;
struct wlr_box *current = &view->current;
- struct wlr_box *pending = &view->pending;
- if (current->width == state->width && current->height == state->height) {
- return;
- }
-
- current->width = state->width;
- current->height = state->height;
-
- if (current->x != pending->x) {
- /* Adjust x for queued up configure events */
- current->x = pending->x + pending->width - current->width;
- }
- if (current->y != pending->y) {
- /* Adjust y for queued up configure events */
- current->y = pending->y + pending->height - current->height;
+ /*
+ * If there is a pending move/resize, wait until the surface
+ * size changes to update geometry. The hope is to update both
+ * the position and the size of the view at the same time,
+ * reducing visual glitches.
+ */
+ if (current->width != state->width || current->height != state->height) {
+ view_impl_apply_geometry(view, state->width, state->height);
}
- view_moved(view);
}
static void
* This event is raised when a client would like to begin an interactive
* move, typically because the user clicked on their client-side
* decorations. Note that a more sophisticated compositor should check
- * the provied serial against a list of button press serials sent to
+ * the provided serial against a list of button press serials sent to
* this client, to prevent the client from requesting this whenever they
* want.
*/
* This event is raised when a client would like to begin an interactive
* resize, typically because the user clicked on their client-side
* decorations. Note that a more sophisticated compositor should check
- * the provied serial against a list of button press serials sent to
+ * the provided serial against a list of button press serials sent to
* this client, to prevent the client from requesting this whenever they
* want.
*/