From 4c7c8daf9ccea7ac6a9089be362d254771c50811 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 9 Oct 2017 02:08:36 +0100 Subject: wayland_common: implement output tracking, cleanups and bugfixes This commit: - Implements output tracking (e.g. monitor plug/unplug) - Creates the surface during registry (no other dependencies) - Queues the callback immediately after surface creation - Cleaner and better event handling (functions return directly) - Better reconfigure handling (resizes reduced to 1 during init) - Don't unnecessarily resize (if dimensions match) Apart from that fixes 2 potential memory leaks (mime type and window title), 2 string ownership issues (output name and make need to be dup'd), fixes some style issues (switches were indented) and finally adds messages when disabling/enabling idle inhibition. The callback setter function was removed in preparation for the commit which will use the frame event cb because it was unnecessary. --- video/out/opengl/context_wayland.c | 6 +- video/out/vulkan/context_wayland.c | 4 +- video/out/wayland_common.c | 430 ++++++++++++++++++++----------------- video/out/wayland_common.h | 21 +- 4 files changed, 246 insertions(+), 215 deletions(-) diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c index 2d3c22abc1..f686fcc4cf 100644 --- a/video/out/opengl/context_wayland.c +++ b/video/out/opengl/context_wayland.c @@ -39,7 +39,7 @@ static void resize(struct ra_ctx *ctx) struct priv *p = ctx->priv; struct vo_wayland_state *wl = ctx->vo->wl; - MP_VERBOSE(wl, "Handling resizing on the egl side\n"); + MP_VERBOSE(wl, "Handling resize on the egl side\n"); const int32_t width = wl->scaling*mp_rect_w(wl->geometry); const int32_t height = wl->scaling*mp_rect_h(wl->geometry); @@ -85,8 +85,6 @@ static bool egl_create_context(struct ra_ctx *ctx) if (!ra_gl_ctx_init(ctx, &p->gl, params)) return false; - vo_wayland_set_cb_exec(ctx->vo, NULL, NULL); - return true; } @@ -104,8 +102,6 @@ static void egl_create_window(struct ra_ctx *ctx) eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, p->egl_context); eglSwapInterval(p->egl_display, 0); - - wl_display_roundtrip(wl->display); } static bool wayland_egl_reconfig(struct ra_ctx *ctx) diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index 67a3383ca3..92ee7aa1a9 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -70,8 +70,6 @@ static bool wayland_vk_init(struct ra_ctx *ctx) if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_MAILBOX_KHR)) goto error; - vo_wayland_set_cb_exec(ctx->vo, NULL, NULL); - return true; error: @@ -83,7 +81,7 @@ static void resize(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; - MP_VERBOSE(wl, "Handling resizing on the vk side\n"); + MP_VERBOSE(wl, "Handling resize on the vk side\n"); const int32_t width = wl->scaling*mp_rect_w(wl->geometry); const int32_t height = wl->scaling*mp_rect_h(wl->geometry); diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index e2d2016546..6f554c107d 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -44,15 +44,15 @@ static const struct zxdg_shell_v6_listener xdg_shell_listener = { xdg_shell_ping, }; -static void set_cursor_visibility(struct vo_wayland_state *wl, int on) +static int set_cursor_visibility(struct vo_wayland_state *wl, int on) { if (!wl->pointer) - return; + return VO_NOTAVAIL; if (on) { struct wl_cursor_image *image = wl->default_cursor->images[0]; struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); if (!buffer) - return; + return VO_FALSE; wl_pointer_set_cursor(wl->pointer, wl->pointer_id, wl->cursor_surface, image->hotspot_x, image->hotspot_y); wl_surface_attach(wl->cursor_surface, buffer, 0, 0); @@ -61,6 +61,7 @@ static void set_cursor_visibility(struct vo_wayland_state *wl, int on) } else { wl_pointer_set_cursor(wl->pointer, wl->pointer_id, NULL, 0, 0); } + return VO_TRUE; } static void pointer_handle_enter(void *data, struct wl_pointer *pointer, @@ -360,7 +361,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, static bool create_input(struct vo_wayland_state *wl) { - wl->xkb_context = xkb_context_new(0); + wl->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!wl->xkb_context) { MP_ERR(wl, "failed to initialize input: check xkbcommon\n"); @@ -502,10 +503,12 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output, int32_t transform) { struct vo_wayland_output *output = data; - output->make = make; - output->model = model; + output->make = talloc_strdup(output->wl, make); + output->model = talloc_strdup(output->wl, model); output->geometry.x0 = x; output->geometry.y0 = y; + output->phys_width = phys_width; + output->phys_height = phys_height; } static void output_handle_mode(void *data, struct wl_output *wl_output, @@ -515,19 +518,29 @@ static void output_handle_mode(void *data, struct wl_output *wl_output, struct vo_wayland_output *output = data; /* Only save current mode */ - if (!output || !(flags & WL_OUTPUT_MODE_CURRENT)) + if (!(flags & WL_OUTPUT_MODE_CURRENT)) return; - output->width = width; - output->height = height; - output->geometry.x1 = width + output->geometry.x0; - output->geometry.y1 = height + output->geometry.y0; + output->geometry.x1 = width; + output->geometry.y1 = height; output->flags = flags; output->refresh_rate = (double)refresh * 0.001; } static void output_handle_done(void* data, struct wl_output *wl_output) { + struct vo_wayland_output *o = data; + + o->geometry.x1 += o->geometry.x0; + o->geometry.y1 += o->geometry.y0; + + MP_VERBOSE(o->wl, "Registered output %s %s (0x%x):\n" + "\tx: %dpx, y: %dpx\n" + "\tw: %dpx (%dmm), h: %dpx (%dmm)\n" + "\tscale: %d\n" + "\tHz: %f\n", o->make, o->model, o->id, o->geometry.x0, + o->geometry.y0, mp_rect_w(o->geometry), o->phys_width, + mp_rect_h(o->geometry), o->phys_height, o->scale, o->refresh_rate); } static void output_handle_scale(void* data, struct wl_output *wl_output, @@ -667,6 +680,68 @@ static const struct wl_data_device_listener data_device_listener = { data_device_handle_selection, }; +static void surface_handle_enter(void *data, struct wl_surface *wl_surface, + struct wl_output *output) +{ + struct vo_wayland_state *wl = data; + wl->current_output = NULL; + + struct vo_wayland_output *o; + wl_list_for_each(o, &wl->output_list, link) { + if (o->output == output) { + wl->current_output = o; + break; + } + } + + wl->current_output->has_surface = true; + if (wl->scaling != wl->current_output->scale) + wl->pending_vo_events |= VO_EVENT_RESIZE; + wl->scaling = wl->current_output->scale; + + MP_VERBOSE(wl, "Surface entered output %s %s (0x%x), scale = %i\n", o->make, + o->model, o->id, wl->scaling); + + wl->pending_vo_events |= VO_EVENT_WIN_STATE; +} + +static void surface_handle_leave(void *data, struct wl_surface *wl_surface, + struct wl_output *output) +{ + struct vo_wayland_state *wl = data; + + struct vo_wayland_output *o; + wl_list_for_each(o, &wl->output_list, link) { + if (o->output == output) { + o->has_surface = false; + wl->pending_vo_events |= VO_EVENT_WIN_STATE; + return; + } + } +} + +static const struct wl_surface_listener surface_listener = { + surface_handle_enter, + surface_handle_leave, +}; + +static const struct wl_callback_listener frame_listener; + +static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) +{ + struct vo_wayland_state *wl = data; + + if (callback) + wl_callback_destroy(callback); + + wl->frame_callback = wl_surface_frame(wl->surface); + wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); +} + +static const struct wl_callback_listener frame_listener = { + frame_callback, +}; + static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, const char *interface, uint32_t ver) { @@ -676,15 +751,21 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id if (!strcmp(interface, wl_compositor_interface.name) && found++) { ver = MPMIN(ver, 4); /* Cap the version */ wl->compositor = wl_registry_bind(reg, id, &wl_compositor_interface, ver); + wl->surface = wl_compositor_create_surface(wl->compositor); + wl_surface_add_listener(wl->surface, &surface_listener, wl); + wl->frame_callback = wl_surface_frame(wl->surface); + wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); } if (!strcmp(interface, wl_output_interface.name) && found++) { struct vo_wayland_output *output = talloc_zero(wl, struct vo_wayland_output); - output->id = id; - output->scale = 1; - output->output = wl_registry_bind(reg, id, &wl_output_interface, - MPMIN(2, ver)); + output->wl = wl; + output->id = id; + output->scale = 1; + output->geometry = (struct mp_rect){ -1, -1, -1, -1 }; + output->output = wl_registry_bind(reg, id, &wl_output_interface, + MPMIN(2, ver)); wl_output_add_listener(output->output, &output_listener, output); wl_list_insert(&wl->output_list, &output->link); @@ -720,54 +801,35 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id MP_VERBOSE(wl, "Registered for protocol %s, ver %i\n", interface, ver); } -static void registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id) -{ -} - -static const struct wl_registry_listener registry_listener = { - registry_handle_add, - registry_handle_remove, -}; - -static void surface_handle_enter(void *data, struct wl_surface *wl_surface, - struct wl_output *output) +static void remove_output(struct vo_wayland_output *out) { - struct vo_wayland_state *wl = data; - wl->current_output = NULL; - - struct vo_wayland_output *o; - wl_list_for_each(o, &wl->output_list, link) { - if (o->output == output) { - wl->current_output = o; - break; - } - } - - wl->current_output->has_surface = 1; - wl->scaling = wl->current_output->scale; - - MP_VERBOSE(wl, "Surface entered an output, scale = %i\n", wl->scaling); + if (!out) + return; - wl->pending_vo_events |= VO_EVENT_WIN_STATE; + MP_VERBOSE(out->wl, "Deregistering output %s %s (0x%x)\n", out->make, + out->model, out->id); + wl_list_remove(&out->link); + talloc_free(out->make); + talloc_free(out->model); + talloc_free(out); + return; } -static void surface_handle_leave(void *data, struct wl_surface *wl_surface, - struct wl_output *output) +static void registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id) { struct vo_wayland_state *wl = data; - - struct vo_wayland_output *o; - wl_list_for_each(o, &wl->output_list, link) { - if (o->output == output) { - o->has_surface = 0; + struct vo_wayland_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &wl->output_list, link) { + if (output->id == id) { + remove_output(output); return; } } } -static const struct wl_surface_listener surface_listener = { - surface_handle_enter, - surface_handle_leave, +static const struct wl_registry_listener registry_listener = { + registry_handle_add, + registry_handle_remove, }; static int spawn_cursor(struct vo_wayland_state *wl) @@ -802,30 +864,31 @@ static const struct zxdg_surface_v6_listener xdg_surface_listener = { static void handle_toplevel_config(void *data, struct zxdg_toplevel_v6 *toplevel, int32_t width, int32_t height, struct wl_array *states) { - uint32_t *p; struct vo_wayland_state *wl = data; struct mp_rect old_geometry = wl->geometry; int prev_fs_state = wl->fullscreen; - int maximized = 0; - wl->fullscreen = 0; - wl_array_for_each(p, states) { - enum zxdg_toplevel_v6_state state = *p; - switch (state) { - case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: - wl->fullscreen = 1; - break; - case ZXDG_TOPLEVEL_V6_STATE_RESIZING: - wl->pending_vo_events |= VO_EVENT_LIVE_RESIZING; - break; - case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: - maximized = 1; - break; - case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: - break; + bool maximized = false; + wl->fullscreen = false; + enum zxdg_toplevel_v6_state *state; + wl_array_for_each(state, states) { + switch (*state) { + case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: + wl->fullscreen = true; + break; + case ZXDG_TOPLEVEL_V6_STATE_RESIZING: + wl->pending_vo_events |= VO_EVENT_LIVE_RESIZING; + break; + case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: + maximized = true; + break; + case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: + break; } } + if (prev_fs_state != wl->fullscreen) + wl->pending_vo_events |= VO_EVENT_FULLSCREEN_STATE; if (!(wl->pending_vo_events & VO_EVENT_LIVE_RESIZING)) vo_query_and_reset_events(wl->vo, VO_EVENT_LIVE_RESIZING); @@ -851,12 +914,13 @@ static void handle_toplevel_config(void *data, struct zxdg_toplevel_v6 *toplevel wl->geometry = wl->window_size; } + if (mp_rect_equals(&old_geometry, &wl->geometry)) + return; + MP_VERBOSE(wl, "Resizing due to xdg from %ix%i to %ix%i\n", mp_rect_w(old_geometry)*wl->scaling, mp_rect_h(old_geometry)*wl->scaling, mp_rect_w(wl->geometry)*wl->scaling, mp_rect_h(wl->geometry)*wl->scaling); - if (prev_fs_state != wl->fullscreen) - wl->pending_vo_events |= VO_EVENT_FULLSCREEN_STATE; wl->pending_vo_events |= VO_EVENT_RESIZE; } @@ -871,10 +935,8 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { handle_toplevel_close, }; -static int create_surface(struct vo_wayland_state *wl) +static int create_xdg_surface(struct vo_wayland_state *wl) { - wl->surface = wl_compositor_create_surface(wl->compositor); - wl->xdg_surface = zxdg_shell_v6_get_xdg_surface(wl->shell, wl->surface); zxdg_surface_v6_add_listener(wl->xdg_surface, &xdg_surface_listener, wl); @@ -887,34 +949,18 @@ static int create_surface(struct vo_wayland_state *wl) return 0; } -static const struct wl_callback_listener frame_listener; - -static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) -{ - struct vo_wayland_state *wl = data; - - wl_callback_destroy(callback); - - wl->frame_callback = wl_surface_frame(wl->surface); - wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); - - if (wl->callback_exec) - wl->callback_exec(wl, wl->callback_exec_priv, time); -} - -static const struct wl_callback_listener frame_listener = { - frame_callback, -}; - static int set_border_decorations(struct vo_wayland_state *wl, int state) { if (!wl->server_decoration) return VO_NOTIMPL; enum org_kde_kwin_server_decoration_mode mode; - if (state) + if (state) { + MP_VERBOSE(wl, "Enabling server decorations\n"); mode = ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER; - else + } else { + MP_VERBOSE(wl, "Disabling server decorations\n"); mode = ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE; + } org_kde_kwin_server_decoration_request_mode(wl->server_decoration, mode); return VO_TRUE; } @@ -946,38 +992,38 @@ int vo_wayland_init(struct vo *vo) /* Do a roundtrip to run the registry */ wl_display_roundtrip(wl->display); - if (!wl->idle_inhibit_manager) - MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", - zwp_idle_inhibit_manager_v1_interface.name); - if (!wl->dnd_devman) - MP_VERBOSE(wl, "Compositor doesn't support the %s (ver. 3) protocol!\n", - wl_data_device_manager_interface.name); - if (!wl->server_decoration_manager) - MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", - org_kde_kwin_server_decoration_manager_interface.name); if (!wl->shell) { MP_FATAL(wl, "Compositor doesn't support the required %s protocol!\n", zxdg_shell_v6_interface.name); return false; } + /* Can't be initialized during registry, as they depend on 2 or more protocols */ if (spawn_cursor(wl)) return false; - if (create_surface(wl)) + if (create_xdg_surface(wl)) return false; - wl_surface_add_listener(wl->surface, &surface_listener, wl); - if (wl->dnd_devman) { wl->dnd_ddev = wl_data_device_manager_get_data_device(wl->dnd_devman, wl->seat); wl_data_device_add_listener(wl->dnd_ddev, &data_device_listener, wl); + } else { + MP_VERBOSE(wl, "Compositor doesn't support the %s (ver. 3) protocol!\n", + wl_data_device_manager_interface.name); } if (wl->server_decoration_manager) { wl->server_decoration = org_kde_kwin_server_decoration_manager_create(wl->server_decoration_manager, wl->surface); set_border_decorations(wl, vo->opts->border); + } else { + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + org_kde_kwin_server_decoration_manager_interface.name); } + if (!wl->idle_inhibit_manager) + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + zwp_idle_inhibit_manager_v1_interface.name); + wl->display_fd = wl_display_get_fd(wl->display); mp_make_wakeup_pipe(wl->wakeup_pipe); @@ -1031,33 +1077,25 @@ void vo_wayland_uninit(struct vo *vo) wl_display_disconnect(wl->display); } + struct vo_wayland_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &wl->output_list, link) + remove_output(output); + + talloc_free(wl->dnd_mime_type); + for (int n = 0; n < 2; n++) close(wl->wakeup_pipe[n]); talloc_free(wl); vo->wl = NULL; } -void vo_wayland_set_cb_exec(struct vo *vo, vo_wayland_frame_cb cb, void *cb_priv) -{ - struct vo_wayland_state *wl = vo->wl; - - if (cb) { - wl->callback_exec = cb; - wl->callback_exec_priv = cb_priv; - wl->frame_callback = wl_surface_frame(wl->surface); - wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); - } -} - static struct vo_wayland_output *find_output(struct vo_wayland_state *wl, int index) { int screen_id = 0; struct vo_wayland_output *output; - wl_list_for_each_reverse(output, &wl->output_list, link) { - if (index == screen_id) + wl_list_for_each(output, &wl->output_list, link) { + if (index == screen_id++) return output; - - screen_id++; } return NULL; } @@ -1073,9 +1111,12 @@ int vo_wayland_reconfig(struct vo *vo) /* Surface enter events happen later but we already know the outputs and we'd * like to know the output the surface would be on (for scaling or fullscreen), * so if fsscreen_id is set or there's only one possible output, use it. */ - if ((wl_list_length(&wl->output_list) == 1) || (vo->opts->fsscreen_id >= 0)) { - int idx = wl_list_length(&wl->output_list) == 1 ? 0 : vo->opts->fsscreen_id; - struct vo_wayland_output *out = out = find_output(wl, idx); + if (((!wl->current_output) && (wl_list_length(&wl->output_list) == 1)) || + (vo->opts->fullscreen && (vo->opts->fsscreen_id >= 0))) { + int idx = 0; + if (vo->opts->fullscreen && (vo->opts->fsscreen_id >= 0)) + idx = vo->opts->fsscreen_id; + struct vo_wayland_output *out = find_output(wl, idx); if (!out) { MP_ERR(wl, "Screen index %i not found/unavailable!\n", idx); } else { @@ -1102,8 +1143,8 @@ int vo_wayland_reconfig(struct vo *vo) if (wl->fullscreen && wl->current_output) { wl->geometry.x0 = 0; wl->geometry.y0 = 0; - wl->geometry.x1 = wl->current_output->width / wl->scaling; - wl->geometry.y1 = wl->current_output->height / wl->scaling; + wl->geometry.x1 = mp_rect_w(wl->current_output->geometry)/wl->scaling; + wl->geometry.y1 = mp_rect_h(wl->current_output->geometry)/wl->scaling; } else { zxdg_toplevel_v6_set_fullscreen(wl->xdg_toplevel, wl_out); } @@ -1111,19 +1152,21 @@ int vo_wayland_reconfig(struct vo *vo) wl_surface_set_buffer_scale(wl->surface, wl->scaling); wl_surface_commit(wl->surface); - if (wl->configured) - wl->pending_vo_events |= VO_EVENT_RESIZE; - wl->configured = 1; + wl->pending_vo_events |= VO_EVENT_RESIZE; + if (!wl->configured) { + wl_display_roundtrip(wl->display); + wl->configured = true; + } return true; } -static int toggle_screensaver_inhibitor(struct vo_wayland_state *wl, int state) +static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state) { if (!wl->idle_inhibit_manager) - return 1; + return VO_NOTIMPL; if (state == (!!wl->idle_inhibitor)) - return 0; + return VO_TRUE; if (state) { MP_VERBOSE(wl, "Enabling idle inhibitor\n"); struct zwp_idle_inhibit_manager_v1 *mgr = wl->idle_inhibit_manager; @@ -1132,23 +1175,26 @@ static int toggle_screensaver_inhibitor(struct vo_wayland_state *wl, int state) MP_VERBOSE(wl, "Disabling the idle inhibitor\n"); zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor); } - return 0; + return VO_TRUE; } -static void toggle_fullscreen(struct vo_wayland_state *wl) +static int toggle_fullscreen(struct vo_wayland_state *wl) { + if (!wl->xdg_toplevel) + return VO_NOTAVAIL; if (wl->fullscreen) zxdg_toplevel_v6_unset_fullscreen(wl->xdg_toplevel); else zxdg_toplevel_v6_set_fullscreen(wl->xdg_toplevel, NULL); + return VO_TRUE; } -static void update_window_title(struct vo_wayland_state *wl, char *title) +static int update_window_title(struct vo_wayland_state *wl, char *title) { - talloc_free(wl->window_title); - wl->window_title = talloc_strdup(wl, title); - if (wl->xdg_toplevel) - zxdg_toplevel_v6_set_title(wl->xdg_toplevel, wl->window_title); + if (!wl->xdg_toplevel) + return VO_NOTAVAIL; + zxdg_toplevel_v6_set_title(wl->xdg_toplevel, title); + return VO_TRUE; } static void check_dnd_fd(struct vo_wayland_state *wl) @@ -1200,7 +1246,7 @@ static char **get_displays_spanned(struct vo_wayland_state *wl) char **names = NULL; int displays_spanned = 0; struct vo_wayland_output *output; - wl_list_for_each_reverse(output, &wl->output_list, link) { + wl_list_for_each(output, &wl->output_list, link) { if (output->has_surface) MP_TARRAY_APPEND(NULL, names, displays_spanned, talloc_strdup(NULL, output->model)); @@ -1215,59 +1261,55 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) wl_display_dispatch_pending(wl->display); switch (request) { - case VOCTRL_CHECK_EVENTS: - check_dnd_fd(wl); - *events |= wl->pending_vo_events; - wl->pending_vo_events = 0; - return VO_TRUE; - case VOCTRL_UPDATE_WINDOW_TITLE: - update_window_title(wl, (char *)arg); - return VO_TRUE; - case VOCTRL_FULLSCREEN: - toggle_fullscreen(wl); - return VO_TRUE; - case VOCTRL_GET_FULLSCREEN: - *(int *)arg = wl->fullscreen; - return VO_TRUE; - case VOCTRL_SET_CURSOR_VISIBILITY: - set_cursor_visibility(wl, *(bool *)arg); - return VO_TRUE; - case VOCTRL_BORDER: - return set_border_decorations(wl, vo->opts->border); - case VOCTRL_GET_DISPLAY_NAMES: { - *(char ***)arg = get_displays_spanned(wl); - return VO_TRUE; - } - case VOCTRL_KILL_SCREENSAVER: - if (toggle_screensaver_inhibitor(wl, true)) - return VO_NOTAVAIL; - return VO_TRUE; - case VOCTRL_RESTORE_SCREENSAVER: - if (toggle_screensaver_inhibitor(wl, false)) - return VO_NOTAVAIL; - return VO_TRUE; - case VOCTRL_GET_UNFS_WINDOW_SIZE: { - int *s = arg; - s[0] = mp_rect_w(wl->geometry)*wl->scaling; - s[1] = mp_rect_h(wl->geometry)*wl->scaling; - return VO_TRUE; - } - case VOCTRL_SET_UNFS_WINDOW_SIZE: { - int *s = arg; - if (!wl->fullscreen) { - wl->geometry.x0 = 0; - wl->geometry.y0 = 0; - wl->geometry.x1 = s[0]/wl->scaling; - wl->geometry.y1 = s[1]/wl->scaling; - wl->pending_vo_events |= VO_EVENT_RESIZE; - } - return VO_TRUE; + case VOCTRL_CHECK_EVENTS: { + check_dnd_fd(wl); + *events |= wl->pending_vo_events; + wl->pending_vo_events = 0; + return VO_TRUE; + } + case VOCTRL_GET_FULLSCREEN: { + *(int *)arg = wl->fullscreen; + return VO_TRUE; + } + case VOCTRL_GET_DISPLAY_NAMES: { + *(char ***)arg = get_displays_spanned(wl); + return VO_TRUE; + } + case VOCTRL_GET_UNFS_WINDOW_SIZE: { + int *s = arg; + s[0] = mp_rect_w(wl->geometry)*wl->scaling; + s[1] = mp_rect_h(wl->geometry)*wl->scaling; + return VO_TRUE; + } + case VOCTRL_SET_UNFS_WINDOW_SIZE: { + int *s = arg; + if (!wl->fullscreen) { + wl->geometry.x0 = 0; + wl->geometry.y0 = 0; + wl->geometry.x1 = s[0]/wl->scaling; + wl->geometry.y1 = s[1]/wl->scaling; + wl->pending_vo_events |= VO_EVENT_RESIZE; } - case VOCTRL_GET_DISPLAY_FPS: - if (!wl->current_output) - return VO_NOTAVAIL; - *(double *)arg = wl->current_output->refresh_rate; - return VO_TRUE; + return VO_TRUE; + } + case VOCTRL_GET_DISPLAY_FPS: { + if (!wl->current_output) + return VO_NOTAVAIL; + *(double *)arg = wl->current_output->refresh_rate; + return VO_TRUE; + } + case VOCTRL_UPDATE_WINDOW_TITLE: + return update_window_title(wl, (char *)arg); + case VOCTRL_FULLSCREEN: + return toggle_fullscreen(wl); + case VOCTRL_SET_CURSOR_VISIBILITY: + return set_cursor_visibility(wl, *(bool *)arg); + case VOCTRL_BORDER: + return set_border_decorations(wl, vo->opts->border); + case VOCTRL_KILL_SCREENSAVER: + return set_screensaver_inhibitor(wl, true); + case VOCTRL_RESTORE_SCREENSAVER: + return set_screensaver_inhibitor(wl, false); } return VO_NOTIMPL; diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 60d5924efa..3903b58a2b 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -25,20 +25,19 @@ #include "vo.h" #include "input/event.h" -typedef void (*vo_wayland_frame_cb)(struct vo_wayland_state *wl, void *priv, uint32_t time); - struct vo_wayland_output { + struct vo_wayland_state *wl; uint32_t id; struct wl_output *output; struct mp_rect geometry; - int width; - int height; + int phys_width; + int phys_height; int scale; uint32_t flags; double refresh_rate; - const char *make; - const char *model; - int has_surface; + char *make; + char *model; + bool has_surface; struct wl_list link; }; @@ -54,8 +53,8 @@ struct vo_wayland_state { struct mp_rect geometry; struct mp_rect window_size; float aspect_ratio; - int fullscreen; - char *window_title; + bool fullscreen; + bool configured; int wakeup_pipe[2]; int pending_vo_events; int mouse_x; @@ -64,9 +63,6 @@ struct vo_wayland_state { int touch_entries; uint32_t pointer_id; int display_fd; - int configured; - vo_wayland_frame_cb callback_exec; - void *callback_exec_priv; struct wl_callback *frame_callback; struct wl_list output_list; struct vo_wayland_output *current_output; @@ -112,6 +108,5 @@ void vo_wayland_check_events(struct vo *vo); void vo_wayland_uninit(struct vo *vo); void vo_wayland_wakeup(struct vo *vo); void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us); -void vo_wayland_set_cb_exec(struct vo *vo, vo_wayland_frame_cb cb, void *cb_priv); #endif /* MPLAYER_WAYLAND_COMMON_H */ -- cgit v1.2.3