static gboolean
gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error)
{
  GstGLDisplayWayland *display;
  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  if (!GST_IS_GL_DISPLAY_WAYLAND (window->display)) {
    g_set_error (error, GST_GL_WINDOW_ERROR,
        GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to retrieve Wayland display (wrong type?)");
    return FALSE;
  }
  display = GST_GL_DISPLAY_WAYLAND (window->display);

  if (!display->display) {
    g_set_error (error, GST_GL_WINDOW_ERROR,
        GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to retrieve Wayland display");
    return FALSE;
  }

  window_egl->window.queue = wl_display_create_queue (display->display);

  window_egl->wl_source = wayland_event_source_new (display->display,
      window_egl->window.queue);

  if (!GST_GL_WINDOW_CLASS (parent_class)->open (window, error))
    return FALSE;

  g_source_attach (window_egl->wl_source, g_main_context_get_thread_default ());

  return TRUE;
}
static void
gst_gl_window_wayland_egl_close (GstGLWindow * window)
{
  GstGLWindowWaylandEGL *window_egl;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  destroy_surface (window_egl);

  if (window_egl->display.cursor_surface)
    wl_surface_destroy (window_egl->display.cursor_surface);

  if (window_egl->display.cursor_theme)
    wl_cursor_theme_destroy (window_egl->display.cursor_theme);

  if (window_egl->display.shell)
    wl_shell_destroy (window_egl->display.shell);

  if (window_egl->display.compositor)
    wl_compositor_destroy (window_egl->display.compositor);

  if (window_egl->display.display) {
    wl_display_flush (window_egl->display.display);
    wl_display_disconnect (window_egl->display.display);
  }
}
static guintptr
gst_gl_window_wayland_egl_get_display (GstGLWindow * window)
{
  GstGLWindowWaylandEGL *window_egl;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  return (guintptr) window_egl->display.display;
}
static void
gst_gl_window_wayland_egl_run (GstGLWindow * window)
{
  GstGLWindowWaylandEGL *window_egl;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  GST_LOG ("starting main loop");
  g_main_loop_run (window_egl->loop);
  GST_LOG ("exiting main loop");
}
static void
gst_gl_window_wayland_egl_show (GstGLWindow * window)
{
  GstGLDisplayWayland *display_wayland =
      GST_GL_DISPLAY_WAYLAND (window->display);
  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  create_surfaces (window_egl);

  if (gst_gl_wl_display_roundtrip_queue (display_wayland->display,
          window_egl->window.queue) < 0)
    GST_WARNING_OBJECT (window, "failed a roundtrip");
}
static void
gst_gl_window_wayland_egl_quit (GstGLWindow * window)
{
  GstGLWindowWaylandEGL *window_egl;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  GST_LOG ("sending quit");

  g_main_loop_quit (window_egl->loop);

  GST_LOG ("quit sent");
}
static void
gst_gl_window_wayland_egl_close (GstGLWindow * window)
{
  GstGLWindowWaylandEGL *window_egl;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  destroy_surfaces (window_egl);

  g_source_destroy (window_egl->wl_source);
  g_source_unref (window_egl->wl_source);
  window_egl->wl_source = NULL;

  GST_GL_WINDOW_CLASS (parent_class)->close (window);
}
static void
gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window,
    guintptr handle)
{
  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
  struct wl_surface *surface = (struct wl_surface *) handle;

  /* already set the NULL handle */
  if (surface == NULL && window_egl->window.foreign_surface == NULL)
    return;

  /* unparent */
  destroy_surfaces (window_egl);
  window_egl->window.foreign_surface = surface;
  create_surfaces (window_egl);
}
static void
gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window,
    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{
  GstGLWindowWaylandEGL *window_egl;
  GstGLMessage *message;

  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
  message = g_slice_new (GstGLMessage);

  message->callback = callback;
  message->data = data;
  message->destroy = destroy;

  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
      message);
}
static gboolean
gst_gl_window_wayland_egl_set_render_rectangle (GstGLWindow * window,
    gint x, gint y, gint width, gint height)
{
  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
  struct SetRenderRectangle *render;

  render = g_new0 (struct SetRenderRectangle, 1);
  render->window_egl = gst_object_ref (window_egl);
  render->rect.x = x;
  render->rect.y = y;
  render->rect.w = width;
  render->rect.h = height;

  gst_gl_window_send_message_async (window,
      (GstGLWindowCB) _set_render_rectangle, render,
      (GDestroyNotify) _free_set_render_rectangle);

  return TRUE;
}
static gboolean
gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error)
{
  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);

  window_egl->display.display = wl_display_connect (NULL);
  if (!window_egl->display.display) {
    g_set_error (error, GST_GL_WINDOW_ERROR,
        GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to connect to Wayland display server");
    goto error;
  }

  window_egl->display.registry =
      wl_display_get_registry (window_egl->display.display);
  wl_registry_add_listener (window_egl->display.registry, &registry_listener,
      window_egl);

  wl_display_dispatch (window_egl->display.display);

  create_surface (window_egl);

  window_egl->display.cursor_surface =
      wl_compositor_create_surface (window_egl->display.compositor);

  window_egl->wl_source =
      wayland_event_source_new (window_egl->display.display);
  window_egl->main_context = g_main_context_new ();
  window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE);

  g_source_attach (window_egl->wl_source, window_egl->main_context);

  return TRUE;

error:
  return FALSE;
}
static guintptr
gst_gl_window_wayland_egl_get_window_handle (GstGLWindow * window)
{
  return (guintptr) GST_GL_WINDOW_WAYLAND_EGL (window)->window.native;
}