summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2016-01-25 18:43:14 -0500
committerMike Blumenkrantz <zmike@osg.samsung.com>2017-06-26 12:53:28 -0400
commit6272b85b4920c1e752c1e0f6714fc3c2243801ff (patch)
tree542901bbdad34cccb667fe9673e25eea26278803
parent63f3fe949cb4f2169a7b9ba74a96df701617b1de (diff)
implement action routing for wayland clientsdevs/discomfitor/action_route
this allows a wayland client to request that a given action name be bound to the requested surface using a mode to restrict activation of the binding modes include: * shared - activated when any surface from the client has focus * topmost - activated when the requested surface has focus and is the topmost client * exclusive - activated when the requested surface has focus; blocks other action routes #SamsungFeatures Signed-off-by: Mike Blumenkrantz <zmike@osg.samsung.com>
-rw-r--r--src/bin/Makefile.mk4
-rw-r--r--src/bin/e_bindings.c37
-rw-r--r--src/bin/e_bindings.h1
-rw-r--r--src/bin/e_comp_wl.h4
-rw-r--r--src/bin/e_comp_wl_extensions.c224
-rw-r--r--src/protocol/action_route.xml49
6 files changed, 304 insertions, 15 deletions
diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk
index 6106b22f2..aa9e2383c 100644
--- a/src/bin/Makefile.mk
+++ b/src/bin/Makefile.mk
@@ -444,6 +444,8 @@ src/bin/generated/www-protocol.c \
444src/bin/generated/www-server-protocol.h \ 444src/bin/generated/www-server-protocol.h \
445src/bin/generated/screenshooter-protocol.c \ 445src/bin/generated/screenshooter-protocol.c \
446src/bin/generated/screenshooter-server-protocol.h \ 446src/bin/generated/screenshooter-server-protocol.h \
447src/bin/generated/action_route-protocol.c \
448src/bin/generated/action_route-server-protocol.h \
447src/bin/generated/xdg-foreign-unstable-v1-protocol.c \ 449src/bin/generated/xdg-foreign-unstable-v1-protocol.c \
448src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \ 450src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \
449src/bin/generated/relative-pointer-unstable-v1-protocol.c \ 451src/bin/generated/relative-pointer-unstable-v1-protocol.c \
@@ -456,6 +458,8 @@ src/bin/e_comp_wl_extensions.c: \
456 src/bin/generated/session-recovery-server-protocol.h \ 458 src/bin/generated/session-recovery-server-protocol.h \
457 src/bin/generated/xdg-foreign-unstable-v1-protocol.c \ 459 src/bin/generated/xdg-foreign-unstable-v1-protocol.c \
458 src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \ 460 src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h \
461 src/bin/generated/action_route-protocol.c \
462 src/bin/generated/action_route-server-protocol.h \
459 src/bin/generated/relative-pointer-unstable-v1-protocol.c \ 463 src/bin/generated/relative-pointer-unstable-v1-protocol.c \
460 src/bin/generated/relative-pointer-unstable-v1-server-protocol.h \ 464 src/bin/generated/relative-pointer-unstable-v1-server-protocol.h \
461 src/bin/generated/pointer-constraints-unstable-v1-protocol.c \ 465 src/bin/generated/pointer-constraints-unstable-v1-protocol.c \
diff --git a/src/bin/e_bindings.c b/src/bin/e_bindings.c
index 79b0fdfe9..a21df8637 100644
--- a/src/bin/e_bindings.c
+++ b/src/bin/e_bindings.c
@@ -7,7 +7,6 @@ static void _e_bindings_edge_free(E_Binding_Edge *bind);
7static void _e_bindings_signal_free(E_Binding_Signal *bind); 7static void _e_bindings_signal_free(E_Binding_Signal *bind);
8static void _e_bindings_wheel_free(E_Binding_Wheel *bind); 8static void _e_bindings_wheel_free(E_Binding_Wheel *bind);
9static void _e_bindings_acpi_free(E_Binding_Acpi *bind); 9static void _e_bindings_acpi_free(E_Binding_Acpi *bind);
10static int _e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt);
11static E_Binding_Modifier _e_bindings_modifiers(unsigned int modifiers); 10static E_Binding_Modifier _e_bindings_modifiers(unsigned int modifiers);
12static Eina_Bool _e_bindings_edge_cb_timer(void *data); 11static Eina_Bool _e_bindings_edge_cb_timer(void *data);
13 12
@@ -22,6 +21,8 @@ static Eina_List *acpi_bindings = NULL;
22 21
23static unsigned int bindings_disabled = 0; 22static unsigned int bindings_disabled = 0;
24 23
24EINTERN E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **);
25
25typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data; 26typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data;
26 27
27struct _E_Binding_Edge_Data 28struct _E_Binding_Edge_Data
@@ -382,7 +383,7 @@ e_bindings_mouse_grab(E_Binding_Context ctxt, Ecore_X_Window win)
382 EINA_LIST_FOREACH(mouse_bindings, l, binding) 383 EINA_LIST_FOREACH(mouse_bindings, l, binding)
383 { 384 {
384 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue; 385 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue;
385 if (_e_bindings_context_match(binding->ctxt, ctxt)) 386 if (e_bindings_context_match(binding->ctxt, ctxt))
386 { 387 {
387#ifndef HAVE_WAYLAND_ONLY 388#ifndef HAVE_WAYLAND_ONLY
388 ecore_x_window_button_grab(win, binding->button, 389 ecore_x_window_button_grab(win, binding->button,
@@ -408,7 +409,7 @@ e_bindings_mouse_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
408 EINA_LIST_FOREACH(mouse_bindings, l, binding) 409 EINA_LIST_FOREACH(mouse_bindings, l, binding)
409 { 410 {
410 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue; 411 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue;
411 if (_e_bindings_context_match(binding->ctxt, ctxt)) 412 if (e_bindings_context_match(binding->ctxt, ctxt))
412 { 413 {
413#ifndef HAVE_WAYLAND_ONLY 414#ifndef HAVE_WAYLAND_ONLY
414 ecore_x_window_button_ungrab(win, binding->button, 415 ecore_x_window_button_ungrab(win, binding->button,
@@ -444,7 +445,7 @@ e_bindings_mouse_button_find(E_Binding_Context ctxt, E_Binding_Event_Mouse_Butto
444 if ((binding->button == (int)ev->button) && 445 if ((binding->button == (int)ev->button) &&
445 ((binding->any_mod) || (binding->mod == ev->modifiers))) 446 ((binding->any_mod) || (binding->mod == ev->modifiers)))
446 { 447 {
447 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 448 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
448 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 449 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
449 act = e_action_find(binding->action); 450 act = e_action_find(binding->action);
450 if (bind_ret) *bind_ret = binding; 451 if (bind_ret) *bind_ret = binding;
@@ -620,7 +621,7 @@ e_bindings_key_grab(E_Binding_Context ctxt, Ecore_X_Window win)
620 621
621 EINA_LIST_FOREACH(key_bindings, l, binding) 622 EINA_LIST_FOREACH(key_bindings, l, binding)
622 { 623 {
623 if (_e_bindings_context_match(binding->ctxt, ctxt)) 624 if (e_bindings_context_match(binding->ctxt, ctxt))
624 { 625 {
625 if (e_bindings_key_allowed(binding->key)) 626 if (e_bindings_key_allowed(binding->key))
626 { 627 {
@@ -644,7 +645,7 @@ e_bindings_key_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
644 645
645 EINA_LIST_FOREACH(key_bindings, l, binding) 646 EINA_LIST_FOREACH(key_bindings, l, binding)
646 { 647 {
647 if (_e_bindings_context_match(binding->ctxt, ctxt)) 648 if (e_bindings_context_match(binding->ctxt, ctxt))
648 { 649 {
649 if (e_bindings_key_allowed(binding->key)) 650 if (e_bindings_key_allowed(binding->key))
650 { 651 {
@@ -701,12 +702,18 @@ e_bindings_key_event_find(E_Binding_Context ctxt, Ecore_Event_Key *ev, E_Binding
701 E_Action *act = NULL; 702 E_Action *act = NULL;
702 703
703 mod = _e_bindings_modifiers(ev->modifiers); 704 mod = _e_bindings_modifiers(ev->modifiers);
705 if (e_binding_key_list_cb)
706 {
707 act = e_binding_key_list_cb(ctxt, ev, mod, bind_ret);
708 if (act) return act;
709 if (bind_ret) *bind_ret = NULL;
710 }
704 EINA_LIST_FOREACH(key_bindings, l, binding) 711 EINA_LIST_FOREACH(key_bindings, l, binding)
705 { 712 {
706 if ((binding->key) && ((!strcmp(binding->key, ev->key)) || (!strcmp(binding->key, ev->keyname))) && 713 if ((binding->key) && ((!strcmp(binding->key, ev->key)) || (!strcmp(binding->key, ev->keyname))) &&
707 ((binding->any_mod) || (binding->mod == mod))) 714 ((binding->any_mod) || (binding->mod == mod)))
708 { 715 {
709 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 716 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
710 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 717 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
711 act = e_action_find(binding->action); 718 act = e_action_find(binding->action);
712 if (bind_ret) *bind_ret = binding; 719 if (bind_ret) *bind_ret = binding;
@@ -866,7 +873,7 @@ e_bindings_edge_event_find(E_Binding_Context ctxt, E_Event_Zone_Edge *ev, Eina_B
866 ((binding->drag_only == ev->drag) || ev->drag) && 873 ((binding->drag_only == ev->drag) || ev->drag) &&
867 ((binding->any_mod) || (binding->mod == mod))) 874 ((binding->any_mod) || (binding->mod == mod)))
868 { 875 {
869 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 876 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
870 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 877 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
871 act = e_action_find(binding->action); 878 act = e_action_find(binding->action);
872 if (bind_ret) *bind_ret = binding; 879 if (bind_ret) *bind_ret = binding;
@@ -1037,7 +1044,7 @@ e_bindings_signal_find(E_Binding_Context ctxt, const char *sig, const char *src,
1037 (e_util_glob_match(src, binding->src)) && 1044 (e_util_glob_match(src, binding->src)) &&
1038 ((binding->any_mod) || (binding->mod == mod))) 1045 ((binding->any_mod) || (binding->mod == mod)))
1039 { 1046 {
1040 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 1047 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
1041 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 1048 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
1042 act = e_action_find(binding->action); 1049 act = e_action_find(binding->action);
1043 if (bind_ret) *bind_ret = binding; 1050 if (bind_ret) *bind_ret = binding;
@@ -1120,7 +1127,7 @@ e_bindings_wheel_grab(E_Binding_Context ctxt, Ecore_X_Window win)
1120 EINA_LIST_FOREACH(wheel_bindings, l, binding) 1127 EINA_LIST_FOREACH(wheel_bindings, l, binding)
1121 { 1128 {
1122 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue; 1129 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue;
1123 if (_e_bindings_context_match(binding->ctxt, ctxt)) 1130 if (e_bindings_context_match(binding->ctxt, ctxt))
1124 { 1131 {
1125 int button = 0; 1132 int button = 0;
1126 1133
@@ -1160,7 +1167,7 @@ e_bindings_wheel_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
1160 EINA_LIST_FOREACH(wheel_bindings, l, binding) 1167 EINA_LIST_FOREACH(wheel_bindings, l, binding)
1161 { 1168 {
1162 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue; 1169 if (binding->ctxt == E_BINDING_CONTEXT_ANY) continue;
1163 if (_e_bindings_context_match(binding->ctxt, ctxt)) 1170 if (e_bindings_context_match(binding->ctxt, ctxt))
1164 { 1171 {
1165 int button = 0; 1172 int button = 0;
1166 1173
@@ -1214,7 +1221,7 @@ e_bindings_wheel_find(E_Binding_Context ctxt, E_Binding_Event_Wheel *ev, E_Bindi
1214 (((binding->z < 0) && (ev->z < 0)) || ((binding->z > 0) && (ev->z > 0))) && 1221 (((binding->z < 0) && (ev->z < 0)) || ((binding->z > 0) && (ev->z > 0))) &&
1215 ((binding->any_mod) || (binding->mod == ev->modifiers))) 1222 ((binding->any_mod) || (binding->mod == ev->modifiers)))
1216 { 1223 {
1217 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 1224 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
1218 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 1225 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
1219 act = e_action_find(binding->action); 1226 act = e_action_find(binding->action);
1220 if (bind_ret) *bind_ret = binding; 1227 if (bind_ret) *bind_ret = binding;
@@ -1321,7 +1328,7 @@ e_bindings_acpi_find(E_Binding_Context ctxt, E_Event_Acpi *ev, E_Binding_Acpi **
1321 /* binding status is set to something, compare event status */ 1328 /* binding status is set to something, compare event status */
1322 if (binding->status != ev->status) continue; 1329 if (binding->status != ev->status) continue;
1323 } 1330 }
1324 if (!_e_bindings_context_match(binding->ctxt, ctxt)) continue; 1331 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
1325 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue; 1332 if (act && (binding->ctxt == E_BINDING_CONTEXT_ANY)) continue;
1326 act = e_action_find(binding->action); 1333 act = e_action_find(binding->action);
1327 if (bind_ret) *bind_ret = binding; 1334 if (bind_ret) *bind_ret = binding;
@@ -1442,8 +1449,8 @@ _e_bindings_acpi_free(E_Binding_Acpi *binding)
1442 E_FREE(binding); 1449 E_FREE(binding);
1443} 1450}
1444 1451
1445static int 1452E_API int
1446_e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt) 1453e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt)
1447{ 1454{
1448 if (bctxt == E_BINDING_CONTEXT_ANY && 1455 if (bctxt == E_BINDING_CONTEXT_ANY &&
1449 !(ctxt == E_BINDING_CONTEXT_ZONE)) return 1; 1456 !(ctxt == E_BINDING_CONTEXT_ZONE)) return 1;
diff --git a/src/bin/e_bindings.h b/src/bin/e_bindings.h
index 0c71c1055..8bc6ef43d 100644
--- a/src/bin/e_bindings.h
+++ b/src/bin/e_bindings.h
@@ -202,6 +202,7 @@ E_API void e_bindings_evas_event_mouse_wheel_convert(const Evas_Event_Mouse_Whee
202E_API void e_bindings_ecore_event_mouse_button_convert(const Ecore_Event_Mouse_Button *ev, E_Binding_Event_Mouse_Button *event); 202E_API void e_bindings_ecore_event_mouse_button_convert(const Ecore_Event_Mouse_Button *ev, E_Binding_Event_Mouse_Button *event);
203E_API void e_bindings_ecore_event_mouse_wheel_convert(const Ecore_Event_Mouse_Wheel *ev, E_Binding_Event_Wheel *event); 203E_API void e_bindings_ecore_event_mouse_wheel_convert(const Ecore_Event_Mouse_Wheel *ev, E_Binding_Event_Wheel *event);
204 204
205E_API int e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt);
205 206
206E_API void e_bindings_disabled_set(Eina_Bool disabled); 207E_API void e_bindings_disabled_set(Eina_Bool disabled);
207#endif 208#endif
diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h
index f52830617..b43040c57 100644
--- a/src/bin/e_comp_wl.h
+++ b/src/bin/e_comp_wl.h
@@ -132,6 +132,10 @@ typedef struct E_Comp_Wl_Extension_Data
132 struct wl_global *global; 132 struct wl_global *global;
133 Eina_Hash *constraints; 133 Eina_Hash *constraints;
134 } zwp_pointer_constraints_v1; 134 } zwp_pointer_constraints_v1;
135 struct
136 {
137 struct wl_global *global;
138 } action_route;
135} E_Comp_Wl_Extension_Data; 139} E_Comp_Wl_Extension_Data;
136 140
137struct _E_Comp_Wl_Data 141struct _E_Comp_Wl_Data
diff --git a/src/bin/e_comp_wl_extensions.c b/src/bin/e_comp_wl_extensions.c
index 3e9d40920..5816fbf82 100644
--- a/src/bin/e_comp_wl_extensions.c
+++ b/src/bin/e_comp_wl_extensions.c
@@ -9,6 +9,7 @@
9#include "xdg-foreign-unstable-v1-server-protocol.h" 9#include "xdg-foreign-unstable-v1-server-protocol.h"
10#include "relative-pointer-unstable-v1-server-protocol.h" 10#include "relative-pointer-unstable-v1-server-protocol.h"
11#include "pointer-constraints-unstable-v1-server-protocol.h" 11#include "pointer-constraints-unstable-v1-server-protocol.h"
12#include "action_route-server-protocol.h"
12 13
13/* mutter uses 32, seems reasonable */ 14/* mutter uses 32, seems reasonable */
14#define HANDLE_LEN 32 15#define HANDLE_LEN 32
@@ -631,6 +632,218 @@ _e_comp_wl_zwp_pointer_constraints_v1_confine_pointer(struct wl_client *client,
631} 632}
632 633
633///////////////////////////////////////////////////////// 634/////////////////////////////////////////////////////////
635extern E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **);
636static Eina_Hash *key_bindings;
637
638typedef struct Action_Route
639{
640 union
641 {
642 E_Binding_Key key;
643 } binding;
644 uint32_t mode;
645 uint32_t state;
646 struct wl_resource *res;
647 struct wl_resource *surface;
648} Action_Route;
649
650static E_Action *
651_action_route_key_list_cb(E_Binding_Context ctxt, Ecore_Event_Key *ev, E_Binding_Modifier mod, E_Binding_Key **bind_ret)
652{
653 Eina_List *l, *ll;
654 Action_Route *ar;
655 E_Binding_Key *binding;
656
657 if (bind_ret) *bind_ret = NULL;
658 l = eina_hash_find(key_bindings, ev->key);
659 EINA_LIST_FOREACH(l, ll, ar)
660 {
661 E_Client *ec;
662
663 if (ar->state != ACTION_ROUTE_GRAB_STATE_ACTIVE) break;
664 binding = &ar->binding.key;
665 if ((!binding->any_mod) && (binding->mod != mod)) continue;
666 if (!e_bindings_context_match(binding->ctxt, ctxt)) continue;
667 ec = wl_resource_get_user_data(ar->surface);
668 if (!ec) continue;//wtf?
669 if (bind_ret) *bind_ret = binding;
670 switch (ar->mode)
671 {
672 /* if exclusive client has grab, activate. otherwise, no actions allowed */
673 case ACTION_ROUTE_MODE_EXCLUSIVE:
674 if (!ec->focused) return NULL;
675 return e_action_find(binding->action);
676 /* all surfaces for wl_client share the grab; if any surface has focus, activate. */
677 case ACTION_ROUTE_MODE_FOCUS_SHARED:
678 {
679 struct wl_client *client;
680
681 client = wl_resource_get_client(ar->surface);
682 if (!e_client_focused_get()) continue;
683 if (wl_resource_get_client(e_client_focused_get()->comp_data->surface) != client)
684 continue;
685 return e_action_find(binding->action);
686 }
687 /* only activate if surface has focus and is on top */
688 case ACTION_ROUTE_MODE_FOCUS_TOPMOST:
689 if (!ec->focused) continue;
690 {
691 E_Client *aec;
692 Eina_Bool valid = EINA_TRUE;
693
694 for (aec = e_client_above_get(ec); aec; aec = e_client_above_get(aec))
695 {
696 if (aec->layer > E_LAYER_CLIENT_PRIO)
697 return e_action_find(binding->action);
698 if (evas_object_visible_get(aec->frame))
699 {
700 valid = EINA_FALSE;
701 break;
702 }
703 }
704 if (valid)
705 return e_action_find(binding->action);
706 continue;
707 }
708 }
709 }
710 if (bind_ret) *bind_ret = NULL;
711 return NULL;
712}
713
714static Eina_Bool
715_action_route_is_allowed(const char *action, const char *params)
716{
717 /* FIXME: allow 1-2 bindings maybe */
718 return EINA_FALSE;
719}
720
721static Eina_Bool
722_action_route_can_override(const E_Binding_Key *binding)
723{
724 if (!binding) return EINA_TRUE;
725 /* FIXME: determine full list of overridable binding contexts */
726 if ((binding->ctxt == E_BINDING_CONTEXT_ANY) ||
727 (binding->ctxt == E_BINDING_CONTEXT_WINLIST))
728 return EINA_TRUE;
729 return EINA_FALSE;
730}
731
732static void
733_e_comp_wl_action_route_grab_del(struct wl_resource *resource)
734{
735 Eina_List *l, *ll;
736 Action_Route *ar;
737 Eina_Bool update;
738
739 /* FIXME: delete active actions? */
740 ar = wl_resource_get_user_data(resource);
741 if (!ar) return;
742 eina_hash_list_remove(key_bindings, ar->binding.key.key, ar);
743 update = (ar->mode == ACTION_ROUTE_MODE_EXCLUSIVE) && (ar->state == ACTION_ROUTE_GRAB_STATE_ACTIVE);
744 l = eina_hash_find(key_bindings, ar->binding.key.key);
745 eina_stringshare_del(ar->binding.key.key);
746 eina_stringshare_del(ar->binding.key.action);
747 eina_stringshare_del(ar->binding.key.params);
748 free(ar);
749 if (!update) return;
750 EINA_LIST_FOREACH(l, ll, ar)
751 {
752 /* all action routes are active until an exclusive or active grab has been reached */
753 if (ar->state == ACTION_ROUTE_GRAB_STATE_ACTIVE) break;//futureproofing...
754 ar->state = ACTION_ROUTE_GRAB_STATE_ACTIVE;
755 action_route_grab_send_status(ar->res, ar->state);
756 if (ar->mode == ACTION_ROUTE_MODE_EXCLUSIVE) break;
757 }
758}
759
760static void
761_e_comp_wl_action_route_grab_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
762{
763 _e_comp_wl_action_route_grab_del(resource);
764}
765
766static const struct action_route_grab_interface _e_action_route_grab_interface =
767{
768 _e_comp_wl_action_route_grab_destroy,
769};
770
771static void
772_e_comp_wl_action_route_grab_key(struct wl_client *client, struct wl_resource *resource EINA_UNUSED,
773 uint32_t id,
774 struct wl_resource *surface,
775 const char *key,
776 uint32_t mode,
777 uint32_t modifiers,
778 const char *action,
779 const char *params)
780{
781 struct wl_resource *rt;
782 E_Binding_Key *binding;
783 Eina_List *l, *ll;
784 Action_Route *ar, *lar;
785 E_Binding_Context ctxt = E_BINDING_CONTEXT_WINDOW;
786
787 rt = wl_resource_create(client, &action_route_grab_interface, 1, id);
788 if (!rt)
789 {
790 ERR("Could not create action route");
791 wl_client_post_no_memory(client);
792 return;
793 }
794 wl_resource_set_implementation(rt, &_e_action_route_grab_interface, NULL,
795 _e_comp_wl_action_route_grab_del);
796 binding = e_bindings_key_find(key, modifiers, 0);
797 if ((!_action_route_is_allowed(action, params)) || (!_action_route_can_override(binding)))
798 {
799 action_route_grab_send_status(rt, ACTION_ROUTE_GRAB_STATE_REJECTED);
800 wl_resource_destroy(rt);
801 return;
802 }
803 ar = E_NEW(Action_Route, 1);
804 ar->mode = mode;
805 ar->res = rt;
806 ar->surface = surface;
807 binding = &ar->binding.key;
808 switch (mode)
809 {
810 case ACTION_ROUTE_MODE_EXCLUSIVE:
811 ctxt = E_BINDING_CONTEXT_ANY;
812 break;
813 case ACTION_ROUTE_MODE_FOCUS_SHARED:
814 ctxt = E_BINDING_CONTEXT_WINDOW;
815 break;
816 case ACTION_ROUTE_MODE_FOCUS_TOPMOST:
817 ctxt = E_BINDING_CONTEXT_WINDOW;
818 break;
819 }
820 binding->ctxt = ctxt;
821 binding->key = eina_stringshare_add(key);
822 binding->mod = modifiers;
823 binding->any_mod = 0;
824 binding->action = eina_stringshare_add(action);
825 binding->params = eina_stringshare_add(params);
826 wl_resource_set_user_data(rt, ar);
827 l = eina_hash_find(key_bindings, key);
828 EINA_LIST_FOREACH(l, ll, lar)
829 {
830 if (lar->mode == ACTION_ROUTE_MODE_EXCLUSIVE)
831 {
832 ar->state = ACTION_ROUTE_GRAB_STATE_QUEUED;
833 continue;
834 }
835 ar->state = ACTION_ROUTE_GRAB_STATE_ACTIVE;
836 if (ar->mode == ACTION_ROUTE_MODE_EXCLUSIVE)
837 l = eina_list_prepend_relative(l, ar, ll);
838 else
839 l = eina_list_append(l, ar);
840 break;
841 }
842 eina_hash_set(key_bindings, key, l);
843 action_route_grab_send_status(ar->res, ar->state);
844}
845
846/////////////////////////////////////////////////////////
634 847
635static const struct zwp_e_session_recovery_interface _e_session_recovery_interface = 848static const struct zwp_e_session_recovery_interface _e_session_recovery_interface =
636{ 849{
@@ -674,6 +887,11 @@ static const struct zwp_pointer_constraints_v1_interface _e_zwp_pointer_constrai
674 _e_comp_wl_zwp_pointer_constraints_v1_confine_pointer, 887 _e_comp_wl_zwp_pointer_constraints_v1_confine_pointer,
675}; 888};
676 889
890static const struct action_route_interface _e_action_route_interface =
891{
892 _e_comp_wl_action_route_grab_key,
893};
894
677#define GLOBAL_BIND_CB(NAME, IFACE, ...) \ 895#define GLOBAL_BIND_CB(NAME, IFACE, ...) \
678static void \ 896static void \
679_e_comp_wl_##NAME##_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id) \ 897_e_comp_wl_##NAME##_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id) \
@@ -688,6 +906,7 @@ _e_comp_wl_##NAME##_cb_bind(struct wl_client *client, void *data EINA_UNUSED, ui
688 }\ 906 }\
689\ 907\
690 wl_resource_set_implementation(res, &_e_##NAME##_interface, NULL, NULL);\ 908 wl_resource_set_implementation(res, &_e_##NAME##_interface, NULL, NULL);\
909 __VA_ARGS__ \
691} 910}
692 911
693GLOBAL_BIND_CB(session_recovery, zwp_e_session_recovery_interface) 912GLOBAL_BIND_CB(session_recovery, zwp_e_session_recovery_interface)
@@ -697,6 +916,10 @@ GLOBAL_BIND_CB(zxdg_exporter_v1, zxdg_exporter_v1_interface)
697GLOBAL_BIND_CB(zxdg_importer_v1, zxdg_importer_v1_interface) 916GLOBAL_BIND_CB(zxdg_importer_v1, zxdg_importer_v1_interface)
698GLOBAL_BIND_CB(zwp_relative_pointer_manager_v1, zwp_relative_pointer_manager_v1_interface) 917GLOBAL_BIND_CB(zwp_relative_pointer_manager_v1, zwp_relative_pointer_manager_v1_interface)
699GLOBAL_BIND_CB(zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_interface) 918GLOBAL_BIND_CB(zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_interface)
919GLOBAL_BIND_CB(action_route, action_route_interface,
920 e_binding_key_list_cb = _action_route_key_list_cb;
921 key_bindings = eina_hash_string_superfast_new(NULL);
922)
700 923
701 924
702#define GLOBAL_CREATE_OR_RETURN(NAME, IFACE, VERSION) \ 925#define GLOBAL_CREATE_OR_RETURN(NAME, IFACE, VERSION) \
@@ -744,6 +967,7 @@ e_comp_wl_extensions_init(void)
744 GLOBAL_CREATE_OR_RETURN(zwp_relative_pointer_manager_v1, zwp_relative_pointer_manager_v1_interface, 1); 967 GLOBAL_CREATE_OR_RETURN(zwp_relative_pointer_manager_v1, zwp_relative_pointer_manager_v1_interface, 1);
745 GLOBAL_CREATE_OR_RETURN(zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_interface, 1); 968 GLOBAL_CREATE_OR_RETURN(zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_interface, 1);
746 e_comp_wl->extensions->zwp_pointer_constraints_v1.constraints = eina_hash_pointer_new(NULL); 969 e_comp_wl->extensions->zwp_pointer_constraints_v1.constraints = eina_hash_pointer_new(NULL);
970 GLOBAL_CREATE_OR_RETURN(action_route, action_route_interface, 1);
747 971
748 ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _dmabuf_add, NULL); 972 ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _dmabuf_add, NULL);
749 973
diff --git a/src/protocol/action_route.xml b/src/protocol/action_route.xml
new file mode 100644
index 000000000..5f2996aac
--- /dev/null
+++ b/src/protocol/action_route.xml
@@ -0,0 +1,49 @@
1<protocol name="zwp_action_route">
2 <interface name="action_route" version="1">
3 <enum name="mode">
4 <description summary="types of state on the surface">
5 </description>
6 <entry name="focus_shared" value="1" summary="Activatable by any surface if its wl_client has focus">
7 </entry>
8 <entry name="focus_topmost" value="2" summary="Activatable by topmost surface with focus">
9 <description summary="Restricts activation to only the top-most client"/>
10 </entry>
11 <entry name="exclusive" value="3" summary="Activatable by one surface at any time">
12 <description summary="Allows activation for exactly one client at all times"/>
13 </entry>
14 </enum>
15 <enum name="modifiers">
16 <entry name="shift" value="1"></entry>
17 <entry name="control" value="2"></entry>
18 <entry name="alt" value="4"></entry>
19 <entry name="win" value="8"></entry>
20 <entry name="altgr" value="16"></entry>
21 </enum>
22 <request name="grab_key">
23 <description summary="Request a new grab for a key press">
24 </description>
25 <arg name="id" type="new_id" interface="action_route_grab"/>
26 <arg name="surface" type="object" interface="wl_surface"/>
27 <arg name="key" type="string"/>
28 <arg name="mode" type="uint"/>
29 <arg name="modifiers" type="uint"/>
30 <arg name="action" type="string"/>
31 <arg name="params" type="string"/>
32 </request>
33 </interface>
34 <interface name="action_route_grab" version="1">
35 <enum name="state">
36 <entry name="Rejected" value="0"></entry>
37 <entry name="Active" value="1"></entry>
38 <entry name="Queued" value="2"></entry>
39 </enum>
40 <event name="status">
41 <description summary="Status update on a grab request"></description>
42 <arg name="state" type="uint"/>
43 </event>
44 <request name="destroy" type="destructor">
45 <description summary="Destroy a requested grab">
46 </description>
47 </request>
48 </interface>
49</protocol>