From 7510e42c1b89867824685f837160702db31cb6de Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 20 May 2016 14:04:21 -0400 Subject: [PATCH] elm_win: implement v2 of teamwork api using window-based display protocol this adds support for wayland and makes teamwork integration trivial for any application @feature --- src/Makefile_Ecore_Wl2.am | 2 + src/Makefile_Elementary.am | 1 + src/lib/ecore_wl2/ecore_wl2_display.c | 6 + src/lib/ecore_wl2/ecore_wl2_private.h | 4 + src/lib/ecore_wl2/teamwork_protocol.c | 46 ++++++++ src/lib/ecore_wl2/teamwork_protocol.h | 128 +++++++++++++++++++++ src/lib/ecore_x/Ecore_X_Atoms.h | 11 ++ src/lib/ecore_x/ecore_x_atoms_decl.h | 23 +++- src/lib/elementary/elm_win.c | 98 ++++++++++++++++ src/lib/elementary/elm_win.eo | 37 ++++++ .../engines/wayland/ecore_evas_wayland_private.h | 2 +- 11 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 src/lib/ecore_wl2/teamwork_protocol.c create mode 100644 src/lib/ecore_wl2/teamwork_protocol.h diff --git a/src/Makefile_Ecore_Wl2.am b/src/Makefile_Ecore_Wl2.am index 9bf375e..66af6f8 100644 --- a/src/Makefile_Ecore_Wl2.am +++ b/src/Makefile_Ecore_Wl2.am @@ -8,6 +8,8 @@ installed_ecorewl2mainheadersdir = $(includedir)/ecore-wl2-@VMAJ@ dist_installed_ecorewl2mainheaders_DATA = lib/ecore_wl2/Ecore_Wl2.h lib_ecore_wl2_libecore_wl2_la_SOURCES = \ +lib/ecore_wl2/teamwork_protocol.c \ +lib/ecore_wl2/teamwork_protocol.h \ lib/ecore_wl2/session-recovery.h \ lib/ecore_wl2/session-recovery.c \ lib/ecore_wl2/subsurface-client-protocol.h \ diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 825a249..3d9a15f 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -641,6 +641,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_grid.c \ $(NULL) + lib_elementary_libelementary_la_CFLAGS = @ELEMENTARY_CFLAGS@ lib_elementary_libelementary_la_LIBADD = \ @ELEMENTARY_LIBS@ \ diff --git a/src/lib/ecore_wl2/ecore_wl2_display.c b/src/lib/ecore_wl2/ecore_wl2_display.c index 05b2247..cdc859c 100644 --- a/src/lib/ecore_wl2/ecore_wl2_display.c +++ b/src/lib/ecore_wl2/ecore_wl2_display.c @@ -166,6 +166,12 @@ _cb_global_add(void *data, struct wl_registry *registry, unsigned int id, const wl_registry_bind(registry, id, &zwp_e_session_recovery_interface, 1); } + else if (!strcmp(interface, "zwp_teamwork")) + { + ewd->wl.teamwork = + wl_registry_bind(registry, id, + &zwp_teamwork_interface, EFL_TEAMWORK_VERSION); + } else if (!strcmp(interface, "wl_output")) _ecore_wl2_output_add(ewd, id); else if (!strcmp(interface, "wl_seat")) diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h index be69725..680214a 100644 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -6,6 +6,9 @@ # include "Ecore_Input.h" # include "www-protocol.h" +#define EFL_TEAMWORK_VERSION 2 +# include "teamwork_protocol.h" + /* NB: Test if subsurface protocol is part of wayland code, if not then * include our own copy */ # ifndef WL_SUBSURFACE_ERROR_ENUM @@ -84,6 +87,7 @@ struct _Ecore_Wl2_Display struct xdg_shell *xdg_shell; struct www *www; struct zwp_e_session_recovery *session_recovery; + struct zwp_teamwork *teamwork; int compositor_version; } wl; diff --git a/src/lib/ecore_wl2/teamwork_protocol.c b/src/lib/ecore_wl2/teamwork_protocol.c new file mode 100644 index 0000000..baca23d --- /dev/null +++ b/src/lib/ecore_wl2/teamwork_protocol.c @@ -0,0 +1,46 @@ +#include +#include +#include "wayland-util.h" + +extern const struct wl_interface wl_surface_interface; + +static const struct wl_interface *types[] = { + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + NULL, + NULL, + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + NULL, + &wl_surface_interface, + NULL, + NULL, +}; + +static const struct wl_message zwp_teamwork_requests[] = { + { "preload_uri", "os", types + 0 }, + { "activate_uri", "osff", types + 2 }, + { "deactivate_uri", "os", types + 6 }, + { "open_uri", "os", types + 8 }, +}; + +static const struct wl_message zwp_teamwork_events[] = { + { "fetching_uri", "os", types + 10 }, + { "completed_uri", "osi", types + 12 }, + { "fetch_info", "osu", types + 15 }, +}; + +WL_EXPORT const struct wl_interface zwp_teamwork_interface = { + "zwp_teamwork", 2, + 4, zwp_teamwork_requests, + 3, zwp_teamwork_events, +}; + diff --git a/src/lib/ecore_wl2/teamwork_protocol.h b/src/lib/ecore_wl2/teamwork_protocol.h new file mode 100644 index 0000000..129aa2d --- /dev/null +++ b/src/lib/ecore_wl2/teamwork_protocol.h @@ -0,0 +1,128 @@ +#ifndef TEAMWORK_CLIENT_PROTOCOL_H +#define TEAMWORK_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wayland-client.h" + +struct wl_client; +struct wl_resource; + +struct wl_surface; +struct zwp_teamwork; + +extern const struct wl_interface zwp_teamwork_interface; + +struct zwp_teamwork_listener { + /** + * fetching_uri - (none) + * @surface: (none) + * @uri: (none) + */ + void (*fetching_uri)(void *data, + struct zwp_teamwork *zwp_teamwork, + struct wl_surface *surface, + const char *uri); + /** + * completed_uri - (none) + * @surface: (none) + * @uri: (none) + * @valid: 1 if uri can be displayed, else 0 + */ + void (*completed_uri)(void *data, + struct zwp_teamwork *zwp_teamwork, + struct wl_surface *surface, + const char *uri, + int32_t valid); + /** + * fetch_info - (none) + * @surface: (none) + * @uri: (none) + * @progress: percentage of download + */ + void (*fetch_info)(void *data, + struct zwp_teamwork *zwp_teamwork, + struct wl_surface *surface, + const char *uri, + uint32_t progress); +}; + +static inline int +zwp_teamwork_add_listener(struct zwp_teamwork *zwp_teamwork, + const struct zwp_teamwork_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_teamwork, + (void (**)(void)) listener, data); +} + +#define ZWP_TEAMWORK_PRELOAD_URI 0 +#define ZWP_TEAMWORK_ACTIVATE_URI 1 +#define ZWP_TEAMWORK_DEACTIVATE_URI 2 +#define ZWP_TEAMWORK_OPEN_URI 3 + +#define ZWP_TEAMWORK_PRELOAD_URI_SINCE_VERSION 1 +#define ZWP_TEAMWORK_ACTIVATE_URI_SINCE_VERSION 1 +#define ZWP_TEAMWORK_DEACTIVATE_URI_SINCE_VERSION 1 +#define ZWP_TEAMWORK_OPEN_URI_SINCE_VERSION 1 + +static inline void +zwp_teamwork_set_user_data(struct zwp_teamwork *zwp_teamwork, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_teamwork, user_data); +} + +static inline void * +zwp_teamwork_get_user_data(struct zwp_teamwork *zwp_teamwork) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_teamwork); +} + +static inline uint32_t +zwp_teamwork_get_version(struct zwp_teamwork *zwp_teamwork) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_teamwork); +} + +static inline void +zwp_teamwork_destroy(struct zwp_teamwork *zwp_teamwork) +{ + wl_proxy_destroy((struct wl_proxy *) zwp_teamwork); +} + +static inline void +zwp_teamwork_preload_uri(struct zwp_teamwork *zwp_teamwork, struct wl_surface *surface, const char *uri) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_teamwork, + ZWP_TEAMWORK_PRELOAD_URI, surface, uri); +} + +static inline void +zwp_teamwork_activate_uri(struct zwp_teamwork *zwp_teamwork, struct wl_surface *surface, const char *uri, wl_fixed_t x, wl_fixed_t y) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_teamwork, + ZWP_TEAMWORK_ACTIVATE_URI, surface, uri, x, y); +} + +static inline void +zwp_teamwork_deactivate_uri(struct zwp_teamwork *zwp_teamwork, struct wl_surface *surface, const char *uri) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_teamwork, + ZWP_TEAMWORK_DEACTIVATE_URI, surface, uri); +} + +static inline void +zwp_teamwork_open_uri(struct zwp_teamwork *zwp_teamwork, struct wl_surface *surface, const char *uri) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_teamwork, + ZWP_TEAMWORK_OPEN_URI, surface, uri); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/ecore_x/Ecore_X_Atoms.h b/src/lib/ecore_x/Ecore_X_Atoms.h index 3f1f14c..8fbe149 100644 --- a/src/lib/ecore_x/Ecore_X_Atoms.h +++ b/src/lib/ecore_x/Ecore_X_Atoms.h @@ -337,4 +337,15 @@ EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_AUX_HINT_ALLOWED; /**< @since 1.1 /* E keyrouter protocol */ EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_KEYROUTER_SUPPORTED; /**< @since 1.15 */ EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_KEYROUTER_WINDOW_KEYTABLE; /**< @since 1.15 */ + +/* Teamwork protocol */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PROPERTY; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PRELOAD; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_ACTIVATE; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_DEACTIVATE; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_OPEN; /**< @since 1.18 */ + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_COMPLETED; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PROGRESS; /**< @since 1.18 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_STARTED; /**< @since 1.18 */ #endif /* _ECORE_X_ATOMS_H */ diff --git a/src/lib/ecore_x/ecore_x_atoms_decl.h b/src/lib/ecore_x/ecore_x_atoms_decl.h index 1583025..64b5764 100644 --- a/src/lib/ecore_x/ecore_x_atoms_decl.h +++ b/src/lib/ecore_x/ecore_x_atoms_decl.h @@ -367,6 +367,17 @@ EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_AUX_HINT_ALLOWED = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_E_KEYROUTER_SUPPORTED = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_E_KEYROUTER_WINDOW_KEYTABLE = 0; +/* Teamwork protocol */ +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PROPERTY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PRELOAD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_ACTIVATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_DEACTIVATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_OPEN = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_COMPLETED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_PROGRESS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEAMWORK_STARTED = 0; + typedef struct _Atom_Item Atom_Item; struct _Atom_Item @@ -684,6 +695,16 @@ const Atom_Item atom_items[] = { "_E_WINDOW_AUX_HINT_SUPPORTED_LIST", &ECORE_X_ATOM_E_WINDOW_AUX_HINT_SUPPORTED_LIST }, { "_E_WINDOW_AUX_HINT_SUPPORT", &ECORE_X_ATOM_E_WINDOW_AUX_HINT_SUPPORT }, { "_E_WINDOW_AUX_HINT", &ECORE_X_ATOM_E_WINDOW_AUX_HINT }, - { "_E_WINDOW_AUX_HINT_ALLOWED", &ECORE_X_ATOM_E_WINDOW_AUX_HINT_ALLOWED } + { "_E_WINDOW_AUX_HINT_ALLOWED", &ECORE_X_ATOM_E_WINDOW_AUX_HINT_ALLOWED }, + + { "_TEAMWORK_PROP", &ECORE_X_ATOM_TEAMWORK_PROPERTY }, + { "_TEAMWORK_PRELOAD", &ECORE_X_ATOM_TEAMWORK_PRELOAD }, + { "_TEAMWORK_ACTIVATE", &ECORE_X_ATOM_TEAMWORK_ACTIVATE }, + { "_TEAMWORK_DEACTIVATE", &ECORE_X_ATOM_TEAMWORK_DEACTIVATE }, + { "_TEAMWORK_OPEN", &ECORE_X_ATOM_TEAMWORK_OPEN }, + + { "_TEAMWORK_COMPLETED", &ECORE_X_ATOM_TEAMWORK_COMPLETED }, + { "_TEAMWORK_PROGRESS", &ECORE_X_ATOM_TEAMWORK_PROGRESS }, + { "_TEAMWORK_STARTED", &ECORE_X_ATOM_TEAMWORK_STARTED }, }; diff --git a/src/lib/elementary/elm_win.c b/src/lib/elementary/elm_win.c index 9a49dc1..00ab00a 100644 --- a/src/lib/elementary/elm_win.c +++ b/src/lib/elementary/elm_win.c @@ -134,6 +134,7 @@ struct _Elm_Win_Data Ecore_Win32_Window *win; } win32; #endif + Eina_Stringshare *teamwork_uri; Eina_Bool deferred_resize_job; Ecore_Job *deferred_child_eval_job; @@ -2013,6 +2014,7 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd) ecore_job_del(sd->deferred_child_eval_job); eina_stringshare_del(sd->shot.info); ecore_timer_del(sd->shot.timer); + eina_stringshare_replace(&sd->teamwork_uri, NULL); #ifdef HAVE_ELEMENTARY_X ecore_event_handler_del(sd->x.client_message_handler); @@ -6012,4 +6014,100 @@ elm_win_quickpanel_zone_get(const Evas_Object *obj) return 0; } +static EOLIAN void +_elm_win_teamwork_uri_preload(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, const char *uri) +{ +#ifdef HAVE_ELEMENTARY_X + if (sd->x.xwin) + { + ecore_x_window_prop_string_set(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_PROPERTY, uri); + ecore_x_client_message32_send(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_PRELOAD, + ECORE_X_EVENT_MASK_WINDOW_MANAGE | ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE, EFL_TEAMWORK_VERSION, 0, 0, 0, 0); + } +#endif +#ifdef HAVE_ELEMENTARY_WL2 + if (sd->wl.win) + { + Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(sd->wl.win); + if (ewd->wl.teamwork) + zwp_teamwork_preload_uri(ewd->wl.teamwork, ecore_wl2_window_surface_get(sd->wl.win), uri); + } +#endif + eina_stringshare_replace(&sd->teamwork_uri, uri); +} + +static EOLIAN void +_elm_win_teamwork_uri_show(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, const char *uri) +{ + int x, y; + + EINA_SAFETY_ON_NULL_RETURN(uri); + if (eina_streq(uri, sd->teamwork_uri)) return; + + evas_pointer_canvas_xy_get(sd->evas, &x, &y); +#ifdef HAVE_ELEMENTARY_X + if (sd->x.xwin) + { + ecore_x_window_prop_string_set(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_PROPERTY, uri); + ecore_x_client_message32_send(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_ACTIVATE, + ECORE_X_EVENT_MASK_WINDOW_MANAGE | ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE, EFL_TEAMWORK_VERSION, x, y, 0, 0); + } +#endif +#ifdef HAVE_ELEMENTARY_WL2 + if (sd->wl.win) + { + Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(sd->wl.win); + if (ewd->wl.teamwork) + zwp_teamwork_activate_uri(ewd->wl.teamwork, ecore_wl2_window_surface_get(sd->wl.win), + uri, wl_fixed_from_int(x), wl_fixed_from_int(y)); + } +#endif + eina_stringshare_replace(&sd->teamwork_uri, uri); +} + +static EOLIAN void +_elm_win_teamwork_uri_hide(Eo *obj EINA_UNUSED, Elm_Win_Data *sd) +{ + if (!sd->teamwork_uri) return; +#ifdef HAVE_ELEMENTARY_X + if (sd->x.xwin) + { + ecore_x_window_prop_string_set(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_PROPERTY, sd->teamwork_uri); + ecore_x_client_message32_send(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_DEACTIVATE, + ECORE_X_EVENT_MASK_WINDOW_MANAGE | ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE, EFL_TEAMWORK_VERSION, 0, 0, 0, 0); + } +#endif +#ifdef HAVE_ELEMENTARY_WL2 + if (sd->wl.win) + { + Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(sd->wl.win); + if (ewd->wl.teamwork) + zwp_teamwork_deactivate_uri(ewd->wl.teamwork, ecore_wl2_window_surface_get(sd->wl.win), sd->teamwork_uri); + } +#endif + eina_stringshare_replace(&sd->teamwork_uri, NULL); +} + +static EOLIAN void +_elm_win_teamwork_uri_open(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, const char *uri) +{ + EINA_SAFETY_ON_NULL_RETURN(uri); +#ifdef HAVE_ELEMENTARY_X + if (sd->x.xwin) + { + ecore_x_window_prop_string_set(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_PROPERTY, uri); + ecore_x_client_message32_send(sd->x.xwin, ECORE_X_ATOM_TEAMWORK_OPEN, + ECORE_X_EVENT_MASK_WINDOW_MANAGE | ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE, EFL_TEAMWORK_VERSION, 0, 0, 0, 0); + } +#endif +#ifdef HAVE_ELEMENTARY_WL2 + if (sd->wl.win) + { + Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(sd->wl.win); + if (ewd->wl.teamwork) + zwp_teamwork_open_uri(ewd->wl.teamwork, ecore_wl2_window_surface_get(sd->wl.win), uri); + } +#endif +} + #include "elm_win.eo.c" diff --git a/src/lib/elementary/elm_win.eo b/src/lib/elementary/elm_win.eo index 469d9df..69571bf 100644 --- a/src/lib/elementary/elm_win.eo +++ b/src/lib/elementary/elm_win.eo @@ -1132,6 +1132,43 @@ class Elm.Win (Elm.Widget, Elm.Interface.Atspi.Window, @in not_modifiers: Evas.Modifier_Mask; [[This is for the keymask feature. Currently this feature is not supported.]] } } + teamwork_uri_preload { + [[Notify the compositor that a uri should be preloaded + @since 1.18 + ]] + params { + @in uri: const(char)*; [[This is the uri to notify with]] + } + } + teamwork_uri_show { + [[Notify the compositor that a uri should be displayed + + Sends the current mouse coordinates as a hint for displaying the + related uri in the compositor. + @since 1.18 + ]] + params { + @in uri: const(char)*; [[This is the uri to notify with]] + } + } + teamwork_uri_hide { + [[Notify the compositor that a uri should be hidden + + Hides any uri-related media displayed in the compositor through + previous \@ref elm_win_teamwork_uri_show request + @since 1.18 + ]] + } + teamwork_uri_open { + [[Notify the compositor that a uri should be opened + + Use the compositor's default application to open a uri + @since 1.18 + ]] + params { + @in uri: const(char)*; [[This is the uri to open]] + } + } } implements { class.constructor; diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h index 49d02c4..06b188d 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h @@ -20,10 +20,10 @@ #include #include #include -#include "ecore_wl2_private.h" #include #endif +#include "ecore_wl2_private.h" #include "ecore_private.h" #include "ecore_evas_private.h" #include "ecore_evas_wayland.h" -- 2.7.4