Commit 21047ec4 authored by Rémi Denis-Courmont's avatar 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.
parent ac07b760
......@@ -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
......
/**
* @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));
}
/*****************************************************************************
* 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);
......@@ -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, &registry_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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment