+++ /dev/null
-#include "e_eom_intern.h"
-#include "e_client_intern.h"
-#include "e_desktop_xdg_shell_v6_intern.h"
-#include "e_comp_screen_intern.h"
-#include "e_comp_wl_intern.h"
-#include "e_comp_wl_subsurface_intern.h"
-#include "e_output_intern.h"
-#include "e_display_intern.h"
-
-#include <xdg-shell-unstable-v5-server-protocol.h>
-#include <eom-server-protocol.h>
-#include <eom.h>
-#include <tbm_surface.h>
-#include <wayland-tbm-server.h>
-#ifdef FRAMES
-#include <time.h>
-#endif
-
-static int eom_trace_debug = 0;
-
-#define ALEN(array) (sizeof(array) / sizeof(array)[0])
-
-#define EOM_NUM_ATTR 3
-#define EOM_CONNECT_CHECK_TIMEOUT 4.0
-#define EOM_DELAY_CONNECT_CHECK_TIMEOUT 1.0
-
-#define EOMERR(f, output, x...) \
- do \
- { \
- if (!output) \
- ELOGFE("EOM", "%7s|"f, \
- NULL, "Unknown", ##x); \
- else \
- ELOGFE("EOM", "%7s|"f, \
- NULL, (e_output_output_id_get(output)), ##x); \
- } \
- while (0)
-
-#define EOMINF(f, ec, output, x...) \
- do \
- { \
- ELOGF("EOM", "%7s|"f, \
- (ec), (e_output_output_id_get(output)), ##x); \
- } \
- while (0)
-
-typedef struct _E_Eom E_Eom, *E_EomPtr;
-typedef struct _E_Eom_Client E_EomClient, *E_EomClientPtr;
-typedef struct _E_Eom_Output E_EomOutput, *E_EomOutputPtr;
-typedef struct _E_Eom_Comp_Object_Intercept_Hook_Data E_EomCompObjectInterceptHookData;
-
-struct _E_Eom
-{
- struct wl_global *global;
-
- unsigned int eom_output_count;
- Eina_List *eom_outputs;
- Eina_List *clients;
- Eina_List *handlers;
- Eina_List *comp_object_intercept_hooks;
- E_Output_Hook *output_connect_status_hook;
- E_Output_Hook *output_mode_changes_hook;
- E_Output_Hook *output_add_hook;
- E_Output_Hook *output_remove_hook;
-};
-
-struct _E_Eom_Client
-{
- struct wl_resource *resource;
- Eina_Bool current;
-
- /* EOM output the client related to */
- int output_id;
- /* E_Client the client related to */
- E_Client *ec;
-};
-
-struct _E_Eom_Output
-{
- unsigned int id;
- eom_output_type_e type;
- eom_output_attribute_e attribute;
- enum wl_eom_status connection;
-
- E_Output *output;
- Eina_Bool added;
-
- E_EomClientPtr eom_client;
- Eina_Bool wait_presentation;
- /* If attribute has been set while external output is disconnected
- * then show black screen and wait until EOM client start sending
- * buffers. After expiring of the delay start mirroring */
- Ecore_Timer *delay_timer;
-};
-
-struct _E_Eom_Comp_Object_Intercept_Hook_Data
-{
- E_Client *ec;
- E_EomOutput *eom_output;
- E_Comp_Object_Intercept_Hook *hook;
-};
-
-/*
- * EOM Output Attributes
- * +-----------------+------------+-----------------+------------+
- * | | normal | exclusive_share | exclusive |
- * +-----------------+------------+-----------------+------------+
- * | normal | possible | possible | possible |
- * +-----------------+------------+-----------------+------------+
- * | exclusive_share | impossible | possible | possible |
- * +-----------------+------------+-----------------+------------+
- * | exclusive | impossible | impossible | impossible |
- * +-----------------+------------+-----------------+------------+
- *
- * possible = 1
- * impossible = 0
- */
-static int eom_output_attributes[EOM_NUM_ATTR][EOM_NUM_ATTR] =
-{
- {1, 1, 1},
- {0, 1, 1},
- {0, 0, 0},
-};
-
-static E_EomPtr g_eom = NULL;
-
-static inline eom_output_attribute_e
-_e_eom_output_attribute_get(E_EomOutputPtr eom_output)
-{
- if (eom_output == NULL) return EOM_OUTPUT_ATTRIBUTE_NONE;
-
- return eom_output->attribute;
-}
-
-static inline void
-_e_eom_output_attribute_force_set(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
-{
- if (eom_output == NULL) return;
-
- eom_output->attribute = attribute;
-}
-
-static inline Eina_Bool
-_e_eom_output_attribute_set(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
-{
- if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE || eom_output->attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
- {
- eom_output->attribute = attribute;
- return EINA_TRUE;
- }
-
- if (eom_output_attributes[eom_output->attribute - 1][attribute - 1] == 1)
- {
- eom_output->attribute = attribute;
- return EINA_TRUE;
- }
-
- return EINA_FALSE;
-}
-
-static eom_output_mode_e
-_e_eom_output_mode_get(E_Output_Display_Mode display_mode)
-{
- switch (display_mode)
- {
- case E_OUTPUT_DISPLAY_MODE_NONE:
- return EOM_OUTPUT_MODE_NONE;
- case E_OUTPUT_DISPLAY_MODE_MIRROR:
- return EOM_OUTPUT_MODE_MIRROR;
- case E_OUTPUT_DISPLAY_MODE_PRESENTATION:
- return EOM_OUTPUT_MODE_PRESENTATION;
- default:
- break;
- }
-
- return EOM_OUTPUT_MODE_NONE;
-}
-
-static void
-_e_eom_output_info_broadcast(E_EomOutputPtr eom_output, eom_output_attribute_state_e attribute_state)
-{
- E_EomClientPtr eom_client = NULL;
- Eina_List *l = NULL;
- int w, h, pw, ph;
-
- /* get the output size */
- e_output_size_get(eom_output->output, &w, &h);
- e_output_phys_size_get(eom_output->output, &pw, &ph);
-
- /* If there were previously connected clients to the output - notify them */
- EINA_LIST_FOREACH(g_eom->clients, l, eom_client)
- {
- if (!eom_client) continue;
- if (!eom_client->resource) continue;
-
- if (attribute_state == EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE)
- EOMINF("Send output connected notification", eom_client->ec, eom_output->output);
- if (attribute_state == EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE)
- EOMINF("Send output disconnected notification", eom_client->ec, eom_output->output);
-
- if (eom_client->ec == e_output_presentation_ec_get(eom_output->output))
- wl_eom_send_output_info(eom_client->resource,
- eom_output->id,
- eom_output->type,
- e_output_display_mode_get(eom_output->output),
- w, h, pw, ph,
- eom_output->connection,
- 0,
- _e_eom_output_attribute_get(eom_output),
- attribute_state,
- EOM_ERROR_NONE);
- else
- wl_eom_send_output_info(eom_client->resource,
- eom_output->id,
- eom_output->type,
- e_output_display_mode_get(eom_output->output),
- w, h, pw, ph,
- eom_output->connection,
- 1, 0, 0, 0);
- }
-}
-
-static void
-_e_eom_output_status_broadcast(E_EomOutputPtr eom_output, E_EomClientPtr except_client, eom_output_attribute_state_e attribute_state)
-{
- E_EomClientPtr eom_client = NULL;
- Eina_List *l = NULL;
- E_Output_Display_Mode display_mode;
-
- EINA_LIST_FOREACH(g_eom->clients, l, eom_client)
- {
- if (!eom_client) continue;
- if (eom_client->output_id != eom_output->id) continue;
- if (eom_client == except_client) continue;
-
- wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
- _e_eom_output_attribute_get(eom_output),
- attribute_state,
- EOM_ERROR_NONE);
-
- display_mode = e_output_display_mode_get(eom_output->output);
- wl_eom_send_output_mode(eom_client->resource, eom_output->id, _e_eom_output_mode_get(display_mode));
- }
-}
-
-static E_EomOutputPtr
-_e_eom_output_find(E_Output *output)
-{
- E_EomOutputPtr eom_output = NULL;
- Eina_List *l;
-
- EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
- {
- if (eom_output->output == output)
- return eom_output;
- }
-
- return NULL;
-}
-
-static E_EomOutputPtr
-_e_eom_output_create(E_Output *output, Eina_Bool added)
-{
- E_EomOutputPtr eom_output = NULL;
-
- if (!g_eom) return NULL;
-
- eom_output = E_NEW(E_EomOutput, 1);
- EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
-
- eom_output->id = output->index;
- eom_output->connection = WL_EOM_STATUS_NONE;
- eom_output->output = output;
- eom_output->type = (eom_output_type_e)output->toutput_type;
- eom_output->added = added;
- eom_output->eom_client = NULL;
-
- g_eom->eom_outputs = eina_list_append(g_eom->eom_outputs, eom_output);
-
- EOMINF("create (%d)output, type:%d, added:%d", NULL, eom_output->output,
- eom_output->id, eom_output->type, eom_output->added);
-
- return eom_output;
-}
-
-static Eina_Bool
-_e_eom_output_destroy(E_Output *output)
-{
- E_EomOutputPtr eom_output = NULL;
-
- if (!g_eom) return EINA_TRUE;
-
- eom_output = _e_eom_output_find(output);
- EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
-
- EOMINF("destroy (%d)output, type:%d, added:%d", NULL, eom_output->output,
- eom_output->id, eom_output->type, eom_output->added);
-
- g_eom->eom_outputs = eina_list_remove(g_eom->eom_outputs, eom_output);
-
- E_FREE(eom_output);
-
- return EINA_TRUE;
-}
-
-static E_EomOutputPtr
-_e_eom_output_get_by_id(int id)
-{
- E_EomOutputPtr eom_output;
- Eina_List *l;
-
- EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
- {
- if (eom_output && eom_output->id == id)
- return eom_output;
- }
-
- return NULL;
-}
-
-static E_EomOutputPtr
-_e_eom_output_by_ec_child_get(E_Client *ec)
-{
- E_EomOutputPtr eom_output = NULL;
- E_Client *parent_ec = NULL, *output_ec = NULL;
- Eina_List *l;
-
- EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
- {
- output_ec = e_output_presentation_ec_get(eom_output->output);
- if (!output_ec) continue;
-
- if (output_ec == ec) return eom_output;
-
- if (!e_comp_wl_subsurface_check(ec)) continue;
-
- parent_ec = e_comp_wl_subsurface_parent_get(ec);
- while (parent_ec)
- {
- if (parent_ec == output_ec) return eom_output;
- if (!e_comp_wl_subsurface_check(parent_ec)) break;
-
- parent_ec = e_comp_wl_subsurface_parent_get(parent_ec);
- }
- }
-
- return NULL;
-}
-
-static void
-_e_eom_output_send_configure_event(E_EomOutput *eom_output, E_Client *ec)
-{
- E_Comp_Wl_Client_Data *cdata;
- int w, h;
-
- cdata = e_client_cdata_get(ec);
- EINA_SAFETY_ON_NULL_RETURN(cdata);
- EINA_SAFETY_ON_NULL_RETURN(cdata->shell.configure_send);
-
- /* get the output size */
- e_output_size_get(eom_output->output, &w, &h);
- e_client_shell_configure_send(ec, 0, w, h);
-
- EOMINF("Send Configure Event for Presentation (%d X %d)", ec, eom_output->output, w, h);
-
- return;
-}
-
-static E_EomClientPtr
-_e_eom_client_get_by_resource(struct wl_resource *resource)
-{
- Eina_List *l;
- E_EomClientPtr client;
-
- EINA_LIST_FOREACH(g_eom->clients, l, client)
- {
- if (client && client->resource == resource)
- return client;
- }
-
- return NULL;
-}
-
-static E_EomClientPtr
-_e_eom_client_get_current_by_ec(E_Client *ec)
-{
- Eina_List *l;
- E_EomClientPtr client;
-
- EINA_LIST_FOREACH(g_eom->clients, l, client)
- {
- if (client && client->current == EINA_TRUE && client->ec == ec)
- return client;
- }
-
- return NULL;
-}
-
-static E_EomClientPtr
-_e_eom_client_get_current_by_ec_parrent(E_Client *ec)
-{
- Eina_List *l;
- E_EomClientPtr client;
- E_Client *parent = NULL;
-
- if (!e_comp_wl_subsurface_check(ec))
- return NULL;
-
- EINA_LIST_FOREACH(g_eom->clients, l, client)
- {
- parent = e_comp_wl_subsurface_parent_get(ec);
- while (parent)
- {
- if (client->ec == parent)
- return client;
-
- if (!e_comp_wl_subsurface_check(parent))
- break;
-
- parent = e_comp_wl_subsurface_parent_get(parent);
- }
- }
-
- return NULL;
-}
-
-static Eina_Bool
-_e_eom_cb_client_buffer_change(void *data, int type, void *event)
-{
- E_EomClientPtr eom_client = NULL, eom_client_itr = NULL;
- E_EomOutputPtr eom_output = NULL;
- E_Event_Client *ev = event;
- E_Client *ec = NULL;
- E_Comp_Wl_Buffer *wl_buffer = NULL;
- tbm_surface_h tbm_buffer = NULL;
- E_Comp_Wl_Data *comp_wl;
- Eina_List *l;
- E_Output_Display_Mode display_mode, display_mode_prev;
- int width, height;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
-
- ec = ev->ec;
- EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), ECORE_CALLBACK_PASS_ON);
-
- eom_client = _e_eom_client_get_current_by_ec(ec);
- if (eom_client == NULL)
- {
- eom_client = _e_eom_client_get_current_by_ec_parrent(ec);
- if (eom_client == NULL)
- return ECORE_CALLBACK_PASS_ON;
- }
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, ECORE_CALLBACK_PASS_ON);
-
- wl_buffer = e_pixmap_resource_get(ec->pixmap);
- EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer, ECORE_CALLBACK_PASS_ON);
- EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer->resource, ECORE_CALLBACK_PASS_ON);
-
- /* TODO: support different SHMEM buffers etc. */
- comp_wl = e_comp_wl_get();
- tbm_buffer = wayland_tbm_server_get_surface(comp_wl->tbm.server, wl_buffer->resource);
- EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_buffer, ECORE_CALLBACK_PASS_ON);
-
- width = tbm_surface_get_width(tbm_buffer);
- height = tbm_surface_get_height(tbm_buffer);
-
- if ((width <= 1) || (height <= 1)) return ECORE_CALLBACK_PASS_ON;
-
- eom_output = _e_eom_output_get_by_id(eom_client->output_id);
- EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, ECORE_CALLBACK_PASS_ON);
-
- if (eom_output->delay_timer)
- {
- ecore_timer_del(eom_output->delay_timer);
- eom_output->delay_timer = NULL;
- eom_output->wait_presentation = EINA_FALSE;
- }
-
- if (eom_trace_debug)
- EOMINF("===============> EXT START", ec, eom_output->output);
-
- /* TODO: It works but maybe there is better solution exists ?
- * Also I do not know how it affects on performance */
- if (ec->map_timer)
- {
- if (eom_trace_debug)
- EOMINF("delete map_timer", ec, eom_output->output);
- E_FREE_FUNC(ec->map_timer, ecore_timer_del);
- }
-
- if (eom_trace_debug)
- EOMINF("buffer_changed callback", ec, eom_output->output);
-
- display_mode_prev = e_output_display_mode_get(eom_output->output);
-
- e_output_presentation_ec_set(eom_output->output, eom_client->ec);
-
- /* set the ec to the output for presentation. */
- if (!e_output_presentation_update(eom_output->output, eom_client->ec))
- {
- EOMERR("e_output_presentation_update fail", eom_output->output);
- return ECORE_CALLBACK_PASS_ON;
- }
-
- display_mode = e_output_display_mode_get(eom_output->output);
- if (display_mode != display_mode_prev)
- {
- EINA_LIST_FOREACH(g_eom->clients, l, eom_client_itr)
- {
- if (eom_client_itr->output_id == eom_output->id)
- wl_eom_send_output_mode(eom_client->resource, eom_output->id, _e_eom_output_mode_get(display_mode));
- }
- }
-
- /* unset the mirror mode */
- if (display_mode_prev == E_OUTPUT_DISPLAY_MODE_MIRROR)
- e_output_mirror_unset(eom_output->output);
-
- if (eom_trace_debug)
- EOMINF("===============< EXT START", ec, eom_output->output);
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_eom_presentation_check(void *data)
-{
- E_EomOutputPtr eom_output = NULL;
- E_Output *primary_output;
-
- if (!data) return ECORE_CALLBACK_CANCEL;
-
- eom_output = (E_EomOutputPtr)data;
-
- if (eom_output->wait_presentation)
- {
- if (eom_trace_debug)
- EOMINF("_e_eom_presentation_check wait expired set to mirror", NULL, eom_output->output);
- primary_output = e_display_primary_output_get();
- e_output_mirror_set(eom_output->output, primary_output);
- eom_output->wait_presentation = EINA_FALSE;
- }
-
- eom_output->delay_timer = NULL;
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static void
-_e_eom_cb_wl_request_set_attribute(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
-{
- E_EomClientPtr eom_client = NULL;
- E_EomOutputPtr eom_output = NULL;
- E_Output *primary_output = NULL;
-
- eom_client = _e_eom_client_get_by_resource(resource);
- EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
- eom_output = _e_eom_output_get_by_id(output_id);
- EINA_SAFETY_ON_NULL_GOTO(eom_output, no_eom_output);
-
- EOMINF("Set attribute:%d", eom_client->ec, eom_output->output, attribute);
-
- /* Bind the client with a concrete output */
- eom_client->output_id = output_id;
-
- /* Set the attribute to the eom_client */
- if (eom_output->eom_client)
- {
- if (eom_output->eom_client == eom_client)
- {
- /* Current client can set any flag it wants */
- _e_eom_output_attribute_force_set(eom_output, attribute);
-
- if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
- wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
- _e_eom_output_attribute_get(eom_output),
- EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
- EOM_ERROR_NONE);
- }
- else
- {
- /* A client is trying to set new attribute */
- if (!_e_eom_output_attribute_set(eom_output, attribute))
- {
- EOMINF("client failed to set attribute", eom_client->ec, eom_output->output);
- wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
- _e_eom_output_attribute_get(eom_output),
- EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
- EOM_ERROR_INVALID_PARAMETER);
- return;
- }
-
- EOMINF("Send changes to previous current client(%p)", eom_client->ec, eom_output->output, eom_output->eom_client->ec);
- /* eom_output->eom_client is lost the attribute */
- wl_eom_send_output_attribute(eom_output->eom_client->resource, eom_output->id,
- _e_eom_output_attribute_get(eom_output),
- EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
- EOM_ERROR_NONE);
-
- eom_output->eom_client->current = EINA_FALSE;
- eom_output->eom_client = NULL;
- }
- }
- else
- {
- /* Current client can set any flag it wants */
- _e_eom_output_attribute_force_set(eom_output, attribute);
- }
-
- /* set the output display_mode */
- if (_e_eom_output_attribute_get(eom_output) == EOM_OUTPUT_ATTRIBUTE_NONE)
- {
- if (e_output_presentation_ec_get(eom_output->output) == eom_client->ec)
- e_output_presentation_unset(eom_output->output);
-
- primary_output = e_display_primary_output_get();
- if (!e_output_mirror_set(eom_output->output, primary_output))
- {
- EOMERR("e_output_mirror_set fail", eom_output->output);
- goto no_eom_output;
- }
-
- /* broadcast the status */
- _e_eom_output_status_broadcast(eom_output, NULL, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
- return;
- }
- else
- {
- /* Set the client as current client of the eom_output */
- eom_client->current = EINA_TRUE;
- eom_output->eom_client = eom_client;
-
- if (eom_output->delay_timer)
- ecore_timer_del(eom_output->delay_timer);
- eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CONNECT_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
- eom_output->wait_presentation = EINA_TRUE;
- EOMINF("e_eom_presentation_wait_set", NULL, eom_output->output);
-
- /* Send changes to the caller-client */
- wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
- _e_eom_output_attribute_get(eom_output),
- EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
- EOM_ERROR_NONE);
- }
-
- return;
-
-no_eom_output:
- /* Get here if EOM does not have output referred by output_id */
- wl_eom_send_output_attribute(eom_client->resource, output_id,
- EOM_OUTPUT_ATTRIBUTE_NONE,
- EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
- EOM_ERROR_NO_SUCH_DEVICE);
-
- wl_eom_send_output_mode(eom_client->resource, output_id, EOM_OUTPUT_MODE_NONE);
-
- wl_eom_send_output_type(eom_client->resource, output_id,
- EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
- TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
-}
-
-static void
-_e_eom_cb_wl_request_set_shell_window(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, struct wl_resource *surface)
-{
- E_EomOutputPtr eom_output = NULL;
- E_EomClientPtr eom_client = NULL;
- E_Client *ec = NULL;
-
- ec = e_desktop_xdg_shell_v6_xdg_surface_ec_get(surface);
- if (!ec)
- {
- wl_resource_post_error(surface, WL_DISPLAY_ERROR_INVALID_OBJECT, "No Client For Shell Surface");
- return;
- }
-
- eom_client = _e_eom_client_get_by_resource(resource);
- EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
- /* ec is used in buffer_change callback for distinguishing external ec and its buffers */
- eom_client->ec = ec;
- e_object_ref(E_OBJECT(ec));
-
- eom_output = _e_eom_output_get_by_id(output_id);
- if (eom_output == NULL)
- {
- wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NO_OUTPUT);
- EOMERR("no eom_output error\n", NULL);
- return;
- }
-
- EOMINF("set shell output id:%d resource:%p surface:%p", ec, eom_output->output, output_id, resource, surface);
-
- if (!eom_client->current)
- {
- wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_OUTPUT_OCCUPIED);
- return;
- }
-
- _e_eom_output_send_configure_event(eom_output, ec);
-
- wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NONE);
-}
-
-static void
-_e_eom_cb_wl_request_get_output_info(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
-{
- E_EomOutputPtr eom_output = NULL;
- E_EomClientPtr eom_client = NULL;
- int w, h, pw, ph;
-
- eom_output = _e_eom_output_get_by_id(output_id);
- EINA_SAFETY_ON_FALSE_RETURN(eom_output);
-
- eom_client = _e_eom_client_get_by_resource(resource);
- EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
- /* get the output size */
- e_output_size_get(eom_output->output, &w, &h);
- e_output_phys_size_get(eom_output->output, &pw, &ph);
-
- wl_eom_send_output_info(resource,
- eom_output->id,
- eom_output->type,
- e_output_display_mode_get(eom_output->output),
- w, h, pw, ph,
- eom_output->connection,
- 1, 0, 0, 0);
-
- EOMINF("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d",
- eom_client->ec, eom_output->output,
- eom_output->id, eom_output->type, e_output_display_mode_get(eom_output->output),
- w, h, pw, ph, e_output_connected(eom_output->output));
-}
-
-static const struct wl_eom_interface _e_eom_wl_implementation =
-{
- _e_eom_cb_wl_request_set_attribute,
- _e_eom_cb_wl_request_set_shell_window,
- _e_eom_cb_wl_request_get_output_info
-};
-
-static void
-_e_eom_cb_wl_eom_client_destroy(struct wl_resource *resource)
-{
- E_EomClientPtr eom_client = NULL;
- E_EomOutputPtr eom_output = NULL;
- E_Output *primary_output = NULL;
- E_Client *output_ec = NULL;
-
- EINA_SAFETY_ON_NULL_RETURN(resource);
-
- eom_client = _e_eom_client_get_by_resource(resource);
- EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
- eom_output = _e_eom_output_get_by_id(eom_client->output_id);
- EINA_SAFETY_ON_NULL_GOTO(eom_output, end);
-
- EOMINF("=======================> CLIENT DESTROY", eom_client->ec, eom_output->output);
-
- if (eom_client == eom_output->eom_client)
- eom_output->eom_client = NULL;
-
- output_ec = e_output_presentation_ec_get(eom_output->output);
- if (eom_client->ec == output_ec)
- {
- _e_eom_output_attribute_set(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
- e_output_presentation_unset(eom_output->output);
-
- primary_output = e_display_primary_output_get();
- if (!e_output_mirror_set(eom_output->output, primary_output))
- EOMERR("e_output_mirror_set fail", eom_output->output);
- }
-
-end:
- /* Notify eom clients which are binded to a concrete output that the
- * state and mode of the output has been changed */
- if (eom_output)
- _e_eom_output_status_broadcast(eom_output, eom_client, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
-
- g_eom->clients = eina_list_remove(g_eom->clients, eom_client);
- e_object_unref(E_OBJECT(eom_client->ec));
- free(eom_client);
-}
-
-static void
-_e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
- struct wl_resource *resource = NULL;
- E_EomPtr eom = NULL;
- E_EomClientPtr eom_client = NULL;
- E_EomOutputPtr eom_output = NULL;
- Eina_List *l;
- int w, h, pw, ph;
-
- EINA_SAFETY_ON_NULL_RETURN(data);
- eom = data;
-
- resource = wl_resource_create(client, &wl_eom_interface, MIN(version, 1), id);
- if (resource == NULL)
- {
- EOMERR("resource is null. (version :%d, id:%d)", NULL, version, id);
- wl_client_post_no_memory(client);
- return;
- }
-
- wl_resource_set_implementation(resource, &_e_eom_wl_implementation, eom, _e_eom_cb_wl_eom_client_destroy);
-
- wl_eom_send_output_count(resource, g_eom->eom_output_count);
-
- EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
- {
- if (!eom_output) continue;
-
- /* get the output size */
- e_output_size_get(eom_output->output, &w, &h);
- e_output_phys_size_get(eom_output->output, &pw, &ph);
-
- wl_eom_send_output_info(resource,
- eom_output->id,
- eom_output->type,
- e_output_display_mode_get(eom_output->output),
- w, h, pw, ph,
- eom_output->connection,
- 1, 0, 0, 0);
-
- EOMINF("BIND send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d",
- NULL, eom_output->output,
- eom_output->id, eom_output->type, e_output_display_mode_get(eom_output->output),
- w, h, pw, ph, e_output_connected(eom_output->output));
- }
-
- eom_client = E_NEW(E_EomClient, 1);
- EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
- eom_client->resource = resource;
- eom_client->current = EINA_FALSE;
- eom_client->output_id = -1;
- eom_client->ec = NULL;
-
- g_eom->clients = eina_list_append(g_eom->clients, eom_client);
-
- EOMINF("=======================> BIND CLIENT", NULL, NULL);
-}
-
-static Eina_Bool
-_e_eom_connect(E_EomOutputPtr eom_output)
-{
- E_Output *primary_output = NULL;
- E_Client *ec = NULL;
- int w, h;
-
- if (!g_eom) return EINA_TRUE;
-
- if (eom_output->eom_client)
- {
- EOMINF("Start Wait Presentation", NULL, eom_output->output);
- /* the fallback timer for not setting the presentation. */
- if (eom_output->delay_timer)
- ecore_timer_del(eom_output->delay_timer);
- eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CONNECT_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
- eom_output->wait_presentation = EINA_TRUE;
-
- EOMINF("Send Configure Event for Presentation", NULL, eom_output->output);
- ec = e_output_presentation_ec_get(eom_output->output);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-
- _e_eom_output_send_configure_event(eom_output, ec);
- }
- else
- {
- EOMINF("Start Mirroring", NULL, eom_output->output);
-
- primary_output = e_display_primary_output_get();
- if (!e_output_mirror_set(eom_output->output, primary_output))
- {
- EOMERR("e_output_mirror_set fail", eom_output->output);
- return EINA_FALSE;
- }
- }
-
- eom_output->connection = WL_EOM_STATUS_CONNECTION;
-
- /* If there were previously connected clients to the output - notify them */
- _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE);
-
- /* get the output size */
- e_output_size_get(eom_output->output, &w, &h);
- EOMINF("eom_output: (%dx%d) connected", NULL, eom_output->output, w, h);
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_eom_disconnect(E_EomOutputPtr eom_output)
-{
- if (!g_eom) return EINA_TRUE;
-
- switch (e_output_display_mode_get(eom_output->output))
- {
- case E_OUTPUT_DISPLAY_MODE_NONE:
- break;
- case E_OUTPUT_DISPLAY_MODE_MIRROR:
- /* unset mirror */
- e_output_mirror_unset(eom_output->output);
- break;
- case E_OUTPUT_DISPLAY_MODE_PRESENTATION:
- /* only change the display_mode */
- e_output_presentation_unset(eom_output->output);
- break;
- default:
- EOMERR("unknown display_mode:%d", eom_output->output, e_output_display_mode_get(eom_output->output));
- break;
- }
-
- /* delete presentation_delay_timer */
- if (eom_output->delay_timer)
- {
- ecore_timer_del(eom_output->delay_timer);
- eom_output->delay_timer = NULL;
- }
-
- /* update eom_output disconnect */
- eom_output->connection = WL_EOM_STATUS_DISCONNECTION;
-
- /* If there were previously connected clients to the output - notify them */
- _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE);
-
- EOMINF("eom_output: disconnected.", NULL, eom_output->output);
-
- return EINA_TRUE;
-}
-
-static void
-_e_eom_output_cb_output_connect_status_change(void *data, E_Output *output)
-{
- E_EomOutputPtr eom_output = NULL;
-
- eom_output = _e_eom_output_find(output);
- if (!eom_output)
- {
- EOMERR("cannot find eom_output", output);
- return;
- }
-
- if (e_output_connected(output))
- _e_eom_connect(eom_output);
- else
- _e_eom_disconnect(eom_output);
-}
-
-static void
-_e_eom_output_cb_output_mode_change(void *data, E_Output *output)
-{
- E_EomOutputPtr eom_output = NULL;
- E_Client *ec = NULL;
-
- /* if presentation, send configure notify to all eom_clients */
- if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_PRESENTATION)
- {
- eom_output = _e_eom_output_find(output);
- EINA_SAFETY_ON_NULL_RETURN(eom_output);
-
- ec = e_output_presentation_ec_get(output);
- EINA_SAFETY_ON_NULL_RETURN(ec);
-
- _e_eom_output_send_configure_event(eom_output, ec);
-
- if (eom_output->delay_timer)
- ecore_timer_del(eom_output->delay_timer);
- eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CONNECT_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
- eom_output->wait_presentation = EINA_TRUE;
- }
-}
-
-static void
-_e_eom_output_cb_output_add(void *data, E_Output *output)
-{
- E_EomOutputPtr eom_output;
-
- eom_output = _e_eom_output_create(output, EINA_TRUE);
- if (!eom_output)
- {
- EOMERR("_e_eom_output_create fail", output);
- return;
- }
-
- if (e_output_connected(output))
- _e_eom_connect(eom_output);
- else
- _e_eom_disconnect(eom_output);
-}
-
-static void
-_e_eom_output_cb_output_del(void *data, E_Output *output)
-{
- if (!_e_eom_output_destroy(output))
- {
- EOMERR("_e_eom_output_destroy fail", output);
- return;
- }
-}
-
-static void
-_e_eom_output_deinit(void)
-{
- E_EomOutputPtr eom_output;
- Eina_List *l;
-
- if (!g_eom) return;
- if (!g_eom->eom_outputs) return;
-
- EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
- _e_eom_output_destroy(eom_output->output);
-
- eina_list_free(g_eom->eom_outputs);
- g_eom->eom_outputs = NULL;
-}
-
-static Eina_Bool
-_e_eom_output_init(void)
-{
- E_Output *output = NULL;
- E_Output *primary_output = NULL;
- E_EomOutputPtr eom_output;
- Eina_List *l;
-
- primary_output = e_display_primary_output_get();
- EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, EINA_FALSE);
-
- g_eom->eom_output_count = e_display_num_outputs_get() - 1;
- EOMINF("external output count : %d", NULL, NULL, g_eom->eom_output_count);
-
- /* create the eom_output except for the primary output */
- EINA_LIST_FOREACH(e_display_outputs_get(), l, output)
- {
- if (!output) continue;
- if (output == primary_output) continue;
-
- eom_output = _e_eom_output_create(output, EINA_FALSE);
- if (!eom_output)
- {
- EOMERR("_e_eom_output_create fail", output);
- goto err;
- }
-
- if (e_output_connected(output))
- _e_eom_connect(eom_output);
- else
- _e_eom_disconnect(eom_output);
- }
-
- return EINA_TRUE;
-
-err:
- _e_eom_output_deinit();
-
- return EINA_FALSE;
-}
-
-EINTERN Eina_Bool
-e_eom_init(void)
-{
- E_Comp_Screen *comp_screen;
- E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
-
- EINA_SAFETY_ON_NULL_GOTO(comp_wl, err);
-
- comp_screen = e_comp_screen_get();
- if (!comp_screen || comp_screen->num_outputs < 1)
- return EINA_FALSE;
-
- g_eom = E_NEW(E_Eom, 1);
- EINA_SAFETY_ON_NULL_RETURN_VAL(g_eom, EINA_FALSE);
-
- g_eom->global = wl_global_create(comp_wl->wl.disp, &wl_eom_interface, 1, g_eom, _e_eom_cb_wl_bind);
- EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
-
- if (!_e_eom_output_init())
- {
- EOMERR("_e_eom_output_init fail", NULL);
- goto err;
- }
-
- g_eom->output_connect_status_hook = e_output_hook_add(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, _e_eom_output_cb_output_connect_status_change, g_eom);
- g_eom->output_mode_changes_hook = e_output_hook_add(E_OUTPUT_HOOK_MODE_CHANGE, _e_eom_output_cb_output_mode_change, g_eom);
- g_eom->output_add_hook = e_output_hook_add(E_OUTPUT_HOOK_ADD, _e_eom_output_cb_output_add, g_eom);
- g_eom->output_remove_hook = e_output_hook_add(E_OUTPUT_HOOK_REMOVE, _e_eom_output_cb_output_del, g_eom);
-
- E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_cb_client_buffer_change, g_eom);
-
- return EINA_TRUE;
-
-err:
- e_eom_shutdown();
-
- return EINA_FALSE;
-}
-
-EINTERN int
-e_eom_shutdown(void)
-{
- Ecore_Event_Handler *h = NULL;
-
- if (!g_eom) return 1;
-
- if (g_eom->handlers)
- {
- EINA_LIST_FREE(g_eom->handlers, h)
- ecore_event_handler_del(h);
- g_eom->handlers = NULL;
- }
-
- if (g_eom->output_remove_hook)
- {
- e_output_hook_del(g_eom->output_remove_hook);
- g_eom->output_remove_hook = NULL;
- }
-
- if (g_eom->output_add_hook)
- {
- e_output_hook_del(g_eom->output_add_hook);
- g_eom->output_add_hook = NULL;
- }
-
- if (g_eom->output_mode_changes_hook)
- {
- e_output_hook_del(g_eom->output_mode_changes_hook);
- g_eom->output_mode_changes_hook = NULL;
- }
-
- if (g_eom->output_connect_status_hook)
- {
- e_output_hook_del(g_eom->output_connect_status_hook);
- g_eom->output_connect_status_hook = NULL;
- }
-
- _e_eom_output_deinit();
-
- if (g_eom->global)
- wl_global_destroy(g_eom->global);
- g_eom->global = NULL;
-
- E_FREE(g_eom);
-
- return 1;
-}
-
-E_API Eina_Bool
-e_eom_is_ec_external(E_Client *ec)
-{
- E_EomOutputPtr eom_output;
-
- if (!g_eom) return EINA_FALSE;
-
- eom_output = _e_eom_output_by_ec_child_get(ec);
- if (!eom_output) return EINA_FALSE;
-
- return EINA_TRUE;
-}