mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-12-20 13:50:14 +01:00
Compare commits
41 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
33 changed files with 338 additions and 170 deletions
|
|
@ -20,7 +20,7 @@ packages:
|
||||||
- x11/xcb-util-errors
|
- x11/xcb-util-errors
|
||||||
- x11/xcb-util-renderutil
|
- x11/xcb-util-renderutil
|
||||||
- x11/xcb-util-wm
|
- x11/xcb-util-wm
|
||||||
- x11-servers/xwayland-devel
|
- x11-servers/xwayland
|
||||||
- sysutils/libdisplay-info
|
- sysutils/libdisplay-info
|
||||||
- sysutils/seatd
|
- sysutils/seatd
|
||||||
- gmake
|
- 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,
|
bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm,
|
||||||
int width, int height, const pixman_region32_t *damage, uint32_t *blob_id) {
|
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_t clipped;
|
||||||
pixman_region32_init(&clipped);
|
pixman_region32_init(&clipped);
|
||||||
pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height);
|
pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height);
|
||||||
|
|
||||||
int rects_len;
|
int rects_len;
|
||||||
const pixman_box32_t *rects = pixman_region32_rectangles(&clipped, &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);
|
pixman_region32_fini(&clipped);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to create FB_DAMAGE_CLIPS property blob");
|
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];
|
struct wlr_drm_plane *plane = &drm->planes[i];
|
||||||
drm_plane_finish_surface(plane);
|
drm_plane_finish_surface(plane);
|
||||||
wlr_drm_format_set_finish(&plane->formats);
|
wlr_drm_format_set_finish(&plane->formats);
|
||||||
|
free(plane->cursor_sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(drm->planes);
|
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->cursor_enabled = false;
|
||||||
conn->crtc = NULL;
|
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) {
|
if (page_flip == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
page_flip->async = (flags & DRM_MODE_PAGE_FLIP_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = drm->iface->commit(drm, state, page_flip, flags, test_only);
|
bool ok = drm->iface->commit(drm, state, page_flip, flags, test_only);
|
||||||
|
|
@ -801,6 +813,22 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
|
||||||
return false;
|
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 (test_only && conn->backend->parent) {
|
||||||
// If we're running as a secondary GPU, we can't perform an atomic
|
// If we're running as a secondary GPU, we can't perform an atomic
|
||||||
// commit without blitting a buffer.
|
// commit without blitting a buffer.
|
||||||
|
|
@ -2008,6 +2036,12 @@ static void handle_page_flip(int fd, unsigned seq,
|
||||||
if (conn != NULL) {
|
if (conn != NULL) {
|
||||||
conn->pending_page_flip = 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) {
|
if (page_flip->connectors_len == 0) {
|
||||||
drm_page_flip_destroy(page_flip);
|
drm_page_flip_destroy(page_flip);
|
||||||
}
|
}
|
||||||
|
|
@ -2038,8 +2072,6 @@ static void handle_page_flip(int fd, unsigned seq,
|
||||||
drm_fb_move(&layer->current_fb, &layer->queued_fb);
|
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
|
/* 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
|
* data between the GPUs, even if we were using the direct scanout
|
||||||
* interface.
|
* interface.
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
||||||
state->base->adaptive_sync_enabled ? "enabled" : "disabled");
|
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;
|
struct wlr_drm_fb *cursor_fb = state->cursor_fb;
|
||||||
if (cursor_fb == NULL) {
|
if (cursor_fb == NULL) {
|
||||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB");
|
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)) {
|
if (drmModePageFlip(drm->fd, crtc->id, fb_id, flags, page_flip)) {
|
||||||
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -170,12 +170,6 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
|
||||||
has_best = true;
|
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) {
|
if (st->exit_early) {
|
||||||
return true;
|
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
|
// Maybe this resource can't be matched
|
||||||
st->res[i] = UNMATCHED;
|
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],
|
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 = {
|
static const struct wlr_output_impl output_impl = {
|
||||||
.destroy = output_destroy,
|
.destroy = output_destroy,
|
||||||
|
.test = output_test,
|
||||||
.commit = output_commit,
|
.commit = output_commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,9 @@ static void linux_dmabuf_feedback_v1_handle_main_device(void *data,
|
||||||
"falling back to primary node", name);
|
"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);
|
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,
|
static void legacy_drm_handle_device(void *data, struct wl_drm *drm,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
struct wlr_wl_backend *wl = data;
|
struct wlr_wl_backend *wl = data;
|
||||||
|
assert(wl->drm_render_name == NULL);
|
||||||
wl->drm_render_name = get_render_name(name);
|
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;
|
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 zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback_v1 = NULL;
|
||||||
struct wlr_wl_linux_dmabuf_feedback_v1 feedback_data = { .backend = wl };
|
struct wlr_wl_linux_dmabuf_feedback_v1 feedback_data = { .backend = wl };
|
||||||
if (wl->zwp_linux_dmabuf_v1 != NULL &&
|
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) {
|
if (wl->legacy_drm != NULL) {
|
||||||
wl_drm_destroy(wl->legacy_drm);
|
wl_drm_destroy(wl->legacy_drm);
|
||||||
wl->legacy_drm = NULL;
|
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) {
|
if (feedback_data.format_table != NULL) {
|
||||||
munmap(feedback_data.format_table, feedback_data.format_table_size);
|
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);
|
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) {
|
struct wlr_shm_attributes *shm) {
|
||||||
enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format);
|
enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format);
|
||||||
uint32_t size = shm->stride * shm->height;
|
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) {
|
if (pool == NULL) {
|
||||||
return 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));
|
layers_arr.size / sizeof(struct wlr_output_layer_state));
|
||||||
|
|
||||||
if (!wlr_output_test_state(output->wlr_output, &output_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,8 @@ struct wlr_drm_page_flip {
|
||||||
struct wl_list link; // wlr_drm_connector.page_flips
|
struct wl_list link; // wlr_drm_connector.page_flips
|
||||||
struct wlr_drm_page_flip_connector *connectors;
|
struct wlr_drm_page_flip_connector *connectors;
|
||||||
size_t connectors_len;
|
size_t connectors_len;
|
||||||
|
// True if DRM_MODE_PAGE_FLIP_ASYNC was set
|
||||||
|
bool async;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_drm_page_flip_connector {
|
struct wlr_drm_page_flip_connector {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <wlr/types/wlr_keyboard.h>
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
|
|
||||||
void keyboard_key_update(struct wlr_keyboard *keyboard,
|
bool keyboard_key_update(struct wlr_keyboard *keyboard,
|
||||||
struct wlr_keyboard_key_event *event);
|
struct wlr_keyboard_key_event *event);
|
||||||
|
|
||||||
bool keyboard_modifier_update(struct wlr_keyboard *keyboard);
|
bool keyboard_modifier_update(struct wlr_keyboard *keyboard);
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ struct wlr_drag {
|
||||||
|
|
||||||
struct wl_listener source_destroy;
|
struct wl_listener source_destroy;
|
||||||
struct wl_listener seat_client_destroy;
|
struct wl_listener seat_client_destroy;
|
||||||
|
struct wl_listener focus_destroy;
|
||||||
struct wl_listener icon_destroy;
|
struct wl_listener icon_destroy;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/util/addon.h>
|
#include <wlr/util/addon.h>
|
||||||
|
|
||||||
|
struct wlr_buffer;
|
||||||
|
struct wlr_surface;
|
||||||
|
|
||||||
struct wlr_linux_drm_syncobj_surface_v1_state {
|
struct wlr_linux_drm_syncobj_surface_v1_state {
|
||||||
struct wlr_drm_syncobj_timeline *acquire_timeline;
|
struct wlr_drm_syncobj_timeline *acquire_timeline;
|
||||||
uint64_t acquire_point;
|
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
|
* The `frame` event will be emitted when it is a good time for the compositor
|
||||||
* to submit a new frame.
|
* to submit a new frame.
|
||||||
*
|
*
|
||||||
* To render a new frame, compositors should call wlr_output_begin_render_pass(),
|
* 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().
|
* perform rendering on that render pass, and finally call
|
||||||
|
* wlr_output_commit_state().
|
||||||
*/
|
*/
|
||||||
struct wlr_output {
|
struct wlr_output {
|
||||||
const struct wlr_output_impl *impl;
|
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.
|
* the allocator and renderer to different values.
|
||||||
*
|
*
|
||||||
* Call this function prior to any call to wlr_output_begin_render_pass(),
|
* 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
|
* The buffer capabilities of the provided must match the capabilities of the
|
||||||
* output's backend. Returns false otherwise.
|
* output's backend. Returns false otherwise.
|
||||||
|
|
@ -369,12 +370,6 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock);
|
||||||
* a lock.
|
* a lock.
|
||||||
*/
|
*/
|
||||||
void wlr_output_lock_software_cursors(struct wlr_output *output, bool 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.
|
* Render software cursors.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,16 @@
|
||||||
*
|
*
|
||||||
* To configure output layers, callers should call wlr_output_layer_create() to
|
* To configure output layers, callers should call wlr_output_layer_create() to
|
||||||
* create layers, attach struct wlr_output_layer_state onto
|
* create layers, attach struct wlr_output_layer_state onto
|
||||||
* struct wlr_output_state via wlr_output_set_layers() to describe their new
|
* struct wlr_output_state via wlr_output_state_set_layers() to describe their new
|
||||||
* state, and commit the output via wlr_output_commit().
|
* state, and commit the output via wlr_output_commit_state().
|
||||||
*
|
*
|
||||||
* Backends may have arbitrary limitations when it comes to displaying output
|
* Backends may have arbitrary limitations when it comes to displaying output
|
||||||
* layers. Backends indicate whether or not a layer can be displayed via
|
* layers. Backends indicate whether or not a layer can be displayed via
|
||||||
* wlr_output_layer_state.accepted after wlr_output_test() or
|
* wlr_output_layer_state.accepted after wlr_output_test_state() or
|
||||||
* wlr_output_commit() is called. Compositors using the output layers API
|
* wlr_output_commit_state() is called. Compositors using the output layers API
|
||||||
* directly are expected to setup layers, call wlr_output_test(), paint the
|
* directly are expected to setup layers, call wlr_output_test_state(), paint
|
||||||
* layers that the backend rejected with the renderer, then call
|
* the layers that the backend rejected with the renderer, then call
|
||||||
* wlr_output_commit().
|
* wlr_output_commit_state().
|
||||||
*
|
*
|
||||||
* Callers are responsible for disabling output layers when they need the full
|
* 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
|
* 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.
|
// to damage the whole buffer.
|
||||||
const pixman_region32_t *damage;
|
const pixman_region32_t *damage;
|
||||||
|
|
||||||
// Populated by the backend after wlr_output_test() and wlr_output_commit(),
|
// Populated by the backend after wlr_output_test_state() and
|
||||||
// indicates whether the backend has acknowledged and will take care of
|
// wlr_output_commit_state(), indicates whether the backend has acknowledged
|
||||||
// displaying the layer
|
// and will take care of displaying the layer
|
||||||
bool accepted;
|
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
|
* Instead of calling wlr_presentation_surface_sampled() and managing the
|
||||||
* struct wlr_presentation_feedback itself, the compositor can call this function
|
* 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.
|
* 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,
|
void wlr_presentation_surface_textured_on_output(struct wlr_surface *surface,
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ struct wlr_xwm {
|
||||||
|
|
||||||
struct wlr_drag *drag;
|
struct wlr_drag *drag;
|
||||||
struct wlr_xwayland_surface *drag_focus;
|
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 *xfixes;
|
||||||
const xcb_query_extension_reply_t *xres;
|
const xcb_query_extension_reply_t *xres;
|
||||||
|
|
@ -135,6 +136,7 @@ struct wlr_xwm {
|
||||||
struct wl_listener compositor_new_surface;
|
struct wl_listener compositor_new_surface;
|
||||||
struct wl_listener compositor_destroy;
|
struct wl_listener compositor_destroy;
|
||||||
struct wl_listener shell_v1_new_surface;
|
struct wl_listener shell_v1_new_surface;
|
||||||
|
struct wl_listener shell_v1_destroy;
|
||||||
struct wl_listener seat_set_selection;
|
struct wl_listener seat_set_selection;
|
||||||
struct wl_listener seat_set_primary_selection;
|
struct wl_listener seat_set_primary_selection;
|
||||||
struct wl_listener seat_start_drag;
|
struct wl_listener seat_start_drag;
|
||||||
|
|
@ -143,6 +145,8 @@ struct wlr_xwm {
|
||||||
struct wl_listener seat_drag_drop;
|
struct wl_listener seat_drag_drop;
|
||||||
struct wl_listener seat_drag_destroy;
|
struct wl_listener seat_drag_destroy;
|
||||||
struct wl_listener seat_drag_source_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);
|
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_event(struct wlr_xwm *xwm, xcb_generic_event_t *event);
|
||||||
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
||||||
xcb_client_message_event_t *ev);
|
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);
|
void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'wlroots',
|
'wlroots',
|
||||||
'c',
|
'c',
|
||||||
version: '0.18.0',
|
version: '0.18.2',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.59.0',
|
meson_version: '>=0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
|
||||||
|
|
@ -572,16 +572,10 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
VkClearRect clear_rect = {
|
VkClearRect clear_rect = {
|
||||||
.rect = {
|
|
||||||
.offset = { box.x, box.y },
|
|
||||||
.extent = { box.width, box.height },
|
|
||||||
},
|
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
for (int i = 0; i < clip_rects_len; i++) {
|
for (int i = 0; i < clip_rects_len; i++) {
|
||||||
VkRect2D rect;
|
convert_pixman_box_to_vk_rect(&clip_rects[i], &clear_rect.rect);
|
||||||
convert_pixman_box_to_vk_rect(&clip_rects[i], &rect);
|
|
||||||
vkCmdSetScissor(cb, 0, 1, &rect);
|
|
||||||
vkCmdClearAttachments(cb, 1, &clear_att, 1, &clear_rect);
|
vkCmdClearAttachments(cb, 1, &clear_att, 1, &clear_rect);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,8 @@ struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r,
|
||||||
goto error_alloc;
|
goto error_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_init(&buf->link);
|
||||||
|
|
||||||
VkResult res;
|
VkResult res;
|
||||||
VkBufferCreateInfo buf_info = {
|
VkBufferCreateInfo buf_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_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,
|
int mem_type = vulkan_find_mem_type(vk_renderer->dev,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
|
||||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||||
mem_reqs.memoryTypeBits);
|
mem_reqs.memoryTypeBits);
|
||||||
if (mem_type < 0) {
|
if (mem_type < 0) {
|
||||||
|
|
@ -1361,6 +1362,19 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
||||||
return false;
|
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;
|
const char *d = (const char *)v + img_sub_layout.offset;
|
||||||
unsigned char *p = (unsigned char *)data + dst_y * stride;
|
unsigned char *p = (unsigned char *)data + dst_y * stride;
|
||||||
uint32_t bytes_per_pixel = pixel_format_info->bytes_per_block;
|
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);
|
vkUnmapMemory(dev, dst_img_memory);
|
||||||
// Don't need to free anything else, since memory and image are cached
|
// Don't need to free anything else, since memory and image are cached
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
free_memory:
|
free_memory:
|
||||||
vkFreeMemory(dev, dst_img_memory, NULL);
|
vkFreeMemory(dev, dst_img_memory, NULL);
|
||||||
destroy_image:
|
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);
|
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,
|
static void drag_set_focus(struct wlr_drag *drag,
|
||||||
struct wlr_surface *surface, double sx, double sy) {
|
struct wlr_surface *surface, double sx, double sy) {
|
||||||
if (drag->focus == surface) {
|
if (drag->focus == surface) {
|
||||||
|
|
@ -48,9 +56,12 @@ static void drag_set_focus(struct wlr_drag *drag,
|
||||||
}
|
}
|
||||||
|
|
||||||
drag->focus_client = NULL;
|
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) {
|
if (!surface) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +110,8 @@ static void drag_set_focus(struct wlr_drag *drag,
|
||||||
|
|
||||||
drag->focus = surface;
|
drag->focus = surface;
|
||||||
drag->focus_client = focus_client;
|
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;
|
drag->seat_client_destroy.notify = drag_handle_seat_client_destroy;
|
||||||
wl_signal_add(&focus_client->events.destroy, &drag->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) {
|
if (drag->source) {
|
||||||
wl_list_remove(&drag->source_destroy.link);
|
wl_list_remove(&drag->source_destroy.link);
|
||||||
}
|
}
|
||||||
|
wl_list_remove(&drag->focus_destroy.link);
|
||||||
|
|
||||||
if (drag->icon != NULL) {
|
if (drag->icon != NULL) {
|
||||||
drag_icon_destroy(drag->icon);
|
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.drop);
|
||||||
wl_signal_init(&drag->events.destroy);
|
wl_signal_init(&drag->events.destroy);
|
||||||
|
|
||||||
|
wl_list_init(&drag->focus_destroy.link);
|
||||||
|
|
||||||
drag->seat = seat_client->seat;
|
drag->seat = seat_client->seat;
|
||||||
drag->seat_client = seat_client;
|
drag->seat_client = seat_client;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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) {
|
static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) {
|
||||||
if (!pixman_region32_not_empty(damage)) {
|
if (!pixman_region32_not_empty(damage)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -328,9 +365,7 @@ static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *dam
|
||||||
pixman_region32_translate(&output_damage,
|
pixman_region32_translate(&output_damage,
|
||||||
-scene_output->x, -scene_output->y);
|
-scene_output->x, -scene_output->y);
|
||||||
scale_output_damage(&output_damage, scene_output->output->scale);
|
scale_output_damage(&output_damage, scene_output->output->scale);
|
||||||
if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) {
|
scene_output_damage(scene_output, &output_damage);
|
||||||
wlr_output_schedule_frame(scene_output->output);
|
|
||||||
}
|
|
||||||
pixman_region32_fini(&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,
|
pixman_region32_translate(&output_damage,
|
||||||
(int)round((lx - scene_output->x) * output_scale),
|
(int)round((lx - scene_output->x) * output_scale),
|
||||||
(int)round((ly - scene_output->y) * output_scale));
|
(int)round((ly - scene_output->y) * output_scale));
|
||||||
if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) {
|
scene_output_damage(scene_output, &output_damage);
|
||||||
wlr_output_schedule_frame(scene_output->output);
|
|
||||||
}
|
|
||||||
pixman_region32_fini(&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,
|
struct wlr_texture *texture = scene_buffer_get_texture(scene_buffer,
|
||||||
data->output->output->renderer);
|
data->output->output->renderer);
|
||||||
if (texture == NULL) {
|
if (texture == NULL) {
|
||||||
wlr_damage_ring_add(&data->output->damage_ring, &render_region);
|
scene_output_damage(data->output, &render_region);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1242,7 +1275,8 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
|
||||||
.clip = &render_region,
|
.clip = &render_region,
|
||||||
.alpha = &scene_buffer->opacity,
|
.alpha = &scene_buffer->opacity,
|
||||||
.filter_mode = scene_buffer->filter_mode,
|
.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,
|
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,
|
static void scene_output_update_geometry(struct wlr_scene_output *scene_output,
|
||||||
bool force_update) {
|
bool force_update) {
|
||||||
wlr_damage_ring_add_whole(&scene_output->damage_ring);
|
int ring_width, ring_height;
|
||||||
wlr_output_schedule_frame(scene_output->output);
|
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_node_output_update(&scene_output->scene->tree.node,
|
||||||
&scene_output->scene->outputs, NULL, force_update ? scene_output : NULL);
|
&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;
|
struct wlr_output_event_commit *event = data;
|
||||||
const struct wlr_output_state *state = event->state;
|
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 & (
|
bool force_update = state->committed & (
|
||||||
WLR_OUTPUT_STATE_TRANSFORM |
|
WLR_OUTPUT_STATE_TRANSFORM |
|
||||||
WLR_OUTPUT_STATE_SCALE |
|
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);
|
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 &&
|
if (scene_output->scene->debug_damage_option == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT &&
|
||||||
!wl_list_empty(&scene_output->damage_highlight_regions)) {
|
!wl_list_empty(&scene_output->damage_highlight_regions)) {
|
||||||
wlr_output_schedule_frame(scene_output->output);
|
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,
|
struct wlr_scene_output *scene_output = wl_container_of(listener,
|
||||||
scene_output, output_damage);
|
scene_output, output_damage);
|
||||||
struct wlr_output_event_damage *event = data;
|
struct wlr_output_event_damage *event = data;
|
||||||
if (wlr_damage_ring_add(&scene_output->damage_ring, event->damage)) {
|
scene_output_damage(scene_output, event->damage);
|
||||||
wlr_output_schedule_frame(scene_output->output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_output_handle_needs_frame(struct wl_listener *listener, void *data) {
|
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;
|
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,
|
static void scene_buffer_send_dmabuf_feedback(const struct wlr_scene *scene,
|
||||||
struct wlr_scene_buffer *scene_buffer,
|
struct wlr_scene_buffer *scene_buffer,
|
||||||
const struct wlr_linux_dmabuf_feedback_v1_init_options *options) {
|
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 (state->committed & WLR_OUTPUT_STATE_TRANSFORM) {
|
||||||
if (render_data.transform != 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;
|
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 (state->committed & WLR_OUTPUT_STATE_SCALE) {
|
||||||
if (render_data.scale != 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;
|
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);
|
render_data.trans_width, render_data.trans_height);
|
||||||
|
|
||||||
if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_RERENDER) {
|
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;
|
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);
|
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:
|
// We only want to try direct scanout if:
|
||||||
// - There is only one entry in the render list
|
// - 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);
|
int64_t time_diff_ms = timespec_to_msec(&time_diff);
|
||||||
float alpha = 1.0 - (double)time_diff_ms / HIGHLIGHT_DAMAGE_FADEOUT_TIME;
|
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){
|
wlr_render_pass_add_rect(render_pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = buffer->width, .height = buffer->height },
|
.box = { .width = buffer->width, .height = buffer->height },
|
||||||
.color = { .r = alpha * 0.5, .g = 0, .b = 0, .a = alpha * 0.5 },
|
.color = { .r = alpha * 0.5, .g = 0, .b = 0, .a = alpha * 0.5 },
|
||||||
.clip = &damage->region,
|
.clip = &clip,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pixman_region32_fini(&clip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,18 @@
|
||||||
|
|
||||||
#define FOREIGN_TOPLEVEL_LIST_V1_VERSION 1
|
#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,
|
static void foreign_toplevel_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&ext_foreign_toplevel_handle_v1_interface,
|
||||||
|
&toplevel_handle_impl));
|
||||||
|
|
||||||
wl_resource_destroy(resource);
|
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,
|
.destroy = foreign_toplevel_handle_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -191,12 +195,23 @@ static void foreign_toplevel_list_handle_stop(struct wl_client *client,
|
||||||
&foreign_toplevel_list_impl));
|
&foreign_toplevel_list_impl));
|
||||||
|
|
||||||
ext_foreign_toplevel_list_v1_send_finished(resource);
|
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);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_foreign_toplevel_list_v1_interface
|
static const struct ext_foreign_toplevel_list_v1_interface
|
||||||
foreign_toplevel_list_impl = {
|
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(
|
static void foreign_toplevel_list_resource_destroy(
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,9 @@ bool keyboard_modifier_update(struct wlr_keyboard *keyboard) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_key_update(struct wlr_keyboard *keyboard,
|
bool keyboard_key_update(struct wlr_keyboard *keyboard,
|
||||||
struct wlr_keyboard_key_event *event) {
|
struct wlr_keyboard_key_event *event) {
|
||||||
|
size_t old_num_keycodes = keyboard->num_keycodes;
|
||||||
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
set_add(keyboard->keycodes, &keyboard->num_keycodes,
|
set_add(keyboard->keycodes, &keyboard->num_keycodes,
|
||||||
WLR_KEYBOARD_KEYS_CAP, event->keycode);
|
WLR_KEYBOARD_KEYS_CAP, event->keycode);
|
||||||
|
|
@ -77,6 +78,8 @@ void keyboard_key_update(struct wlr_keyboard *keyboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(keyboard->num_keycodes <= WLR_KEYBOARD_KEYS_CAP);
|
assert(keyboard->num_keycodes <= WLR_KEYBOARD_KEYS_CAP);
|
||||||
|
|
||||||
|
return old_num_keycodes != keyboard->num_keycodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
|
void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
|
||||||
|
|
@ -98,8 +101,9 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
|
||||||
|
|
||||||
void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard,
|
void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard,
|
||||||
struct wlr_keyboard_key_event *event) {
|
struct wlr_keyboard_key_event *event) {
|
||||||
keyboard_key_update(keyboard, event);
|
if (keyboard_key_update(keyboard, event)) {
|
||||||
wl_signal_emit_mutable(&keyboard->events.key, event);
|
wl_signal_emit_mutable(&keyboard->events.key, event);
|
||||||
|
}
|
||||||
|
|
||||||
if (keyboard->xkb_state == NULL) {
|
if (keyboard->xkb_state == NULL) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -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 wlr_linux_drm_syncobj_manager_v1 *wlr_linux_drm_syncobj_manager_v1_create(
|
||||||
struct wl_display *display, uint32_t version, int drm_fd) {
|
struct wl_display *display, uint32_t version, int drm_fd) {
|
||||||
|
assert(version <= LINUX_DRM_SYNCOBJ_V1_VERSION);
|
||||||
|
|
||||||
if (!check_syncobj_eventfd(drm_fd)) {
|
if (!check_syncobj_eventfd(drm_fd)) {
|
||||||
wlr_log(WLR_INFO, "DRM syncobj eventfd unavailable, disabling linux-drm-syncobj-v1");
|
wlr_log(WLR_INFO, "DRM syncobj eventfd unavailable, disabling linux-drm-syncobj-v1");
|
||||||
return NULL;
|
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,
|
manager->global = wl_global_create(display,
|
||||||
&wp_linux_drm_syncobj_manager_v1_interface,
|
&wp_linux_drm_syncobj_manager_v1_interface,
|
||||||
LINUX_DRM_SYNCOBJ_V1_VERSION, manager, manager_bind);
|
version, manager, manager_bind);
|
||||||
if (manager->global == NULL) {
|
if (manager->global == NULL) {
|
||||||
goto error_drm_fd;
|
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);
|
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.
|
// Output doesn't have a fixed mode set. Send a virtual one.
|
||||||
head_send_mode(head, head_resource, NULL);
|
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;
|
struct wl_resource *resource;
|
||||||
wl_resource_for_each(resource, &head->resources) {
|
wl_resource_for_each(resource, &head->resources) {
|
||||||
head_send_mode(head, resource, NULL);
|
head_send_mode(head, resource, NULL);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ static void output_power_handle_output_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct wlr_output_power_v1 *output_power =
|
struct wlr_output_power_v1 *output_power =
|
||||||
wl_container_of(listener, output_power, output_destroy_listener);
|
wl_container_of(listener, output_power, output_destroy_listener);
|
||||||
|
zwlr_output_power_v1_send_failed(output_power->resource);
|
||||||
output_power_destroy(output_power);
|
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_commit.link);
|
||||||
wl_list_remove(&constraint->surface_destroy.link);
|
wl_list_remove(&constraint->surface_destroy.link);
|
||||||
wl_list_remove(&constraint->seat_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);
|
pixman_region32_fini(&constraint->region);
|
||||||
free(constraint);
|
free(constraint);
|
||||||
}
|
}
|
||||||
|
|
@ -258,9 +256,6 @@ static void pointer_constraint_create(struct wl_client *client,
|
||||||
|
|
||||||
pixman_region32_init(&constraint->region);
|
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_set_region(constraint, region_resource);
|
||||||
pointer_constraint_commit(constraint);
|
pointer_constraint_commit(constraint);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -361,15 +361,6 @@ static const struct wlr_surface_synced_impl surface_synced_impl = {
|
||||||
.state_size = sizeof(struct wlr_xdg_popup_state),
|
.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,
|
void create_xdg_popup(struct wlr_xdg_surface *surface, struct wlr_xdg_surface *parent,
|
||||||
struct wlr_xdg_positioner *positioner, uint32_t id) {
|
struct wlr_xdg_positioner *positioner, uint32_t id) {
|
||||||
if (!wlr_xdg_positioner_is_complete(positioner)) {
|
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;
|
goto error_synced;
|
||||||
}
|
}
|
||||||
wl_resource_set_implementation(surface->popup->resource,
|
wl_resource_set_implementation(surface->popup->resource,
|
||||||
&xdg_popup_implementation, surface->popup,
|
&xdg_popup_implementation, surface->popup, NULL);
|
||||||
xdg_popup_handle_resource_destroy);
|
|
||||||
|
|
||||||
surface->role = WLR_XDG_SURFACE_ROLE_POPUP;
|
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;
|
bool performed = data->data32[1] & 1;
|
||||||
xcb_atom_t action_atom = data->data32[2];
|
xcb_atom_t action_atom = data->data32[2];
|
||||||
|
|
||||||
if (xwm->drag_focus == NULL ||
|
if (xwm->drop_focus == NULL ||
|
||||||
target_window != xwm->drag_focus->window_id) {
|
target_window != xwm->drop_focus->window_id) {
|
||||||
wlr_log(WLR_DEBUG, "ignoring XdndFinished client message because "
|
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;
|
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) {
|
static void seat_handle_drag_focus(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_drag *drag = data;
|
struct wlr_drag *drag = data;
|
||||||
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus);
|
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus);
|
||||||
|
|
||||||
struct wlr_xwayland_surface *focus = NULL;
|
struct wlr_xwayland_surface *focus = NULL;
|
||||||
if (drag->focus != NULL) {
|
if (drag->focus != NULL) {
|
||||||
// TODO: check for subsurfaces?
|
focus = wlr_xwayland_surface_try_from_wlr_surface(drag->focus);
|
||||||
struct wlr_xwayland_surface *surface;
|
|
||||||
wl_list_for_each(surface, &xwm->surfaces, link) {
|
|
||||||
if (surface->surface == drag->focus) {
|
|
||||||
focus = surface;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus == xwm->drag_focus) {
|
xwm_set_drag_focus(xwm, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_handle_drag_motion(struct wl_listener *listener, void *data) {
|
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");
|
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);
|
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_container_of(listener, xwm, seat_drag_source_destroy);
|
||||||
|
|
||||||
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
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;
|
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) {
|
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 = drag;
|
||||||
xwm->drag_focus = NULL;
|
xwm->drag_focus = NULL;
|
||||||
|
xwm->drop_focus = NULL;
|
||||||
|
|
||||||
if (drag != NULL) {
|
if (drag != NULL) {
|
||||||
wl_signal_add(&drag->events.focus, &xwm->seat_drag_focus);
|
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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dnd_allowed = selection == &xwm->dnd_selection
|
||||||
|
&& (xwm->drag_focus != NULL || xwm->drop_focus != NULL);
|
||||||
|
|
||||||
// No xwayland surface focused, deny access to clipboard
|
// 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) {
|
if (wlr_log_get_verbosity() >= WLR_DEBUG) {
|
||||||
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
||||||
wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): "
|
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;
|
xwayland->server = NULL;
|
||||||
wlr_xwayland_shell_v1_destroy(xwayland->shell_v1);
|
wlr_xwayland_shell_v1_destroy(xwayland->shell_v1);
|
||||||
|
xwm_destroy(xwayland->xwm);
|
||||||
free(xwayland);
|
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,
|
void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface,
|
||||||
bool activated) {
|
bool activated) {
|
||||||
struct wlr_xwayland_surface *focused = xsurface->xwm->focus_surface;
|
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->primary_selection);
|
||||||
xwm_selection_finish(&xwm->dnd_selection);
|
xwm_selection_finish(&xwm->dnd_selection);
|
||||||
|
|
||||||
|
xwm_seat_unlink_drag_handlers(xwm);
|
||||||
|
|
||||||
if (xwm->seat) {
|
if (xwm->seat) {
|
||||||
if (xwm->seat->selection_source &&
|
if (xwm->seat->selection_source &&
|
||||||
data_source_is_xwayland(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_new_surface.link);
|
||||||
wl_list_remove(&xwm->compositor_destroy.link);
|
wl_list_remove(&xwm->compositor_destroy.link);
|
||||||
wl_list_remove(&xwm->shell_v1_new_surface.link);
|
wl_list_remove(&xwm->shell_v1_new_surface.link);
|
||||||
|
wl_list_remove(&xwm->shell_v1_destroy.link);
|
||||||
xcb_disconnect(xwm->xcb_conn);
|
xcb_disconnect(xwm->xcb_conn);
|
||||||
|
|
||||||
struct pending_startup_id *pending, *next;
|
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->surfaces_in_stack_order);
|
||||||
wl_list_init(&xwm->unpaired_surfaces);
|
wl_list_init(&xwm->unpaired_surfaces);
|
||||||
wl_list_init(&xwm->pending_startup_ids);
|
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->ping_timeout = 10000;
|
||||||
|
|
||||||
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
|
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;
|
xwm->shell_v1_new_surface.notify = handle_shell_v1_new_surface;
|
||||||
wl_signal_add(&xwayland->shell_v1->events.new_surface,
|
wl_signal_add(&xwayland->shell_v1->events.new_surface,
|
||||||
&xwm->shell_v1_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);
|
xwm_create_wm_window(xwm);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue