77c0f0106db4a2b5ac7f445d31c75157f7e218af
[platform/core/uifw/dali-adaptor.git] / adaptors / mobile / accessibility-adaptor-impl-mobile.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "accessibility-adaptor-impl-mobile.h"
20
21 // EXTERNAL INCLUDES
22 #include <vconf.h>
23 #include <Ecore_X.h>
24 #include <Elementary.h>
25 #include <vconf.h>
26
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/integration-api/debug.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/integration-api/events/gesture-requests.h>
31
32 // INTERNAL INCLUDES
33 #include <singleton-service-impl.h>
34 #include "system-settings.h"
35
36 #define MSG_DOMAIN_CONTROL_ACCESS (int)ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL
37
38 namespace Dali
39 {
40
41 namespace Internal
42 {
43
44 namespace Adaptor
45 {
46
47 namespace // unnamed namespace
48 {
49
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gAccessibilityAdaptorLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ACCESSIBILITY_ADAPTOR");
52 #endif
53
54 const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS = "db/setting/accessibility/atspi";
55
56 bool GetEnabledVConf()
57 {
58   int isEnabled = 0;
59   vconf_get_bool( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, &isEnabled );
60
61   if( isEnabled == 0 )
62   {
63     vconf_get_bool( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &isEnabled );
64   }
65
66   return (bool)isEnabled;
67 }
68
69
70 void AccessibilityOnOffNotification(keynode_t* node, void* data)
71 {
72   AccessibilityAdaptor* adaptor = static_cast<AccessibilityAdaptor*>( data );
73
74   bool isEnabled = GetEnabledVConf();
75
76   DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );
77
78   if( isEnabled )
79   {
80     adaptor->EnableAccessibility();
81   }
82   else
83   {
84     adaptor->DisableAccessibility();
85   }
86 }
87
88 BaseHandle Create()
89 {
90   BaseHandle handle( AccessibilityAdaptor::Get() );
91
92   if ( !handle )
93   {
94     Dali::SingletonService service( SingletonService::Get() );
95     if ( service )
96     {
97       Dali::AccessibilityAdaptor adaptor = Dali::AccessibilityAdaptor( new AccessibilityAdaptorMobile() );
98       AccessibilityAdaptorMobile& adaptorImpl = AccessibilityAdaptorMobile::GetImplementation( adaptor );
99
100       bool isEnabled = GetEnabledVConf();
101
102       if( isEnabled )
103       {
104         adaptorImpl.EnableAccessibility();
105       }
106       DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );
107
108       vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification, &adaptorImpl );
109       vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification, &adaptorImpl );
110
111       service.Register( typeid( adaptor ), adaptor );
112       handle = adaptor;
113     }
114   }
115
116   return handle;
117 }
118
119 TypeRegistration ACCESSIBILITY_ADAPTOR_TYPE( typeid(Dali::AccessibilityAdaptor), typeid(Dali::BaseHandle), Create, true /* Create Instance At Startup */ );
120
121 } // unnamed namespace
122
123 Dali::AccessibilityAdaptor AccessibilityAdaptor::Get()
124 {
125   Dali::AccessibilityAdaptor adaptor;
126
127   Dali::SingletonService service( SingletonService::Get() );
128   if ( service )
129   {
130     // Check whether the singleton is already created
131     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::AccessibilityAdaptor ) );
132     if(handle)
133     {
134       // If so, downcast the handle
135       adaptor = Dali::AccessibilityAdaptor( dynamic_cast< AccessibilityAdaptor* >( handle.GetObjectPtr() ) );
136     }
137   }
138
139   return adaptor;
140 }
141
142 void AccessibilityAdaptor::OnDestroy()
143 {
144   vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification );
145   vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification );
146 }
147
148 AccessibilityAdaptorMobile::AccessibilityAdaptorMobile()
149 {
150 }
151
152 bool AccessibilityAdaptorMobile::HandleActionNextEvent(bool allowEndFeedback)
153 {
154   bool ret = false;
155
156   if( mIndicator && mIndicatorFocused )
157   {
158     Elm_Access_Action_Info actionInfo;
159     actionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
160
161     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
162   }
163   else if( mActionHandler )
164   {
165     ret = mActionHandler->AccessibilityActionNext(allowEndFeedback);
166   }
167
168   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
169
170   return ret;
171 }
172
173 bool AccessibilityAdaptorMobile::HandleActionPreviousEvent(bool allowEndFeedback)
174 {
175   bool ret = false;
176
177   if( mIndicator && mIndicatorFocused )
178   {
179     Elm_Access_Action_Info actionInfo;
180     actionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
181
182     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
183   }
184   else if( mActionHandler )
185   {
186     ret = mActionHandler->AccessibilityActionPrevious(allowEndFeedback);
187   }
188
189   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
190
191   return ret;
192 }
193
194 bool AccessibilityAdaptorMobile::HandleActionActivateEvent()
195 {
196   bool ret = false;
197
198   if( mIndicator && mIndicatorFocused )
199   {
200     Elm_Access_Action_Info actionInfo;
201     actionInfo.action_type = ELM_ACCESS_ACTION_ACTIVATE;
202
203     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
204   }
205   else if( mActionHandler )
206   {
207     ret = mActionHandler->AccessibilityActionActivate();
208   }
209
210   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
211
212   return ret;
213 }
214
215 bool AccessibilityAdaptorMobile::HandleActionReadEvent(unsigned int x, unsigned int y, bool allowReadAgain)
216 {
217   bool ret = false;
218
219   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %d , %d\n", __FUNCTION__, __LINE__, x, y);
220
221   mReadPosition.x = x;
222   mReadPosition.y = y;
223
224   Dali::AccessibilityAdaptor handle( this );
225
226   bool indicatorFocused = false;
227
228   // Check whether the Indicator is focused
229   if( mIndicator && mIndicator->IsConnected() )
230   {
231     // Check the position and size of Indicator actor
232     Dali::Actor indicatorActor = mIndicator->GetActor();
233     Vector3 position = Vector3(0.0f, 0.0f, 0.0f);
234     Vector3 size = indicatorActor.GetCurrentSize();
235
236     if(mReadPosition.x >= position.x &&
237        mReadPosition.x <= position.x + size.width &&
238        mReadPosition.y >= position.y &&
239        mReadPosition.y <= position.y + size.height)
240     {
241       indicatorFocused = true;
242       DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] Indicator area!!!!\n", __FUNCTION__, __LINE__);
243     }
244   }
245
246   if( mIndicator )
247   {
248     if( !mIndicatorFocused && indicatorFocused )
249     {
250       // If Indicator is focused, the focus should be cleared in Dali focus chain.
251       if( mActionHandler )
252       {
253         mActionHandler->ClearAccessibilityFocus();
254       }
255     }
256     else if( mIndicatorFocused && !indicatorFocused )
257     {
258       Elm_Access_Action_Info actionInfo;
259       actionInfo.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
260
261       // Indicator should be unhighlighted
262       ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
263       DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] Send unhighlight message to indicator!!!!\n", __FUNCTION__, __LINE__);
264     }
265
266     mIndicatorFocused = indicatorFocused;
267
268     // Send accessibility READ action information to Indicator
269     if( mIndicatorFocused )
270     {
271       Elm_Access_Action_Info actionInfo;
272       actionInfo.x = mReadPosition.x;
273       actionInfo.y = mReadPosition.y;
274
275       if(allowReadAgain)
276       {
277         actionInfo.action_type = ELM_ACCESS_ACTION_READ;
278       }
279       else
280       {
281         actionInfo.action_type = static_cast<Elm_Access_Action_Type>( GetElmAccessActionOver() );
282       }
283
284       ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
285
286       DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] Send READ message to indicator!!!!\n", __FUNCTION__, __LINE__);
287     }
288   }
289
290   if( mActionHandler && !mIndicatorFocused)
291   {
292     // If Indicator is not focused, the accessibility actions should be handled by the registered
293     // accessibility action handler (e.g. focus manager)
294     ret = mActionHandler->AccessibilityActionRead(allowReadAgain);
295     DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
296   }
297
298   return ret;
299 }
300
301 bool AccessibilityAdaptorMobile::HandleActionReadNextEvent(bool allowEndFeedback)
302 {
303   bool ret = false;
304
305   if( mIndicator && mIndicatorFocused )
306   {
307     Elm_Access_Action_Info actionInfo;
308     actionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
309
310     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
311   }
312   else if( mActionHandler )
313   {
314     ret = mActionHandler->AccessibilityActionReadNext(allowEndFeedback);
315   }
316
317   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
318
319   return ret;
320 }
321
322 bool AccessibilityAdaptorMobile::HandleActionReadPreviousEvent(bool allowEndFeedback)
323 {
324   bool ret = false;
325
326   if( mIndicator && mIndicatorFocused )
327   {
328     Elm_Access_Action_Info actionInfo;
329     actionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
330
331     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
332   }
333   else if( mActionHandler )
334   {
335     ret = mActionHandler->AccessibilityActionReadPrevious(allowEndFeedback);
336   }
337
338   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
339
340   return ret;
341 }
342
343 bool AccessibilityAdaptorMobile::HandleActionUpEvent()
344 {
345   bool ret = false;
346
347   if( mIndicator && mIndicatorFocused )
348   {
349     Elm_Access_Action_Info actionInfo;
350     actionInfo.action_type = ELM_ACCESS_ACTION_UP;
351
352     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
353   }
354   else if( mActionHandler )
355   {
356     ret = mActionHandler->AccessibilityActionUp();
357   }
358
359   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
360
361   return ret;
362 }
363
364 bool AccessibilityAdaptorMobile::HandleActionDownEvent()
365 {
366   bool ret = false;
367
368   if( mIndicator && mIndicatorFocused )
369   {
370     Elm_Access_Action_Info actionInfo;
371     actionInfo.action_type = ELM_ACCESS_ACTION_DOWN;
372
373     ret = mIndicator->SendMessage(MSG_DOMAIN_CONTROL_ACCESS, actionInfo.action_type, &actionInfo, sizeof(actionInfo));
374   }
375   else if( mActionHandler )
376   {
377     ret = mActionHandler->AccessibilityActionDown();
378   }
379
380   DALI_LOG_INFO(gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
381
382   return ret;
383 }
384
385 AccessibilityAdaptorMobile::~AccessibilityAdaptorMobile()
386 {
387 }
388
389 } // namespace Adaptor
390
391 } // namespace Internal
392
393 } // namespace Dali