struct list_head change_handler_list;
unsigned int req_id;
+ unsigned int watch_output_changes;
struct list_head link;
} tdm_private_client_output;
h = calloc(1, sizeof *h);
TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY);
- if (LIST_IS_EMPTY(&private_output->change_handler_list))
+ if (LIST_IS_EMPTY(&private_output->change_handler_list)) {
wl_tdm_output_watch_output_changes(private_output->output, 1);
+ /* TODO: this is very tricky.
+ * If a client adds the change_handler, we might be able to guess that
+ * the client will watch the tdm client's fd and handle tdm events in
+ * event loop. Otherwise, we CAN'T make sure if a client has event loop
+ * which handles tdm events.
+ */
+ private_output->watch_output_changes = 1;
+ }
+
h->private_output = private_output;
h->func = func;
h->user_data = user_data;
tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refresh)
{
tdm_private_client_output *private_output;
+ tdm_private_client *private_client;
TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
TDM_RETURN_VAL_IF_FAIL(refresh != NULL, TDM_ERROR_INVALID_PARAMETER);
private_output = (tdm_private_client_output*)output;
+ if (private_output->watch_output_changes) {
+ *refresh = private_output->refresh;
+ return TDM_ERROR_NONE;
+ }
+
+ private_client = private_output->private_client;
+ TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ wl_tdm_output_get_mode(private_output->output);
+ wl_display_roundtrip(private_client->display);
+
*refresh = private_output->refresh;
return TDM_ERROR_NONE;
tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_status *status)
{
tdm_private_client_output *private_output;
+ tdm_private_client *private_client;
TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
private_output = (tdm_private_client_output*)output;
+ if (private_output->watch_output_changes) {
+ *status = private_output->connection;
+ return TDM_ERROR_NONE;
+ }
+
+ private_client = private_output->private_client;
+ TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ wl_tdm_output_get_connection(private_output->output);
+ wl_display_roundtrip(private_client->display);
+
*status = private_output->connection;
return TDM_ERROR_NONE;
tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms)
{
tdm_private_client_output *private_output;
+ tdm_private_client *private_client;
TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
TDM_RETURN_VAL_IF_FAIL(dpms != NULL, TDM_ERROR_INVALID_PARAMETER);
private_output = (tdm_private_client_output*)output;
+ if (private_output->watch_output_changes) {
+ *dpms = private_output->dpms;
+ return TDM_ERROR_NONE;
+ }
+
+ private_client = private_output->private_client;
+ TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ wl_tdm_output_get_dpms(private_output->output);
+ wl_display_roundtrip(private_client->display);
+
*dpms = private_output->dpms;
return TDM_ERROR_NONE;
if (!private_vblank->started)
private_vblank->started = 1;
- if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
- TDM_INFO("dpms off");
- return TDM_ERROR_DPMS_OFF;
- }
+ if (private_output->watch_output_changes)
+ if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
+ TDM_INFO("dpms off");
+ return TDM_ERROR_DPMS_OFF;
+ }
w = calloc(1, sizeof *w);
if (!w) {
if (!private_vblank->started)
private_vblank->started = 1;
- if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
- TDM_INFO("dpms off");
- return TDM_ERROR_DPMS_OFF;
- }
+ if (private_output->watch_output_changes)
+ if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
+ TDM_INFO("dpms off");
+ return TDM_ERROR_DPMS_OFF;
+ }
w = calloc(1, sizeof *w);
if (!w) {
output_info->watch_output_changes = enable;
}
+static void
+_tdm_server_output_cb_get_connection(struct wl_client *client, struct wl_resource *resource)
+{
+ tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_error ret;
+
+ TDM_RETURN_IF_FAIL(output_info != NULL);
+
+ ret = tdm_output_get_conn_status(output_info->output, &status);
+ TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+ wl_tdm_output_send_connection(output_info->resource, status);
+
+ return;
+
+failed:
+ wl_tdm_output_send_connection(output_info->resource, TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+}
+
+static void
+_tdm_server_output_cb_get_mode(struct wl_client *client, struct wl_resource *resource)
+{
+ tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_error ret;
+
+ TDM_RETURN_IF_FAIL(output_info != NULL);
+
+ ret = tdm_output_get_conn_status(output_info->output, &status);
+ TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+ if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+ const tdm_output_mode *mode = NULL;
+ unsigned int hdisplay, vdisplay, vrefresh;
+
+ ret = tdm_output_get_mode(output_info->output, &mode);
+ TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+ hdisplay = (mode) ? mode->hdisplay : 0;
+ vdisplay = (mode) ? mode->vdisplay : 0;
+ vrefresh = (mode) ? mode->vrefresh : 0;
+
+ wl_tdm_output_send_mode(output_info->resource, hdisplay, vdisplay, vrefresh);
+ } else {
+ wl_tdm_output_send_mode(output_info->resource, 0, 0, 0);
+ }
+
+ return;
+failed:
+ wl_tdm_output_send_mode(output_info->resource, 0, 0, 0);
+}
+
+static void
+_tdm_server_output_cb_get_dpms(struct wl_client *client, struct wl_resource *resource)
+{
+ tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_error ret;
+
+ TDM_RETURN_IF_FAIL(output_info != NULL);
+
+ ret = tdm_output_get_conn_status(output_info->output, &status);
+ TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+ if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+ tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF;
+
+ ret = tdm_output_get_dpms(output_info->output, &dpms_value);
+ TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+ wl_tdm_output_send_dpms(output_info->resource, dpms_value);
+ } else {
+ wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF);
+ }
+
+ return;
+failed:
+ wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF);
+}
+
static const struct wl_tdm_output_interface tdm_output_implementation = {
_tdm_server_output_cb_destroy,
_tdm_server_output_cb_create_vblank,
_tdm_server_output_cb_watch_output_changes,
+ _tdm_server_output_cb_get_connection,
+ _tdm_server_output_cb_get_mode,
+ _tdm_server_output_cb_get_dpms,
};
static void
tdm_server_output_info *output_info;
struct wl_resource *output_resource = NULL;
tdm_output *output;
- const tdm_output_mode *mode = NULL;
- tdm_output_dpms dpms_value;
- tdm_output_conn_status status;
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
output = _tdm_server_find_output(private_server, name);
if (!output) {
return;
}
- tdm_output_get_mode(output, &mode);
- if (!mode) {
- TDM_ERR("no mode for '%s' output", name);
- wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
- "no mode for '%s' output", name);
- return;
- }
-
- tdm_output_get_dpms(output, &dpms_value);
- tdm_output_get_conn_status(output, &status);
-
output_resource =
wl_resource_create(client, &wl_tdm_output_interface,
wl_resource_get_version(resource), id);
wl_resource_set_implementation(output_resource, &tdm_output_implementation,
output_info, destroy_output_callback);
- wl_tdm_output_send_mode(output_resource, mode->hdisplay, mode->vdisplay, mode->vrefresh);
- wl_tdm_output_send_dpms(output_resource, dpms_value);
+ tdm_output_get_conn_status(output, &status);
wl_tdm_output_send_connection(output_resource, status);
+
+ if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+ tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF;
+ const tdm_output_mode *mode = NULL;
+ unsigned int hdisplay, vdisplay, vrefresh;
+
+ tdm_output_get_mode(output, &mode);
+ hdisplay = (mode) ? mode->hdisplay : 0;
+ vdisplay = (mode) ? mode->vdisplay : 0;
+ vrefresh = (mode) ? mode->vrefresh : 0;
+ wl_tdm_output_send_mode(output_resource, hdisplay, vdisplay, vrefresh);
+
+ tdm_output_get_dpms(output, &dpms_value);
+ wl_tdm_output_send_dpms(output_resource, dpms_value);
+ } else {
+ wl_tdm_output_send_mode(output_resource, 0, 0, 0);
+ wl_tdm_output_send_dpms(output_resource, TDM_OUTPUT_DPMS_OFF);
+ }
}
static void