3f621c15ee7d7303830032fb0d754c95221a22a2
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-impl.cpp
1 /*
2  * Copyright (c) 2019 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
20 // EXTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22 #include <iostream>
23 #include <unordered_map>
24
25 // INTERNAL INCLUDES
26 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
27 #include <dali/internal/accessibility/bridge/bridge-action.h>
28 #include <dali/internal/accessibility/bridge/bridge-collection.h>
29 #include <dali/internal/accessibility/bridge/bridge-component.h>
30 #include <dali/internal/accessibility/bridge/bridge-object.h>
31 #include <dali/internal/accessibility/bridge/bridge-value.h>
32 #include <dali/internal/accessibility/bridge/bridge-text.h>
33 #include <dali/internal/accessibility/bridge/bridge-editable-text.h>
34
35 using namespace Dali::Accessibility;
36
37 class BridgeImpl : public virtual BridgeBase,
38                    public BridgeAccessible,
39                    public BridgeObject,
40                    public BridgeComponent,
41                    public BridgeCollection,
42                    public BridgeAction,
43                    public BridgeValue,
44                    public BridgeText,
45                    public BridgeEditableText
46 {
47   DBus::DBusClient listenOnAtspiEnabledSignalClient;
48   DBus::DBusClient registryClient, directReadingClient;
49   bool screenReaderEnabled = false, isEnabled = false, isShown = false;
50   std::unordered_map <int32_t, std::function<void(std::string)>> directReadingCallbacks;
51   Dali::Actor highlightedActor;
52   std::function<void(Dali::Actor)> highlightClearAction;
53 public:
54   BridgeImpl()
55   {
56     listenOnAtspiEnabledSignalClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface,
57                                                              DBus::ConnectionType::SESSION};
58     listenOnAtspiEnabledSignalClient.addPropertyChangedEvent< bool >( "ScreenReaderEnabled", [this]( bool res ) {
59       screenReaderEnabled = res;
60       if( screenReaderEnabled || isEnabled )
61         ForceUp();
62       else
63         ForceDown();
64     } );
65     listenOnAtspiEnabledSignalClient.addPropertyChangedEvent< bool >( "IsEnabled", [this]( bool res ) {
66       isEnabled = res;
67       if( screenReaderEnabled || isEnabled )
68         ForceUp();
69       else
70         ForceDown();
71     } );
72   }
73
74   Consumed Emit( KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText ) override
75   {
76     if (!IsUp()) return Consumed::NO;
77     unsigned int evType = 0;
78
79     switch( type )
80     {
81       case KeyEventType::KEY_PRESSED:
82         evType = 0;
83         {
84           break;
85         }
86       case KeyEventType::KEY_RELEASED:
87         evType = 1;
88         {
89           break;
90         }
91       default:
92       {
93         return Consumed::NO;
94       }
95     }
96     auto m = registryClient.method< bool( std::tuple< uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool > ) >( "NotifyListenersSync" );
97     auto result = m.call( std::tuple< uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool >{evType, 0, static_cast< int32_t >( keyCode ), 0, static_cast< int32_t >( timeStamp ), keyName, isText ? 1 : 0} );
98     if( !result )
99     {
100       LOG() << result.getError().message;
101       return Consumed::NO;
102     }
103     return std::get< 0 >( result ) ? Consumed::YES : Consumed::NO;
104   }
105
106   void PauseResume( bool pause ) override
107   {
108     auto r = directReadingClient.method< DBus::ValueOrError< void >( bool ) > ( "PauseResume" ).call( pause );
109     if (!r) {
110       LOG() << "Direct reading command failed (" << r.getError().message << ")";
111     }
112   }
113
114   void Say( const std::string& text, bool discardable, std::function< void(std::string) > callback ) override
115   {
116           auto commandId = directReadingClient.method< DBus::ValueOrError< std::string, bool, int32_t >( std::string, bool ) > ( "ReadCommand" ).call( text, discardable );
117           if ( !commandId ) {
118                   LOG() << "Direct reading command failed (" << commandId.getError().message << ")";
119           } else if( callback ) {
120             directReadingCallbacks.emplace( std::get< 2 >( commandId ), callback);
121           }
122   }
123
124   void ForceDown() override
125   {
126     if (data) {
127       if (data->currentlyHighlightedActor && data->highlightActor) {
128         data->currentlyHighlightedActor.Remove(data->highlightActor);
129       }
130       data->currentlyHighlightedActor = {};
131       data->highlightActor = {};
132     }
133     highlightedActor = {};
134     highlightClearAction = {};
135     BridgeAccessible::ForceDown();
136     registryClient = {};
137     directReadingClient = {};
138     directReadingCallbacks.clear();
139   }
140   void Terminate() override
141   {
142     if (data) {
143       data->currentlyHighlightedActor = {};
144       data->highlightActor = {};
145     }
146     ForceDown();
147     listenOnAtspiEnabledSignalClient = {};
148     dbusServer = {};
149     con = {};
150   }
151
152   ForceUpResult ForceUp() override
153   {
154     if( BridgeAccessible::ForceUp() == ForceUpResult::ALREADY_UP )
155       return ForceUpResult::ALREADY_UP;
156
157     BridgeObject::RegisterInterfaces();
158     BridgeAccessible::RegisterInterfaces();
159     BridgeComponent::RegisterInterfaces();
160     BridgeCollection::RegisterInterfaces();
161     BridgeAction::RegisterInterfaces();
162     BridgeValue::RegisterInterfaces();
163     BridgeText::RegisterInterfaces();
164     BridgeEditableText::RegisterInterfaces();
165
166     RegisterOnBridge( &application );
167
168     registryClient = { AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, con };
169     directReadingClient = DBus::DBusClient{ DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, con };
170     directReadingClient.addSignal< void(int32_t, std::string) >( "ReadingStateChanged", [=]( int32_t id, std::string readingState ) {
171       auto it = directReadingCallbacks.find( id );
172       if (it != directReadingCallbacks.end())
173       {
174         it->second( readingState );
175         directReadingCallbacks.erase( it );
176       }
177     });
178     auto proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, con};
179     Address root{"", "root"};
180     auto res = proxy.method< Address( Address ) >( "Embed" ).call( root );
181     if (!res)
182       LOG() << "Call to Embed failed: " << res.getError().message;
183     assert( res );
184     application.parent.SetAddress( std::move( std::get< 0 >( res ) ) );
185     if (isShown) {
186       EmitActivate();
187     }
188     return ForceUpResult::JUST_STARTED;
189   }
190
191   void EmitActivate()
192   {
193     auto win = application.getActiveWindow();
194     if (win) {
195       win->Emit( WindowEvent::ACTIVATE, 0 );
196     }
197   }
198   void EmitDeactivate()
199   {
200     auto win = application.getActiveWindow();
201     if (win) {
202       win->Emit( WindowEvent::DEACTIVATE, 0 );
203     }
204   }
205   void ApplicationHidden() override
206   {
207     if ( isShown && IsUp() )
208       EmitDeactivate();
209     isShown = false;
210   }
211   void ApplicationShown() override
212   {
213     if ( !isShown && IsUp() )
214       EmitActivate();
215     isShown = true;
216   }
217   void Initialize() override
218   {
219     auto req = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
220     auto p = req.property< bool >( "ScreenReaderEnabled" ).get();
221     if( p )
222       screenReaderEnabled = std::get< 0 >( p );
223     p = req.property< bool >( "IsEnabled" ).get();
224     if( p )
225       isEnabled = std::get< 0 >( p );
226     if( screenReaderEnabled || isEnabled )
227       ForceUp();
228   }
229 };
230
231 Bridge* Bridge::GetCurrentBridge()
232 {
233   static BridgeImpl *bridge = new BridgeImpl;
234   return bridge;
235 }