struct wayland_parent_output {
struct wayland_backend *backend; /**< convenience */
- struct wayland_output *output;
+ struct wayland_head *head;
struct wl_list link;
struct wl_output *global;
struct weston_mode *current_mode;
};
+struct wayland_head {
+ struct weston_head base;
+ struct wayland_parent_output *parent_output;
+};
+
struct wayland_shm_buffer {
struct wayland_output *output;
struct wl_list link;
struct gl_renderer_interface *gl_renderer;
+static inline struct wayland_head *
+to_wayland_head(struct weston_head *base)
+{
+ return container_of(base, struct wayland_head, base);
+}
+
static inline struct wayland_output *
to_wayland_output(struct weston_output *base)
{
return -1;
}
-static struct wayland_output *
-wayland_output_create_common(struct weston_compositor *compositor,
- const char *name)
+static int
+wayland_output_setup_for_parent_output(struct wayland_output *output,
+ struct wayland_parent_output *poutput);
+
+static int
+wayland_output_setup_fullscreen(struct wayland_output *output,
+ struct wayland_head *head);
+
+static int
+wayland_output_attach_head(struct weston_output *output_base,
+ struct weston_head *head_base)
+{
+ struct wayland_backend *b = to_wayland_backend(output_base->compositor);
+ struct wayland_output *output = to_wayland_output(output_base);
+ struct wayland_head *head = to_wayland_head(head_base);
+
+ if (!wl_list_empty(&output->base.head_list))
+ return -1;
+
+ if (head->parent_output) {
+ if (wayland_output_setup_for_parent_output(output,
+ head->parent_output) < 0)
+ return -1;
+ } else if (b->fullscreen) {
+ if (wayland_output_setup_fullscreen(output, head) < 0)
+ return -1;
+ } else {
+ /* A floating window, nothing to do. */
+ }
+
+ return 0;
+}
+
+static void
+wayland_output_detach_head(struct weston_output *output_base,
+ struct weston_head *head)
+{
+ struct wayland_output *output = to_wayland_output(output_base);
+
+ /* Rely on the disable hook if the output was enabled. We do not
+ * support cloned heads, so detaching is guaranteed to disable the
+ * output.
+ */
+ if (output->base.enabled)
+ return;
+
+ /* undo setup fullscreen */
+ if (output->parent.surface)
+ wayland_backend_destroy_output_surface(output);
+}
+
+static struct weston_output *
+wayland_output_create(struct weston_compositor *compositor, const char *name)
{
struct wayland_output *output;
char *title;
output->base.destroy = wayland_output_destroy;
output->base.disable = wayland_output_disable;
output->base.enable = wayland_output_enable;
+ output->base.attach_head = wayland_output_attach_head;
+ output->base.detach_head = wayland_output_detach_head;
+
+ weston_compositor_add_pending_output(&output->base, compositor);
+
+ return &output->base;
+}
+
+static struct wayland_head *
+wayland_head_create(struct weston_compositor *compositor, const char *name)
+{
+ struct wayland_head *head;
+
+ assert(name);
+
+ head = zalloc(sizeof *head);
+ if (!head)
+ return NULL;
+
+ weston_head_init(&head->base, name);
+ weston_head_set_connection_status(&head->base, true);
+ weston_compositor_add_head(compositor, &head->base);
- return output;
+ return head;
}
static int
-wayland_output_create(struct weston_compositor *compositor, const char *name)
+wayland_head_create_windowed(struct weston_compositor *compositor,
+ const char *name)
{
- struct wayland_output *output;
+ if (!wayland_head_create(compositor, name))
+ return -1;
- output = wayland_output_create_common(compositor, name);
- if (!output)
+ return 0;
+}
+
+static int
+wayland_head_create_for_parent_output(struct weston_compositor *compositor,
+ struct wayland_parent_output *poutput)
+{
+ struct wayland_head *head;
+ char name[100];
+ int ret;
+
+ ret = snprintf(name, sizeof(name), "wlparent-%d", poutput->id);
+ if (ret < 1 || (unsigned)ret >= sizeof(name))
return -1;
- weston_compositor_add_pending_output(&output->base, compositor);
+ head = wayland_head_create(compositor, name);
+ if (!head)
+ return -1;
+
+ assert(!poutput->head);
+ head->parent_output = poutput;
+ poutput->head = head;
+
+ weston_head_set_monitor_strings(&head->base,
+ poutput->physical.make,
+ poutput->physical.model, NULL);
+ weston_head_set_physical_size(&head->base,
+ poutput->physical.width,
+ poutput->physical.height);
return 0;
}
+static void
+wayland_head_destroy(struct wayland_head *head)
+{
+ if (head->parent_output)
+ head->parent_output->head = NULL;
+
+ weston_head_release(&head->base);
+ free(head);
+}
+
static int
wayland_output_set_size(struct weston_output *base, int width, int height)
{
struct wayland_output *output = to_wayland_output(base);
- struct weston_head *head = &output->base.head;
+ struct weston_head *head;
int output_width, output_height;
/* We can only be called once. */
return -1;
}
+ wl_list_for_each(head, &output->base.head_list, output_link) {
+ weston_head_set_monitor_strings(head, "wayland", "none", NULL);
+
+ /* XXX: Calculate proper size. */
+ weston_head_set_physical_size(head, width, height);
+ }
+
output_width = width * output->base.scale;
output_height = height * output->base.scale;
output->base.current_mode = &output->mode;
- weston_head_set_monitor_strings(head, "wayland", "none", NULL);
-
- /* XXX: Calculate proper size. */
- weston_head_set_physical_size(head, width, height);
-
return 0;
}
static int
-wayland_output_create_for_parent_output(struct wayland_backend *b,
- struct wayland_parent_output *poutput)
+wayland_output_setup_for_parent_output(struct wayland_output *output,
+ struct wayland_parent_output *poutput)
{
- struct wayland_output *output;
struct weston_mode *mode;
- output = wayland_output_create_common(b->compositor, "wlparent");
- if (!output)
- return -1;
-
if (poutput->current_mode) {
mode = poutput->current_mode;
} else if (poutput->preferred_mode) {
struct weston_mode, link);
} else {
weston_log("No valid modes found. Skipping output.\n");
- goto out;
+ return -1;
}
output->base.scale = 1;
output->parent.output = poutput->global;
- weston_head_set_monitor_strings(&output->base.head,
- poutput->physical.make,
- poutput->physical.model, NULL);
- weston_head_set_physical_size(&output->base.head,
- poutput->physical.width,
- poutput->physical.height);
-
wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
wl_list_init(&poutput->mode_list);
/* output->mode is unused in this path. */
- weston_compositor_add_pending_output(&output->base, b->compositor);
-
return 0;
-
-out:
- weston_output_release(&output->base);
- free(output->title);
- free(output);
-
- return -1;
}
static int
-wayland_output_create_fullscreen(struct wayland_backend *b)
+wayland_output_setup_fullscreen(struct wayland_output *output,
+ struct wayland_head *head)
{
- struct wayland_output *output;
+ struct wayland_backend *b = to_wayland_backend(output->base.compositor);
int width = 0, height = 0;
- output = wayland_output_create_common(b->compositor, "wayland-fullscreen");
- if (!output)
- return -1;
-
output->base.scale = 1;
output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
if (wayland_backend_create_output_surface(output) < 0)
- goto err_surface;
+ return -1;
/* What should size be set if conditional is false? */
if (b->parent.xdg_shell || b->parent.shell) {
if (wayland_output_set_size(&output->base, width, height) < 0)
goto err_set_size;
- weston_compositor_add_pending_output(&output->base, b->compositor);
+ /* The head is not attached yet, so set_size did not set these. */
+ weston_head_set_monitor_strings(&head->base, "wayland", "none", NULL);
+ /* XXX: Calculate proper size. */
+ weston_head_set_physical_size(&head->base, width, height);
return 0;
err_set_size:
wayland_backend_destroy_output_surface(output);
-err_surface:
- weston_output_release(&output->base);
- free(output->title);
- free(output);
return -1;
}
return mode;
}
+static struct weston_output *
+wayland_parent_output_get_enabled_output(struct wayland_parent_output *poutput)
+{
+ struct wayland_head *head = poutput->head;
+
+ if (!head)
+ return NULL;
+
+ if (!weston_head_is_enabled(&head->base))
+ return NULL;
+
+ return weston_head_get_output(&head->base);
+}
+
static void
wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
uint32_t flags, int32_t width, int32_t height,
int32_t refresh)
{
struct wayland_parent_output *output = data;
+ struct weston_output *enabled_output;
struct weston_mode *mode;
- if (output->output) {
- mode = find_mode(&output->output->base.mode_list,
+ enabled_output = wayland_parent_output_get_enabled_output(output);
+ if (enabled_output) {
+ mode = find_mode(&enabled_output->mode_list,
width, height, refresh);
if (!mode)
return;
assert(output->backend->sprawl_across_outputs);
- wayland_output_create_for_parent_output(output->backend, output);
+ wayland_head_create_for_parent_output(output->backend->compositor, output);
}
static const struct wl_callback_listener output_sync_listener = {
if (output->sync_cb)
wl_callback_destroy(output->sync_cb);
- if (output->output)
- wayland_output_destroy(&output->output->base);
+ if (output->head)
+ wayland_head_destroy(output->head);
wl_output_destroy(output->global);
free(output->physical.make);
wayland_destroy(struct weston_compositor *ec)
{
struct wayland_backend *b = to_wayland_backend(ec);
+ struct weston_head *base, *next;
wl_event_source_remove(b->parent.wl_source);
weston_compositor_shutdown(ec);
+ wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
+ wayland_head_destroy(to_wayland_head(base));
+
if (b->parent.shm)
wl_shm_destroy(b->parent.shm);
}
b->base.destroy = wayland_destroy;
+ b->base.create_output = wayland_output_create;
loop = wl_display_get_event_loop(compositor->wl_display);
static const struct weston_windowed_output_api windowed_api = {
wayland_output_set_size,
- wayland_output_create,
+ wayland_head_create_windowed,
};
static void
wl_display_roundtrip(b->parent.wl_display);
wl_list_for_each(poutput, &b->parent.output_list, link)
- wayland_output_create_for_parent_output(b, poutput);
+ wayland_head_create_for_parent_output(compositor, poutput);
return 0;
}
if (new_config.fullscreen) {
- if (wayland_output_create_fullscreen(b) < 0) {
- weston_log("Unable to create a fullscreen output.\n");
+ if (!wayland_head_create(compositor, "wayland-fullscreen")) {
+ weston_log("Unable to create a fullscreen head.\n");
goto err_outputs;
}