diff options
-rw-r--r-- | rootston/desktop.c | 32 | ||||
-rw-r--r-- | types/wlr_output.c | 416 |
2 files changed, 213 insertions, 235 deletions
diff --git a/rootston/desktop.c b/rootston/desktop.c index f93d1df8..37022ca4 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -45,14 +45,35 @@ void view_get_size(struct roots_view *view, struct wlr_box *box) { box->height = view->wlr_surface->current->height; } +static void view_update_output(struct roots_view *view) { + struct roots_desktop *desktop = view->desktop; + struct roots_output *output = NULL, *_output; + struct wlr_box box; + view_get_size(view, &box); + wl_list_for_each(_output, &desktop->outputs, link) { + if (!wlr_output_layout_intersects(desktop->layout, _output->wlr_output, + view->x, view->y, view->x + box.width, view->x + box.height)) { + continue; + } + if (output == NULL + || output->wlr_output->scale < _output->wlr_output->scale) { + output = _output; + } + } + if (output && output != view->output) { + view->output = output; + wlr_surface_send_enter(view->wlr_surface, output->wlr_output); + } +} + void view_set_position(struct roots_view *view, double x, double y) { if (view->set_position) { view->set_position(view, x, y); - return; + } else { + view->x = x; + view->y = y; } - - view->x = x; - view->y = y; + view_update_output(view); } void view_activate(struct roots_view *view, bool activate) { @@ -65,6 +86,7 @@ void view_resize(struct roots_view *view, uint32_t width, uint32_t height) { if (view->resize) { view->resize(view, width, height); } + view_update_output(view); } void view_close(struct roots_view *view) { @@ -111,6 +133,8 @@ void view_setup(struct roots_view *view) { struct roots_input *input = view->desktop->server->input; set_view_focus(input, view->desktop, view); + wlr_seat_keyboard_notify_enter(input->wl_seat, view->wlr_surface); + view_update_output(view); } void view_teardown(struct roots_view *view) { diff --git a/types/wlr_output.c b/types/wlr_output.c index 2f5e3086..dd7e8d6a 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -5,7 +5,6 @@ #include <tgmath.h> #include <time.h> #include <wayland-server.h> -#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_output.h> #include <wlr/types/wlr_surface.h> #include <wlr/interfaces/wlr_output.h> @@ -136,9 +135,7 @@ static void wlr_output_update_matrix(struct wlr_output *output) { } void wlr_output_enable(struct wlr_output *output, bool enable) { - if (output->impl->enable) { - output->impl->enable(output, enable); - } + output->impl->enable(output, enable); } bool wlr_output_set_mode(struct wlr_output *output, @@ -191,199 +188,94 @@ void wlr_output_set_position(struct wlr_output *output, int32_t lx, } } -void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, - const struct wlr_output_impl *impl) { - assert(impl->make_current && impl->swap_buffers && impl->transform); - output->backend = backend; - output->impl = impl; - wl_list_init(&output->modes); - output->transform = WL_OUTPUT_TRANSFORM_NORMAL; - output->scale = 1; - wl_list_init(&output->cursors); - wl_signal_init(&output->events.frame); - wl_signal_init(&output->events.swap_buffers); - wl_signal_init(&output->events.resolution); - wl_signal_init(&output->events.destroy); -} - -void wlr_output_destroy(struct wlr_output *output) { - if (!output) { - return; - } - - wl_signal_emit(&output->events.destroy, output); - - struct wlr_output_mode *mode, *tmp_mode; - wl_list_for_each_safe(mode, tmp_mode, &output->modes, link) { - free(mode); - } - wl_list_remove(&output->modes); - if (output->impl && output->impl->destroy) { - output->impl->destroy(output); - } else { - free(output); +static bool set_cursor(struct wlr_output *output, const uint8_t *buf, + int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, + int32_t hotspot_y) { + if (output->impl->set_cursor + && output->impl->set_cursor(output, buf, stride, width, height, + hotspot_x, hotspot_y, true)) { + output->cursor.is_sw = false; + return true; } -} -void wlr_output_effective_resolution(struct wlr_output *output, - int *width, int *height) { - // TODO: Scale factor - if (output->transform % 2 == 1) { - *width = output->height; - *height = output->width; - } else { - *width = output->width; - *height = output->height; - } -} - -void wlr_output_make_current(struct wlr_output *output) { - output->impl->make_current(output); -} + wlr_log(L_INFO, "Falling back to software cursor"); -static void output_cursor_get_box(struct wlr_output_cursor *cursor, - struct wlr_box *box) { - box->x = cursor->x - cursor->hotspot_x; - box->y = cursor->y - cursor->hotspot_y; - box->width = cursor->width; - box->height = cursor->height; -} + output->cursor.is_sw = true; + output->cursor.width = width; + output->cursor.height = height; -static void output_cursor_render(struct wlr_output_cursor *cursor) { - struct wlr_texture *texture = cursor->texture; - struct wlr_renderer *renderer = cursor->renderer; - if (cursor->surface != NULL) { - // Some clients commit a cursor surface with a NULL buffer to hide it. - if (!wlr_surface_has_buffer(cursor->surface)) { - return; + if (!output->cursor.renderer) { + output->cursor.renderer = wlr_gles2_renderer_create(output->backend); + if (!output->cursor.renderer) { + return false; } - texture = cursor->surface->texture; - renderer = cursor->surface->renderer; } - if (texture == NULL || renderer == NULL) { - return; - } - - struct wlr_box output_box; - output_box.x = output_box.y = 0; - output_box.width = cursor->output->width; - output_box.height = cursor->output->height; - - struct wlr_box cursor_box; - output_cursor_get_box(cursor, &cursor_box); - - struct wlr_box intersection; - struct wlr_box *intersection_ptr = &intersection; - if (!wlr_box_intersection(&output_box, &cursor_box, &intersection_ptr)) { - return; - } - - glViewport(0, 0, cursor->output->width, cursor->output->height); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - float matrix[16]; - wlr_texture_get_matrix(texture, &matrix, - &cursor->output->transform_matrix, cursor->x - cursor->hotspot_x, - cursor->y - cursor->hotspot_y); - wlr_render_with_matrix(renderer, texture, &matrix); -} - -void wlr_output_swap_buffers(struct wlr_output *output) { - struct wlr_output_cursor *cursor; - wl_list_for_each(cursor, &output->cursors, link) { - if (output->hardware_cursor == cursor) { - continue; + if (!output->cursor.texture) { + output->cursor.texture = + wlr_render_texture_create(output->cursor.renderer); + if (!output->cursor.texture) { + return false; } - output_cursor_render(cursor); } - wl_signal_emit(&output->events.swap_buffers, &output); - - output->impl->swap_buffers(output); + return wlr_texture_upload_pixels(output->cursor.texture, + WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); } -void wlr_output_set_gamma(struct wlr_output *output, - uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) { - if (output->impl->set_gamma) { - output->impl->set_gamma(output, size, r, g, b); +bool wlr_output_set_cursor(struct wlr_output *output, + const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height, + int32_t hotspot_x, int32_t hotspot_y) { + if (output->cursor.surface) { + wl_list_remove(&output->cursor.surface_commit.link); + wl_list_remove(&output->cursor.surface_destroy.link); + output->cursor.surface = NULL; } -} -uint32_t wlr_output_get_gamma_size(struct wlr_output *output) { - if (!output->impl->get_gamma_size) { - return 0; - } - return output->impl->get_gamma_size(output); + output->cursor.hotspot_x = hotspot_x; + output->cursor.hotspot_y = hotspot_y; + + return set_cursor(output, buf, stride, width, height, hotspot_x, hotspot_y); } -static void output_cursor_reset(struct wlr_output_cursor *cursor) { - if (cursor->surface != NULL) { - wl_list_remove(&cursor->surface_commit.link); - wl_list_remove(&cursor->surface_destroy.link); - cursor->surface = NULL; - } +static inline int64_t timespec_to_msec(const struct timespec *a) { + return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; } -bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, - const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height, - int32_t hotspot_x, int32_t hotspot_y) { - output_cursor_reset(cursor); - - cursor->width = width; - cursor->height = height; - cursor->hotspot_x = hotspot_x; - cursor->hotspot_y = hotspot_y; - - if (cursor->output->hardware_cursor == NULL && - cursor->output->impl->set_cursor) { - int ok = cursor->output->impl->set_cursor(cursor->output, pixels, - stride, width, height, hotspot_x, hotspot_y, true); - if (ok) { - cursor->output->hardware_cursor = cursor; - return true; - } +static void commit_cursor_surface(struct wlr_output *output, + struct wlr_surface *surface) { + if (output->cursor.is_sw) { + return; } - wlr_log(L_INFO, "Falling back to software cursor"); - - if (cursor->renderer == NULL) { - cursor->renderer = wlr_gles2_renderer_create(cursor->output->backend); - if (cursor->renderer == NULL) { - return false; - } + struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer); + if (buffer == NULL) { + return; } - if (cursor->texture == NULL) { - cursor->texture = wlr_render_texture_create(cursor->renderer); - if (cursor->texture == NULL) { - return false; - } + uint32_t format = wl_shm_buffer_get_format(buffer); + if (format != WL_SHM_FORMAT_ARGB8888) { + return; } - return wlr_texture_upload_pixels(cursor->texture, WL_SHM_FORMAT_ARGB8888, - stride, width, height, pixels); -} - -static void output_cursor_commit(struct wlr_output_cursor *cursor) { - cursor->width = cursor->surface->current->width; - cursor->height = cursor->surface->current->height; - - // TODO: if hardware cursor, upload pixels + void *buffer_data = wl_shm_buffer_get_data(buffer); + int32_t width = wl_shm_buffer_get_width(buffer); + int32_t height = wl_shm_buffer_get_height(buffer); + int32_t stride = wl_shm_buffer_get_stride(buffer); + wl_shm_buffer_begin_access(buffer); + wlr_output_set_cursor(output, buffer_data, stride/4, width, height, + output->cursor.hotspot_x - surface->current->sx, + output->cursor.hotspot_y - surface->current->sy); + wl_shm_buffer_end_access(buffer); } -static inline int64_t timespec_to_msec(const struct timespec *a) { - return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; -} - -static void output_cursor_handle_commit(struct wl_listener *listener, +static void handle_cursor_surface_commit(struct wl_listener *listener, void *data) { - struct wlr_output_cursor *cursor = wl_container_of(listener, cursor, - surface_commit); + struct wlr_output *output = wl_container_of(listener, output, + cursor.surface_commit); struct wlr_surface *surface = data; - output_cursor_commit(cursor); + commit_cursor_surface(output, surface); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -396,107 +288,169 @@ static void output_cursor_handle_commit(struct wl_listener *listener, } } -static void output_cursor_handle_destroy(struct wl_listener *listener, +static void handle_cursor_surface_destroy(struct wl_listener *listener, void *data) { - struct wlr_output_cursor *cursor = wl_container_of(listener, cursor, - surface_destroy); - output_cursor_reset(cursor); + struct wlr_output *output = wl_container_of(listener, output, + cursor.surface_destroy); + + wl_list_remove(&output->cursor.surface_commit.link); + wl_list_remove(&output->cursor.surface_destroy.link); + output->cursor.surface = NULL; } -void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor, +void wlr_output_set_cursor_surface(struct wlr_output *output, struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) { if (surface && strcmp(surface->role, "wl_pointer-cursor") != 0) { return; } - if (surface) { - cursor->width = surface->current->width; - cursor->height = surface->current->height; - } - cursor->hotspot_x = hotspot_x; - cursor->hotspot_y = hotspot_y; + output->cursor.hotspot_x = hotspot_x; + output->cursor.hotspot_y = hotspot_y; - if (surface && surface == cursor->surface) { - if (cursor->output->hardware_cursor == cursor && - cursor->output->impl->set_cursor) { - // If the surface hasn't changed and it's an hardware cursor, only - // update the hotspot - cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0, 0, - hotspot_x, hotspot_y, false); + if (surface && surface == output->cursor.surface) { + if (output->impl->set_cursor && !output->cursor.is_sw) { + // Only update the hotspot + output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x, + hotspot_y, false); } return; } - output_cursor_reset(cursor); + if (output->cursor.surface) { + wl_list_remove(&output->cursor.surface_commit.link); + wl_list_remove(&output->cursor.surface_destroy.link); + output->cursor.surface = NULL; + } - // Disable hardware cursor for surfaces + // Disable hardware cursor // TODO: support hardware cursors - if (cursor->output->hardware_cursor == cursor && - cursor->output->impl->set_cursor) { - cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0, 0, 0, 0, + output->cursor.is_sw = true; + if (output->impl->set_cursor) { + output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y, true); - cursor->output->hardware_cursor = NULL; } - cursor->surface = surface; + //output->cursor.is_sw = output->impl->set_cursor == NULL; + output->cursor.surface = surface; if (surface != NULL) { - wl_signal_add(&surface->events.commit, &cursor->surface_commit); - wl_signal_add(&surface->events.destroy, &cursor->surface_destroy); - output_cursor_commit(cursor); + wl_signal_add(&surface->events.commit, &output->cursor.surface_commit); + wl_signal_add(&surface->events.destroy, + &output->cursor.surface_destroy); + commit_cursor_surface(output, surface); } else { - // TODO: if hardware cursor, disable cursor + set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y); } } -bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, int x, int y) { - cursor->x = x; - cursor->y = y; +bool wlr_output_move_cursor(struct wlr_output *output, int x, int y) { + output->cursor.x = x; + output->cursor.y = y; - if (cursor->output->hardware_cursor != cursor) { + if (output->cursor.is_sw) { return true; } - if (!cursor->output->impl->move_cursor) { + if (!output->impl->move_cursor) { return false; } - return cursor->output->impl->move_cursor(cursor->output, x, y); + + return output->impl->move_cursor(output, x, y); } -struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) { - struct wlr_output_cursor *cursor = - calloc(1, sizeof(struct wlr_output_cursor)); - if (cursor == NULL) { - return NULL; - } - cursor->output = output; - wl_list_init(&cursor->surface_commit.link); - cursor->surface_commit.notify = output_cursor_handle_commit; - wl_list_init(&cursor->surface_destroy.link); - cursor->surface_destroy.notify = output_cursor_handle_destroy; - wl_list_insert(&output->cursors, &cursor->link); - return cursor; +void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, + const struct wlr_output_impl *impl) { + output->backend = backend; + output->impl = impl; + wl_list_init(&output->modes); + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + output->scale = 1; + wl_signal_init(&output->events.frame); + wl_signal_init(&output->events.swap_buffers); + wl_signal_init(&output->events.resolution); + wl_signal_init(&output->events.destroy); + + wl_list_init(&output->cursor.surface_commit.link); + output->cursor.surface_commit.notify = handle_cursor_surface_commit; + wl_list_init(&output->cursor.surface_destroy.link); + output->cursor.surface_destroy.notify = handle_cursor_surface_destroy; } -void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) { - if (cursor == NULL) { +void wlr_output_destroy(struct wlr_output *output) { + if (!output) { return; } - output_cursor_reset(cursor); - if (cursor->output->hardware_cursor == cursor) { - // If this cursor was the hardware cursor, disable it - if (cursor->output->impl->set_cursor) { - cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0, 0, 0, - 0, true); + + wl_signal_emit(&output->events.destroy, output); + + wlr_texture_destroy(output->cursor.texture); + wlr_renderer_destroy(output->cursor.renderer); + + struct wlr_output_mode *mode, *tmp_mode; + wl_list_for_each_safe(mode, tmp_mode, &output->modes, link) { + free(mode); + } + wl_list_remove(&output->modes); + if (output->impl && output->impl->destroy) { + output->impl->destroy(output); + } else { + free(output); + } +} + +void wlr_output_effective_resolution(struct wlr_output *output, + int *width, int *height) { + if (output->transform % 2 == 1) { + *width = output->height; + *height = output->width; + } else { + *width = output->width; + *height = output->height; + } +} + +void wlr_output_make_current(struct wlr_output *output) { + output->impl->make_current(output); +} + +void wlr_output_swap_buffers(struct wlr_output *output) { + if (output->cursor.is_sw) { + glViewport(0, 0, output->width, output->height); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + struct wlr_texture *texture = output->cursor.texture; + struct wlr_renderer *renderer = output->cursor.renderer; + if (output->cursor.surface) { + texture = output->cursor.surface->texture; + renderer = output->cursor.surface->renderer; + } + + // We check texture->valid because some clients set a cursor surface + // with a NULL buffer to hide it + if (renderer && texture && texture->valid) { + float matrix[16]; + wlr_texture_get_matrix(texture, &matrix, &output->transform_matrix, + output->cursor.x, output->cursor.y); + wlr_render_with_matrix(renderer, texture, &matrix); } - cursor->output->hardware_cursor = NULL; } - if (cursor->texture != NULL) { - wlr_texture_destroy(cursor->texture); + + wl_signal_emit(&output->events.swap_buffers, &output); + + output->impl->swap_buffers(output); +} + +void wlr_output_set_gamma(struct wlr_output *output, + uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) { + if (output->impl->set_gamma) { + output->impl->set_gamma(output, size, r, g, b); } - if (cursor->renderer != NULL) { - wlr_renderer_destroy(cursor->renderer); +} + +uint32_t wlr_output_get_gamma_size(struct wlr_output *output) { + if (!output->impl->get_gamma_size) { + return 0; } - wl_list_remove(&cursor->link); - free(cursor); + return output->impl->get_gamma_size(output); } |