[Tizen] Disable ATSPI when release or perf image
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-object.cpp
1 /*
2  * Copyright (c) 2023 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 <dali/internal/accessibility/bridge/bridge-object.h>
20
21 // EXTERNAL INCLUDES
22 #include <iostream>
23 #include <string>
24 #include <string_view>
25 #include <unordered_map>
26
27 using namespace Dali::Accessibility;
28
29 namespace
30 {
31 inline std::string GetAccessiblePath(Accessible* accessible)
32 {
33   auto address = accessible->GetAddress();
34   return address ? ATSPI_PREFIX_PATH + address.GetPath() : ATSPI_NULL_PATH;
35 }
36 } // namespace
37
38 BridgeObject::BridgeObject()
39 {
40 }
41
42 void BridgeObject::RegisterInterfaces()
43 {
44   // DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT)};
45   // mStateChanged = addSignal<std::string, int, int, DBus::EldbusVariant<int>, Accessible*>(desc, "StateChanged");
46   // mDbusServer.addInterface("/", desc, true);
47 }
48
49 void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* child)
50 {
51   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::ACTIVE_DESCENDANT_CHANGED] || child->IsHidden())
52   {
53     return;
54   }
55
56   auto index = child->GetIndexInParent();
57
58   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<Address>, Address>(
59     GetAccessiblePath(obj),
60     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
61     "ActiveDescendantChanged",
62     "",
63     index,
64     0,
65     {child->GetAddress()},
66     {"", "root"});
67 }
68
69 void BridgeObject::Emit(Accessible* obj, ObjectPropertyChangeEvent event)
70 {
71   static const std::unordered_map<ObjectPropertyChangeEvent, std::string_view> eventMap{
72     {ObjectPropertyChangeEvent::NAME, "accessible-name"},
73     {ObjectPropertyChangeEvent::DESCRIPTION, "accessible-description"},
74     {ObjectPropertyChangeEvent::VALUE, "accessible-value"},
75     {ObjectPropertyChangeEvent::PARENT, "accessible-parent"},
76     {ObjectPropertyChangeEvent::ROLE, "accessible-role"},
77   };
78
79   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::PROPERTY_CHANGED])
80   {
81     return;
82   }
83
84   auto eventName = eventMap.find(event);
85
86   if(eventName != eventMap.end())
87   {
88     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
89       GetAccessiblePath(obj),
90       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
91       "PropertyChange",
92       std::string{eventName->second},
93       0,
94       0,
95       {0},
96       {"", "root"});
97   }
98 }
99
100 void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
101 {
102   static const std::unordered_map<WindowEvent, std::string_view> eventMap{
103     {WindowEvent::PROPERTY_CHANGE, "PropertyChange"},
104     {WindowEvent::MINIMIZE, "Minimize"},
105     {WindowEvent::MAXIMIZE, "Maximize"},
106     {WindowEvent::RESTORE, "Restore"},
107     {WindowEvent::CLOSE, "Close"},
108     {WindowEvent::CREATE, "Create"},
109     {WindowEvent::REPARENT, "Reparent"},
110     {WindowEvent::DESKTOP_CREATE, "DesktopCreate"},
111     {WindowEvent::DESKTOP_DESTROY, "DesktopDestroy"},
112     {WindowEvent::DESTROY, "Destroy"},
113     {WindowEvent::ACTIVATE, "Activate"},
114     {WindowEvent::DEACTIVATE, "Deactivate"},
115     {WindowEvent::RAISE, "Raise"},
116     {WindowEvent::LOWER, "Lower"},
117     {WindowEvent::MOVE, "Move"},
118     {WindowEvent::RESIZE, "Resize"},
119     {WindowEvent::SHADE, "Shade"},
120     {WindowEvent::UU_SHADE, "uUshade"},
121     {WindowEvent::RESTYLE, "Restyle"},
122     {WindowEvent::POST_RENDER, "PostRender"},
123   };
124
125   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::WINDOW_CHANGED])
126   {
127     return;
128   }
129
130   auto eventName = eventMap.find(event);
131
132   if(eventName != eventMap.end())
133   {
134     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
135       GetAccessiblePath(obj),
136       Accessible::GetInterfaceName(AtspiInterface::EVENT_WINDOW),
137       std::string{eventName->second},
138       "",
139       detail,
140       0,
141       {0},
142       {"", "root"});
143   }
144 }
145
146 void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, int reserved)
147 {
148   static const std::unordered_map<State, std::string_view> stateMap{
149     {State::INVALID, "invalid"},
150     {State::ACTIVE, "active"},
151     {State::ARMED, "armed"},
152     {State::BUSY, "busy"},
153     {State::CHECKED, "checked"},
154     {State::COLLAPSED, "collapsed"},
155     {State::DEFUNCT, "defunct"},
156     {State::EDITABLE, "editable"},
157     {State::ENABLED, "enabled"},
158     {State::EXPANDABLE, "expandable"},
159     {State::EXPANDED, "expanded"},
160     {State::FOCUSABLE, "focusable"},
161     {State::FOCUSED, "focused"},
162     {State::HAS_TOOLTIP, "has-tooltip"},
163     {State::HORIZONTAL, "horizontal"},
164     {State::ICONIFIED, "iconified"},
165     {State::MODAL, "modal"},
166     {State::MULTI_LINE, "multi-line"},
167     {State::MULTI_SELECTABLE, "multiselectable"},
168     {State::OPAQUE, "opaque"},
169     {State::PRESSED, "pressed"},
170     {State::RESIZEABLE, "resizable"},
171     {State::SELECTABLE, "selectable"},
172     {State::SELECTED, "selected"},
173     {State::SENSITIVE, "sensitive"},
174     {State::SHOWING, "showing"},
175     {State::SINGLE_LINE, "single-line"},
176     {State::STALE, "stale"},
177     {State::TRANSIENT, "transient"},
178     {State::VERTICAL, "vertical"},
179     {State::VISIBLE, "visible"},
180     {State::MANAGES_DESCENDANTS, "manages-descendants"},
181     {State::INDETERMINATE, "indeterminate"},
182     {State::REQUIRED, "required"},
183     {State::TRUNCATED, "truncated"},
184     {State::ANIMATED, "animated"},
185     {State::INVALID_ENTRY, "invalid-entry"},
186     {State::SUPPORTS_AUTOCOMPLETION, "supports-autocompletion"},
187     {State::SELECTABLE_TEXT, "selectable-text"},
188     {State::IS_DEFAULT, "is-default"},
189     {State::VISITED, "visited"},
190     {State::CHECKABLE, "checkable"},
191     {State::HAS_POPUP, "has-popup"},
192     {State::READ_ONLY, "read-only"},
193     {State::HIGHLIGHTED, "highlighted"},
194     {State::HIGHLIGHTABLE, "highlightable"},
195   };
196
197   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::STATE_CHANGED]) // separate ?
198   {
199     return;
200   }
201
202   auto stateName = stateMap.find(state);
203
204   if(stateName != stateMap.end())
205   {
206     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
207       GetAccessiblePath(obj),
208       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
209       "StateChanged",
210       std::string{stateName->second},
211       newValue,
212       reserved,
213       {0},
214       {"", "root"});
215   }
216 }
217
218 void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
219 {
220   if(!IsUp() || !IsBoundsChangedEventAllowed || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::BOUNDS_CHANGED])
221   {
222     return;
223   }
224
225   DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
226     std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
227
228   AddCoalescableMessage(CoalescableMessages::BOUNDS_CHANGED, obj, 1.0f, [=]() {
229     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
230       GetAccessiblePath(obj),
231       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
232       "BoundsChanged",
233       "",
234       0,
235       0,
236       tmp,
237       {"", "root"});
238   });
239 }
240
241 void BridgeObject::EmitPostRender(Accessible *obj)
242 {
243   AddCoalescableMessage(CoalescableMessages::POST_RENDER, obj, 0.5f, [=]() {
244     Emit(obj, WindowEvent::POST_RENDER);
245   });
246 }
247
248 void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
249 {
250   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
251   {
252     return;
253   }
254
255   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
256     GetAccessiblePath(obj),
257     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
258     "TextCaretMoved",
259     "",
260     cursorPosition,
261     0,
262     {0},
263     {"", "root"});
264 }
265
266 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
267 {
268   static const std::unordered_map<TextChangedState, std::string_view> stateMap{
269     {TextChangedState::INSERTED, "insert"},
270     {TextChangedState::DELETED, "delete"},
271   };
272
273   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CHANGED])
274   {
275     return;
276   }
277
278   auto stateName = stateMap.find(state);
279
280   if(stateName != stateMap.end())
281   {
282     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
283       GetAccessiblePath(obj),
284       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
285       "TextChanged",
286       std::string{stateName->second},
287       position,
288       length,
289       {content},
290       {"", "root"});
291   }
292 }
293
294 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
295 {
296   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::MOVED_OUT])
297   {
298     return;
299   }
300
301   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
302     GetAccessiblePath(obj),
303     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
304     "MoveOuted",
305     "",
306     static_cast<int>(type),
307     0,
308     {0},
309     {"", "root"});
310 }
311
312 void BridgeObject::EmitSocketAvailable(Accessible* obj)
313 {
314   if(!IsUp() || obj->IsHidden()) //TODO Suppress SocketAvailable event
315   {
316     return;
317   }
318
319   mDbusServer.emit2<Address, Address>(
320     GetAccessiblePath(obj),
321     Accessible::GetInterfaceName(AtspiInterface::SOCKET),
322     "Available",
323     obj->GetAddress(),
324     {"", "root"});
325 }
326
327 void BridgeObject::EmitScrollStarted(Accessible* obj)
328 {
329   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_STARTED])
330   {
331     return;
332   }
333
334   mDbusServer.emit2<Address>(
335     GetAccessiblePath(obj),
336     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
337     "ScrollStarted",
338     {"", "root"});
339 }
340
341 void BridgeObject::EmitScrollFinished(Accessible* obj)
342 {
343   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_FINISHED])
344   {
345     return;
346   }
347
348   mDbusServer.emit2<Address>(
349     GetAccessiblePath(obj),
350     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
351     "ScrollFinished",
352     {"", "root"});
353 }