mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-12-20 16:10:04 +01:00
Compare commits
53 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0ae9dffdb | ||
|
|
1cd9d3bec5 | ||
|
|
de06f60a29 | ||
|
|
d8f110c5bc | ||
|
|
f02d3ef28b | ||
|
|
38f18cd684 | ||
|
|
bcba7cb12b | ||
|
|
1a6702938d | ||
|
|
f57e7e40d3 | ||
|
|
766a228da4 | ||
|
|
ff55f91055 | ||
|
|
d981860314 | ||
|
|
cda69b696d | ||
|
|
0c437f6e98 | ||
|
|
35ab453360 | ||
|
|
1fc9409df2 | ||
|
|
885bf8f5e8 | ||
|
|
74be9ddaab | ||
|
|
b28b269106 | ||
|
|
f870d63bad | ||
|
|
bdc75d058b | ||
|
|
86eaa44a3a | ||
|
|
0e002db57c | ||
|
|
b29ebe4a1c | ||
|
|
efe820f575 | ||
|
|
a21c618cd3 | ||
|
|
5bc39071d1 | ||
|
|
6f2ce4766f | ||
|
|
f43ac6cf9c | ||
|
|
0a4cd88637 | ||
|
|
b79fc11df8 | ||
|
|
1f96bcc1db | ||
|
|
0992422493 | ||
|
|
4900daa787 | ||
|
|
72a290ba01 | ||
|
|
055c0d28d1 | ||
|
|
a4cafc1ef5 | ||
|
|
f9de859194 | ||
|
|
43388cd277 | ||
|
|
89e1ea130d | ||
|
|
b4bec0cd3a | ||
|
|
7df7b0e092 | ||
|
|
a095120b7d | ||
|
|
9e107e3c77 | ||
|
|
490769f2a6 | ||
|
|
2b8f94cf09 | ||
|
|
52834f29ad | ||
|
|
03f06207f0 | ||
|
|
81a08aeeb0 | ||
|
|
6cc80472cb | ||
|
|
2005cc0fd6 | ||
|
|
7d0f337a35 | ||
|
|
4534421279 |
39 changed files with 389 additions and 210 deletions
|
|
@ -41,9 +41,10 @@ tasks:
|
|||
cd wlroots/build-gcc/tinywl
|
||||
sudo modprobe vkms
|
||||
udevadm settle
|
||||
card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)"
|
||||
export WLR_BACKENDS=drm
|
||||
export WLR_RENDERER=pixman
|
||||
export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card
|
||||
export WLR_DRM_DEVICES="$card"
|
||||
export UBSAN_OPTIONS=halt_on_error=1
|
||||
sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card
|
||||
sudo chmod ugo+rw "$card"
|
||||
sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ packages:
|
|||
- x11/xcb-util-errors
|
||||
- x11/xcb-util-renderutil
|
||||
- x11/xcb-util-wm
|
||||
- x11-servers/xwayland-devel
|
||||
- x11-servers/xwayland
|
||||
- sysutils/libdisplay-info
|
||||
- sysutils/seatd
|
||||
- gmake
|
||||
|
|
|
|||
|
|
@ -152,18 +152,20 @@ static bool create_gamma_lut_blob(struct wlr_drm_backend *drm,
|
|||
|
||||
bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm,
|
||||
int width, int height, const pixman_region32_t *damage, uint32_t *blob_id) {
|
||||
if (!pixman_region32_not_empty(damage)) {
|
||||
*blob_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
pixman_region32_t clipped;
|
||||
pixman_region32_init(&clipped);
|
||||
pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height);
|
||||
|
||||
int rects_len;
|
||||
const pixman_box32_t *rects = pixman_region32_rectangles(&clipped, &rects_len);
|
||||
int ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id);
|
||||
|
||||
int ret;
|
||||
if (rects_len > 0) {
|
||||
ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id);
|
||||
} else {
|
||||
ret = 0;
|
||||
*blob_id = 0;
|
||||
}
|
||||
pixman_region32_fini(&clipped);
|
||||
if (ret != 0) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to create FB_DAMAGE_CLIPS property blob");
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
|
|||
struct wlr_drm_plane *plane = &drm->planes[i];
|
||||
drm_plane_finish_surface(plane);
|
||||
wlr_drm_format_set_finish(&plane->formats);
|
||||
free(plane->cursor_sizes);
|
||||
}
|
||||
|
||||
free(drm->planes);
|
||||
|
|
@ -576,6 +577,16 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta
|
|||
|
||||
conn->cursor_enabled = false;
|
||||
conn->crtc = NULL;
|
||||
|
||||
// Legacy uAPI doesn't support requesting page-flip events when
|
||||
// turning off a CRTC
|
||||
if (page_flip != NULL && conn->backend->iface == &legacy_iface) {
|
||||
drm_page_flip_pop(page_flip, crtc->id);
|
||||
conn->pending_page_flip = NULL;
|
||||
if (page_flip->connectors_len == 0) {
|
||||
drm_page_flip_destroy(page_flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -607,6 +618,7 @@ static bool drm_commit(struct wlr_drm_backend *drm,
|
|||
if (page_flip == NULL) {
|
||||
return false;
|
||||
}
|
||||
page_flip->async = (flags & DRM_MODE_PAGE_FLIP_ASYNC);
|
||||
}
|
||||
|
||||
bool ok = drm->iface->commit(drm, state, page_flip, flags, test_only);
|
||||
|
|
@ -784,13 +796,12 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) {
|
||||
if (output->current_mode == NULL &&
|
||||
!(state->committed & WLR_OUTPUT_STATE_MODE)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Can't enable an output without a mode");
|
||||
return false;
|
||||
}
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled &&
|
||||
output->width == 0 && output->height == 0 &&
|
||||
!(state->committed & WLR_OUTPUT_STATE_MODE)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Can't enable an output without a mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) &&
|
||||
|
|
@ -801,6 +812,22 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_BUFFER) && conn->backend->mgpu_renderer.wlr_rend) {
|
||||
struct wlr_dmabuf_attributes dmabuf;
|
||||
if (!wlr_buffer_get_dmabuf(state->buffer, &dmabuf)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Buffer is not a DMA-BUF");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wlr_drm_format_set_has(&conn->backend->mgpu_formats, dmabuf.format, dmabuf.modifier)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Buffer format 0x%"PRIX32" with modifier 0x%"PRIX64" cannot be "
|
||||
"imported into multi-GPU renderer",
|
||||
dmabuf.format, dmabuf.modifier);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_only && conn->backend->parent) {
|
||||
// If we're running as a secondary GPU, we can't perform an atomic
|
||||
// commit without blitting a buffer.
|
||||
|
|
@ -1554,6 +1581,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
|
||||
wlr_log(WLR_INFO, "Detected modes:");
|
||||
|
||||
bool found_current_mode = false;
|
||||
for (int i = 0; i < drm_conn->count_modes; ++i) {
|
||||
if (drm_conn->modes[i].flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
continue;
|
||||
|
|
@ -1572,14 +1600,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
if (current_modeinfo != NULL && memcmp(&mode->drm_mode,
|
||||
current_modeinfo, sizeof(*current_modeinfo)) == 0) {
|
||||
wlr_output_state_set_mode(&state, &mode->wlr_mode);
|
||||
|
||||
uint64_t mode_id = 0;
|
||||
get_drm_prop(drm->fd, wlr_conn->crtc->id,
|
||||
wlr_conn->crtc->props.mode_id, &mode_id);
|
||||
|
||||
wlr_conn->crtc->own_mode_id = false;
|
||||
wlr_conn->crtc->mode_id = mode_id;
|
||||
wlr_conn->refresh = calculate_refresh_rate(current_modeinfo);
|
||||
found_current_mode = true;
|
||||
}
|
||||
|
||||
wlr_log(WLR_INFO, " %"PRId32"x%"PRId32" @ %.3f Hz %s",
|
||||
|
|
@ -1590,6 +1611,23 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
wl_list_insert(modes.prev, &mode->wlr_mode.link);
|
||||
}
|
||||
|
||||
if (current_modeinfo != NULL) {
|
||||
int32_t refresh = calculate_refresh_rate(current_modeinfo);
|
||||
|
||||
if (!found_current_mode) {
|
||||
wlr_output_state_set_custom_mode(&state,
|
||||
current_modeinfo->hdisplay, current_modeinfo->vdisplay, refresh);
|
||||
}
|
||||
|
||||
uint64_t mode_id = 0;
|
||||
get_drm_prop(drm->fd, wlr_conn->crtc->id,
|
||||
wlr_conn->crtc->props.mode_id, &mode_id);
|
||||
|
||||
wlr_conn->crtc->own_mode_id = false;
|
||||
wlr_conn->crtc->mode_id = mode_id;
|
||||
wlr_conn->refresh = refresh;
|
||||
}
|
||||
|
||||
free(current_modeinfo);
|
||||
|
||||
wlr_output_init(output, &drm->backend, &output_impl, drm->session->event_loop, &state);
|
||||
|
|
@ -2008,6 +2046,12 @@ static void handle_page_flip(int fd, unsigned seq,
|
|||
if (conn != NULL) {
|
||||
conn->pending_page_flip = NULL;
|
||||
}
|
||||
|
||||
uint32_t present_flags = WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
|
||||
if (!page_flip->async) {
|
||||
present_flags |= WLR_OUTPUT_PRESENT_VSYNC;
|
||||
}
|
||||
|
||||
if (page_flip->connectors_len == 0) {
|
||||
drm_page_flip_destroy(page_flip);
|
||||
}
|
||||
|
|
@ -2038,8 +2082,6 @@ static void handle_page_flip(int fd, unsigned seq,
|
|||
drm_fb_move(&layer->current_fb, &layer->queued_fb);
|
||||
}
|
||||
|
||||
uint32_t present_flags = WLR_OUTPUT_PRESENT_VSYNC |
|
||||
WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
|
||||
/* Don't report ZERO_COPY in multi-gpu situations, because we had to copy
|
||||
* data between the GPUs, even if we were using the direct scanout
|
||||
* interface.
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
|||
state->base->adaptive_sync_enabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
if (cursor != NULL && drm_connector_is_cursor_visible(conn)) {
|
||||
if (cursor != NULL && state->active && drm_connector_is_cursor_visible(conn)) {
|
||||
struct wlr_drm_fb *cursor_fb = state->cursor_fb;
|
||||
if (cursor_fb == NULL) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB");
|
||||
|
|
@ -170,7 +170,9 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
||||
// Legacy uAPI doesn't support requesting page-flip events when
|
||||
// turning off a CRTC
|
||||
if (state->active && (flags & DRM_MODE_PAGE_FLIP_EVENT)) {
|
||||
if (drmModePageFlip(drm->fd, crtc->id, fb_id, flags, page_flip)) {
|
||||
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -170,12 +170,6 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
|
|||
has_best = true;
|
||||
}
|
||||
}
|
||||
if (st->orig[i] == UNMATCHED) {
|
||||
st->res[i] = UNMATCHED;
|
||||
if (match_obj_(st, skips, score, replaced, i + 1)) {
|
||||
has_best = true;
|
||||
}
|
||||
}
|
||||
if (st->exit_early) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -211,13 +205,13 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
|
|||
}
|
||||
}
|
||||
|
||||
if (has_best) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Maybe this resource can't be matched
|
||||
st->res[i] = UNMATCHED;
|
||||
return match_obj_(st, skips, score, replaced, i + 1);
|
||||
if (match_obj_(st, skips, score, replaced, i + 1)) {
|
||||
has_best = true;
|
||||
}
|
||||
|
||||
return has_best;
|
||||
}
|
||||
|
||||
size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs],
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
|
||||
static const struct wlr_output_impl output_impl = {
|
||||
.destroy = output_destroy,
|
||||
.test = output_test,
|
||||
.commit = output_commit,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,9 @@ static void linux_dmabuf_feedback_v1_handle_main_device(void *data,
|
|||
"falling back to primary node", name);
|
||||
}
|
||||
|
||||
feedback_data->backend->drm_render_name = strdup(name);
|
||||
struct wlr_wl_backend *wl = feedback_data->backend;
|
||||
assert(wl->drm_render_name == NULL);
|
||||
wl->drm_render_name = strdup(name);
|
||||
|
||||
drmFreeDevice(&device);
|
||||
}
|
||||
|
|
@ -305,6 +307,7 @@ static char *get_render_name(const char *name) {
|
|||
static void legacy_drm_handle_device(void *data, struct wl_drm *drm,
|
||||
const char *name) {
|
||||
struct wlr_wl_backend *wl = data;
|
||||
assert(wl->drm_render_name == NULL);
|
||||
wl->drm_render_name = get_render_name(name);
|
||||
}
|
||||
|
||||
|
|
@ -621,6 +624,8 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
goto error_registry;
|
||||
}
|
||||
|
||||
wl_display_roundtrip(wl->remote_display); // process initial event bursts
|
||||
|
||||
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback_v1 = NULL;
|
||||
struct wlr_wl_linux_dmabuf_feedback_v1 feedback_data = { .backend = wl };
|
||||
if (wl->zwp_linux_dmabuf_v1 != NULL &&
|
||||
|
|
@ -638,15 +643,17 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
if (wl->legacy_drm != NULL) {
|
||||
wl_drm_destroy(wl->legacy_drm);
|
||||
wl->legacy_drm = NULL;
|
||||
|
||||
free(wl->drm_render_name);
|
||||
wl->drm_render_name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
wl_display_roundtrip(wl->remote_display); // get linux-dmabuf formats
|
||||
wl_display_roundtrip(wl->remote_display); // get linux-dmabuf feedback events
|
||||
|
||||
if (feedback_data.format_table != NULL) {
|
||||
munmap(feedback_data.format_table, feedback_data.format_table_size);
|
||||
}
|
||||
|
||||
if (feedback_data.format_table != NULL) {
|
||||
munmap(feedback_data.format_table, feedback_data.format_table_size);
|
||||
}
|
||||
if (linux_dmabuf_feedback_v1 != NULL) {
|
||||
zwp_linux_dmabuf_feedback_v1_destroy(linux_dmabuf_feedback_v1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ static struct wl_buffer *import_shm(struct wlr_wl_backend *wl,
|
|||
struct wlr_shm_attributes *shm) {
|
||||
enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format);
|
||||
uint32_t size = shm->stride * shm->height;
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, size);
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, shm->offset + size);
|
||||
if (pool == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static void output_handle_frame(struct wl_listener *listener, void *data) {
|
|||
layers_arr.size / sizeof(struct wlr_output_layer_state));
|
||||
|
||||
if (!wlr_output_test_state(output->wlr_output, &output_state)) {
|
||||
wlr_log(WLR_ERROR, "wlr_output_test() failed");
|
||||
wlr_log(WLR_ERROR, "wlr_output_test_state() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ struct wlr_drm_page_flip {
|
|||
struct wl_list link; // wlr_drm_connector.page_flips
|
||||
struct wlr_drm_page_flip_connector *connectors;
|
||||
size_t connectors_len;
|
||||
// True if DRM_MODE_PAGE_FLIP_ASYNC was set
|
||||
bool async;
|
||||
};
|
||||
|
||||
struct wlr_drm_page_flip_connector {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ struct wlr_drag {
|
|||
|
||||
struct wl_listener source_destroy;
|
||||
struct wl_listener seat_client_destroy;
|
||||
struct wl_listener focus_destroy;
|
||||
struct wl_listener icon_destroy;
|
||||
|
||||
void *data;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
#include <wayland-server-core.h>
|
||||
#include <wlr/util/addon.h>
|
||||
|
||||
struct wlr_buffer;
|
||||
struct wlr_surface;
|
||||
|
||||
struct wlr_linux_drm_syncobj_surface_v1_state {
|
||||
struct wlr_drm_syncobj_timeline *acquire_timeline;
|
||||
uint64_t acquire_point;
|
||||
|
|
|
|||
|
|
@ -121,8 +121,9 @@ struct wlr_render_pass;
|
|||
* The `frame` event will be emitted when it is a good time for the compositor
|
||||
* to submit a new frame.
|
||||
*
|
||||
* To render a new frame, compositors should call wlr_output_begin_render_pass(),
|
||||
* perform rendering on that render pass and finally call wlr_output_commit().
|
||||
* To render a new frame compositors should call wlr_output_begin_render_pass(),
|
||||
* perform rendering on that render pass, and finally call
|
||||
* wlr_output_commit_state().
|
||||
*/
|
||||
struct wlr_output {
|
||||
const struct wlr_output_impl *impl;
|
||||
|
|
@ -280,7 +281,7 @@ void wlr_output_destroy_global(struct wlr_output *output);
|
|||
* the allocator and renderer to different values.
|
||||
*
|
||||
* Call this function prior to any call to wlr_output_begin_render_pass(),
|
||||
* wlr_output_commit() or wlr_output_cursor_create().
|
||||
* wlr_output_commit_state() or wlr_output_cursor_create().
|
||||
*
|
||||
* The buffer capabilities of the provided must match the capabilities of the
|
||||
* output's backend. Returns false otherwise.
|
||||
|
|
@ -369,12 +370,6 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock);
|
|||
* a lock.
|
||||
*/
|
||||
void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock);
|
||||
/**
|
||||
* Renders software cursors. This is a utility function that can be called when
|
||||
* compositors render.
|
||||
*/
|
||||
void wlr_output_render_software_cursors(struct wlr_output *output,
|
||||
const pixman_region32_t *damage);
|
||||
/**
|
||||
* Render software cursors.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@
|
|||
*
|
||||
* To configure output layers, callers should call wlr_output_layer_create() to
|
||||
* create layers, attach struct wlr_output_layer_state onto
|
||||
* struct wlr_output_state via wlr_output_set_layers() to describe their new
|
||||
* state, and commit the output via wlr_output_commit().
|
||||
* struct wlr_output_state via wlr_output_state_set_layers() to describe their new
|
||||
* state, and commit the output via wlr_output_commit_state().
|
||||
*
|
||||
* Backends may have arbitrary limitations when it comes to displaying output
|
||||
* layers. Backends indicate whether or not a layer can be displayed via
|
||||
* wlr_output_layer_state.accepted after wlr_output_test() or
|
||||
* wlr_output_commit() is called. Compositors using the output layers API
|
||||
* directly are expected to setup layers, call wlr_output_test(), paint the
|
||||
* layers that the backend rejected with the renderer, then call
|
||||
* wlr_output_commit().
|
||||
* wlr_output_layer_state.accepted after wlr_output_test_state() or
|
||||
* wlr_output_commit_state() is called. Compositors using the output layers API
|
||||
* directly are expected to setup layers, call wlr_output_test_state(), paint
|
||||
* the layers that the backend rejected with the renderer, then call
|
||||
* wlr_output_commit_state().
|
||||
*
|
||||
* Callers are responsible for disabling output layers when they need the full
|
||||
* output contents to be composited onto a single buffer, e.g. during screen
|
||||
|
|
@ -72,9 +72,9 @@ struct wlr_output_layer_state {
|
|||
// to damage the whole buffer.
|
||||
const pixman_region32_t *damage;
|
||||
|
||||
// Populated by the backend after wlr_output_test() and wlr_output_commit(),
|
||||
// indicates whether the backend has acknowledged and will take care of
|
||||
// displaying the layer
|
||||
// Populated by the backend after wlr_output_test_state() and
|
||||
// wlr_output_commit_state(), indicates whether the backend has acknowledged
|
||||
// and will take care of displaying the layer
|
||||
bool accepted;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ void wlr_presentation_event_from_output(struct wlr_presentation_event *event,
|
|||
*
|
||||
* Instead of calling wlr_presentation_surface_sampled() and managing the
|
||||
* struct wlr_presentation_feedback itself, the compositor can call this function
|
||||
* before a wlr_output_commit() call to indicate that the surface's current
|
||||
* before a wlr_output_commit_state() call to indicate that the surface's current
|
||||
* contents have been copied to a buffer which will be displayed on the output.
|
||||
*/
|
||||
void wlr_presentation_surface_textured_on_output(struct wlr_surface *surface,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ struct wlr_screencopy_frame_v1 {
|
|||
struct wlr_output *output;
|
||||
struct wl_listener output_commit;
|
||||
struct wl_listener output_destroy;
|
||||
struct wl_listener output_enable;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ struct wlr_xwm {
|
|||
|
||||
struct wlr_drag *drag;
|
||||
struct wlr_xwayland_surface *drag_focus;
|
||||
struct wlr_xwayland_surface *drop_focus;
|
||||
|
||||
const xcb_query_extension_reply_t *xfixes;
|
||||
const xcb_query_extension_reply_t *xres;
|
||||
|
|
@ -135,6 +136,7 @@ struct wlr_xwm {
|
|||
struct wl_listener compositor_new_surface;
|
||||
struct wl_listener compositor_destroy;
|
||||
struct wl_listener shell_v1_new_surface;
|
||||
struct wl_listener shell_v1_destroy;
|
||||
struct wl_listener seat_set_selection;
|
||||
struct wl_listener seat_set_primary_selection;
|
||||
struct wl_listener seat_start_drag;
|
||||
|
|
@ -143,6 +145,8 @@ struct wlr_xwm {
|
|||
struct wl_listener seat_drag_drop;
|
||||
struct wl_listener seat_drag_destroy;
|
||||
struct wl_listener seat_drag_source_destroy;
|
||||
struct wl_listener drag_focus_destroy;
|
||||
struct wl_listener drop_focus_destroy;
|
||||
};
|
||||
|
||||
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
|
||||
|
|
@ -155,6 +159,7 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride,
|
|||
int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event);
|
||||
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
||||
xcb_client_message_event_t *ev);
|
||||
void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm);
|
||||
|
||||
void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
project(
|
||||
'wlroots',
|
||||
'c',
|
||||
version: '0.18.0',
|
||||
version: '0.18.3',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.59.0',
|
||||
default_options: [
|
||||
'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'c23,c11' : 'c11'),
|
||||
'c_std=' + (meson.version().version_compare('>=1.4.0') ? 'c23,c11' : 'c11'),
|
||||
'warning_level=2',
|
||||
'werror=true',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ void wlr_render_pass_add_texture(struct wlr_render_pass *render_pass,
|
|||
if (!wlr_fbox_empty(&options->src_box)) {
|
||||
const struct wlr_fbox *box = &options->src_box;
|
||||
assert(box->x >= 0 && box->y >= 0 &&
|
||||
box->x + box->width <= options->texture->width &&
|
||||
box->y + box->height <= options->texture->height);
|
||||
(uint32_t)(box->x + box->width) <= options->texture->width &&
|
||||
(uint32_t)(box->y + box->height) <= options->texture->height);
|
||||
}
|
||||
|
||||
render_pass->impl->add_texture(render_pass, options);
|
||||
|
|
|
|||
|
|
@ -572,16 +572,10 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
|||
},
|
||||
};
|
||||
VkClearRect clear_rect = {
|
||||
.rect = {
|
||||
.offset = { box.x, box.y },
|
||||
.extent = { box.width, box.height },
|
||||
},
|
||||
.layerCount = 1,
|
||||
};
|
||||
for (int i = 0; i < clip_rects_len; i++) {
|
||||
VkRect2D rect;
|
||||
convert_pixman_box_to_vk_rect(&clip_rects[i], &rect);
|
||||
vkCmdSetScissor(cb, 0, 1, &rect);
|
||||
convert_pixman_box_to_vk_rect(&clip_rects[i], &clear_rect.rect);
|
||||
vkCmdClearAttachments(cb, 1, &clear_att, 1, &clear_rect);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -267,6 +267,8 @@ struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r,
|
|||
goto error_alloc;
|
||||
}
|
||||
|
||||
wl_list_init(&buf->link);
|
||||
|
||||
VkResult res;
|
||||
VkBufferCreateInfo buf_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
|
|
@ -1224,7 +1226,6 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
|||
|
||||
int mem_type = vulkan_find_mem_type(vk_renderer->dev,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
mem_reqs.memoryTypeBits);
|
||||
if (mem_type < 0) {
|
||||
|
|
@ -1361,6 +1362,19 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
|||
return false;
|
||||
}
|
||||
|
||||
VkMappedMemoryRange mem_range = {
|
||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||
.memory = dst_img_memory,
|
||||
.offset = 0,
|
||||
.size = VK_WHOLE_SIZE,
|
||||
};
|
||||
res = vkInvalidateMappedMemoryRanges(dev, 1, &mem_range);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkInvalidateMappedMemoryRanges", res);
|
||||
vkUnmapMemory(dev, dst_img_memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *d = (const char *)v + img_sub_layout.offset;
|
||||
unsigned char *p = (unsigned char *)data + dst_y * stride;
|
||||
uint32_t bytes_per_pixel = pixel_format_info->bytes_per_block;
|
||||
|
|
@ -1376,6 +1390,7 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
|||
vkUnmapMemory(dev, dst_img_memory);
|
||||
// Don't need to free anything else, since memory and image are cached
|
||||
return true;
|
||||
|
||||
free_memory:
|
||||
vkFreeMemory(dev, dst_img_memory, NULL);
|
||||
destroy_image:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,14 @@ static void drag_handle_seat_client_destroy(struct wl_listener *listener,
|
|||
wl_list_remove(&drag->seat_client_destroy.link);
|
||||
}
|
||||
|
||||
static void drag_set_focus(struct wlr_drag *drag,
|
||||
struct wlr_surface *surface, double sx, double sy);
|
||||
|
||||
static void drag_handle_focus_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_drag *drag = wl_container_of(listener, drag, focus_destroy);
|
||||
drag_set_focus(drag, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static void drag_set_focus(struct wlr_drag *drag,
|
||||
struct wlr_surface *surface, double sx, double sy) {
|
||||
if (drag->focus == surface) {
|
||||
|
|
@ -48,9 +56,12 @@ static void drag_set_focus(struct wlr_drag *drag,
|
|||
}
|
||||
|
||||
drag->focus_client = NULL;
|
||||
drag->focus = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&drag->focus_destroy.link);
|
||||
wl_list_init(&drag->focus_destroy.link);
|
||||
drag->focus = NULL;
|
||||
|
||||
if (!surface) {
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -99,6 +110,8 @@ static void drag_set_focus(struct wlr_drag *drag,
|
|||
|
||||
drag->focus = surface;
|
||||
drag->focus_client = focus_client;
|
||||
drag->focus_destroy.notify = drag_handle_focus_destroy;
|
||||
wl_signal_add(&surface->events.destroy, &drag->focus_destroy);
|
||||
drag->seat_client_destroy.notify = drag_handle_seat_client_destroy;
|
||||
wl_signal_add(&focus_client->events.destroy, &drag->seat_client_destroy);
|
||||
|
||||
|
|
@ -150,6 +163,7 @@ static void drag_destroy(struct wlr_drag *drag) {
|
|||
if (drag->source) {
|
||||
wl_list_remove(&drag->source_destroy.link);
|
||||
}
|
||||
wl_list_remove(&drag->focus_destroy.link);
|
||||
|
||||
if (drag->icon != NULL) {
|
||||
drag_icon_destroy(drag->icon);
|
||||
|
|
@ -410,6 +424,8 @@ struct wlr_drag *wlr_drag_create(struct wlr_seat_client *seat_client,
|
|||
wl_signal_init(&drag->events.drop);
|
||||
wl_signal_init(&drag->events.destroy);
|
||||
|
||||
wl_list_init(&drag->focus_destroy.link);
|
||||
|
||||
drag->seat = seat_client->seat;
|
||||
drag->seat_client = seat_client;
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
|||
buffer_width, buffer_height);
|
||||
wlr_output_transform_coords(state->transform, &buffer_width, &buffer_height);
|
||||
|
||||
src_box.x += (double)(clip->x * buffer_width) / state->width;
|
||||
src_box.y += (double)(clip->y * buffer_height) / state->height;
|
||||
src_box.x += (double)(clip->x * src_box.width) / state->width;
|
||||
src_box.y += (double)(clip->y * src_box.height) / state->height;
|
||||
src_box.width *= (double)width / state->width;
|
||||
src_box.height *= (double)height / state->height;
|
||||
|
||||
|
|
|
|||
|
|
@ -315,6 +315,43 @@ static void transform_output_box(struct wlr_box *box, const struct render_data *
|
|||
wlr_box_transform(box, box, transform, data->trans_width, data->trans_height);
|
||||
}
|
||||
|
||||
static void scene_output_damage(struct wlr_scene_output *scene_output,
|
||||
const pixman_region32_t *region) {
|
||||
if (wlr_damage_ring_add(&scene_output->damage_ring, region)) {
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
|
||||
struct wlr_output *output = scene_output->output;
|
||||
enum wl_output_transform transform =
|
||||
wlr_output_transform_invert(scene_output->output->transform);
|
||||
|
||||
int width = output->width;
|
||||
int height = output->height;
|
||||
if (transform & WL_OUTPUT_TRANSFORM_90) {
|
||||
width = output->height;
|
||||
height = output->width;
|
||||
}
|
||||
|
||||
pixman_region32_t frame_damage;
|
||||
pixman_region32_init(&frame_damage);
|
||||
wlr_region_transform(&frame_damage, region, transform, width, height);
|
||||
|
||||
pixman_region32_union(&scene_output->pending_commit_damage,
|
||||
&scene_output->pending_commit_damage, &frame_damage);
|
||||
pixman_region32_intersect_rect(&scene_output->pending_commit_damage,
|
||||
&scene_output->pending_commit_damage, 0, 0, output->width, output->height);
|
||||
pixman_region32_fini(&frame_damage);
|
||||
}
|
||||
}
|
||||
|
||||
static void scene_output_damage_whole(struct wlr_scene_output *scene_output) {
|
||||
struct wlr_damage_ring *ring = &scene_output->damage_ring;
|
||||
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init_rect(&damage, 0, 0, ring->width, ring->height);
|
||||
scene_output_damage(scene_output, &damage);
|
||||
pixman_region32_fini(&damage);
|
||||
}
|
||||
|
||||
static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) {
|
||||
if (!pixman_region32_not_empty(damage)) {
|
||||
return;
|
||||
|
|
@ -328,9 +365,7 @@ static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *dam
|
|||
pixman_region32_translate(&output_damage,
|
||||
-scene_output->x, -scene_output->y);
|
||||
scale_output_damage(&output_damage, scene_output->output->scale);
|
||||
if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) {
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
}
|
||||
scene_output_damage(scene_output, &output_damage);
|
||||
pixman_region32_fini(&output_damage);
|
||||
}
|
||||
}
|
||||
|
|
@ -800,9 +835,7 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff
|
|||
pixman_region32_translate(&output_damage,
|
||||
(int)round((lx - scene_output->x) * output_scale),
|
||||
(int)round((ly - scene_output->y) * output_scale));
|
||||
if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) {
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
}
|
||||
scene_output_damage(scene_output, &output_damage);
|
||||
pixman_region32_fini(&output_damage);
|
||||
}
|
||||
|
||||
|
|
@ -1226,7 +1259,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
|
|||
struct wlr_texture *texture = scene_buffer_get_texture(scene_buffer,
|
||||
data->output->output->renderer);
|
||||
if (texture == NULL) {
|
||||
wlr_damage_ring_add(&data->output->damage_ring, &render_region);
|
||||
scene_output_damage(data->output, &render_region);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1242,7 +1275,8 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
|
|||
.clip = &render_region,
|
||||
.alpha = &scene_buffer->opacity,
|
||||
.filter_mode = scene_buffer->filter_mode,
|
||||
.blend_mode = pixman_region32_not_empty(&opaque) ?
|
||||
.blend_mode = !data->output->scene->calculate_visibility ||
|
||||
pixman_region32_not_empty(&opaque) ?
|
||||
WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE,
|
||||
});
|
||||
|
||||
|
|
@ -1312,8 +1346,11 @@ static void scene_node_output_update(struct wlr_scene_node *node,
|
|||
|
||||
static void scene_output_update_geometry(struct wlr_scene_output *scene_output,
|
||||
bool force_update) {
|
||||
wlr_damage_ring_add_whole(&scene_output->damage_ring);
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
int ring_width, ring_height;
|
||||
wlr_output_transformed_resolution(scene_output->output, &ring_width, &ring_height);
|
||||
wlr_damage_ring_set_bounds(&scene_output->damage_ring, ring_width, ring_height);
|
||||
|
||||
scene_output_damage_whole(scene_output);
|
||||
|
||||
scene_node_output_update(&scene_output->scene->tree.node,
|
||||
&scene_output->scene->outputs, NULL, force_update ? scene_output : NULL);
|
||||
|
|
@ -1325,6 +1362,19 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data)
|
|||
struct wlr_output_event_commit *event = data;
|
||||
const struct wlr_output_state *state = event->state;
|
||||
|
||||
// if the output has been committed with a certain damage, we know that region
|
||||
// will be acknowledged by the backend so we don't need to keep track of it
|
||||
// anymore
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
pixman_region32_subtract(&scene_output->pending_commit_damage,
|
||||
&scene_output->pending_commit_damage, &state->damage);
|
||||
} else {
|
||||
pixman_region32_fini(&scene_output->pending_commit_damage);
|
||||
pixman_region32_init(&scene_output->pending_commit_damage);
|
||||
}
|
||||
}
|
||||
|
||||
bool force_update = state->committed & (
|
||||
WLR_OUTPUT_STATE_TRANSFORM |
|
||||
WLR_OUTPUT_STATE_SCALE |
|
||||
|
|
@ -1335,28 +1385,6 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data)
|
|||
scene_output_update_geometry(scene_output, force_update);
|
||||
}
|
||||
|
||||
// if the output has been committed with a certain damage, we know that region
|
||||
// will be acknowledged by the backend so we don't need to keep track of it
|
||||
// anymore
|
||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
bool tracking_buffer = false;
|
||||
struct wlr_damage_ring_buffer *buffer;
|
||||
wl_list_for_each(buffer, &scene_output->damage_ring.buffers, link) {
|
||||
if (buffer->buffer == state->buffer) {
|
||||
tracking_buffer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracking_buffer) {
|
||||
pixman_region32_subtract(&scene_output->pending_commit_damage,
|
||||
&scene_output->pending_commit_damage, &state->damage);
|
||||
} else {
|
||||
pixman_region32_union(&scene_output->pending_commit_damage,
|
||||
&scene_output->pending_commit_damage, &state->damage);
|
||||
}
|
||||
}
|
||||
|
||||
if (scene_output->scene->debug_damage_option == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT &&
|
||||
!wl_list_empty(&scene_output->damage_highlight_regions)) {
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
|
|
@ -1367,9 +1395,7 @@ static void scene_output_handle_damage(struct wl_listener *listener, void *data)
|
|||
struct wlr_scene_output *scene_output = wl_container_of(listener,
|
||||
scene_output, output_damage);
|
||||
struct wlr_output_event_damage *event = data;
|
||||
if (wlr_damage_ring_add(&scene_output->damage_ring, event->damage)) {
|
||||
wlr_output_schedule_frame(scene_output->output);
|
||||
}
|
||||
scene_output_damage(scene_output, event->damage);
|
||||
}
|
||||
|
||||
static void scene_output_handle_needs_frame(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -1556,21 +1582,6 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void output_state_apply_damage(const struct render_data *data,
|
||||
struct wlr_output_state *state) {
|
||||
struct wlr_scene_output *output = data->output;
|
||||
|
||||
pixman_region32_t frame_damage;
|
||||
pixman_region32_init(&frame_damage);
|
||||
pixman_region32_copy(&frame_damage, &output->damage_ring.current);
|
||||
transform_output_damage(&frame_damage, data);
|
||||
pixman_region32_union(&output->pending_commit_damage,
|
||||
&output->pending_commit_damage, &frame_damage);
|
||||
pixman_region32_fini(&frame_damage);
|
||||
|
||||
wlr_output_state_set_damage(state, &output->pending_commit_damage);
|
||||
}
|
||||
|
||||
static void scene_buffer_send_dmabuf_feedback(const struct wlr_scene *scene,
|
||||
struct wlr_scene_buffer *scene_buffer,
|
||||
const struct wlr_linux_dmabuf_feedback_v1_init_options *options) {
|
||||
|
|
@ -1749,7 +1760,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
|
||||
if (state->committed & WLR_OUTPUT_STATE_TRANSFORM) {
|
||||
if (render_data.transform != state->transform) {
|
||||
wlr_damage_ring_add_whole(&scene_output->damage_ring);
|
||||
scene_output_damage_whole(scene_output);
|
||||
}
|
||||
|
||||
render_data.transform = state->transform;
|
||||
|
|
@ -1757,7 +1768,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
|
||||
if (state->committed & WLR_OUTPUT_STATE_SCALE) {
|
||||
if (render_data.scale != state->scale) {
|
||||
wlr_damage_ring_add_whole(&scene_output->damage_ring);
|
||||
scene_output_damage_whole(scene_output);
|
||||
}
|
||||
|
||||
render_data.scale = state->scale;
|
||||
|
|
@ -1791,7 +1802,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
render_data.trans_width, render_data.trans_height);
|
||||
|
||||
if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_RERENDER) {
|
||||
wlr_damage_ring_add_whole(&scene_output->damage_ring);
|
||||
scene_output_damage_whole(scene_output);
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
|
|
@ -1828,11 +1839,11 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
}
|
||||
}
|
||||
|
||||
wlr_damage_ring_add(&scene_output->damage_ring, &acc_damage);
|
||||
scene_output_damage(scene_output, &acc_damage);
|
||||
pixman_region32_fini(&acc_damage);
|
||||
}
|
||||
|
||||
output_state_apply_damage(&render_data, state);
|
||||
wlr_output_state_set_damage(state, &scene_output->pending_commit_damage);
|
||||
|
||||
// We only want to try direct scanout if:
|
||||
// - There is only one entry in the render list
|
||||
|
|
@ -1969,11 +1980,18 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
int64_t time_diff_ms = timespec_to_msec(&time_diff);
|
||||
float alpha = 1.0 - (double)time_diff_ms / HIGHLIGHT_DAMAGE_FADEOUT_TIME;
|
||||
|
||||
pixman_region32_t clip;
|
||||
pixman_region32_init(&clip);
|
||||
pixman_region32_copy(&clip, &damage->region);
|
||||
transform_output_damage(&clip, &render_data);
|
||||
|
||||
wlr_render_pass_add_rect(render_pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = buffer->width, .height = buffer->height },
|
||||
.color = { .r = alpha * 0.5, .g = 0, .b = 0, .a = alpha * 0.5 },
|
||||
.clip = &damage->region,
|
||||
.clip = &clip,
|
||||
});
|
||||
|
||||
pixman_region32_fini(&clip);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,9 +214,10 @@ uint32_t wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return grab->interface->up(grab, time, point);
|
||||
uint32_t serial = grab->interface->up(grab, time, point);
|
||||
|
||||
touch_point_destroy(point);
|
||||
return serial;
|
||||
}
|
||||
|
||||
void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time,
|
||||
|
|
|
|||
|
|
@ -574,9 +574,15 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_
|
|||
wlr_xcursor_manager_load(manager, scale);
|
||||
struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(manager, name, scale);
|
||||
if (xcursor == NULL) {
|
||||
wlr_log(WLR_DEBUG, "XCursor theme is missing '%s' cursor", name);
|
||||
wlr_output_cursor_set_buffer(output_cursor->output_cursor, NULL, 0, 0);
|
||||
return;
|
||||
/* Try the default cursor: better the wrong image than an invisible
|
||||
* (and therefore practically unusable) cursor */
|
||||
wlr_log(WLR_DEBUG, "XCursor theme is missing '%s' cursor, falling back to 'default'", name);
|
||||
xcursor = wlr_xcursor_manager_get_xcursor(manager, "default", scale);
|
||||
if (xcursor == NULL) {
|
||||
wlr_log(WLR_DEBUG, "XCursor theme is missing a 'default' cursor");
|
||||
wlr_output_cursor_set_buffer(output_cursor->output_cursor, NULL, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
output_cursor->xcursor = xcursor;
|
||||
|
|
|
|||
|
|
@ -12,14 +12,18 @@
|
|||
|
||||
#define FOREIGN_TOPLEVEL_LIST_V1_VERSION 1
|
||||
|
||||
static const struct ext_foreign_toplevel_list_v1_interface toplevel_handle_impl;
|
||||
static const struct ext_foreign_toplevel_handle_v1_interface toplevel_handle_impl;
|
||||
|
||||
static void foreign_toplevel_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&ext_foreign_toplevel_handle_v1_interface,
|
||||
&toplevel_handle_impl));
|
||||
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_foreign_toplevel_list_v1_interface toplevel_handle_impl = {
|
||||
static const struct ext_foreign_toplevel_handle_v1_interface toplevel_handle_impl = {
|
||||
.destroy = foreign_toplevel_handle_destroy,
|
||||
};
|
||||
|
||||
|
|
@ -191,12 +195,23 @@ static void foreign_toplevel_list_handle_stop(struct wl_client *client,
|
|||
&foreign_toplevel_list_impl));
|
||||
|
||||
ext_foreign_toplevel_list_v1_send_finished(resource);
|
||||
wl_list_remove(wl_resource_get_link(resource));
|
||||
wl_list_init(wl_resource_get_link(resource));
|
||||
}
|
||||
|
||||
static void foreign_toplevel_list_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&ext_foreign_toplevel_list_v1_interface,
|
||||
&foreign_toplevel_list_impl));
|
||||
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_foreign_toplevel_list_v1_interface
|
||||
foreign_toplevel_list_impl = {
|
||||
.stop = foreign_toplevel_list_handle_stop
|
||||
.stop = foreign_toplevel_list_handle_stop,
|
||||
.destroy = foreign_toplevel_list_handle_destroy
|
||||
};
|
||||
|
||||
static void foreign_toplevel_list_resource_destroy(
|
||||
|
|
|
|||
|
|
@ -307,10 +307,19 @@ void wlr_keyboard_group_remove_keyboard(struct wlr_keyboard_group *group,
|
|||
}
|
||||
|
||||
void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) {
|
||||
struct keyboard_group_device *device, *tmp;
|
||||
wl_list_for_each_safe(device, tmp, &group->devices, link) {
|
||||
struct keyboard_group_device *device, *tmp_device;
|
||||
wl_list_for_each_safe(device, tmp_device, &group->devices, link) {
|
||||
wlr_keyboard_group_remove_keyboard(group, device->keyboard);
|
||||
}
|
||||
|
||||
// Now group->keys might not be empty if a wlr_keyboard has emitted
|
||||
// duplicated key presses
|
||||
struct keyboard_group_key *key, *tmp_key;
|
||||
wl_list_for_each_safe(key, tmp_key, &group->keys, link) {
|
||||
wl_list_remove(&key->link);
|
||||
free(key);
|
||||
}
|
||||
|
||||
wlr_keyboard_finish(&group->keyboard);
|
||||
wl_list_remove(&group->events.enter.listener_list);
|
||||
wl_list_remove(&group->events.leave.listener_list);
|
||||
|
|
|
|||
|
|
@ -424,6 +424,8 @@ static bool check_syncobj_eventfd(int drm_fd) {
|
|||
|
||||
struct wlr_linux_drm_syncobj_manager_v1 *wlr_linux_drm_syncobj_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version, int drm_fd) {
|
||||
assert(version <= LINUX_DRM_SYNCOBJ_V1_VERSION);
|
||||
|
||||
if (!check_syncobj_eventfd(drm_fd)) {
|
||||
wlr_log(WLR_INFO, "DRM syncobj eventfd unavailable, disabling linux-drm-syncobj-v1");
|
||||
return NULL;
|
||||
|
|
@ -441,7 +443,7 @@ struct wlr_linux_drm_syncobj_manager_v1 *wlr_linux_drm_syncobj_manager_v1_create
|
|||
|
||||
manager->global = wl_global_create(display,
|
||||
&wp_linux_drm_syncobj_manager_v1_interface,
|
||||
LINUX_DRM_SYNCOBJ_V1_VERSION, manager, manager_bind);
|
||||
version, manager, manager_bind);
|
||||
if (manager->global == NULL) {
|
||||
goto error_drm_fd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -867,7 +867,7 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager,
|
|||
head_send_mode(head, head_resource, mode);
|
||||
}
|
||||
|
||||
if (output->current_mode == NULL) {
|
||||
if (head->state.mode == NULL && head->state.enabled) {
|
||||
// Output doesn't have a fixed mode set. Send a virtual one.
|
||||
head_send_mode(head, head_resource, NULL);
|
||||
}
|
||||
|
|
@ -927,7 +927,7 @@ static bool manager_update_head(struct wlr_output_manager_v1 *manager,
|
|||
}
|
||||
}
|
||||
|
||||
if (next->mode == NULL && !head_has_custom_mode_resources(head)) {
|
||||
if (next->mode == NULL && next->enabled && !head_has_custom_mode_resources(head)) {
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &head->resources) {
|
||||
head_send_mode(head, resource, NULL);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ static void output_power_handle_output_destroy(struct wl_listener *listener,
|
|||
void *data) {
|
||||
struct wlr_output_power_v1 *output_power =
|
||||
wl_container_of(listener, output_power, output_destroy_listener);
|
||||
zwlr_output_power_v1_send_failed(output_power->resource);
|
||||
output_power_destroy(output_power);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constra
|
|||
wl_list_remove(&constraint->surface_commit.link);
|
||||
wl_list_remove(&constraint->surface_destroy.link);
|
||||
wl_list_remove(&constraint->seat_destroy.link);
|
||||
pixman_region32_fini(&constraint->current.region);
|
||||
pixman_region32_fini(&constraint->pending.region);
|
||||
pixman_region32_fini(&constraint->region);
|
||||
free(constraint);
|
||||
}
|
||||
|
|
@ -258,9 +256,6 @@ static void pointer_constraint_create(struct wl_client *client,
|
|||
|
||||
pixman_region32_init(&constraint->region);
|
||||
|
||||
pixman_region32_init(&constraint->pending.region);
|
||||
pixman_region32_init(&constraint->current.region);
|
||||
|
||||
pointer_constraint_set_region(constraint, region_resource);
|
||||
pointer_constraint_commit(constraint);
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,6 @@ static void frame_destroy(struct wlr_screencopy_frame_v1 *frame) {
|
|||
wl_list_remove(&frame->link);
|
||||
wl_list_remove(&frame->output_commit.link);
|
||||
wl_list_remove(&frame->output_destroy.link);
|
||||
wl_list_remove(&frame->output_enable.link);
|
||||
// Make the frame resource inert
|
||||
wl_resource_set_user_data(frame->resource, NULL);
|
||||
wlr_buffer_unlock(frame->buffer);
|
||||
|
|
@ -286,6 +285,10 @@ static void frame_handle_output_commit(struct wl_listener *listener,
|
|||
struct wlr_output_event_commit *event = data;
|
||||
struct wlr_output *output = frame->output;
|
||||
|
||||
if (event->state->committed & WLR_OUTPUT_STATE_ENABLED && !output->enabled) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(event->state->committed & WLR_OUTPUT_STATE_BUFFER)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -338,16 +341,6 @@ err:
|
|||
frame_destroy(frame);
|
||||
}
|
||||
|
||||
static void frame_handle_output_enable(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_screencopy_frame_v1 *frame =
|
||||
wl_container_of(listener, frame, output_enable);
|
||||
if (!frame->output->enabled) {
|
||||
zwlr_screencopy_frame_v1_send_failed(frame->resource);
|
||||
frame_destroy(frame);
|
||||
}
|
||||
}
|
||||
|
||||
static void frame_handle_output_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_screencopy_frame_v1 *frame =
|
||||
|
|
@ -439,9 +432,6 @@ static void frame_handle_copy(struct wl_client *wl_client,
|
|||
wl_signal_add(&output->events.commit, &frame->output_commit);
|
||||
frame->output_commit.notify = frame_handle_output_commit;
|
||||
|
||||
wl_signal_add(&output->events.destroy, &frame->output_enable);
|
||||
frame->output_enable.notify = frame_handle_output_enable;
|
||||
|
||||
// Request a frame because we can't assume that the current front buffer is still usable. It may
|
||||
// have been released already, and we shouldn't lock it here because compositors want to render
|
||||
// into the least damaged buffer.
|
||||
|
|
@ -526,7 +516,6 @@ static void capture_output(struct wl_client *wl_client,
|
|||
wl_list_insert(&client->manager->frames, &frame->link);
|
||||
|
||||
wl_list_init(&frame->output_commit.link);
|
||||
wl_list_init(&frame->output_enable.link);
|
||||
|
||||
wl_signal_add(&output->events.destroy, &frame->output_destroy);
|
||||
frame->output_destroy.notify = frame_handle_output_destroy;
|
||||
|
|
|
|||
|
|
@ -361,15 +361,6 @@ static const struct wlr_surface_synced_impl surface_synced_impl = {
|
|||
.state_size = sizeof(struct wlr_xdg_popup_state),
|
||||
};
|
||||
|
||||
static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_xdg_popup *popup =
|
||||
wlr_xdg_popup_from_resource(resource);
|
||||
if (popup == NULL) {
|
||||
return;
|
||||
}
|
||||
wlr_xdg_popup_destroy(popup);
|
||||
}
|
||||
|
||||
void create_xdg_popup(struct wlr_xdg_surface *surface, struct wlr_xdg_surface *parent,
|
||||
struct wlr_xdg_positioner *positioner, uint32_t id) {
|
||||
if (!wlr_xdg_positioner_is_complete(positioner)) {
|
||||
|
|
@ -409,8 +400,7 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, struct wlr_xdg_surface *p
|
|||
goto error_synced;
|
||||
}
|
||||
wl_resource_set_implementation(surface->popup->resource,
|
||||
&xdg_popup_implementation, surface->popup,
|
||||
xdg_popup_handle_resource_destroy);
|
||||
&xdg_popup_implementation, surface->popup, NULL);
|
||||
|
||||
surface->role = WLR_XDG_SURFACE_ROLE_POPUP;
|
||||
|
||||
|
|
|
|||
|
|
@ -212,10 +212,10 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
|||
bool performed = data->data32[1] & 1;
|
||||
xcb_atom_t action_atom = data->data32[2];
|
||||
|
||||
if (xwm->drag_focus == NULL ||
|
||||
target_window != xwm->drag_focus->window_id) {
|
||||
if (xwm->drop_focus == NULL ||
|
||||
target_window != xwm->drop_focus->window_id) {
|
||||
wlr_log(WLR_DEBUG, "ignoring XdndFinished client message because "
|
||||
"it doesn't match the finished drag focus window ID");
|
||||
"it doesn't match the finished drop focus window ID");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -234,37 +234,54 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
|||
}
|
||||
}
|
||||
|
||||
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus);
|
||||
|
||||
static void drag_focus_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xwm *xwm = wl_container_of(listener, xwm, drag_focus_destroy);
|
||||
xwm_set_drag_focus(xwm, NULL);
|
||||
}
|
||||
|
||||
static void drop_focus_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xwm *xwm = wl_container_of(listener, xwm, drop_focus_destroy);
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||
xwm->drop_focus = NULL;
|
||||
}
|
||||
|
||||
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) {
|
||||
if (focus == xwm->drag_focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xwm->drag_focus != NULL) {
|
||||
wlr_data_source_dnd_action(xwm->drag->source,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE);
|
||||
xwm_dnd_send_leave(xwm);
|
||||
}
|
||||
|
||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||
|
||||
xwm->drag_focus = focus;
|
||||
|
||||
if (xwm->drag_focus != NULL) {
|
||||
xwm->drag_focus_destroy.notify = drag_focus_handle_destroy;
|
||||
wl_signal_add(&xwm->drag_focus->events.destroy, &xwm->drag_focus_destroy);
|
||||
|
||||
xwm_dnd_send_enter(xwm);
|
||||
}
|
||||
}
|
||||
|
||||
static void seat_handle_drag_focus(struct wl_listener *listener, void *data) {
|
||||
struct wlr_drag *drag = data;
|
||||
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus);
|
||||
|
||||
struct wlr_xwayland_surface *focus = NULL;
|
||||
if (drag->focus != NULL) {
|
||||
// TODO: check for subsurfaces?
|
||||
struct wlr_xwayland_surface *surface;
|
||||
wl_list_for_each(surface, &xwm->surfaces, link) {
|
||||
if (surface->surface == drag->focus) {
|
||||
focus = surface;
|
||||
break;
|
||||
}
|
||||
}
|
||||
focus = wlr_xwayland_surface_try_from_wlr_surface(drag->focus);
|
||||
}
|
||||
|
||||
if (focus == xwm->drag_focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xwm->drag_focus != NULL) {
|
||||
wlr_data_source_dnd_action(drag->source,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE);
|
||||
xwm_dnd_send_leave(xwm);
|
||||
}
|
||||
|
||||
xwm->drag_focus = focus;
|
||||
|
||||
if (xwm->drag_focus != NULL) {
|
||||
xwm_dnd_send_enter(xwm);
|
||||
}
|
||||
xwm_set_drag_focus(xwm, focus);
|
||||
}
|
||||
|
||||
static void seat_handle_drag_motion(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -289,6 +306,12 @@ static void seat_handle_drag_drop(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "Wayland drag dropped over an Xwayland window");
|
||||
|
||||
xwm->drop_focus = xwm->drag_focus;
|
||||
xwm->drop_focus_destroy.notify = drop_focus_handle_destroy;
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
wl_signal_add(&xwm->drop_focus->events.destroy, &xwm->drop_focus_destroy);
|
||||
|
||||
xwm_dnd_send_drop(xwm, event->time);
|
||||
}
|
||||
|
||||
|
|
@ -315,12 +338,25 @@ static void seat_handle_drag_source_destroy(struct wl_listener *listener,
|
|||
wl_container_of(listener, xwm, seat_drag_source_destroy);
|
||||
|
||||
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_init(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||
xwm->drag_focus = NULL;
|
||||
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||
xwm->drop_focus = NULL;
|
||||
}
|
||||
|
||||
void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
|
||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||
|
||||
xwm->drag = drag;
|
||||
xwm->drag_focus = NULL;
|
||||
xwm->drop_focus = NULL;
|
||||
|
||||
if (drag != NULL) {
|
||||
wl_signal_add(&drag->events.focus, &xwm->seat_drag_focus);
|
||||
|
|
@ -337,3 +373,17 @@ void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
|
|||
xwm->seat_drag_source_destroy.notify = seat_handle_drag_source_destroy;
|
||||
}
|
||||
}
|
||||
|
||||
void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm) {
|
||||
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
|
||||
if (!xwm->drag) {
|
||||
return;
|
||||
}
|
||||
wl_list_remove(&xwm->seat_drag_focus.link);
|
||||
wl_list_remove(&xwm->seat_drag_motion.link);
|
||||
wl_list_remove(&xwm->seat_drag_drop.link);
|
||||
wl_list_remove(&xwm->seat_drag_destroy.link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -410,8 +410,11 @@ void xwm_handle_selection_request(struct wlr_xwm *xwm,
|
|||
return;
|
||||
}
|
||||
|
||||
bool dnd_allowed = selection == &xwm->dnd_selection
|
||||
&& (xwm->drag_focus != NULL || xwm->drop_focus != NULL);
|
||||
|
||||
// No xwayland surface focused, deny access to clipboard
|
||||
if (xwm->focus_surface == NULL && xwm->drag_focus == NULL) {
|
||||
if (xwm->focus_surface == NULL && !dnd_allowed) {
|
||||
if (wlr_log_get_verbosity() >= WLR_DEBUG) {
|
||||
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
||||
wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): "
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) {
|
|||
}
|
||||
xwayland->server = NULL;
|
||||
wlr_xwayland_shell_v1_destroy(xwayland->shell_v1);
|
||||
xwm_destroy(xwayland->xwm);
|
||||
free(xwayland);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1786,6 +1786,16 @@ static void handle_shell_v1_new_surface(struct wl_listener *listener,
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_shell_v1_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_xwm *xwm =
|
||||
wl_container_of(listener, xwm, shell_v1_destroy);
|
||||
wl_list_remove(&xwm->shell_v1_new_surface.link);
|
||||
wl_list_remove(&xwm->shell_v1_destroy.link);
|
||||
wl_list_init(&xwm->shell_v1_new_surface.link);
|
||||
wl_list_init(&xwm->shell_v1_destroy.link);
|
||||
}
|
||||
|
||||
void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface,
|
||||
bool activated) {
|
||||
struct wlr_xwayland_surface *focused = xsurface->xwm->focus_surface;
|
||||
|
|
@ -1869,6 +1879,8 @@ void xwm_destroy(struct wlr_xwm *xwm) {
|
|||
xwm_selection_finish(&xwm->primary_selection);
|
||||
xwm_selection_finish(&xwm->dnd_selection);
|
||||
|
||||
xwm_seat_unlink_drag_handlers(xwm);
|
||||
|
||||
if (xwm->seat) {
|
||||
if (xwm->seat->selection_source &&
|
||||
data_source_is_xwayland(xwm->seat->selection_source)) {
|
||||
|
|
@ -1913,6 +1925,7 @@ void xwm_destroy(struct wlr_xwm *xwm) {
|
|||
wl_list_remove(&xwm->compositor_new_surface.link);
|
||||
wl_list_remove(&xwm->compositor_destroy.link);
|
||||
wl_list_remove(&xwm->shell_v1_new_surface.link);
|
||||
wl_list_remove(&xwm->shell_v1_destroy.link);
|
||||
xcb_disconnect(xwm->xcb_conn);
|
||||
|
||||
struct pending_startup_id *pending, *next;
|
||||
|
|
@ -2162,6 +2175,10 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
|||
wl_list_init(&xwm->surfaces_in_stack_order);
|
||||
wl_list_init(&xwm->unpaired_surfaces);
|
||||
wl_list_init(&xwm->pending_startup_ids);
|
||||
wl_list_init(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||
|
||||
xwm->ping_timeout = 10000;
|
||||
|
||||
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
|
||||
|
|
@ -2257,6 +2274,9 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
|||
xwm->shell_v1_new_surface.notify = handle_shell_v1_new_surface;
|
||||
wl_signal_add(&xwayland->shell_v1->events.new_surface,
|
||||
&xwm->shell_v1_new_surface);
|
||||
xwm->shell_v1_destroy.notify = handle_shell_v1_destroy;
|
||||
wl_signal_add(&xwayland->shell_v1->events.destroy,
|
||||
&xwm->shell_v1_destroy);
|
||||
|
||||
xwm_create_wm_window(xwm);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue