[ATSPI] Introduce SetListenPostRender interface
[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::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
242 {
243   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
244   {
245     return;
246   }
247
248   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
249     GetAccessiblePath(obj),
250     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
251     "TextCaretMoved",
252     "",
253     cursorPosition,
254     0,
255     {0},
256     {"", "root"});
257 }
258
259 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
260 {
261   static const std::unordered_map<TextChangedState, std::string_view> stateMap{
262     {TextChangedState::INSERTED, "insert"},
263     {TextChangedState::DELETED, "delete"},
264   };
265
266   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CHANGED])
267   {
268     return;
269   }
270
271   auto stateName = stateMap.find(state);
272
273   if(stateName != stateMap.end())
274   {
275     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
276       GetAccessiblePath(obj),
277       Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
278       "TextChanged",
279       std::string{stateName->second},
280       position,
281       length,
282       {content},
283       {"", "root"});
284   }
285 }
286
287 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
288 {
289   if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::MOVED_OUT])
290   {
291     return;
292   }
293
294   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
295     GetAccessiblePath(obj),
296     Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
297     "MoveOuted",
298     "",
299     static_cast<int>(type),
300     0,
301     {0},
302     {"", "root"});
303 }
304
305 void BridgeObject::EmitSocketAvailable(Accessible* obj)
306 {
307   if(!IsUp() || obj->IsHidden()) //TODO Suppress SocketAvailable event
308   {
309     return;
310   }
311
312   mDbusServer.emit2<Address, Address>(
313     GetAccessiblePath(obj),
314     Accessible::GetInterfaceName(AtspiInterface::SOCKET),
315     "Available",
316     obj->GetAddress(),
317     {"", "root"});
318 }