diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 46588f0a..b89da87a 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -8,57 +8,32 @@ #include #include -#define WLR_SURFACE_INVALID_BUFFER 1 -#define WLR_SURFACE_INVALID_SURFACE_DAMAGE 2 -#define WLR_SURFACE_INVALID_BUFFER_DAMAGE 4 -#define WLR_SURFACE_INVALID_OPAQUE_REGION 8 -#define WLR_SURFACE_INVALID_INPUT_REGION 16 -#define WLR_SURFACE_INVALID_TRANSFORM 32 -#define WLR_SURFACE_INVALID_SCALE 64 -#define WLR_SURFACE_INVALID_SUBSURFACE_POSITION 128 -#define WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST 256 +enum wlr_surface_state_field { + WLR_SURFACE_STATE_BUFFER = 1, + WLR_SURFACE_STATE_SURFACE_DAMAGE = 2, + WLR_SURFACE_STATE_BUFFER_DAMAGE = 4, + WLR_SURFACE_STATE_OPAQUE_REGION = 8, + WLR_SURFACE_STATE_INPUT_REGION = 16, + WLR_SURFACE_STATE_TRANSFORM = 32, + WLR_SURFACE_STATE_SCALE = 64, + WLR_SURFACE_STATE_FRAME_CALLBACK_LIST = 128, +}; struct wlr_surface_state { - uint32_t invalid; - struct wl_resource *buffer; - struct wl_listener buffer_destroy_listener; - int32_t sx, sy; + uint32_t committed; // enum wlr_surface_state_field + + struct wl_resource *buffer_resource; + int32_t dx, dy; // relative to previous position pixman_region32_t surface_damage, buffer_damage; pixman_region32_t opaque, input; enum wl_output_transform transform; int32_t scale; - int width, height; + struct wl_list frame_callback_list; // wl_resource + + int width, height; // in surface-local coordinates int buffer_width, buffer_height; - struct { - int32_t x, y; - } subsurface_position; - - struct wl_list frame_callback_list; // wl_surface.frame -}; - -struct wlr_subsurface { - struct wl_resource *resource; - struct wlr_surface *surface; - struct wlr_surface *parent; - - struct wlr_surface_state *cached; - bool has_cache; - - bool synchronized; - bool reordered; - - struct wl_list parent_link; - struct wl_list parent_pending_link; - - struct wl_listener surface_destroy; - struct wl_listener parent_destroy; - - struct { - struct wl_signal destroy; - } events; - - void *data; + struct wl_listener buffer_destroy; }; struct wlr_surface { @@ -71,7 +46,28 @@ struct wlr_surface { * or something went wrong with uploading the buffer. */ struct wlr_buffer *buffer; - struct wlr_surface_state *current, *pending; + /** + * The buffer position, in surface-local units. + */ + int sx, sy; + /** + * The last commit's buffer damage, in buffer-local coordinates. This + * contains both the damage accumulated by the client via + * `wlr_surface_state.surface_damage` and `wlr_surface_state.buffer_damage`. + * If the buffer has changed its size or moved, the whole buffer is + * damaged. + * + * This region needs to be scaled and transformed into output coordinates, + * just like the buffer's texture. + */ + pixman_region32_t buffer_damage; + /** + * `current` contains the current, committed surface state. `pending` + * accumulates state changes from the client between commits and shouldn't + * be accessed by the compositor directly. `previous` contains the state of + * the previous commit. + */ + struct wlr_surface_state current, pending, previous; const char *role; // the lifetime-bound role or null struct { @@ -94,6 +90,36 @@ struct wlr_surface { void *data; }; +struct wlr_subsurface_state { + int32_t x, y; +}; + +struct wlr_subsurface { + struct wl_resource *resource; + struct wlr_surface *surface; + struct wlr_surface *parent; + + struct wlr_subsurface_state current, pending; + + struct wlr_surface_state cached; + bool has_cache; + + bool synchronized; + bool reordered; + + struct wl_list parent_link; + struct wl_list parent_pending_link; + + struct wl_listener surface_destroy; + struct wl_listener parent_destroy; + + struct { + struct wl_signal destroy; + } events; + + void *data; +}; + typedef void (*wlr_surface_iterator_func_t)(struct wlr_surface *surface, int sx, int sy, void *data); diff --git a/rootston/cursor.c b/rootston/cursor.c index 1cf81704..904af67f 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -200,8 +200,8 @@ static void roots_cursor_update_position( case ROOTS_CURSOR_ROTATE: view = roots_seat_get_focus(seat); if (view != NULL) { - int ox = view->x + view->wlr_surface->current->width/2, - oy = view->y + view->wlr_surface->current->height/2; + int ox = view->x + view->wlr_surface->current.width/2, + oy = view->y + view->wlr_surface->current.height/2; int ux = cursor->offs_x - ox, uy = cursor->offs_y - oy; int vx = cursor->cursor->x - ox, @@ -239,12 +239,12 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, break; case BTN_RIGHT: edges = 0; - if (sx < view->wlr_surface->current->width/2) { + if (sx < view->wlr_surface->current.width/2) { edges |= WLR_EDGE_LEFT; } else { edges |= WLR_EDGE_RIGHT; } - if (sy < view->wlr_surface->current->height/2) { + if (sy < view->wlr_surface->current.height/2) { edges |= WLR_EDGE_TOP; } else { edges |= WLR_EDGE_BOTTOM; diff --git a/rootston/desktop.c b/rootston/desktop.c index d670c33b..4b5a5c9a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -69,8 +69,8 @@ enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, return ROOTS_DECO_PART_NONE; } - int sw = view->wlr_surface->current->width; - int sh = view->wlr_surface->current->height; + int sw = view->wlr_surface->current.width; + int sh = view->wlr_surface->current.height; int bw = view->border_width; int titlebar_h = view->titlebar_height; @@ -558,7 +558,7 @@ static bool view_at(struct roots_view *view, double lx, double ly, double view_sx = lx - view->x; double view_sy = ly - view->y; - struct wlr_surface_state *state = view->wlr_surface->current; + struct wlr_surface_state *state = &view->wlr_surface->current; struct wlr_box box = { .x = 0, .y = 0, .width = state->width, .height = state->height, diff --git a/rootston/output.c b/rootston/output.c index 8154816d..fd7df99c 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -44,8 +44,8 @@ struct layout_data { static void get_layout_position(struct layout_data *data, double *lx, double *ly, const struct wlr_surface *surface, int sx, int sy) { double _sx = sx, _sy = sy; - rotate_child_position(&_sx, &_sy, surface->current->width, - surface->current->height, data->width, data->height, data->rotation); + rotate_child_position(&_sx, &_sy, surface->current.width, + surface->current.height, data->width, data->height, data->rotation); *lx = data->x + _sx; *ly = data->y + _sy; } @@ -55,8 +55,8 @@ static void surface_for_each_surface(struct wlr_surface *surface, wlr_surface_iterator_func_t iterator, void *user_data) { layout_data->x = lx; layout_data->y = ly; - layout_data->width = surface->current->width; - layout_data->height = surface->current->height; + layout_data->width = surface->current.width; + layout_data->height = surface->current.height; layout_data->rotation = rotation; wlr_surface_for_each_surface(surface, iterator, user_data); @@ -67,8 +67,8 @@ static void view_for_each_surface(struct roots_view *view, void *user_data) { layout_data->x = view->x; layout_data->y = view->y; - layout_data->width = view->wlr_surface->current->width; - layout_data->height = view->wlr_surface->current->height; + layout_data->width = view->wlr_surface->current.width; + layout_data->height = view->wlr_surface->current.height; layout_data->rotation = view->rotation; switch (view->type) { @@ -146,16 +146,19 @@ static bool surface_intersect_output(struct wlr_surface *surface, double ox = lx, oy = ly; wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); + ox += surface->sx; + oy += surface->sy; + if (box != NULL) { box->x = ox * wlr_output->scale; box->y = oy * wlr_output->scale; - box->width = surface->current->width * wlr_output->scale; - box->height = surface->current->height * wlr_output->scale; + box->width = surface->current.width * wlr_output->scale; + box->height = surface->current.height * wlr_output->scale; } struct wlr_box layout_box = { .x = lx, .y = ly, - .width = surface->current->width, .height = surface->current->height, + .width = surface->current.width, .height = surface->current.height, }; wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); @@ -223,7 +226,7 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy, float matrix[9]; enum wl_output_transform transform = - wlr_output_transform_invert(surface->current->transform); + wlr_output_transform_invert(surface->current.transform); wlr_matrix_project_box(matrix, &box, transform, rotation, output->wlr_output->transform_matrix); @@ -247,8 +250,8 @@ static void get_decoration_box(struct roots_view *view, double sx = deco_box.x - view->x; double sy = deco_box.y - view->y; rotate_child_position(&sx, &sy, deco_box.width, deco_box.height, - view->wlr_surface->current->width, - view->wlr_surface->current->height, view->rotation); + view->wlr_surface->current.width, + view->wlr_surface->current.height, view->rotation); double x = sx + view->x; double y = sy + view->y; @@ -692,15 +695,21 @@ static void damage_from_surface(struct wlr_surface *surface, int sx, int sy, int center_x = box.x + box.width/2; int center_y = box.y + box.height/2; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current->surface_damage); - wlr_region_scale(&damage, &damage, wlr_output->scale); - if (ceil(wlr_output->scale) > surface->current->scale) { + pixman_region32_copy(&damage, &surface->buffer_damage); + wlr_region_transform(&damage, &damage, transform, + surface->current.buffer_width, surface->current.buffer_height); + wlr_region_scale(&damage, &damage, + wlr_output->scale / (float)surface->current.scale); + if (ceil(wlr_output->scale) > surface->current.scale) { // When scaling up a surface, it'll become blurry so we need to // expand the damage region wlr_region_expand(&damage, &damage, - ceil(wlr_output->scale) - surface->current->scale); + ceil(wlr_output->scale) - surface->current.scale); } pixman_region32_translate(&damage, box.x, box.y); wlr_region_rotated_bounds(&damage, &damage, rotation, center_x, center_y); diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index d58f030a..02160773 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -158,8 +158,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { view_apply_damage(view); - int width = wlr_surface->current->width; - int height = wlr_surface->current->height; + int width = wlr_surface->current.width; + int height = wlr_surface->current.height; view_update_size(view, width, height); double x = view->x; @@ -236,8 +236,8 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } view->type = ROOTS_WL_SHELL_VIEW; - view->width = surface->surface->current->width; - view->height = surface->surface->current->height; + view->width = surface->surface->current.width; + view->height = surface->surface->current.height; view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; diff --git a/rootston/xwayland.c b/rootston/xwayland.c index b7dbab54..d0b80821 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -206,8 +206,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { view_apply_damage(view); - int width = wlr_surface->current->width; - int height = wlr_surface->current->height; + int width = wlr_surface->current.width; + int height = wlr_surface->current.height; view_update_size(view, width, height); double x = view->x; @@ -233,8 +233,8 @@ static void handle_map(struct wl_listener *listener, void *data) { view->x = surface->x; view->y = surface->y; - view->width = surface->surface->current->width; - view->height = surface->surface->current->height; + view->width = surface->surface->current.width; + view->height = surface->surface->current.height; roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&surface->surface->events.commit, diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index 4f0b2521..bae098c5 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -341,8 +341,8 @@ static void drag_icon_handle_surface_destroy(struct wl_listener *listener, static void drag_icon_handle_surface_commit(struct wlr_surface *surface, void *role_data) { struct wlr_drag_icon *icon = role_data; - icon->sx += icon->surface->current->sx; - icon->sy += icon->surface->current->sy; + icon->sx += icon->surface->current.dx; + icon->sy += icon->surface->current.dy; drag_icon_set_mapped(icon, wlr_surface_has_buffer(surface)); } diff --git a/types/wlr_output.c b/types/wlr_output.c index 9f13bef4..fc86f411 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -352,13 +352,13 @@ static void output_fullscreen_surface_get_box(struct wlr_output *output, int width, height; wlr_output_effective_resolution(output, &width, &height); - int x = (width - surface->current->width) / 2; - int y = (height - surface->current->height) / 2; + int x = (width - surface->current.width) / 2; + int y = (height - surface->current.height) / 2; box->x = x * output->scale; box->y = y * output->scale; - box->width = surface->current->width * output->scale; - box->height = surface->current->height * output->scale; + box->width = surface->current.width * output->scale; + box->height = surface->current.height * output->scale; } static void output_fullscreen_surface_render(struct wlr_output *output, @@ -378,7 +378,7 @@ static void output_fullscreen_surface_render(struct wlr_output *output, float matrix[9]; enum wl_output_transform transform = - wlr_output_transform_invert(surface->current->transform); + wlr_output_transform_invert(surface->current.transform); wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix); @@ -403,11 +403,6 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor, box->y = cursor->y - cursor->hotspot_y; box->width = cursor->width; box->height = cursor->height; - - if (cursor->surface != NULL) { - box->x += cursor->surface->current->sx * cursor->output->scale; - box->y += cursor->surface->current->sy * cursor->output->scale; - } } static void output_cursor_render(struct wlr_output_cursor *cursor, @@ -602,10 +597,10 @@ static void output_fullscreen_surface_handle_commit( fullscreen_surface_commit); struct wlr_surface *surface = output->fullscreen_surface; - if (output->fullscreen_width != surface->current->width || - output->fullscreen_height != surface->current->height) { - output->fullscreen_width = surface->current->width; - output->fullscreen_height = surface->current->height; + if (output->fullscreen_width != surface->current.width || + output->fullscreen_height != surface->current.height) { + output->fullscreen_width = surface->current.width; + output->fullscreen_height = surface->current.height; wlr_output_damage_whole(output); return; } @@ -615,7 +610,7 @@ static void output_fullscreen_surface_handle_commit( pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current->surface_damage); + pixman_region32_copy(&damage, &surface->current.surface_damage); wlr_region_scale(&damage, &damage, output->scale); pixman_region32_translate(&damage, box.x, box.y); pixman_region32_union(&output->damage, &output->damage, &damage); @@ -714,8 +709,8 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { struct wlr_texture *texture = cursor->texture; if (cursor->surface != NULL) { texture = wlr_surface_get_texture(cursor->surface); - scale = cursor->surface->current->scale; - transform = cursor->surface->current->transform; + scale = cursor->surface->current.scale; + transform = cursor->surface->current.transform; } struct wlr_output_cursor *hwcur = cursor->output->hardware_cursor; @@ -771,20 +766,28 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, return true; } -static void output_cursor_commit(struct wlr_output_cursor *cursor) { +static void output_cursor_commit(struct wlr_output_cursor *cursor, + bool update_hotspot) { if (cursor->output->hardware_cursor != cursor) { output_cursor_damage_whole(cursor); } + struct wlr_surface *surface = cursor->surface; + assert(surface != NULL); + // Some clients commit a cursor surface with a NULL buffer to hide it. - cursor->enabled = wlr_surface_has_buffer(cursor->surface); - cursor->width = cursor->surface->current->width * cursor->output->scale; - cursor->height = cursor->surface->current->height * cursor->output->scale; + cursor->enabled = wlr_surface_has_buffer(surface); + cursor->width = surface->current.width * cursor->output->scale; + cursor->height = surface->current.height * cursor->output->scale; + if (update_hotspot) { + cursor->hotspot_x -= surface->current.dx * cursor->output->scale; + cursor->hotspot_y -= surface->current.dy * cursor->output->scale; + } if (output_cursor_attempt_hardware(cursor)) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(cursor->surface, &now); + wlr_surface_send_frame_done(surface, &now); return; } @@ -794,9 +797,9 @@ static void output_cursor_commit(struct wlr_output_cursor *cursor) { static void output_cursor_handle_commit(struct wl_listener *listener, void *data) { - struct wlr_output_cursor *cursor = wl_container_of(listener, cursor, - surface_commit); - output_cursor_commit(cursor); + struct wlr_output_cursor *cursor = + wl_container_of(listener, cursor, surface_commit); + output_cursor_commit(cursor, true); } static void output_cursor_handle_destroy(struct wl_listener *listener, @@ -842,7 +845,7 @@ void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor, if (surface != NULL) { wl_signal_add(&surface->events.commit, &cursor->surface_commit); wl_signal_add(&surface->events.destroy, &cursor->surface_destroy); - output_cursor_commit(cursor); + output_cursor_commit(cursor, false); cursor->visible = false; output_cursor_update_visible(cursor); diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 9c32bda2..973686ef 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -32,28 +32,28 @@ static int max(int fst, int snd) { } static void surface_state_reset_buffer(struct wlr_surface_state *state) { - if (state->buffer) { - wl_list_remove(&state->buffer_destroy_listener.link); - state->buffer = NULL; + if (state->buffer_resource) { + wl_list_remove(&state->buffer_destroy.link); + state->buffer_resource = NULL; } } static void surface_handle_buffer_destroy(struct wl_listener *listener, void *data) { struct wlr_surface_state *state = - wl_container_of(listener, state, buffer_destroy_listener); + wl_container_of(listener, state, buffer_destroy); surface_state_reset_buffer(state); } static void surface_state_set_buffer(struct wlr_surface_state *state, - struct wl_resource *buffer) { + struct wl_resource *buffer_resource) { surface_state_reset_buffer(state); - state->buffer = buffer; - if (buffer) { - wl_resource_add_destroy_listener(buffer, - &state->buffer_destroy_listener); - state->buffer_destroy_listener.notify = surface_handle_buffer_destroy; + state->buffer_resource = buffer_resource; + if (buffer_resource != NULL) { + wl_resource_add_destroy_listener(buffer_resource, + &state->buffer_destroy); + state->buffer_destroy.notify = surface_handle_buffer_destroy; } } @@ -64,13 +64,13 @@ static void surface_destroy(struct wl_client *client, static void surface_attach(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *buffer, int32_t sx, int32_t sy) { + struct wl_resource *buffer, int32_t dx, int32_t dy) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER; - surface->pending->sx = sx; - surface->pending->sy = sy; - surface_state_set_buffer(surface->pending, buffer); + surface->pending.committed |= WLR_SURFACE_STATE_BUFFER; + surface->pending.dx = dx; + surface->pending.dy = dy; + surface_state_set_buffer(&surface->pending, buffer); } static void surface_damage(struct wl_client *client, @@ -80,9 +80,9 @@ static void surface_damage(struct wl_client *client, if (width < 0 || height < 0) { return; } - surface->pending->invalid |= WLR_SURFACE_INVALID_SURFACE_DAMAGE; - pixman_region32_union_rect(&surface->pending->surface_damage, - &surface->pending->surface_damage, + surface->pending.committed |= WLR_SURFACE_STATE_SURFACE_DAMAGE; + pixman_region32_union_rect(&surface->pending.surface_damage, + &surface->pending.surface_damage, x, y, width, height); } @@ -103,192 +103,172 @@ static void surface_frame(struct wl_client *client, wl_resource_set_implementation(callback_resource, NULL, NULL, callback_handle_resource_destroy); - wl_list_insert(surface->pending->frame_callback_list.prev, + wl_list_insert(surface->pending.frame_callback_list.prev, wl_resource_get_link(callback_resource)); - surface->pending->invalid |= WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST; + surface->pending.committed |= WLR_SURFACE_STATE_FRAME_CALLBACK_LIST; } static void surface_set_opaque_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region_resource) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - if ((surface->pending->invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) { - pixman_region32_clear(&surface->pending->opaque); + if ((surface->pending.committed & WLR_SURFACE_STATE_OPAQUE_REGION)) { + pixman_region32_clear(&surface->pending.opaque); } - surface->pending->invalid |= WLR_SURFACE_INVALID_OPAQUE_REGION; + surface->pending.committed |= WLR_SURFACE_STATE_OPAQUE_REGION; if (region_resource) { pixman_region32_t *region = wlr_region_from_resource(region_resource); - pixman_region32_copy(&surface->pending->opaque, region); + pixman_region32_copy(&surface->pending.opaque, region); } else { - pixman_region32_clear(&surface->pending->opaque); + pixman_region32_clear(&surface->pending.opaque); } } static void surface_set_input_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region_resource) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - surface->pending->invalid |= WLR_SURFACE_INVALID_INPUT_REGION; + surface->pending.committed |= WLR_SURFACE_STATE_INPUT_REGION; if (region_resource) { pixman_region32_t *region = wlr_region_from_resource(region_resource); - pixman_region32_copy(&surface->pending->input, region); + pixman_region32_copy(&surface->pending.input, region); } else { - pixman_region32_fini(&surface->pending->input); - pixman_region32_init_rect(&surface->pending->input, + pixman_region32_fini(&surface->pending.input); + pixman_region32_init_rect(&surface->pending.input, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); } } -static bool surface_update_size(struct wlr_surface *surface, +static void surface_state_finalize(struct wlr_surface *surface, struct wlr_surface_state *state) { - if (!state->buffer) { - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, state->width, state->height); - state->height = 0; - state->width = 0; - return true; + if ((state->committed & WLR_SURFACE_STATE_BUFFER)) { + if (state->buffer_resource != NULL) { + wlr_buffer_get_resource_size(state->buffer_resource, + surface->renderer, &state->buffer_width, &state->buffer_height); + } else { + state->buffer_width = state->buffer_height = 0; + } } - int scale = state->scale; - enum wl_output_transform transform = state->transform; - - wlr_buffer_get_resource_size(state->buffer, surface->renderer, - &state->buffer_width, &state->buffer_height); - - int width = state->buffer_width / scale; - int height = state->buffer_height / scale; - - if (transform == WL_OUTPUT_TRANSFORM_90 || - transform == WL_OUTPUT_TRANSFORM_270 || - transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 || - transform == WL_OUTPUT_TRANSFORM_FLIPPED_270) { + int width = state->buffer_width / state->scale; + int height = state->buffer_height / state->scale; + if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) { int tmp = width; width = height; height = tmp; } - - bool update_damage = false; - if (width != state->width || height != state->height) { - // Damage the whole surface on resize - // This isn't in the spec, but Weston does it and QT expects it - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, state->width, state->height); - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, width, height); - update_damage = true; - } - state->width = width; state->height = height; - return update_damage; + pixman_region32_intersect_rect(&state->surface_damage, + &state->surface_damage, 0, 0, state->width, state->height); + + pixman_region32_intersect_rect(&state->buffer_damage, + &state->buffer_damage, 0, 0, state->buffer_width, + state->buffer_height); +} + +static void surface_update_damage(pixman_region32_t *buffer_damage, + struct wlr_surface_state *previous, struct wlr_surface_state *current) { + pixman_region32_clear(buffer_damage); + + if (current->buffer_width != previous->buffer_width || + current->buffer_height != previous->buffer_height || + current->dx != 0 || current->dy != 0) { + // Damage the whole surface on resize or move + int prev_x = -current->dx; + int prev_y = -current->dy; + if ((previous->transform & WL_OUTPUT_TRANSFORM_90) != 0) { + int tmp = prev_x; + prev_x = prev_y; + prev_y = tmp; + } + + pixman_region32_union_rect(buffer_damage, buffer_damage, + prev_x * previous->scale, prev_y * previous->scale, + previous->buffer_width, previous->buffer_height); + pixman_region32_union_rect(buffer_damage, buffer_damage, 0, 0, + current->buffer_width, current->buffer_height); + } else { + // Copy over surface damage + buffer damage + pixman_region32_union(buffer_damage, buffer_damage, + ¤t->buffer_damage); + + pixman_region32_t surface_damage; + pixman_region32_init(&surface_damage); + pixman_region32_copy(&surface_damage, ¤t->surface_damage); + wlr_region_transform(&surface_damage, &surface_damage, + current->transform, current->buffer_width, current->buffer_height); + wlr_region_scale(&surface_damage, &surface_damage, current->scale); + pixman_region32_union(buffer_damage, buffer_damage, &surface_damage); + pixman_region32_fini(&surface_damage); + } +} + +static void surface_state_copy(struct wlr_surface_state *state, + struct wlr_surface_state *next) { + state->width = next->width; + state->height = next->height; + state->buffer_width = next->buffer_width; + state->buffer_height = next->buffer_height; + + if (next->committed & WLR_SURFACE_STATE_SCALE) { + state->scale = next->scale; + } + if (next->committed & WLR_SURFACE_STATE_TRANSFORM) { + state->transform = next->transform; + } + if (next->committed & WLR_SURFACE_STATE_BUFFER) { + state->dx = next->dx; + state->dy = next->dy; + } else { + state->dx = state->dy = 0; + } + if (next->committed & WLR_SURFACE_STATE_SURFACE_DAMAGE) { + pixman_region32_copy(&state->surface_damage, &next->surface_damage); + } else { + pixman_region32_clear(&state->surface_damage); + } + if (next->committed & WLR_SURFACE_STATE_BUFFER_DAMAGE) { + pixman_region32_copy(&state->buffer_damage, &next->buffer_damage); + } else { + pixman_region32_clear(&state->buffer_damage); + } + if (next->committed & WLR_SURFACE_STATE_OPAQUE_REGION) { + pixman_region32_copy(&state->opaque, &next->opaque); + } + if (next->committed & WLR_SURFACE_STATE_INPUT_REGION) { + pixman_region32_copy(&state->input, &next->input); + } + + state->committed |= next->committed; } /** * Append pending state to current state and clear pending state. */ -static void surface_move_state(struct wlr_surface *surface, - struct wlr_surface_state *next, struct wlr_surface_state *state) { - bool update_damage = false; - bool update_size = false; +static void surface_state_move(struct wlr_surface_state *state, + struct wlr_surface_state *next) { + surface_state_copy(state, next); - int oldw = state->width; - int oldh = state->height; - - if ((next->invalid & WLR_SURFACE_INVALID_SCALE)) { - state->scale = next->scale; - update_size = true; - } - if ((next->invalid & WLR_SURFACE_INVALID_TRANSFORM)) { - state->transform = next->transform; - update_size = true; - } - if ((next->invalid & WLR_SURFACE_INVALID_BUFFER)) { - surface_state_set_buffer(state, next->buffer); + if (next->committed & WLR_SURFACE_STATE_BUFFER) { + surface_state_set_buffer(state, next->buffer_resource); surface_state_reset_buffer(next); - state->sx = next->sx; - state->sy = next->sy; - update_size = true; + next->dx = next->dy = 0; } - if (update_size) { - update_damage = surface_update_size(surface, state); - } - if ((next->invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) { - pixman_region32_intersect_rect(&next->surface_damage, - &next->surface_damage, 0, 0, state->width, state->height); - pixman_region32_union(&state->surface_damage, &state->surface_damage, - &next->surface_damage); + if (next->committed & WLR_SURFACE_STATE_SURFACE_DAMAGE) { pixman_region32_clear(&next->surface_damage); - update_damage = true; } - if ((next->invalid & WLR_SURFACE_INVALID_BUFFER_DAMAGE)) { - pixman_region32_intersect_rect(&next->buffer_damage, - &next->buffer_damage, 0, 0, state->buffer_width, - state->buffer_height); - pixman_region32_union(&state->buffer_damage, &state->buffer_damage, - &next->buffer_damage); + if (next->committed & WLR_SURFACE_STATE_BUFFER_DAMAGE) { pixman_region32_clear(&next->buffer_damage); - update_damage = true; } - if (update_damage) { - pixman_region32_t buffer_damage, surface_damage; - pixman_region32_init(&buffer_damage); - pixman_region32_init(&surface_damage); - - // Surface to buffer damage - pixman_region32_copy(&buffer_damage, &state->surface_damage); - wlr_region_transform(&buffer_damage, &buffer_damage, - wlr_output_transform_invert(state->transform), - state->width, state->height); - wlr_region_scale(&buffer_damage, &buffer_damage, state->scale); - - // Buffer to surface damage - pixman_region32_copy(&surface_damage, &state->buffer_damage); - wlr_region_transform(&surface_damage, &surface_damage, state->transform, - state->buffer_width, state->buffer_height); - wlr_region_scale(&surface_damage, &surface_damage, 1.0f/state->scale); - - pixman_region32_union(&state->buffer_damage, &state->buffer_damage, - &buffer_damage); - pixman_region32_union(&state->surface_damage, &state->surface_damage, - &surface_damage); - - pixman_region32_fini(&buffer_damage); - pixman_region32_fini(&surface_damage); - } - if ((next->invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) { - // TODO: process buffer - pixman_region32_clear(&next->opaque); - } - if ((next->invalid & WLR_SURFACE_INVALID_INPUT_REGION)) { - // TODO: process buffer - pixman_region32_copy(&state->input, &next->input); - } - if ((next->invalid & WLR_SURFACE_INVALID_SUBSURFACE_POSITION)) { - // Subsurface has moved - int dx = state->subsurface_position.x - next->subsurface_position.x; - int dy = state->subsurface_position.y - next->subsurface_position.y; - - state->subsurface_position.x = next->subsurface_position.x; - state->subsurface_position.y = next->subsurface_position.y; - next->subsurface_position.x = 0; - next->subsurface_position.y = 0; - - if (dx != 0 || dy != 0) { - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, dx, dy, oldw, oldh); - pixman_region32_union_rect(&state->surface_damage, - &state->surface_damage, 0, 0, state->width, state->height); - } - } - if ((next->invalid & WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST)) { + if (next->committed & WLR_SURFACE_STATE_FRAME_CALLBACK_LIST) { wl_list_insert_list(&state->frame_callback_list, &next->frame_callback_list); wl_list_init(&next->frame_callback_list); } - state->invalid |= next->invalid; - next->invalid = 0; + next->committed = 0; } static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) { @@ -297,10 +277,9 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) { // seems to work ok. See the comment on weston_surface_damage for more info // about a better approach. struct wlr_surface *surface = subsurface->surface; - pixman_region32_union_rect(&surface->current->surface_damage, - &surface->current->surface_damage, - 0, 0, surface->current->width, - surface->current->height); + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, 0, 0, + surface->current.buffer_width, surface->current.buffer_height); subsurface->reordered = false; @@ -311,7 +290,7 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) { } static void surface_apply_damage(struct wlr_surface *surface) { - struct wl_resource *resource = surface->current->buffer; + struct wl_resource *resource = surface->current.buffer_resource; if (resource == NULL) { // NULL commit wlr_buffer_unref(surface->buffer); @@ -322,9 +301,21 @@ static void surface_apply_damage(struct wlr_surface *surface) { if (surface->buffer != NULL && surface->buffer->released) { pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current->buffer_damage); + pixman_region32_copy(&damage, &surface->current.buffer_damage); + + pixman_region32_t surface_damage; + pixman_region32_init(&surface_damage); + pixman_region32_copy(&surface_damage, &surface->current.surface_damage); + wlr_region_transform(&surface_damage, &surface_damage, + surface->current.transform, + surface->current.buffer_width, surface->current.buffer_height); + wlr_region_scale(&surface_damage, &surface_damage, + surface->current.scale); + pixman_region32_union(&damage, &damage, &surface_damage); + pixman_region32_fini(&surface_damage); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, - surface->current->buffer_width, surface->current->buffer_height); + surface->current.buffer_width, surface->current.buffer_height); struct wlr_buffer *updated_buffer = wlr_buffer_apply_damage(surface->buffer, resource, &damage); @@ -350,9 +341,17 @@ static void surface_apply_damage(struct wlr_surface *surface) { } static void surface_commit_pending(struct wlr_surface *surface) { - bool invalid_buffer = surface->pending->invalid & WLR_SURFACE_INVALID_BUFFER; + bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER; - surface_move_state(surface, surface->pending, surface->current); + surface_state_finalize(surface, &surface->pending); + + surface->sx += surface->pending.dx; + surface->sy += surface->pending.dy; + surface_update_damage(&surface->buffer_damage, + &surface->current, &surface->pending); + + surface_state_copy(&surface->previous, &surface->current); + surface_state_move(&surface->current, &surface->pending); if (invalid_buffer) { surface_apply_damage(surface); @@ -375,11 +374,7 @@ static void surface_commit_pending(struct wlr_surface *surface) { surface->role_committed(surface, surface->role_data); } - // TODO: add the invalid bitfield to this callback wlr_signal_emit_safe(&surface->events.commit, surface); - - pixman_region32_clear(&surface->current->surface_damage); - pixman_region32_clear(&surface->current->buffer_damage); } static bool subsurface_is_synchronized(struct wlr_subsurface *subsurface) { @@ -406,18 +401,18 @@ static bool subsurface_is_synchronized(struct wlr_subsurface *subsurface) { */ static void subsurface_parent_commit(struct wlr_subsurface *subsurface, bool synchronized) { - struct wlr_surface *surface = subsurface->surface; + struct wlr_surface *surface = subsurface->surface; if (synchronized || subsurface->synchronized) { if (subsurface->has_cache) { - surface_move_state(surface, subsurface->cached, surface->pending); + surface_state_move(&surface->pending, &subsurface->cached); surface_commit_pending(surface); subsurface->has_cache = false; - subsurface->cached->invalid = 0; + subsurface->cached.committed = 0; } - struct wlr_subsurface *tmp; - wl_list_for_each(tmp, &surface->subsurfaces, parent_link) { - subsurface_parent_commit(tmp, true); + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { + subsurface_parent_commit(subsurface, true); } } } @@ -426,22 +421,16 @@ static void subsurface_commit(struct wlr_subsurface *subsurface) { struct wlr_surface *surface = subsurface->surface; if (subsurface_is_synchronized(subsurface)) { - surface_move_state(surface, surface->pending, subsurface->cached); + surface_state_move(&subsurface->cached, &surface->pending); subsurface->has_cache = true; } else { if (subsurface->has_cache) { - surface_move_state(surface, subsurface->cached, surface->pending); + surface_state_move(&surface->pending, &subsurface->cached); surface_commit_pending(surface); subsurface->has_cache = false; - } else { surface_commit_pending(surface); } - - struct wlr_subsurface *tmp; - wl_list_for_each(tmp, &surface->subsurfaces, parent_link) { - subsurface_parent_commit(tmp, false); - } } } @@ -453,30 +442,29 @@ static void surface_commit(struct wl_client *client, struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(surface); subsurface_commit(subsurface); - return; + } else { + surface_commit_pending(surface); } - surface_commit_pending(surface); - - struct wlr_subsurface *tmp; - wl_list_for_each(tmp, &surface->subsurfaces, parent_link) { - subsurface_parent_commit(tmp, false); + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { + subsurface_parent_commit(subsurface, false); } } static void surface_set_buffer_transform(struct wl_client *client, struct wl_resource *resource, int transform) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - surface->pending->invalid |= WLR_SURFACE_INVALID_TRANSFORM; - surface->pending->transform = transform; + surface->pending.committed |= WLR_SURFACE_STATE_TRANSFORM; + surface->pending.transform = transform; } static void surface_set_buffer_scale(struct wl_client *client, struct wl_resource *resource, int32_t scale) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - surface->pending->invalid |= WLR_SURFACE_INVALID_SCALE; - surface->pending->scale = scale; + surface->pending.committed |= WLR_SURFACE_STATE_SCALE; + surface->pending.scale = scale; } static void surface_damage_buffer(struct wl_client *client, @@ -487,9 +475,9 @@ static void surface_damage_buffer(struct wl_client *client, if (width < 0 || height < 0) { return; } - surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER_DAMAGE; - pixman_region32_union_rect(&surface->pending->buffer_damage, - &surface->pending->buffer_damage, + surface->pending.committed |= WLR_SURFACE_STATE_BUFFER_DAMAGE; + pixman_region32_union_rect(&surface->pending.buffer_damage, + &surface->pending.buffer_damage, x, y, width, height); } @@ -512,12 +500,7 @@ struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource) { return wl_resource_get_user_data(resource); } -static struct wlr_surface_state *surface_state_create(void) { - struct wlr_surface_state *state = - calloc(1, sizeof(struct wlr_surface_state)); - if (state == NULL) { - return NULL; - } +static void surface_state_init(struct wlr_surface_state *state) { state->scale = 1; state->transform = WL_OUTPUT_TRANSFORM_NORMAL; @@ -528,12 +511,11 @@ static struct wlr_surface_state *surface_state_create(void) { pixman_region32_init(&state->opaque); pixman_region32_init_rect(&state->input, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); - - return state; } -static void surface_state_destroy(struct wlr_surface_state *state) { +static void surface_state_finish(struct wlr_surface_state *state) { surface_state_reset_buffer(state); + struct wl_resource *resource, *tmp; wl_resource_for_each_safe(resource, tmp, &state->frame_callback_list) { wl_resource_destroy(resource); @@ -543,8 +525,6 @@ static void surface_state_destroy(struct wlr_surface_state *state) { pixman_region32_fini(&state->buffer_damage); pixman_region32_fini(&state->opaque); pixman_region32_fini(&state->input); - - free(state); } static void subsurface_destroy(struct wlr_subsurface *subsurface) { @@ -555,7 +535,7 @@ static void subsurface_destroy(struct wlr_subsurface *subsurface) { wlr_signal_emit_safe(&subsurface->events.destroy, subsurface); wl_list_remove(&subsurface->surface_destroy.link); - surface_state_destroy(subsurface->cached); + surface_state_finish(&subsurface->cached); if (subsurface->parent) { wl_list_remove(&subsurface->parent_link); @@ -578,8 +558,10 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(surface->resource)); wl_list_remove(&surface->renderer_destroy.link); - surface_state_destroy(surface->pending); - surface_state_destroy(surface->current); + surface_state_finish(&surface->pending); + surface_state_finish(&surface->current); + surface_state_finish(&surface->previous); + pixman_region32_fini(&surface->buffer_damage); wlr_buffer_unref(surface->buffer); free(surface); } @@ -615,14 +597,16 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client, surface->renderer = renderer; - surface->current = surface_state_create(); - surface->pending = surface_state_create(); + surface_state_init(&surface->current); + surface_state_init(&surface->pending); + surface_state_init(&surface->previous); wl_signal_init(&surface->events.commit); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.new_subsurface); wl_list_init(&surface->subsurfaces); wl_list_init(&surface->subsurface_pending_list); + pixman_region32_init(&surface->buffer_damage); wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy); surface->renderer_destroy.notify = surface_handle_renderer_destroy; @@ -696,10 +680,8 @@ static void subsurface_handle_set_position(struct wl_client *client, return; } - struct wlr_surface *surface = subsurface->surface; - surface->pending->invalid |= WLR_SURFACE_INVALID_SUBSURFACE_POSITION; - surface->pending->subsurface_position.x = x; - surface->pending->subsurface_position.y = y; + subsurface->pending.x = x; + subsurface->pending.y = y; } static struct wlr_subsurface *subsurface_find_sibling( @@ -806,6 +788,34 @@ static const struct wl_subsurface_interface subsurface_implementation = { .set_desync = subsurface_handle_set_desync, }; +static void subsurface_role_committed(struct wlr_surface *surface, void *data) { + struct wlr_subsurface *subsurface = data; + + if (subsurface->current.x != subsurface->pending.x || + subsurface->current.y != subsurface->pending.y) { + // Subsurface has moved + int dx = subsurface->current.x - subsurface->pending.x; + int dy = subsurface->current.y - subsurface->pending.y; + + subsurface->current.x = subsurface->pending.x; + subsurface->current.y = subsurface->pending.y; + + if ((surface->current.transform & WL_OUTPUT_TRANSFORM_90) != 0) { + int tmp = dx; + dx = dy; + dy = tmp; + } + + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, + dx * surface->previous.scale, dy * surface->previous.scale, + surface->previous.buffer_width, surface->previous.buffer_height); + pixman_region32_union_rect(&surface->buffer_damage, + &surface->buffer_damage, 0, 0, + surface->current.buffer_width, surface->current.buffer_height); + } +} + static void subsurface_handle_parent_destroy(struct wl_listener *listener, void *data) { struct wlr_subsurface *subsurface = @@ -836,18 +846,13 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface, wl_client_post_no_memory(client); return NULL; } - subsurface->cached = surface_state_create(); - if (subsurface->cached == NULL) { - free(subsurface); - wl_client_post_no_memory(client); - return NULL; - } + surface_state_init(&subsurface->cached); subsurface->synchronized = true; subsurface->surface = surface; subsurface->resource = wl_resource_create(client, &wl_subsurface_interface, version, id); if (subsurface->resource == NULL) { - surface_state_destroy(subsurface->cached); + surface_state_finish(&subsurface->cached); free(subsurface); wl_client_post_no_memory(client); return NULL; @@ -869,7 +874,8 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface, wl_list_insert(parent->subsurface_pending_list.prev, &subsurface->parent_pending_link); - surface->role_data = subsurface; + wlr_surface_set_role_committed(surface, subsurface_role_committed, + subsurface); struct wl_list *resource_link = wl_resource_get_link(subsurface->resource); if (resource_list != NULL) { @@ -895,17 +901,17 @@ struct wlr_surface *wlr_surface_get_root_surface(struct wlr_surface *surface) { bool wlr_surface_point_accepts_input(struct wlr_surface *surface, double sx, double sy) { - return sx >= 0 && sx < surface->current->width && - sy >= 0 && sy < surface->current->height && - pixman_region32_contains_point(&surface->current->input, sx, sy, NULL); + return sx >= 0 && sx < surface->current.width && + sy >= 0 && sy < surface->current.height && + pixman_region32_contains_point(&surface->current.input, sx, sy, NULL); } struct wlr_surface *wlr_surface_surface_at(struct wlr_surface *surface, double sx, double sy, double *sub_x, double *sub_y) { struct wlr_subsurface *subsurface; wl_list_for_each_reverse(subsurface, &surface->subsurfaces, parent_link) { - double _sub_x = subsurface->surface->current->subsurface_position.x; - double _sub_y = subsurface->surface->current->subsurface_position.y; + double _sub_x = subsurface->current.x; + double _sub_y = subsurface->current.y; struct wlr_surface *sub = wlr_surface_surface_at(subsurface->surface, sx - _sub_x, sy - _sub_y, sub_x, sub_y); if (sub != NULL) { @@ -952,7 +958,7 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface, const struct timespec *when) { struct wl_resource *resource, *tmp; wl_resource_for_each_safe(resource, tmp, - &surface->current->frame_callback_list) { + &surface->current.frame_callback_list) { wl_callback_send_done(resource, timespec_to_msec(when)); wl_resource_destroy(resource); } @@ -971,9 +977,9 @@ static void surface_for_each_surface(struct wlr_surface *surface, int x, int y, struct wlr_subsurface *subsurface; wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { - struct wlr_surface_state *state = subsurface->surface->current; - int sx = state->subsurface_position.x; - int sy = state->subsurface_position.y; + struct wlr_subsurface_state *state = &subsurface->current; + int sx = state->x; + int sy = state->y; surface_for_each_surface(subsurface->surface, x + sx, y + sy, iterator, user_data); @@ -997,16 +1003,16 @@ static void handle_bounding_box_surface(struct wlr_surface *surface, acc->min_x = min(x, acc->min_x); acc->min_y = min(y, acc->min_y); - acc->max_x = max(x + surface->current->width, acc->max_x); - acc->max_y = max(y + surface->current->height, acc->max_y); + acc->max_x = max(x + surface->current.width, acc->max_x); + acc->max_y = max(y + surface->current.height, acc->max_y); } void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box) { struct bound_acc acc = { .min_x = 0, .min_y = 0, - .max_x = surface->current->width, - .max_y = surface->current->height, + .max_x = surface->current.width, + .max_y = surface->current.height, }; wlr_surface_for_each_surface(surface, handle_bounding_box_surface, &acc); diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index c1350931..5d0bfa1f 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -39,8 +39,8 @@ bool compare_xdg_surface_toplevel_state(struct wlr_xdg_toplevel *state) { if (wl_list_empty(&state->base->configure_list)) { // last configure is actually the current state, just use it configured.state = state->current; - configured.width = state->base->surface->current->width; - configured.height = state->base->surface->current->height; + configured.width = state->base->surface->current.width; + configured.height = state->base->surface->current.height; } else { struct wlr_xdg_surface_configure *configure = wl_container_of(state->base->configure_list.prev, configure, link); diff --git a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c index e2e1e480..29cbe2dd 100644 --- a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c +++ b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c @@ -287,8 +287,8 @@ bool compare_xdg_surface_v6_toplevel_state(struct wlr_xdg_toplevel_v6 *state) { if (wl_list_empty(&state->base->configure_list)) { // last configure is actually the current state, just use it configured.state = state->current; - configured.width = state->base->surface->current->width; - configured.height = state->base->surface->current->height; + configured.width = state->base->surface->current.width; + configured.height = state->base->surface->current.height; } else { struct wlr_xdg_surface_v6_configure *configure = wl_container_of(state->base->configure_list.prev, configure, link);