2 * Copyright (c) 2024 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(std::shared_ptr<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.get(), 1.0f, [weakObj = std::weak_ptr<Accessible>(obj), eventName, this]() {
89 if(auto obj = weakObj.lock())
91 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
92 GetAccessiblePath(obj.get()),
93 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
95 std::string{eventName->second},
105 void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
107 static const std::unordered_map<WindowEvent, std::string_view> eventMap{
108 {WindowEvent::PROPERTY_CHANGE, "PropertyChange"},
109 {WindowEvent::MINIMIZE, "Minimize"},
110 {WindowEvent::MAXIMIZE, "Maximize"},
111 {WindowEvent::RESTORE, "Restore"},
112 {WindowEvent::CLOSE, "Close"},
113 {WindowEvent::CREATE, "Create"},
114 {WindowEvent::REPARENT, "Reparent"},
115 {WindowEvent::DESKTOP_CREATE, "DesktopCreate"},
116 {WindowEvent::DESKTOP_DESTROY, "DesktopDestroy"},
117 {WindowEvent::DESTROY, "Destroy"},
118 {WindowEvent::ACTIVATE, "Activate"},
119 {WindowEvent::DEACTIVATE, "Deactivate"},
120 {WindowEvent::RAISE, "Raise"},
121 {WindowEvent::LOWER, "Lower"},
122 {WindowEvent::MOVE, "Move"},
123 {WindowEvent::RESIZE, "Resize"},
124 {WindowEvent::SHADE, "Shade"},
125 {WindowEvent::UU_SHADE, "uUshade"},
126 {WindowEvent::RESTYLE, "Restyle"},
127 {WindowEvent::POST_RENDER, "PostRender"},
130 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::WINDOW_CHANGED])
135 auto eventName = eventMap.find(event);
137 if(eventName != eventMap.end())
139 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
140 GetAccessiblePath(obj),
141 Accessible::GetInterfaceName(AtspiInterface::EVENT_WINDOW),
142 std::string{eventName->second},
151 void BridgeObject::EmitStateChanged(std::shared_ptr<Accessible> obj, State state, int newValue, int reserved)
153 static const std::unordered_map<State, std::string_view> stateMap{
154 {State::INVALID, "invalid"},
155 {State::ACTIVE, "active"},
156 {State::ARMED, "armed"},
157 {State::BUSY, "busy"},
158 {State::CHECKED, "checked"},
159 {State::COLLAPSED, "collapsed"},
160 {State::DEFUNCT, "defunct"},
161 {State::EDITABLE, "editable"},
162 {State::ENABLED, "enabled"},
163 {State::EXPANDABLE, "expandable"},
164 {State::EXPANDED, "expanded"},
165 {State::FOCUSABLE, "focusable"},
166 {State::FOCUSED, "focused"},
167 {State::HAS_TOOLTIP, "has-tooltip"},
168 {State::HORIZONTAL, "horizontal"},
169 {State::ICONIFIED, "iconified"},
170 {State::MODAL, "modal"},
171 {State::MULTI_LINE, "multi-line"},
172 {State::MULTI_SELECTABLE, "multiselectable"},
173 {State::OPAQUE, "opaque"},
174 {State::PRESSED, "pressed"},
175 {State::RESIZEABLE, "resizable"},
176 {State::SELECTABLE, "selectable"},
177 {State::SELECTED, "selected"},
178 {State::SENSITIVE, "sensitive"},
179 {State::SHOWING, "showing"},
180 {State::SINGLE_LINE, "single-line"},
181 {State::STALE, "stale"},
182 {State::TRANSIENT, "transient"},
183 {State::VERTICAL, "vertical"},
184 {State::VISIBLE, "visible"},
185 {State::MANAGES_DESCENDANTS, "manages-descendants"},
186 {State::INDETERMINATE, "indeterminate"},
187 {State::REQUIRED, "required"},
188 {State::TRUNCATED, "truncated"},
189 {State::ANIMATED, "animated"},
190 {State::INVALID_ENTRY, "invalid-entry"},
191 {State::SUPPORTS_AUTOCOMPLETION, "supports-autocompletion"},
192 {State::SELECTABLE_TEXT, "selectable-text"},
193 {State::IS_DEFAULT, "is-default"},
194 {State::VISITED, "visited"},
195 {State::CHECKABLE, "checkable"},
196 {State::HAS_POPUP, "has-popup"},
197 {State::READ_ONLY, "read-only"},
198 {State::HIGHLIGHTED, "highlighted"},
199 {State::HIGHLIGHTABLE, "highlightable"},
202 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::STATE_CHANGED]) // separate ?
207 auto stateName = stateMap.find(state);
209 if(stateName != stateMap.end())
211 AddCoalescableMessage(static_cast<CoalescableMessages>(static_cast<int>(CoalescableMessages::STATE_CHANGED_BEGIN) + static_cast<int>(state)), obj.get(), 1.0f, [weakObj = std::weak_ptr<Accessible>(obj), stateName, newValue, reserved, this]() {
212 if(auto obj = weakObj.lock())
214 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
215 GetAccessiblePath(obj.get()),
216 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
218 std::string{stateName->second},
228 void BridgeObject::EmitBoundsChanged(std::shared_ptr<Accessible> obj, Dali::Rect<> rect)
230 if(!IsUp() || !IsBoundsChangedEventAllowed || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::BOUNDS_CHANGED])
235 AddCoalescableMessage(CoalescableMessages::BOUNDS_CHANGED, obj.get(), 1.0f, [weakObj = std::weak_ptr<Accessible>(obj), rect = std::move(rect), this]() {
236 if(auto obj = weakObj.lock())
238 DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
239 std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
241 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
242 GetAccessiblePath(obj.get()),
243 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
254 void BridgeObject::EmitPostRender(std::shared_ptr<Accessible> obj)
256 if(!IsUp() || obj->IsHidden())
261 AddCoalescableMessage(CoalescableMessages::POST_RENDER, obj.get(), 0.5f, [weakObj = std::weak_ptr<Accessible>(obj), this]() {
262 if(auto obj = weakObj.lock())
264 Emit(obj.get(), WindowEvent::POST_RENDER);
269 void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
271 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
276 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
277 GetAccessiblePath(obj),
278 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
287 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
289 static const std::unordered_map<TextChangedState, std::string_view> stateMap{
290 {TextChangedState::INSERTED, "insert"},
291 {TextChangedState::DELETED, "delete"},
294 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CHANGED])
299 auto stateName = stateMap.find(state);
301 if(stateName != stateMap.end())
303 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
304 GetAccessiblePath(obj),
305 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
307 std::string{stateName->second},
315 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
317 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::MOVED_OUT])
322 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
323 GetAccessiblePath(obj),
324 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
327 static_cast<int>(type),
333 void BridgeObject::EmitSocketAvailable(Accessible* obj)
335 if(!IsUp() || obj->IsHidden()) //TODO Suppress SocketAvailable event
340 mDbusServer.emit2<Address, Address>(
341 GetAccessiblePath(obj),
342 Accessible::GetInterfaceName(AtspiInterface::SOCKET),
348 void BridgeObject::EmitScrollStarted(Accessible* obj)
350 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_STARTED])
355 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
356 GetAccessiblePath(obj),
357 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
366 void BridgeObject::EmitScrollFinished(Accessible* obj)
368 if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::SCROLL_FINISHED])
373 mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
374 GetAccessiblePath(obj),
375 Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),