<commit_before>#include <assert.h>
#include <stdlib.h>
#include <wayland-server.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
#include <wlr/render/matrix.h>
#include <wlr/types/wlr_region.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h>
#include <wlr/util/region.h>
#include "util/signal.h"

static void wlr_surface_state_reset_buffer(struct wlr_surface_state *state) {
	if (state->buffer) {
		wl_list_remove(&state->buffer_destroy_listener.link);
		state->buffer = NULL;
	}
}

static void buffer_destroy(struct wl_listener *listener, void *data) {
	struct wlr_surface_state *state =
		wl_container_of(listener, state, buffer_destroy_listener);

	wl_list_remove(&state->buffer_destroy_listener.link);
	state->buffer = NULL;
}

static void wlr_surface_state_release_buffer(struct wlr_surface_state *state) {
	if (state->buffer) {
		wl_resource_post_event(state->buffer, WL_BUFFER_RELEASE);
		wl_list_remove(&state->buffer_destroy_listener.link);
		state->buffer = NULL;
	}
}

static void wlr_surface_state_set_buffer(struct wlr_surface_state *state,
		struct wl_resource *buffer) {
	state->buffer = buffer;
	if (buffer) {
		wl_resource_add_destroy_listener(buffer,
			&state->buffer_destroy_listener);
		state->buffer_destroy_listener.notify = buffer_destroy;
	}
}

static void surface_destroy(struct wl_client *client,
		struct wl_resource *resource) {
	wl_resource_destroy(resource);
}

static void surface_attach(struct wl_client *client,
		struct wl_resource *resource,
		struct wl_resource *buffer, int32_t sx, int32_t sy) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);

	surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER;
	surface->pending->sx = sx;
	surface->pending->sy = sy;
	wlr_surface_state_reset_buffer(surface->pending);
	wlr_surface_state_set_buffer(surface->pending, buffer);
}

static void surface_damage(struct wl_client *client,
		struct wl_resource *resource,
		int32_t x, int32_t y, int32_t width, int32_t height) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);
	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,
		x, y, width, height);
}

static struct wlr_frame_callback *frame_callback_from_resource(
		struct wl_resource *resource) {
	assert(wl_resource_instance_of(resource, &wl_callback_interface, NULL));
	return wl_resource_get_user_data(resource);
}

static void destroy_frame_callback(struct wl_resource *resource) {
	struct wlr_frame_callback *cb = frame_callback_from_resource(resource);
	wl_list_remove(&cb->link);
	free(cb);
}

static void surface_frame(struct wl_client *client,
		struct wl_resource *resource, uint32_t callback) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);

	struct wlr_frame_callback *cb =
		calloc(1, sizeof(struct wlr_frame_callback));
	if (cb == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
		callback);
	if (cb->resource == NULL) {
		free(cb);
		wl_resource_post_no_memory(resource);
		return;
	}

	wl_resource_set_implementation(cb->resource, NULL, cb,
		destroy_frame_callback);

	wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link);

	surface->pending->invalid |= WLR_SURFACE_INVALID_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);
	}
	surface->pending->invalid |= WLR_SURFACE_INVALID_OPAQUE_REGION;
	if (region_resource) {
		pixman_region32_t *region = wlr_region_from_resource(region_resource);
		pixman_region32_copy(&surface->pending->opaque, region);
	} else {
		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;
	if (region_resource) {
		pixman_region32_t *region = wlr_region_from_resource(region_resource);
		pixman_region32_copy(&surface->pending->input, region);
	} else {
		pixman_region32_init_rect(&surface->pending->input,
			INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
	}
}

static bool wlr_surface_update_size(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;
	}

	int scale = state->scale;
	enum wl_output_transform transform = state->transform;

	wlr_texture_get_buffer_size(surface->texture, state->buffer,
		&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 tmp = width;
		width = height;
		height = tmp;
	}

	struct wlr_frame_callback *cb, *tmp;
	wl_list_for_each_safe(cb, tmp, &state->frame_callback_list, link) {
		wl_resource_destroy(cb->resource);
	}
	wl_list_init(&state->frame_callback_list);

	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;
}

/**
 * Append pending state to current state and clear pending state.
 */
static void wlr_surface_move_state(struct wlr_surface *surface,
		struct wlr_surface_state *next, struct wlr_surface_state *state) {<commit_msg>surface: don't reset frame_callback_list on resize<commit_after>#include <assert.h>
#include <stdlib.h>
#include <wayland-server.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
#include <wlr/render/matrix.h>
#include <wlr/types/wlr_region.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h>
#include <wlr/util/region.h>
#include "util/signal.h"

static void wlr_surface_state_reset_buffer(struct wlr_surface_state *state) {
	if (state->buffer) {
		wl_list_remove(&state->buffer_destroy_listener.link);
		state->buffer = NULL;
	}
}

static void buffer_destroy(struct wl_listener *listener, void *data) {
	struct wlr_surface_state *state =
		wl_container_of(listener, state, buffer_destroy_listener);

	wl_list_remove(&state->buffer_destroy_listener.link);
	state->buffer = NULL;
}

static void wlr_surface_state_release_buffer(struct wlr_surface_state *state) {
	if (state->buffer) {
		wl_resource_post_event(state->buffer, WL_BUFFER_RELEASE);
		wl_list_remove(&state->buffer_destroy_listener.link);
		state->buffer = NULL;
	}
}

static void wlr_surface_state_set_buffer(struct wlr_surface_state *state,
		struct wl_resource *buffer) {
	state->buffer = buffer;
	if (buffer) {
		wl_resource_add_destroy_listener(buffer,
			&state->buffer_destroy_listener);
		state->buffer_destroy_listener.notify = buffer_destroy;
	}
}

static void surface_destroy(struct wl_client *client,
		struct wl_resource *resource) {
	wl_resource_destroy(resource);
}

static void surface_attach(struct wl_client *client,
		struct wl_resource *resource,
		struct wl_resource *buffer, int32_t sx, int32_t sy) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);

	surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER;
	surface->pending->sx = sx;
	surface->pending->sy = sy;
	wlr_surface_state_reset_buffer(surface->pending);
	wlr_surface_state_set_buffer(surface->pending, buffer);
}

static void surface_damage(struct wl_client *client,
		struct wl_resource *resource,
		int32_t x, int32_t y, int32_t width, int32_t height) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);
	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,
		x, y, width, height);
}

static struct wlr_frame_callback *frame_callback_from_resource(
		struct wl_resource *resource) {
	assert(wl_resource_instance_of(resource, &wl_callback_interface, NULL));
	return wl_resource_get_user_data(resource);
}

static void destroy_frame_callback(struct wl_resource *resource) {
	struct wlr_frame_callback *cb = frame_callback_from_resource(resource);
	wl_list_remove(&cb->link);
	free(cb);
}

static void surface_frame(struct wl_client *client,
		struct wl_resource *resource, uint32_t callback) {
	struct wlr_surface *surface = wlr_surface_from_resource(resource);

	struct wlr_frame_callback *cb =
		calloc(1, sizeof(struct wlr_frame_callback));
	if (cb == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
		callback);
	if (cb->resource == NULL) {
		free(cb);
		wl_resource_post_no_memory(resource);
		return;
	}

	wl_resource_set_implementation(cb->resource, NULL, cb,
		destroy_frame_callback);

	wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link);

	surface->pending->invalid |= WLR_SURFACE_INVALID_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);
	}
	surface->pending->invalid |= WLR_SURFACE_INVALID_OPAQUE_REGION;
	if (region_resource) {
		pixman_region32_t *region = wlr_region_from_resource(region_resource);
		pixman_region32_copy(&surface->pending->opaque, region);
	} else {
		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;
	if (region_resource) {
		pixman_region32_t *region = wlr_region_from_resource(region_resource);
		pixman_region32_copy(&surface->pending->input, region);
	} else {
		pixman_region32_init_rect(&surface->pending->input,
			INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
	}
}

static bool wlr_surface_update_size(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;
	}

	int scale = state->scale;
	enum wl_output_transform transform = state->transform;

	wlr_texture_get_buffer_size(surface->texture, state->buffer,
		&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 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;
}

/**
 * Append pending state to current state and clear pending state.
 */
static void wlr_surface_move_state(struct wlr_surface *surface,
		struct wlr_surface_state *next, struct wlr_surface_state *state) {
{'fraction_non_alphanumeric': 0.11204905630325715, 'fraction_numerical': 0.010512064983674444, 'mean_word_length': 6.267361111111111, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 178, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3264272', 'n_tokens_mistral': 4616, 'n_tokens_neox': 4349, 'n_words': 813}