[dali_2.3.24] Merge branch 'devel/master'
[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     AddCoalescableMessage(static_cast<CoalescableMessages>(static_cast<int>(CoalescableMessages::PROPERTY_CHANGED_BEGIN) + static_cast<int>(event)), obj, 1.0f, [=]() {
89       mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
90         GetAccessiblePath(obj),
91         Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
92         "PropertyChange",
93         std::string{eventName->second},
94         0,
95         0,
96         {0},
97         {"", "root"});
98     });
99   }
100 }
101
102 void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
103 {
104   static const std::unordered_map<WindowEvent, std::string_view> eventMap{
105     {WindowEvent::PROPERTY_CHANGE, "PropertyChange"},
106     {WindowEvent::MINIMIZE, "Minimize"},
107     {WindowEvent::MAXIMIZE, "Maximize"},
108     {WindowEvent::RESTORE, "Restore"},
109     {WindowEvent::CLOSE, "Close"},
110     {WindowEvent::CREATE, "Create"},
111     {WindowEvent::REPARENT, "Reparent"},
112     {WindowEvent::DESKTOP_CREATE, "DesktopCreate"},
113     {WindowEvent::DESKTOP_DESTROY, "DesktopDestroy"},
114     {WindowEvent::DESTROY, "Destroy"},
115     {WindowEvent::ACTIVATE, "Activate"},
116     {WindowEvent::DEACTIVATE, "Deactivate"},
117     {WindowEvent::RAISE, "Raise"},
118     {WindowEvent::LOWER, "Lower"},
119     {WindowEvent::MOVE, "Move"},
120     {WindowEvent::RESIZE, "Resize"},
121     {WindowEvent::SHADE, "Shade"},
122     {WindowEvent::UU_SHADE, "uUshade"},
123     {WindowEvent::RESTYLE, "Restyle"},
124     {WindowEvent::POST_RENDER, "PostRender"},
125   };
126
127   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::WINDOW_CHANGED])
128   {
129     return;
130   }
131
132   auto eventName = eventMap.find(event);
133
134   if(eventName != eventMap.end())
135   {
136     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
137       GetAccessiblePath(obj),
138       Accessible::GetInterfaceName(AtspiInterface::EVENT_WINDOW),
139       std::string{eventName->second},
140       "",
141       detail,
142       0,
143       {0},
144       {"", "root"});
145   }
146 }
147
148 void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, int reserved)
149 {
150   static const std::unordered_map<State, std::string_view> stateMap{
151     {State::INVALID, "invalid"},
152     {State::ACTIVE, "active"},
153     {State::ARMED, "armed"},
154     {State::BUSY, "busy"},
155     {State::CHECKED, "checked"},
156     {State::COLLAPSED, "collapsed"},
157     {State::DEFUNCT, "defunct"},
158     {State::EDITABLE, "editable"},
159     {State::ENABLED, "enabled"},
160     {State::EXPANDABLE, "expandable"},
161     {State::EXPANDED, "expanded"},
162     {State::FOCUSABLE, "focusable"},
163     {State::FOCUSED, "focused"},
164     {State::HAS_TOOLTIP, "has-tooltip"},
165     {State::HORIZONTAL, "horizontal"},
166     {State::ICONIFIED, "iconified"},
167     {State::MODAL, "modal"},
168     {State::MULTI_LINE, "multi-line"},
169     {State::MULTI_SELECTABLE, "multiselectable"},
170     {State::OPAQUE, "opaque"},
171     {State::PRESSED, "pressed"},
172     {State::RESIZEABLE, "resizable"},
173     {State::SELECTABLE, "selectable"},
174     {State::SELECTED, "selected"},
175     {State::SENSITIVE, "sensitive"},
176     {State::SHOWING, "showing"},
177     {State::SINGLE_LINE, "single-line"},
178     {State::STALE, "stale"},
179     {State::TRANSIENT, "transient"},
180     {State::VERTICAL, "vertical"},
181     {State::VISIBLE, "visible"},
182     {State::MANAGES_DESCENDANTS, "manages-descendants"},
183     {State::INDETERMINATE, "indeterminate"},
184     {State::REQUIRED, "required"},
185     {State::TRUNCATED, "truncated"},
186     {State::ANIMATED, "animated"},
187     {State::INVALID_ENTRY, "invalid-entry"},
188     {State::SUPPORTS_AUTOCOMPLETION, "supports-autocompletion"},
189     {State::SELECTABLE_TEXT, "selectable-text"},
190     {State::IS_DEFAULT, "is-default"},
191     {State::VISITED, "visited"},
192     {State::CHECKABLE, "checkable"},
193     {State::HAS_POPUP, "has-popup"},
194     {State::READ_ONLY, "read-only"},
195     {State::HIGHLIGHTED, "highlighted"},
196     {State::HIGHLIGHTABLE, "highlightable"},
197   };
198
199   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::STATE_CHANGED]) // separate ?
200   {
201     return;
202   }
203
204   auto stateName = stateMap.find(state);
205
206   if(stateName != stateMap.end())
207   {
208     AddCoalescableMessage(static_cast<CoalescableMessages>(static_cast<int>(CoalescableMessages::STATE_CHANGED_BEGIN) + static_cast<int>(state)), obj, 1.0f, [=]() {
209       mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
210         GetAccessiblePath(obj),
211         Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
212         "StateChanged",
213         std::string{stateName->second},
214         newValue,
215         reserved,
216         {0},
217         {"", "root"});
218     });
219   }
220 }
221
222 void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
223 {
224   if(!IsUp() || !IsBoundsChangedEventAllowed || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::BOUNDS_CHANGED])
225   {
226     return;
227   }
228
229   DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
230     std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
231
232   AddCoalescableMessage(CoalescableMessages::BOUNDS_CHANGED, obj, 1.0f, [=]() {
233     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
234       GetAccessiblePath(obj),
235       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
236       "BoundsChanged",
237       "",
238       0,
239       0,
240       tmp,
241       {"", "root"});
242   });
243 }
244
245 void BridgeObject::EmitPostRender(Accessible *obj)
246 {
247   if(!IsUp() || obj->IsHidden())
248   {
249     return;
250   }
251
252   AddCoalescableMessage(CoalescableMessages::POST_RENDER, obj, 0.5f, [=]() {
253     Emit(obj, WindowEvent::POST_RENDER);
254   });
255 }
256
257 void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
258 {
259   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
260   {
261     return;
262   }
263
264   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
265     GetAccessiblePath(obj),
266     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
267     "TextCaretMoved",
268     "",
269     cursorPosition,
270     0,
271     {0},
272     {"", "root"});
273 }
274
275 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
276 {
277   static const std::unordered_map<TextChangedState, std::string_view> stateMap{
278     {TextChangedState::INSERTED, "insert"},
279     {TextChangedState::DELETED, "delete"},
280   };
281
282   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CHANGED])
283   {
284     return;
285   }
286
287   auto stateName = stateMap.find(state);
288
289   if(stateName != stateMap.end())
290   {
291     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
292       GetAccessiblePath(obj),
293       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
294       "TextChanged",
295       std::string{stateName->second},
296       position,
297       length,
298       {content},
299       {"", "root"});
300   }
301 }
302
303 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
304 {
305   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::MOVED_OUT])
306   {
307     return;
308   }
309
310   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
311     GetAccessiblePath(obj),
312     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
313     "MoveOuted",
314     "",
315     static_cast<int>(type),
316     0,
317     {0},
318     {"", "root"});
319 }
320
321 void BridgeObject::EmitSocketAvailable(Accessible* obj)
322 {
323   if(!IsUp() || obj->IsHidden()) //TODO Suppress SocketAvailable event
324   {
325     return;
326   }
327
328   mDbusServer.emit2<Address, Address>(
329     GetAccessiblePath(obj),
330     Accessible::GetInterfaceName(AtspiInterface::SOCKET),
331     "Available",
332     obj->GetAddress(),
333     {"", "root"});
334 }
335
336 void BridgeObject::EmitScrollStarted(Accessible* obj)
337 {
338   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_STARTED])
339   {
340     return;
341   }
342
343   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
344     GetAccessiblePath(obj),
345     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
346     "ScrollStarted",
347     "",
348     0,
349     0,
350     {0},
351     {"", "root"});
352 }
353
354 void BridgeObject::EmitScrollFinished(Accessible* obj)
355 {
356   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_FINISHED])
357   {
358     return;
359   }
360
361   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
362     GetAccessiblePath(obj),
363     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
364     "ScrollFinished",
365     "",
366     0,
367     0,
368     {0},
369     {"", "root"});
370 }