libweston: add heads_changed_signal

Add a hook for compositors to get a callback when heads are added or
their connection status changes, to which compositors likely want to
react to by enabling or disabling outputs (API for that to be added
later).

As many head changes as possible should be coalesced into a single
heads_changed call. Therefore the callback is made from an idle task.
This anticipates a future atomic output configuration API, where the
global output configuration is tested and set atomically instead of one
by one.

weston_pending_output_coldplug() needs to manually execute the
heads_changed call so that initial outputs are created before any
plugins get their start-up idle tasks ran. This is especially important
for ivi-shell which does not support output hotplug, and for tests to
guarantee the expected outputs.

v8:
- Change the callback function pointer into a wl_signal. The API is
  changed and renamed.

v6:
- fix a typo
- add comment in weston_pending_output_coldplug()

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
v6 Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
v6 Reviewed-by: Ian Ray <ian.ray@ge.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Derek Foreman <derekf@osg.samsung.com>
dev
Pekka Paalanen 7 years ago
parent 1adcbacd5b
commit 37e6c9e537
  1. 81
      libweston/compositor.c
  2. 6
      libweston/compositor.h

@ -4448,12 +4448,44 @@ weston_head_init(struct weston_head *head, const char *name)
head->name = strdup(name); head->name = strdup(name);
} }
/** Idle task for emitting heads_changed_signal */
static void
weston_compositor_call_heads_changed(void *data)
{
struct weston_compositor *compositor = data;
compositor->heads_changed_source = NULL;
wl_signal_emit(&compositor->heads_changed_signal, compositor);
}
/** Schedule a call on idle to heads_changed callback
*
* \param compositor The Compositor.
*
* \memberof weston_compositor
* \internal
*/
static void
weston_compositor_schedule_heads_changed(struct weston_compositor *compositor)
{
struct wl_event_loop *loop;
if (compositor->heads_changed_source)
return;
loop = wl_display_get_event_loop(compositor->wl_display);
compositor->heads_changed_source = wl_event_loop_add_idle(loop,
weston_compositor_call_heads_changed, compositor);
}
/** Register a new head /** Register a new head
* *
* \param compositor The compositor. * \param compositor The compositor.
* \param head The head to register, must not be already registered. * \param head The head to register, must not be already registered.
* *
* This signals the core that a new head has become available. * This signals the core that a new head has become available, leading to
* heads_changed hook being called later.
* *
* \memberof weston_compositor * \memberof weston_compositor
* \internal * \internal
@ -4467,6 +4499,30 @@ weston_compositor_add_head(struct weston_compositor *compositor,
wl_list_insert(compositor->head_list.prev, &head->compositor_link); wl_list_insert(compositor->head_list.prev, &head->compositor_link);
head->compositor = compositor; head->compositor = compositor;
weston_compositor_schedule_heads_changed(compositor);
}
/** Adds a listener to be called when heads change
*
* \param compositor The compositor.
* \param listener The listener to add.
*
* The listener notify function argument is the \var compositor.
*
* The listener function will be called after heads are added or their
* connection status has changed. Several changes may be accumulated into a
* single call. The user is expected to iterate over the existing heads and
* check their statuses to find out what changed.
*
* \sa weston_compositor_iterate_heads, weston_head_is_connected,
* weston_head_is_enabled
* \memberof weston_compositor
*/
WL_EXPORT void
weston_compositor_add_heads_changed_listener(struct weston_compositor *compositor,
struct wl_listener *listener)
{
wl_signal_add(&compositor->heads_changed_signal, listener);
} }
/** Iterate over available heads /** Iterate over available heads
@ -4690,13 +4746,23 @@ weston_head_set_internal(struct weston_head *head)
* disconnected. For nested backends, the connection status should reflect the * disconnected. For nested backends, the connection status should reflect the
* connection to the parent display server. * connection to the parent display server.
* *
* When the connection status changes, it schedules a call to the heads_changed
* hook.
*
* \sa weston_compositor_set_heads_changed_cb
* \memberof weston_head * \memberof weston_head
* \internal * \internal
*/ */
WL_EXPORT void WL_EXPORT void
weston_head_set_connection_status(struct weston_head *head, bool connected) weston_head_set_connection_status(struct weston_head *head, bool connected)
{ {
if (head->connected == connected)
return;
head->connected = connected; head->connected = connected;
if (head->compositor)
weston_compositor_schedule_heads_changed(head->compositor);
} }
/** Is the head currently connected? /** Is the head currently connected?
@ -5354,6 +5420,15 @@ weston_pending_output_coldplug(struct weston_compositor *compositor)
wl_list_for_each_safe(output, next, &compositor->pending_output_list, link) wl_list_for_each_safe(output, next, &compositor->pending_output_list, link)
wl_signal_emit(&compositor->output_pending_signal, output); wl_signal_emit(&compositor->output_pending_signal, output);
/* Execute the heads changed callback manually to ensure it is
* processed before any plugins get their start-up idle tasks ran.
* This ensures the plugins see all the initial outputs.
*/
if (compositor->heads_changed_source) {
wl_event_source_remove(compositor->heads_changed_source);
weston_compositor_call_heads_changed(compositor);
}
} }
/** Uninitialize an output /** Uninitialize an output
@ -5751,6 +5826,7 @@ weston_compositor_create(struct wl_display *display, void *user_data)
wl_signal_init(&ec->output_destroyed_signal); wl_signal_init(&ec->output_destroyed_signal);
wl_signal_init(&ec->output_moved_signal); wl_signal_init(&ec->output_moved_signal);
wl_signal_init(&ec->output_resized_signal); wl_signal_init(&ec->output_resized_signal);
wl_signal_init(&ec->heads_changed_signal);
wl_signal_init(&ec->session_signal); wl_signal_init(&ec->session_signal);
ec->session_active = 1; ec->session_active = 1;
@ -6065,6 +6141,9 @@ weston_compositor_destroy(struct weston_compositor *compositor)
weston_plugin_api_destroy_list(compositor); weston_plugin_api_destroy_list(compositor);
if (compositor->heads_changed_source)
wl_event_source_remove(compositor->heads_changed_source);
free(compositor); free(compositor);
} }

@ -983,6 +983,8 @@ struct weston_compositor {
/* Whether to let the compositor run without any input device. */ /* Whether to let the compositor run without any input device. */
bool require_input; bool require_input;
struct wl_signal heads_changed_signal;
struct wl_event_source *heads_changed_source;
}; };
struct weston_buffer { struct weston_buffer {
@ -1991,6 +1993,10 @@ struct weston_head *
weston_compositor_iterate_heads(struct weston_compositor *compositor, weston_compositor_iterate_heads(struct weston_compositor *compositor,
struct weston_head *iter); struct weston_head *iter);
void
weston_compositor_add_heads_changed_listener(struct weston_compositor *compositor,
struct wl_listener *listener);
void void
weston_output_set_scale(struct weston_output *output, weston_output_set_scale(struct weston_output *output,
int32_t scale); int32_t scale);

Loading…
Cancel
Save