summaryrefslogtreecommitdiffstats
path: root/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0004-ivi-ilmcontrol-added-focus-notification.patch
blob: a665c060fcbc160215f9ddcf1cc2608515764e83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
diff --git a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
index a88f2b0..12a2017 100644
--- a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
+++ b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
@@ -245,6 +245,7 @@ typedef enum
     ILM_NOTIFICATION_CONTENT_AVAILABLE = ILM_BIT(6),
     ILM_NOTIFICATION_CONTENT_REMOVED = ILM_BIT(7),
     ILM_NOTIFICATION_CONFIGURED = ILM_BIT(8),
+    ILM_NOTIFICATION_FOCUS = ILM_BIT(9),
     ILM_NOTIFICATION_ALL = 0xffff
 } t_ilm_notification_mask;
 
diff --git a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
index 9b4762b..5104459 100644
--- a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
+++ b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
@@ -779,6 +779,12 @@ input_listener_input_focus(void *data,
             surf_ctx->prop.focus |= device;
         else
             surf_ctx->prop.focus &= ~device;
+
+        if (surf_ctx->notification != NULL) {
+            surf_ctx->notification(surf_ctx->id_surface,
+                                    &surf_ctx->prop,
+                                    ILM_NOTIFICATION_FOCUS);
+        }
     }
 }
: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (C) 2015, 2016 "IoT.bzh"
 * Author "Romain Forlot" <romain.forlot@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#include <string>
#include <string.h>
// afb-utilities
#include <wrap-json.h>
#include <filescan-utils.h>

#include "signal-composer-binding.hpp"
#include "signal-composer-apidef.h"
#include "clientApp.hpp"

/// @brief callback for receiving message from low bindings. This will callback
/// an action defined in the configuration files depending on the event received
///
/// @param[in] event - event name
/// @param[in] object - eventual data that comes with the event
void onEvent(const char *event, json_object *object)
{
	Composer& composer = Composer::instance();
	AFB_NOTICE("event: %s", json_object_to_json_string(object));

	std::vector<std::shared_ptr<Signal>> signals = composer.searchSignals(event);
	if(!signals.empty())
	{
		// If there is more than 1 element then maybe we can find a more
		// detailled event name in JSON object as 1 event may carry several
		// signals. Try to find that one.
		if(signals.size() > 1)
		{
			bool found = false;
			json_object_iterator iter = json_object_iter_begin(object);
			json_object_iterator iterEnd = json_object_iter_end(object);
			while(!json_object_iter_equal(&iter, &iterEnd))
			{
				json_object *value = json_object_iter_peek_value(&iter);
				if(json_object_is_type(value, json_type_string))
				{
					std::string name = json_object_get_string(value);
					for(auto& sig: signals)
					{
						if(*sig == name)
						{
							found = true;
							sig->onReceivedCB(object);
						}
					}
				}
				json_object_iter_next(&iter);
			}
			// If nothing found in JSON data then apply onReceived callback
			// for all signals found
			if(! found)
			{
				for(auto& sig: signals)
					{sig->onReceivedCB(object);}
			}
		}
		else
			{signals[0]->onReceivedCB(object);}
	}
}

static int one_subscribe_unsubscribe(struct afb_req request,
	bool subscribe,
	const std::string& event,
	json_object* args,
	clientAppCtx* cContext)
{
	int err = 0;
	std::vector<std::shared_ptr<Signal>> signals = Composer::instance().searchSignals(event);

	cContext->appendSignals(signals);
	if(subscribe)
		{err = cContext->makeSubscription(request);}
	else
		{err = cContext->makeUnsubscription(request);}

	return err;
}

static int subscribe_unsubscribe(struct afb_req request,
	bool subscribe,
	json_object* args,
	clientAppCtx* cContext)
{
	int rc = 0;
	json_object *event = nullptr;
	if (args == NULL || !json_object_object_get_ex(args, "event", &event))
	{
		rc = one_subscribe_unsubscribe(request, subscribe, "*", args, cContext);
	}
	else if (json_object_get_type(event) == json_type_string)
	{
		rc = one_subscribe_unsubscribe(request, subscribe, json_object_get_string(event), args, cContext);
	}
	else if (json_object_get_type(event) == json_type_array)
	{
		for (int i = 0 ; i < json_object_array_length(event) ; i++)
		{
			json_object *x = json_object_array_get_idx(event, i);
			rc += one_subscribe_unsubscribe(request, subscribe, json_object_get_string(x), args, cContext);
		}
	}
	else {rc = -1;}

	return rc;
}

/// @brief entry point for client subscription request.
static void do_subscribe_unsubscribe(afb_req request, bool subscribe, clientAppCtx* cContext)
{
	int rc = 0;
	json_object *oneArg = nullptr, *args = afb_req_json(request);
	if (json_object_get_type(args) == json_type_array)
	{
		for (int i = 0 ; i < json_object_array_length(args); i++)
		{
			oneArg = json_object_array_get_idx(args, i);
			rc += subscribe_unsubscribe(request, subscribe, oneArg, cContext);
		}
	}
	else
	{
		rc = subscribe_unsubscribe(request, subscribe, args, cContext);
	}

	if(rc >= 0)
		afb_req_success(request, NULL, NULL);
	else
		afb_req_fail(request, "error", NULL);
}

/// @brief entry point for client un-subscription request.
void subscribe(afb_req request)
{
	clientAppCtx *cContext = reinterpret_cast<clientAppCtx*>(afb_req_context_make(request, 0, Composer::createContext, Composer::destroyContext, nullptr));

	do_subscribe_unsubscribe(request, true, cContext);
}

/// @brief entry point for client un-subscription request.
void unsubscribe(afb_req request)
{
	clientAppCtx *cContext = reinterpret_cast<clientAppCtx*>(afb_req_context_make(request, 0, Composer::createContext, Composer::destroyContext, nullptr));

	do_subscribe_unsubscribe(request, false, cContext);
}

/// @brief verb that loads JSON configuration (old SigComp.json file now)
void loadConf(afb_req request)
{
	json_object* args = afb_req_json(request), *fileJ;
	const char* filepath;

	wrap_json_unpack(args, "{s:s}", "filepath", &filepath);
	fileJ = json_object_from_file(filepath);

	if(Composer::instance().loadSignals(fileJ))
		{afb_req_fail_f(request, "Loading configuration or subscription error", "Error code: -1");}
	else
	{

		afb_req_success(request, NULL, NULL);
	}
}

/// @brief entry point to list available signals
void list(afb_req request)
{
	struct json_object *allSignalsJ = json_object_new_array();

	std::vector<std::shared_ptr<Signal>> allSignals = Composer::instance().getAllSignals();
	for(auto& sig: allSignals)
		{json_object_array_add(allSignalsJ, sig->toJSON());}

	if(json_object_array_length(allSignalsJ) && !execConf())
		{afb_req_success(request, allSignalsJ, NULL);}
	else
		{afb_req_fail(request, "error", "No Signals recorded so far");}
}

/// @brief entry point for get requests.
void get(struct afb_req request)
{
	int err = 0;
	struct json_object* args = afb_req_json(request), *ans = nullptr,
	*options = nullptr;
	const char* sig;

	// Process about Raw CAN message on CAN bus directly
	err = wrap_json_unpack(args, "{ss,s?o!}", "signal", &sig,
			"options", &options);
	if(err)
	{
		AFB_ERROR("Can't process your request '%s'. Valid arguments are: string for 'signal' and JSON object for 'options' (optionnal)", json_object_to_json_string_ext(args, JSON_C_TO_STRING_PRETTY));
		afb_req_fail(request, "error", NULL);
		return;
	}

	ans = Composer::instance().getsignalValue(sig, options);

	if (json_object_array_length(ans))
		afb_req_success(request, ans, NULL);
	else
		afb_req_fail(request, "error", "No signals found.");

}

int loadConf()
{
	int err = 0;
	std::string bindingDirPath = GetBindingDirPath();
	std::string rootdir = bindingDirPath + "/etc";

	err = Composer::instance().loadConfig(rootdir.c_str());

	return err;
}

int execConf()
{
	Composer& composer = Composer::instance();
	int err = 0;
	CtlConfigExec(nullptr, composer.ctlConfig());
	std::vector<std::shared_ptr<Signal>> allSignals = composer.getAllSignals();
	ssize_t sigCount = allSignals.size();
	for( std::shared_ptr<Signal>& sig: allSignals)
	{
		sig->attachToSourceSignals(composer);
	}

	for(auto& sig: allSignals)
	{
		if( (err += sig->initialRecursionCheck()) )
		{
			AFB_ERROR("There is an infinite recursion loop in your signals definition. Root coming from signal: %s", sig->id().c_str());
			return err;
		}
	}

	composer.execSignalsSubscription();

	AFB_DEBUG("Signal Composer Control configuration Done.\n signals=%d", (int)sigCount);

	return err;
}