Revert "[Tizen] Use dummy AT-SPI bridge in the absence of a DBus session"
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-impl.cpp
1 /*
2  * Copyright (c) 2021 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-editable-text.h>
31 #include <dali/internal/accessibility/bridge/bridge-object.h>
32 #include <dali/internal/accessibility/bridge/bridge-text.h>
33 #include <dali/internal/accessibility/bridge/bridge-value.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;
50   bool                                                          isEnabled           = false;
51   bool                                                          isShown             = false;
52   std::unordered_map<int32_t, std::function<void(std::string)>> directReadingCallbacks;
53   Dali::Actor                                                   highlightedActor;
54   std::function<void(Dali::Actor)>                              highlightClearAction;
55
56 public:
57   BridgeImpl()
58   {
59     listenOnAtspiEnabledSignalClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
60
61     listenOnAtspiEnabledSignalClient.addPropertyChangedEvent<bool>("ScreenReaderEnabled", [this](bool res) {
62       screenReaderEnabled = res;
63       if(screenReaderEnabled || isEnabled)
64       {
65         ForceUp();
66       }
67       else
68       {
69         ForceDown();
70       }
71     });
72
73     listenOnAtspiEnabledSignalClient.addPropertyChangedEvent<bool>("IsEnabled", [this](bool res) {
74       isEnabled = res;
75       if(screenReaderEnabled || isEnabled)
76       {
77         ForceUp();
78       }
79       else
80       {
81         ForceDown();
82       }
83     });
84   }
85
86   Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
87   {
88     if(!IsUp())
89     {
90       return Consumed::NO;
91     }
92
93     unsigned int evType = 0;
94
95     switch(type)
96     {
97       case KeyEventType::KEY_PRESSED:
98       {
99         evType = 0;
100         break;
101       }
102       case KeyEventType::KEY_RELEASED:
103       {
104         evType = 1;
105         break;
106       }
107       default:
108       {
109         return Consumed::NO;
110       }
111     }
112     auto m      = registryClient.method<bool(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>)>("NotifyListenersSync");
113     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});
114     if(!result)
115     {
116       LOG() << result.getError().message;
117       return Consumed::NO;
118     }
119     return std::get<0>(result) ? Consumed::YES : Consumed::NO;
120   }
121
122   void Pause() override
123   {
124     if(!IsUp())
125     {
126       return;
127     }
128
129     directReadingClient.method<DBus::ValueOrError<void>(bool)>("PauseResume").asyncCall([](DBus::ValueOrError<void> msg) {
130       if(!msg)
131       {
132         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
133       }
134     },
135                                                                                         true);
136   }
137
138   void Resume() override
139   {
140     if(!IsUp())
141     {
142       return;
143     }
144
145     directReadingClient.method<DBus::ValueOrError<void>(bool)>("PauseResume").asyncCall([](DBus::ValueOrError<void> msg) {
146       if(!msg)
147       {
148         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
149       }
150     },
151                                                                                         false);
152   }
153
154   void Say(const std::string& text, bool discardable, std::function<void(std::string)> callback) override
155   {
156     if(!IsUp())
157     {
158       return;
159     }
160
161     directReadingClient.method<DBus::ValueOrError<std::string, bool, int32_t>(std::string, bool)>("ReadCommand").asyncCall([=](DBus::ValueOrError<std::string, bool, int32_t> msg) {
162       if(!msg)
163       {
164         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
165       }
166       else if(callback)
167       {
168         directReadingCallbacks.emplace(std::get<2>(msg), callback);
169       }
170     },
171                                                                                                                            text,
172                                                                                                                            discardable);
173   }
174
175   void ForceDown() override
176   {
177     if(data)
178     {
179       if(data->currentlyHighlightedActor && data->highlightActor)
180       {
181         data->currentlyHighlightedActor.Remove(data->highlightActor);
182       }
183       data->currentlyHighlightedActor = {};
184       data->highlightActor            = {};
185     }
186     highlightedActor     = {};
187     highlightClearAction = {};
188     BridgeAccessible::ForceDown();
189     registryClient      = {};
190     directReadingClient = {};
191     directReadingCallbacks.clear();
192   }
193
194   void Terminate() override
195   {
196     if(data)
197     {
198       data->currentlyHighlightedActor = {};
199       data->highlightActor            = {};
200     }
201     ForceDown();
202     listenOnAtspiEnabledSignalClient = {};
203     dbusServer                       = {};
204     con                              = {};
205   }
206
207   ForceUpResult ForceUp() override
208   {
209     if(BridgeAccessible::ForceUp() == ForceUpResult::ALREADY_UP)
210     {
211       return ForceUpResult::ALREADY_UP;
212     }
213
214     BridgeObject::RegisterInterfaces();
215     BridgeAccessible::RegisterInterfaces();
216     BridgeComponent::RegisterInterfaces();
217     BridgeCollection::RegisterInterfaces();
218     BridgeAction::RegisterInterfaces();
219     BridgeValue::RegisterInterfaces();
220     BridgeText::RegisterInterfaces();
221     BridgeEditableText::RegisterInterfaces();
222
223     RegisterOnBridge(&application);
224
225     registryClient      = {AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, con};
226     directReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, con};
227     directReadingClient.addSignal<void(int32_t, std::string)>("ReadingStateChanged", [=](int32_t id, std::string readingState) {
228       auto it = directReadingCallbacks.find(id);
229       if(it != directReadingCallbacks.end())
230       {
231         it->second(readingState);
232         if(readingState != "ReadingPaused" && readingState != "ReadingResumed" && readingState != "ReadingStarted")
233           directReadingCallbacks.erase(it);
234       }
235     });
236
237     auto    proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, con};
238     Address root{"", "root"};
239     auto    res = proxy.method<Address(Address)>("Embed").call(root);
240     if(!res)
241     {
242       LOG() << "Call to Embed failed: " << res.getError().message;
243     }
244     assert(res);
245     application.parent.SetAddress(std::move(std::get<0>(res)));
246     if(isShown)
247     {
248       EmitActivate();
249     }
250     return ForceUpResult::JUST_STARTED;
251   }
252
253   void EmitActivate()
254   {
255     auto win = application.getActiveWindow();
256     if(win)
257     {
258       win->Emit(WindowEvent::ACTIVATE, 0);
259     }
260   }
261
262   void EmitDeactivate()
263   {
264     auto win = application.getActiveWindow();
265     if(win)
266     {
267       win->Emit(WindowEvent::DEACTIVATE, 0);
268     }
269   }
270
271   void ApplicationHidden() override
272   {
273     if(isShown && IsUp())
274     {
275       EmitDeactivate();
276     }
277     isShown = false;
278   }
279
280   void ApplicationShown() override
281   {
282     if(!isShown && IsUp())
283     {
284       EmitActivate();
285     }
286     isShown = true;
287   }
288
289   void Initialize() override
290   {
291     auto req = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
292     auto p   = req.property<bool>("ScreenReaderEnabled").get();
293     if(p)
294     {
295       screenReaderEnabled = std::get<0>(p);
296     }
297     p = req.property<bool>("IsEnabled").get();
298     if(p)
299     {
300       isEnabled = std::get<0>(p);
301     }
302     if(screenReaderEnabled || isEnabled)
303     {
304       ForceUp();
305     }
306   }
307
308   bool GetScreenReaderEnabled()
309   {
310     return screenReaderEnabled;
311   }
312
313   bool GetIsEnabled()
314   {
315     return isEnabled;
316   }
317 };
318
319 Bridge* Bridge::GetCurrentBridge()
320 {
321   static BridgeImpl* bridge = new BridgeImpl;
322   return bridge;
323 }