vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Thu May 24 19:10:56 2018 +0300| [21047ec421f4bdfb1345284ebe285965b7aee237] | committer: Rémi Denis-Courmont
xdg-shell: move output handling to separate file This follows the model already used for seats (i.e. inputs). This avoids one race-prone round-trip at start-up. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=21047ec421f4bdfb1345284ebe285965b7aee237 --- modules/video_output/Makefile.am | 1 + modules/video_output/wayland/output.c | 162 +++++++++++++++++++++++++++++++ modules/video_output/wayland/output.h | 28 ++++++ modules/video_output/wayland/xdg-shell.c | 96 ++---------------- 4 files changed, 201 insertions(+), 86 deletions(-) diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am index 279f461efd..89b71a4dc6 100644 --- a/modules/video_output/Makefile.am +++ b/modules/video_output/Makefile.am @@ -212,6 +212,7 @@ libwl_shell_plugin_la_CFLAGS = $(libxdg_shell_plugin_la_CFLAGS) libwl_shell_plugin_la_LIBADD = $(libxdg_shell_plugin_la_LIBADD) libxdg_shell_plugin_la_SOURCES = \ + video_output/wayland/output.h video_output/wayland/output.c \ video_output/wayland/input.h video_output/wayland/input.c \ video_output/xcb/vlc_xkb.h video_output/xcb/xkb.c \ video_output/wayland/xdg-shell.c diff --git a/modules/video_output/wayland/output.c b/modules/video_output/wayland/output.c new file mode 100644 index 0000000000..dc85aac7c7 --- /dev/null +++ b/modules/video_output/wayland/output.c @@ -0,0 +1,162 @@ +/** + * @file input.c + * @brief Wayland input events for VLC media player + */ +/***************************************************************************** + * Copyright © 2018 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <wayland-client.h> +#include <vlc_common.h> +#include <vlc_vout_window.h> + +#include "output.h" + +/* TODO: xdg_output protocol */ + +struct output_data +{ + vout_window_t *owner; + struct wl_output *wl_output; + + uint32_t name; + struct wl_list node; +}; + +static void output_geometry_cb(void *data, struct wl_output *output, + int32_t x, int32_t y, int32_t w, int32_t h, + int32_t sp, const char *make, const char *model, + int32_t transform) +{ + struct output_data *od = data; + vout_window_t *wnd = od->owner; + char idstr[11]; + char *name; + + msg_Dbg(wnd, "output %"PRIu32" geometry: %"PRId32"x%"PRId32"mm" + "+%"PRId32"+%"PRId32", subpixel %"PRId32", transform %"PRId32, + od->name, w, h, x, y, sp, transform); + + sprintf(idstr, "%"PRIu32, od->name); + if (likely(asprintf(&name, "%s - %s", make, model) >= 0)) + { + vout_window_ReportOutputDevice(wnd, idstr, name); + free(name); + } + (void) output; +} + +static void output_mode_cb(void *data, struct wl_output *output, + uint32_t flags, int32_t w, int32_t h, int32_t vr) +{ + struct output_data *od = data; + vout_window_t *wnd = od->owner; + div_t d = div(vr, 1000); + + msg_Dbg(wnd, "output %"PRIu32" mode: 0x%"PRIx32" %"PRId32"x%"PRId32 + ", %d.%03d Hz", od->name, flags, w, h, d.quot, d.rem); + (void) output; +} + +static void output_done_cb(void *data, struct wl_output *output) +{ + (void) data; (void) output; +} + +static void output_scale_cb(void *data, struct wl_output *output, int32_t f) +{ + struct output_data *od = data; + vout_window_t *wnd = od->owner; + + msg_Dbg(wnd, "output %"PRIu32" scale: %"PRId32, od->name, f); + (void) output; +} + +static const struct wl_output_listener wl_output_cbs = +{ + output_geometry_cb, + output_mode_cb, + output_done_cb, + output_scale_cb, +}; + +int output_create(vout_window_t *wnd, struct wl_registry *registry, + uint32_t name, uint32_t version, struct wl_list *list) +{ + struct output_data *od = malloc(sizeof (*od)); + if (unlikely(od == NULL)) + return -1; + + if (version > 2) + version = 2; + + od->wl_output = wl_registry_bind(registry, name, &wl_output_interface, + version); + if (unlikely(od->wl_output == NULL)) + { + free(od); + return -1; + } + + od->owner = wnd; + od->name = name; + + wl_output_add_listener(od->wl_output, &wl_output_cbs, od); + wl_list_insert(list, &od->node); + return 0; +} + +static void output_destroy(struct output_data *od) +{ + char idstr[11]; + + sprintf(idstr, "%"PRIu32, od->name); + vout_window_ReportOutputDevice(od->owner, idstr, NULL); + + wl_list_remove(&od->node); + wl_output_destroy(od->wl_output); + free(od); +} + +int output_destroy_one(struct wl_list *list, uint32_t name) +{ + struct output_data *od; + + wl_list_for_each(od, list, node) + { + if (od->name == name) + { + output_destroy(od); + /* Note: return here so no needs for safe walk variant */ + return 0; + } + } + + return -1; +} + +void output_destroy_all(struct wl_list *list) +{ + while (!wl_list_empty(list)) + output_destroy(container_of(list->next, struct output_data, node)); +} diff --git a/modules/video_output/wayland/output.h b/modules/video_output/wayland/output.h new file mode 100644 index 0000000000..7d6710d90e --- /dev/null +++ b/modules/video_output/wayland/output.h @@ -0,0 +1,28 @@ +/***************************************************************************** + * Copyright © 2018 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include <stdint.h> + +struct vout_window_t; +struct wl_registry; +struct wl_list; + +int output_create(struct vout_window_t *wnd, struct wl_registry *, + uint32_t name, uint32_t version, struct wl_list *list); +int output_destroy_one(struct wl_list *list, uint32_t name); +void output_destroy_all(struct wl_list *list); diff --git a/modules/video_output/wayland/xdg-shell.c b/modules/video_output/wayland/xdg-shell.c index 40dca03738..06d3a286a5 100644 --- a/modules/video_output/wayland/xdg-shell.c +++ b/modules/video_output/wayland/xdg-shell.c @@ -65,6 +65,7 @@ #include <vlc_vout_window.h> #include "input.h" +#include "output.h" struct vout_window_sys_t { @@ -85,6 +86,7 @@ struct vout_window_sys_t bool unstable; #endif + struct wl_list outputs; struct wl_list seats; vlc_thread_t thread; @@ -130,12 +132,6 @@ static void *Thread(void *data) //return NULL; } -struct device_data -{ - uint32_t name; - struct vout_window_t *window; -}; - static int Control(vout_window_t *wnd, int cmd, va_list ap) { vout_window_sys_t *sys = wnd->sys; @@ -321,64 +317,6 @@ static const struct wl_shell_surface_listener wl_shell_surface_cbs = #define xdg_surface_cbs wl_shell_surface_cbs #endif -static void output_geometry_cb(void *data, struct wl_output *output, - int32_t x, int32_t y, int32_t w, int32_t h, - int32_t sp, const char *make, const char *model, - int32_t transform) -{ - struct device_data *dd = data; - struct vout_window_t *wnd = dd->window; - char idstr[11]; - char *name; - - msg_Dbg(wnd, "output %"PRIu32" geometry: %"PRId32"x%"PRId32"mm" - "+%"PRId32"+%"PRId32", subpixel %"PRId32", transform %"PRId32, - dd->name, w, h, x, y, sp, transform); - - sprintf(idstr, "%"PRIu32, dd->name); - if (likely(asprintf(&name, "%s - %s", make, model) >= 0)) - { - vout_window_ReportOutputDevice(wnd, idstr, name); - free(name); - } - (void) output; -} - -static void output_mode_cb(void *data, struct wl_output *output, - uint32_t flags, int32_t w, int32_t h, int32_t vr) -{ - struct device_data *dd = data; - struct vout_window_t *wnd = dd->window; - div_t d = div(vr, 1000); - - msg_Dbg(wnd, "output %"PRIu32" mode: 0x%"PRIx32" %"PRId32"x%"PRId32 - ", %d.%03d Hz", dd->name, flags, w, h, d.quot, d.rem); - (void) output; -} - -static void output_done_cb(void *data, struct wl_output *output) -{ - wl_output_destroy(output); - free(data); -} - -static void output_scale_cb(void *data, struct wl_output *output, int32_t f) -{ - struct device_data *dd = data; - struct vout_window_t *wnd = dd->window; - - msg_Dbg(wnd, "output %"PRIu32" scale: %"PRId32, dd->name, f); - (void) output; -} - -static const struct wl_output_listener output_cbs = -{ - output_geometry_cb, - output_mode_cb, - output_done_cb, - output_scale_cb, -}; - static void registry_global_cb(void *data, struct wl_registry *registry, uint32_t name, const char *iface, uint32_t vers) { @@ -392,22 +330,6 @@ static void registry_global_cb(void *data, struct wl_registry *registry, &wl_compositor_interface, (vers < 2) ? vers : 2); else - if (!strcmp(iface, "wl_output") && vers >= 2) - { - struct device_data *dd = malloc(sizeof (*dd)); - if (unlikely(dd == NULL)) - return; - - struct wl_output *output = wl_registry_bind(registry, name, - &wl_output_interface, 2); - if (unlikely(output == NULL)) - return; - - dd->name = name; - dd->window = wnd; - wl_output_add_listener(output, &output_cbs, dd); - } - else #ifdef XDG_SHELL # ifdef XDG_SHELL_UNSTABLE if (!strcmp(iface, "zxdg_shell_v6") && sys->wm_base == NULL) @@ -436,6 +358,9 @@ static void registry_global_cb(void *data, struct wl_registry *registry, if (!strcmp(iface, "wl_seat")) seat_create(wnd, registry, name, vers, &sys->seats); else + if (!strcmp(iface, "wl_output")) + output_create(wnd, registry, name, vers, &sys->outputs); + else if (!strcmp(iface, "org_kde_kwin_server_decoration_manager")) sys->deco_manager = wl_registry_bind(registry, name, &org_kde_kwin_server_decoration_manager_interface, 1); @@ -446,16 +371,13 @@ static void registry_global_remove_cb(void *data, struct wl_registry *registry, { vout_window_t *wnd = data; vout_window_sys_t *sys = wnd->sys; - char idstr[11]; msg_Dbg(wnd, "global remove %3"PRIu32, name); if (seat_destroy_one(&sys->seats, name) == 0) return; - - /* If the global was an output, this will remove it. Otherwise, no-op. */ - sprintf(idstr, "%"PRIu32, name); - vout_window_ReportOutputDevice(wnd, idstr, NULL); + if (output_destroy_one(&sys->outputs, name) == 0) + return; (void) registry; } @@ -485,6 +407,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg) sys->width = cfg->width; sys->height = cfg->height; sys->fullscreen = false; + wl_list_init(&sys->outputs); wl_list_init(&sys->seats); wnd->sys = sys; wnd->handle.wl = NULL; @@ -511,7 +434,6 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg) #endif wl_registry_add_listener(sys->registry, ®istry_cbs, wnd); wl_display_roundtrip(display); /* complete registry enumeration */ - wl_display_roundtrip(display); /* complete devices enumeration */ if (sys->compositor == NULL || sys->wm_base == NULL) goto error; @@ -601,6 +523,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg) error: seat_destroy_all(&sys->seats); + output_destroy_all(&sys->outputs); if (sys->deco != NULL) org_kde_kwin_server_decoration_destroy(sys->deco); if (sys->deco_manager != NULL) @@ -633,6 +556,7 @@ static void Close(vout_window_t *wnd) vlc_join(sys->thread, NULL); seat_destroy_all(&sys->seats); + output_destroy_all(&sys->outputs); if (sys->deco != NULL) org_kde_kwin_server_decoration_destroy(sys->deco); if (sys->deco_manager != NULL) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
