implement support for wl aux hints

this is a direct copy of a feature from tizen git with no modifications other
than what was required for compilation and functionality

https://git.tizen.org/cgit/platform/upstream/enlightenment/commit/?id=8ea090222cee86b57e54f1444c5b63252380fba5
https://git.tizen.org/cgit/platform/upstream/enlightenment/commit/?id=2c5593325c3f32efa92da3c371a780e434a30efd

fix T5780
This commit is contained in:
Mike Blumenkrantz 2017-07-28 14:33:03 -04:00
parent 0b887245cc
commit ab328c6512
10 changed files with 606 additions and 10 deletions

View File

@ -431,7 +431,8 @@ src/bin/e_comp_wl_data.c \
src/bin/e_comp_wl_input.c \
src/bin/e_comp_wl_dmabuf.c \
src/bin/e_comp_wl.c \
src/bin/e_comp_wl_extensions.c
src/bin/e_comp_wl_extensions.c \
src/bin/e_comp_wl_extensions_tizen.c
enlightenment_gen_src += \
src/bin/generated/linux-dmabuf-unstable-v1-server-protocol.h \
@ -445,16 +446,12 @@ src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \
src/bin/generated/relative-pointer-unstable-v1-protocol.c \
src/bin/generated/relative-pointer-unstable-v1-server-protocol.h \
src/bin/generated/pointer-constraints-unstable-v1-protocol.c \
src/bin/generated/pointer-constraints-unstable-v1-server-protocol.h
src/bin/generated/pointer-constraints-unstable-v1-server-protocol.h \
src/bin/generated/efl-aux-hints-protocol.c \
src/bin/generated/efl-aux-hints-server-protocol.h
src/bin/e_comp_wl_extensions.c: \
src/bin/generated/session-recovery-server-protocol.h \
src/bin/generated/xdg-foreign-unstable-v1-protocol.c \
src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \
src/bin/generated/relative-pointer-unstable-v1-protocol.c \
src/bin/generated/relative-pointer-unstable-v1-server-protocol.h \
src/bin/generated/pointer-constraints-unstable-v1-protocol.c \
src/bin/generated/pointer-constraints-unstable-v1-server-protocol.h
$(enlightenment_gen_src)
src/bin/e_comp_wl.c: \
src/bin/generated/www-server-protocol.h

View File

@ -2517,6 +2517,17 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
}
if (ec->comp_data->aux_hint.hints)
{
E_Comp_Wl_Aux_Hint *hint;
EINA_LIST_FREE(ec->comp_data->aux_hint.hints, hint)
{
eina_stringshare_del(hint->hint);
eina_stringshare_del(hint->val);
E_FREE(hint);
}
}
/* The resource destroy callback will walk the state->frames list,
* so move the list to a temporary first.
*/

View File

@ -41,7 +41,7 @@
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
(type *)(void *)( (char *)__mptr - offsetof(type,member) ); \
})
typedef struct _E_Comp_Wl_Aux_Hint E_Comp_Wl_Aux_Hint;
typedef struct _E_Comp_Wl_Buffer E_Comp_Wl_Buffer;
typedef struct _E_Comp_Wl_Subsurf_Data E_Comp_Wl_Subsurf_Data;
typedef struct _E_Comp_Wl_Surface_State E_Comp_Wl_Surface_State;
@ -51,6 +51,15 @@ typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output;
typedef struct E_Shell_Data E_Shell_Data;
typedef void (*E_Comp_Wl_Grab_End_Cb)(E_Client*);
struct _E_Comp_Wl_Aux_Hint
{
int id;
const char *hint;
const char *val;
Eina_Bool changed;
Eina_Bool deleted;
};
struct _E_Comp_Wl_Buffer
{
struct wl_resource *resource;
@ -126,6 +135,10 @@ typedef struct E_Comp_Wl_Extension_Data
struct wl_global *global;
Eina_Hash *constraints;
} zwp_pointer_constraints_v1;
struct
{
struct wl_global *global;
} efl_aux_hints;
} E_Comp_Wl_Extension_Data;
struct _E_Comp_Wl_Data
@ -327,6 +340,13 @@ struct _E_Comp_Wl_Client_Data
int32_t x, y;
} popup;
struct
{
Eina_Bool changed : 1;
Eina_List *hints;
Eina_Bool use_msg : 1;
} aux_hint;
int32_t on_outputs; /* Bitfield of the outputs this client is present on */
E_Maximize max;
@ -400,6 +420,12 @@ E_API void e_comp_wl_extension_pointer_constraints_commit(E_Client *ec);
E_API Eina_Bool e_comp_wl_extension_pointer_constraints_update(E_Client *ec, int x, int y);
E_API void e_comp_wl_extension_pointer_unconstrain(E_Client *ec);
E_API void
e_policy_wl_aux_message_send(E_Client *ec,
const char *key,
const char *val,
Eina_List *options);
# ifndef HAVE_WAYLAND_ONLY
EINTERN void e_comp_wl_xwayland_client_queue(E_Client *ec);
static inline E_Comp_X_Client_Data *

View File

@ -9,6 +9,7 @@
#include "relative-pointer-unstable-v1-server-protocol.h"
#include "pointer-constraints-unstable-v1-server-protocol.h"
/* mutter uses 32, seems reasonable */
#define HANDLE_LEN 32
@ -661,6 +662,8 @@ _dmabuf_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
return ECORE_CALLBACK_PASS_ON;
}
EINTERN Eina_Bool e_comp_wl_extensions_tizen_init(void);
EINTERN Eina_Bool
e_comp_wl_extensions_init(void)
{
@ -681,6 +684,8 @@ e_comp_wl_extensions_init(void)
e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_wl_extensions_client_move_begin, NULL);
e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_wl_extensions_client_move_end, NULL);
e_comp_wl_extensions_tizen_init();
return EINA_TRUE;
}

View File

@ -0,0 +1,276 @@
#define E_COMP_WL
#include "e.h"
#include "efl-aux-hints-server-protocol.h"
enum _E_Policy_Hint_Type
{
E_POLICY_HINT_MSG_USE = 0,
};
static const char *hint_names[] =
{
"wm.policy.win.msg.use",
};
static Eina_List *aux_hints;
static void
_e_policy_wl_allowed_aux_hint_send(E_Client *ec, int id)
{
Eina_List *l;
struct wl_client *wc;
struct wl_resource *res;
wc = wl_resource_get_client(ec->comp_data->surface);
EINA_LIST_FOREACH(aux_hints, l, res)
if (wl_resource_get_client(res) == wc) break;
if (!res) return;
efl_aux_hints_send_allowed_aux_hint(
res,
ec->comp_data->surface,
id);
}
static void
_e_policy_wl_aux_hint_apply(E_Client *ec)
{
E_Comp_Wl_Aux_Hint *hint;
Eina_List *l;
Eina_Bool send;
if (!ec->comp_data) return;
if (!ec->comp_data->aux_hint.changed) return;
EINA_LIST_FOREACH(ec->comp_data->aux_hint.hints, l, hint)
{
if (!hint->changed) continue;
send = EINA_FALSE;
if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_MSG_USE]))
{
if ((hint->deleted) || (!strcmp(hint->val, "0")))
ec->comp_data->aux_hint.use_msg = EINA_FALSE;
else if (!strcmp(hint->val, "1"))
ec->comp_data->aux_hint.use_msg = EINA_TRUE;
}
if (send)
_e_policy_wl_allowed_aux_hint_send(ec, hint->id);
}
}
static void
_tzpol_iface_cb_aux_hint_add(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t id, const char *name, const char *value)
{
E_Client *ec;
Eina_Bool res = EINA_FALSE;
ec = wl_resource_get_user_data(surf);
EINA_SAFETY_ON_NULL_RETURN(ec);
res = e_hints_aux_hint_add(ec, id, name, value);
if (res)
{
_e_policy_wl_aux_hint_apply(ec);
efl_aux_hints_send_allowed_aux_hint(res_tzpol, surf, id);
EC_CHANGED(ec);
}
}
static void
_tzpol_iface_cb_aux_hint_change(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t id, const char *value)
{
E_Client *ec;
Eina_Bool res = EINA_FALSE;
ec = wl_resource_get_user_data(surf);
EINA_SAFETY_ON_NULL_RETURN(ec);
res = e_hints_aux_hint_change(ec, id, value);
if (res)
{
_e_policy_wl_aux_hint_apply(ec);
efl_aux_hints_send_allowed_aux_hint(res_tzpol, surf, id);
EC_CHANGED(ec);
}
}
static void
_tzpol_iface_cb_aux_hint_del(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf, int32_t id)
{
E_Client *ec;
unsigned int res = -1;
ec = wl_resource_get_user_data(surf);
EINA_SAFETY_ON_NULL_RETURN(ec);
res = e_hints_aux_hint_del(ec, id);
if (res)
{
_e_policy_wl_aux_hint_apply(ec);
EC_CHANGED(ec);
}
}
static void
_tzpol_iface_cb_supported_aux_hints_get(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
{
E_Client *ec;
const Eina_List *hints_list;
const Eina_List *l;
struct wl_array hints;
const char *hint_name;
int len;
char *p;
ec = wl_resource_get_user_data(surf);
EINA_SAFETY_ON_NULL_RETURN(ec);
hints_list = e_hints_aux_hint_supported_get();
wl_array_init(&hints);
EINA_LIST_FOREACH(hints_list, l, hint_name)
{
len = strlen(hint_name) + 1;
p = wl_array_add(&hints, len);
if (p == NULL)
break;
strncpy(p, hint_name, len);
}
efl_aux_hints_send_supported_aux_hints(res_tzpol, surf, &hints, eina_list_count(hints_list));
wl_array_release(&hints);
}
E_API void
e_policy_wl_aux_message_send(E_Client *ec,
const char *key,
const char *val,
Eina_List *options)
{
Eina_List *l;
struct wl_client *wc;
struct wl_resource *res;
struct wl_array opt_array;
const char *option;
int len;
char *p;
if (!ec->comp_data) return;
if (!ec->comp_data->aux_hint.use_msg) return;
wc = wl_resource_get_client(ec->comp_data->surface);
EINA_LIST_FOREACH(aux_hints, l, res)
if (wl_resource_get_client(res) == wc) break;
if (!res) return;
wl_array_init(&opt_array);
EINA_LIST_FOREACH(options, l, option)
{
len = strlen(option) + 1;
p = wl_array_add(&opt_array, len);
if (p == NULL)
break;
strncpy(p, option, len);
}
efl_aux_hints_send_aux_message(res, ec->comp_data->surface,
key, val, &opt_array);
wl_array_release(&opt_array);
}
void
e_policy_wl_aux_hint_init(void)
{
int i, n;
//E_Config_Aux_Hint_Supported *auxhint;
//Eina_List *l;
n = (sizeof(hint_names) / sizeof(char *));
for (i = 0; i < n; i++)
{
e_hints_aux_hint_supported_add(hint_names[i]);
}
//EINA_LIST_FOREACH(e_config->aux_hint_supported, l, auxhint)
//{
//if (!auxhint->name) continue;
//e_hints_aux_hint_supported_add(auxhint->name);
//}
return;
}
#define GLOBAL_BIND_CB(NAME, IFACE, ...) \
static void \
_e_comp_wl_##NAME##_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id) \
{ \
struct wl_resource *res; \
\
if (!(res = wl_resource_create(client, &(IFACE), 1, id))) \
{ \
ERR("Could not create %s interface", #NAME);\
wl_client_post_no_memory(client);\
return;\
}\
\
wl_resource_set_implementation(res, &_e_##NAME##_interface, NULL, NULL);\
}
static const struct efl_aux_hints_interface _e_efl_aux_hints_interface =
{
_tzpol_iface_cb_aux_hint_add,
_tzpol_iface_cb_aux_hint_change,
_tzpol_iface_cb_aux_hint_del,
_tzpol_iface_cb_supported_aux_hints_get,
};
static void
_efl_aux_hints_destroy(struct wl_resource *res)
{
aux_hints = eina_list_remove(aux_hints, res);
}
static void
_e_comp_wl_efl_aux_hints_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
{
struct wl_resource *res;
if (!(res = wl_resource_create(client, &efl_aux_hints_interface, 1, id)))
{
ERR("Could not create %s interface", "efl-aux-hints");
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(res, &_e_efl_aux_hints_interface, NULL, _efl_aux_hints_destroy);
aux_hints = eina_list_append(aux_hints, res);
}
#define GLOBAL_CREATE_OR_RETURN(NAME, IFACE, VERSION) \
do { \
struct wl_global *global; \
\
global = wl_global_create(e_comp_wl->wl.disp, &(IFACE), VERSION, \
NULL, _e_comp_wl_##NAME##_cb_bind); \
if (!global) \
{ \
ERR("Could not add %s to wayland globals", #IFACE); \
return EINA_FALSE; \
} \
e_comp_wl->extensions->NAME.global = global; \
} while (0)
EINTERN Eina_Bool
e_comp_wl_extensions_tizen_init(void)
{
GLOBAL_CREATE_OR_RETURN(efl_aux_hints, efl_aux_hints_interface, 1);
e_policy_wl_aux_hint_init();
return EINA_TRUE;
}

View File

@ -1668,3 +1668,227 @@ e_hints_scale_update(void)
#endif
}
#ifdef HAVE_WAYLAND
static Eina_List *aux_hints_supported = NULL;
static E_Comp_Client_Data *
e_pixmap_cdata_get(E_Pixmap *cp)
{
return e_pixmap_client_get(cp)->comp_data;
}
E_API const Eina_List *
e_hints_aux_hint_supported_add(const char *hint)
{
Eina_List *l;
const char *supported;
EINA_LIST_FOREACH(aux_hints_supported, l, supported)
{
if (!strcmp(supported, hint))
return aux_hints_supported;
}
aux_hints_supported = eina_list_append(aux_hints_supported, hint);
return aux_hints_supported;
}
E_API const Eina_List *
e_hints_aux_hint_supported_del(const char *hint)
{
Eina_List *l;
const char *supported;
EINA_LIST_FOREACH(aux_hints_supported, l, supported)
{
if (!strcmp(supported, hint))
{
aux_hints_supported = eina_list_remove(aux_hints_supported, hint);
break;
}
}
return aux_hints_supported;
}
E_API const Eina_List *
e_hints_aux_hint_supported_get(void)
{
return aux_hints_supported;
}
E_API Eina_Bool
e_hints_aux_hint_add(E_Client *ec, int32_t id, const char *name, const char *val)
{
if (!ec) return EINA_FALSE;
return e_hints_aux_hint_add_with_pixmap(ec->pixmap, id, name, val);
}
E_API Eina_Bool
e_hints_aux_hint_change(E_Client *ec, int32_t id, const char *val)
{
if (!ec) return EINA_FALSE;
return e_hints_aux_hint_change_with_pixmap(ec->pixmap, id, val);
}
E_API Eina_Bool
e_hints_aux_hint_del(E_Client *ec, int32_t id)
{
if (!ec) return EINA_FALSE;
return e_hints_aux_hint_del_with_pixmap(ec->pixmap, id);
}
E_API const char *
e_hints_aux_hint_value_get(E_Client *ec, const char *name)
{
if (!ec) return NULL;
return e_hints_aux_hint_value_get_with_pixmap(ec->pixmap, name);
}
E_API Eina_Bool
e_hints_aux_hint_add_with_pixmap(E_Pixmap *cp, int32_t id, const char *name, const char *val)
{
E_Comp_Wl_Client_Data *cdata;
Eina_Bool found = EINA_FALSE;
E_Comp_Wl_Aux_Hint *hint;
Eina_List *l;
if (!cp) return EINA_FALSE;
cdata = (E_Comp_Wl_Client_Data*)e_pixmap_cdata_get(cp);
if (!cdata) return EINA_FALSE;
EINA_LIST_FOREACH(cdata->aux_hint.hints, l, hint)
{
if (hint->id == id)
{
if (strcmp(hint->val, val) != 0)
{
eina_stringshare_del(hint->val);
hint->val = eina_stringshare_add(val);
hint->changed = EINA_TRUE;
if (hint->deleted)
hint->deleted = EINA_FALSE;
cdata->aux_hint.changed = 1;
}
found = EINA_TRUE;
break;
}
}
if (!found)
{
hint = E_NEW(E_Comp_Wl_Aux_Hint, 1);
EINA_SAFETY_ON_NULL_RETURN_VAL(hint, EINA_FALSE);
memset(hint, 0, sizeof(E_Comp_Wl_Aux_Hint));
hint->id = id;
hint->hint = eina_stringshare_add(name);
hint->val = eina_stringshare_add(val);
hint->changed = EINA_TRUE;
hint->deleted = EINA_FALSE;
cdata->aux_hint.hints = eina_list_append(cdata->aux_hint.hints, hint);
cdata->aux_hint.changed = 1;
}
if (!found)
return EINA_TRUE;
return EINA_FALSE;
}
E_API Eina_Bool
e_hints_aux_hint_change_with_pixmap(E_Pixmap *cp, int32_t id, const char *val)
{
E_Comp_Wl_Client_Data *cdata;
Eina_List *l;
E_Comp_Wl_Aux_Hint *hint;
Eina_Bool found = EINA_FALSE;
if (!cp) return EINA_FALSE;
cdata = (E_Comp_Wl_Client_Data*)e_pixmap_cdata_get(cp);
if (!cdata) return EINA_FALSE;
EINA_LIST_FOREACH(cdata->aux_hint.hints, l, hint)
{
if (hint->id == id)
{
if ((hint->val) && (strcmp(hint->val, val) != 0))
{
eina_stringshare_del(hint->val);
hint->val = eina_stringshare_add(val);
hint->changed = EINA_TRUE;
cdata->aux_hint.changed = 1;
}
if (hint->deleted)
hint->deleted = EINA_FALSE;
found = EINA_TRUE;
break;
}
}
if (found)
return EINA_TRUE;
return EINA_FALSE;
}
E_API Eina_Bool
e_hints_aux_hint_del_with_pixmap(E_Pixmap *cp, int32_t id)
{
E_Comp_Wl_Client_Data *cdata;
Eina_List *l, *ll;
E_Comp_Wl_Aux_Hint *hint;
int res = -1;
if (!cp) return EINA_FALSE;
cdata = (E_Comp_Wl_Client_Data*)e_pixmap_cdata_get(cp);
if (!cdata) return EINA_FALSE;
EINA_LIST_FOREACH_SAFE(cdata->aux_hint.hints, l, ll, hint)
{
if (hint->id == id)
{
hint->changed = EINA_TRUE;
hint->deleted = EINA_TRUE;
cdata->aux_hint.changed = 1;
res = hint->id;
break;
}
}
if (res == -1)
return EINA_FALSE;
return EINA_TRUE;
}
E_API const char *
e_hints_aux_hint_value_get_with_pixmap(E_Pixmap *cp, const char *name)
{
E_Comp_Wl_Client_Data *cdata;
Eina_List *l;
E_Comp_Wl_Aux_Hint *hint;
const char *res = NULL;
if (!cp) return NULL;
cdata = (E_Comp_Wl_Client_Data*)e_pixmap_cdata_get(cp);
if (!cdata) return NULL;
EINA_LIST_REVERSE_FOREACH(cdata->aux_hint.hints, l, hint)
{
if ((!hint->deleted) &&
(!strcmp(hint->hint, name)))
{
res = hint->val;
break;
}
}
return res;
}
#endif

View File

@ -59,5 +59,21 @@ extern E_API Ecore_X_Atom ATM_NETWM_SHOW_WINDOW_MENU;
extern E_API Ecore_X_Atom ATM_NETWM_PERFORM_BUTTON_ACTION;
extern E_API Ecore_X_Atom ATM_GTK_FRAME_EXTENTS;
#endif
#ifdef HAVE_WAYLAND
E_API const Eina_List * e_hints_aux_hint_supported_add(const char *hint);
E_API const Eina_List * e_hints_aux_hint_supported_del(const char *hint);
E_API const Eina_List * e_hints_aux_hint_supported_get(void);
E_API Eina_Bool e_hints_aux_hint_add(E_Client *ec, int32_t id, const char *name, const char *val);
E_API Eina_Bool e_hints_aux_hint_change(E_Client *ec, int32_t id, const char *val);
E_API Eina_Bool e_hints_aux_hint_del(E_Client *ec, int32_t id);
E_API const char * e_hints_aux_hint_value_get(E_Client *ec, const char *name);
E_API Eina_Bool e_hints_aux_hint_add_with_pixmap(E_Pixmap *cp, int32_t id, const char *name, const char *val);
E_API Eina_Bool e_hints_aux_hint_change_with_pixmap(E_Pixmap *cp, int32_t id, const char *val);
E_API Eina_Bool e_hints_aux_hint_del_with_pixmap(E_Pixmap *cp, int32_t id);
E_API const char * e_hints_aux_hint_value_get_with_pixmap(E_Pixmap *cp, const char *name);
#endif
#endif
#endif

View File

@ -2,6 +2,7 @@ protos = [
'@0@/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'.format(dir_wayland_protocols),
'../../protocol/session-recovery.xml',
'../../protocol/www.xml',
'../../protocol/efl-aux-hints.xml',
'@0@/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml'.format(dir_wayland_protocols),
'@0@/unstable/relative-pointer/relative-pointer-unstable-v1.xml'.format(dir_wayland_protocols),
'@0@/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'.format(dir_wayland_protocols),

View File

@ -395,6 +395,7 @@ if config_h.has('HAVE_WAYLAND') == true
'e_comp_wl_dmabuf.c',
'e_comp_wl.c',
'e_comp_wl_extensions.c',
'e_comp_wl_extensions_tizen.c',
wayland_proto_c,
wayland_proto_h
]

View File

@ -0,0 +1,39 @@
<protocol name="efl_aux_hints">
<interface name="efl_aux_hints" version="1">
<request name="add_aux_hint">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="int"/>
<arg name="hint" type="string"/>
<arg name="val" type="string"/>
</request>
<request name="change_aux_hint">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="int"/>
<arg name="val" type="string"/>
</request>
<request name="del_aux_hint">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="int"/>
</request>
<request name="get_supported_aux_hints">
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<event name="supported_aux_hints">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="hints" type="array"/>
<arg name="num_hints" type="uint"/>
</event>
<event name="allowed_aux_hint">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="int"/>
</event>
<event name="aux_message">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="key" type="string"/>
<arg name="val" type="string"/>
<arg name="options" type="array"/>
</event>
</interface>
</protocol>