2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/accessibility/bridge/bridge-object.h>
24 #include <string_view>
25 #include <unordered_map>
27 using namespace Dali::Accessibility;
31 inline std::string GetAccessiblePath(Accessible* accessible)
33 auto address = accessible->GetAddress();
34 return address ? ATSPI_PREFIX_PATH + address.GetPath() : ATSPI_NULL_PATH;
38 BridgeObject::BridgeObject()
42 void BridgeObject::RegisterInterfaces()
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);
49 void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* child)
51 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::ACTIVE_DESCENDANT_CHANGED] || child->IsHidden())
56 auto index = child->GetIndexInParent();
58 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<Address>, Address>(
59 GetAccessiblePath(obj),
60 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
61 "ActiveDescendantChanged",
65 {child->GetAddress()},
69 void BridgeObject::Emit(Accessible* obj, ObjectPropertyChangeEvent event)
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"},
79 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::PROPERTY_CHANGED])
84 auto eventName = eventMap.find(event);
86 if(eventName != eventMap.end())
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),
93 std::string{eventName->second},
102 void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
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"},
127 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::WINDOW_CHANGED])
132 auto eventName = eventMap.find(event);
134 if(eventName != eventMap.end())
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},
148 void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, int reserved)
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"},
199 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::STATE_CHANGED]) // separate ?
204 auto stateName = stateMap.find(state);
206 if(stateName != stateMap.end())
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),
213 std::string{stateName->second},
222 void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
224 if(!IsUp() || !IsBoundsChangedEventAllowed || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::BOUNDS_CHANGED])
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}};
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),
245 void BridgeObject::EmitPostRender(Accessible *obj)
247 if(!IsUp() || obj->IsHidden())
252 AddCoalescableMessage(CoalescableMessages::POST_RENDER, obj, 0.5f, [=]() {
253 Emit(obj, WindowEvent::POST_RENDER);
257 void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
259 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
264 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
265 GetAccessiblePath(obj),
266 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
275 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
277 static const std::unordered_map<TextChangedState, std::string_view> stateMap{
278 {TextChangedState::INSERTED, "insert"},
279 {TextChangedState::DELETED, "delete"},
282 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CHANGED])
287 auto stateName = stateMap.find(state);
289 if(stateName != stateMap.end())
291 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
292 GetAccessiblePath(obj),
293 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
295 std::string{stateName->second},
303 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
305 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::MOVED_OUT])
310 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
311 GetAccessiblePath(obj),
312 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
315 static_cast<int>(type),
321 void BridgeObject::EmitSocketAvailable(Accessible* obj)
323 if(!IsUp() || obj->IsHidden()) //TODO Suppress SocketAvailable event
328 mDbusServer.emit2<Address, Address>(
329 GetAccessiblePath(obj),
330 Accessible::GetInterfaceName(AtspiInterface::SOCKET),
336 void BridgeObject::EmitScrollStarted(Accessible* obj)
338 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_STARTED])
343 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
344 GetAccessiblePath(obj),
345 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
354 void BridgeObject::EmitScrollFinished(Accessible* obj)
356 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_FINISHED])
361 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
362 GetAccessiblePath(obj),
363 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),