[ATSPI] Blocking unwanted emission of "MoveOuted" signal
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-object.cpp
1 /*
2  * Copyright (c) 2021 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
25 using namespace Dali::Accessibility;
26
27 BridgeObject::BridgeObject()
28 {
29 }
30
31 void BridgeObject::RegisterInterfaces()
32 {
33   // DBus::DBusInterfaceDescription desc{ AtspiDbusInterfaceEventObject };
34   // stateChanged = addSignal<std::string, int, int, DBus::EldbusVariant<int>, Accessible*>(desc, "StateChanged");
35   // dbusServer.addInterface("/", desc, true);
36 }
37
38 void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* child)
39 {
40   if(!IsUp()) return;
41   auto index = child->GetIndexInParent();
42
43   auto        addr       = obj->GetAddress();
44   const auto  prefixPath = "/org/a11y/atspi/accessible/";
45   const auto  nullPath   = "/org/a11y/atspi/null";
46   std::string p;
47   if(addr)
48     p = prefixPath + addr.GetPath();
49   else
50     p = nullPath;
51   dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<Address>, Address>(
52     p,
53     AtspiDbusInterfaceEventObject,
54     "ActiveDescendantChanged",
55     "",
56     index,
57     0,
58     {child->GetAddress()},
59     {"", "root"});
60 }
61
62 void BridgeObject::Emit(Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent ev)
63 {
64   if(!IsUp()) return;
65   const char* name = nullptr;
66   switch(ev)
67   {
68     case ObjectPropertyChangeEvent::NAME:
69     {
70       name = "accessible-name";
71       break;
72     }
73     case ObjectPropertyChangeEvent::DESCRIPTION:
74     {
75       name = "accessible-description";
76       break;
77     }
78     case ObjectPropertyChangeEvent::VALUE:
79     {
80       name = "accessible-value";
81       break;
82     }
83     case ObjectPropertyChangeEvent::PARENT:
84     {
85       name = "accessible-parent";
86       break;
87     }
88     case ObjectPropertyChangeEvent::ROLE:
89     {
90       name = "accessible-role";
91       break;
92     }
93   }
94   if(name)
95   {
96     auto        addr = obj->GetAddress();
97     std::string p;
98     if(addr)
99       p = ATSPI_PREFIX_PATH + addr.GetPath();
100     else
101       p = ATSPI_NULL_PATH;
102     dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
103       p,
104       AtspiDbusInterfaceEventObject,
105       "PropertyChange",
106       name,
107       0,
108       0,
109       {0},
110       {"", "root"});
111   }
112 }
113
114 void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
115 {
116   if(!IsUp()) return;
117   const char* name = nullptr;
118   switch(event)
119   {
120     case WindowEvent::PROPERTY_CHANGE:
121     {
122       name = "PropertyChange";
123       break;
124     }
125     case WindowEvent::MINIMIZE:
126     {
127       name = "Minimize";
128       break;
129     }
130     case WindowEvent::MAXIMIZE:
131     {
132       name = "Maximize";
133       break;
134     }
135     case WindowEvent::RESTORE:
136     {
137       name = "Restore";
138       break;
139     }
140     case WindowEvent::CLOSE:
141     {
142       name = "Close";
143       break;
144     }
145     case WindowEvent::CREATE:
146     {
147       name = "Create";
148       break;
149     }
150     case WindowEvent::REPARENT:
151     {
152       name = "Reparent";
153       break;
154     }
155     case WindowEvent::DESKTOP_CREATE:
156     {
157       name = "DesktopCreate";
158       break;
159     }
160     case WindowEvent::DESKTOP_DESTROY:
161     {
162       name = "DesktopDestroy";
163       break;
164     }
165     case WindowEvent::DESTROY:
166     {
167       name = "Destroy";
168       break;
169     }
170     case WindowEvent::ACTIVATE:
171     {
172       name = "Activate";
173       break;
174     }
175     case WindowEvent::DEACTIVATE:
176     {
177       name = "Deactivate";
178       break;
179     }
180     case WindowEvent::RAISE:
181     {
182       name = "Raise";
183       break;
184     }
185     case WindowEvent::LOWER:
186     {
187       name = "Lower";
188       break;
189     }
190     case WindowEvent::MOVE:
191     {
192       name = "Move";
193       break;
194     }
195     case WindowEvent::RESIZE:
196     {
197       name = "Resize";
198       break;
199     }
200     case WindowEvent::SHADE:
201     {
202       name = "Shade";
203       break;
204     }
205     case WindowEvent::UU_SHADE:
206     {
207       name = "uUshade";
208       break;
209     }
210     case WindowEvent::RESTYLE:
211     {
212       name = "Restyle";
213       break;
214     }
215   }
216   if(name)
217   {
218     auto        addr = obj->GetAddress();
219     std::string p;
220     if(addr)
221       p = ATSPI_PREFIX_PATH + addr.GetPath();
222     else
223       p = ATSPI_NULL_PATH;
224     dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
225       p,
226       AtspiDbusInterfaceEventWindow,
227       name,
228       "",
229       detail,
230       0,
231       {0},
232       {"", "root"});
233   }
234 }
235
236 void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, int reserved)
237 {
238   if(!IsUp()) return;
239   const char* stateName = nullptr;
240   switch(state)
241   {
242     case State::INVALID:
243     {
244       stateName = "invalid";
245       break;
246     }
247     case State::ACTIVE:
248     {
249       stateName = "active";
250       break;
251     }
252     case State::ARMED:
253     {
254       stateName = "armed";
255       break;
256     }
257     case State::BUSY:
258     {
259       stateName = "busy";
260       break;
261     }
262     case State::CHECKED:
263     {
264       stateName = "checked";
265       break;
266     }
267     case State::COLLAPSED:
268     {
269       stateName = "collapsed";
270       break;
271     }
272     case State::DEFUNCT:
273     {
274       stateName = "defunct";
275       break;
276     }
277     case State::EDITABLE:
278     {
279       stateName = "editable";
280       break;
281     }
282     case State::ENABLED:
283     {
284       stateName = "enabled";
285       break;
286     }
287     case State::EXPANDABLE:
288     {
289       stateName = "expandable";
290       break;
291     }
292     case State::EXPANDED:
293     {
294       stateName = "expanded";
295       break;
296     }
297     case State::FOCUSABLE:
298     {
299       stateName = "focusable";
300       break;
301     }
302     case State::FOCUSED:
303     {
304       stateName = "focused";
305       break;
306     }
307     case State::HAS_TOOLTIP:
308     {
309       stateName = "has-tooltip";
310       break;
311     }
312     case State::HORIZONTAL:
313     {
314       stateName = "horizontal";
315       break;
316     }
317     case State::ICONIFIED:
318     {
319       stateName = "iconified";
320       break;
321     }
322     case State::MODAL:
323     {
324       stateName = "modal";
325       break;
326     }
327     case State::MULTI_LINE:
328     {
329       stateName = "multi-line";
330       break;
331     }
332     case State::MULTI_SELECTABLE:
333     {
334       stateName = "multiselectable";
335       break;
336     }
337     case State::OPAQUE:
338     {
339       stateName = "opaque";
340       break;
341     }
342     case State::PRESSED:
343     {
344       stateName = "pressed";
345       break;
346     }
347     case State::RESIZEABLE:
348     {
349       stateName = "resizable";
350       break;
351     }
352     case State::SELECTABLE:
353     {
354       stateName = "selectable";
355       break;
356     }
357     case State::SELECTED:
358     {
359       stateName = "selected";
360       break;
361     }
362     case State::SENSITIVE:
363     {
364       stateName = "sensitive";
365       break;
366     }
367     case State::SHOWING:
368     {
369       stateName = "showing";
370       break;
371     }
372     case State::SINGLE_LINE:
373     {
374       stateName = "single-line";
375       break;
376     }
377     case State::STALE:
378     {
379       stateName = "stale";
380       break;
381     }
382     case State::TRANSIENT:
383     {
384       stateName = "transient";
385       break;
386     }
387     case State::VERTICAL:
388     {
389       stateName = "vertical";
390       break;
391     }
392     case State::VISIBLE:
393     {
394       stateName = "visible";
395       break;
396     }
397     case State::MANAGES_DESCENDANTS:
398     {
399       stateName = "manages-descendants";
400       break;
401     }
402     case State::INDETERMINATE:
403     {
404       stateName = "indeterminate";
405       break;
406     }
407     case State::REQUIRED:
408     {
409       stateName = "required";
410       break;
411     }
412     case State::TRUNCATED:
413     {
414       stateName = "truncated";
415       break;
416     }
417     case State::ANIMATED:
418     {
419       stateName = "animated";
420       break;
421     }
422     case State::INVALID_ENTRY:
423     {
424       stateName = "invalid-entry";
425       break;
426     }
427     case State::SUPPORTS_AUTOCOMPLETION:
428     {
429       stateName = "supports-autocompletion";
430       break;
431     }
432     case State::SELECTABLE_TEXT:
433     {
434       stateName = "selectable-text";
435       break;
436     }
437     case State::IS_DEFAULT:
438     {
439       stateName = "is-default";
440       break;
441     }
442     case State::VISITED:
443     {
444       stateName = "visited";
445       break;
446     }
447     case State::CHECKABLE:
448     {
449       stateName = "checkable";
450       break;
451     }
452     case State::HAS_POPUP:
453     {
454       stateName = "has-popup";
455       break;
456     }
457     case State::READ_ONLY:
458     {
459       stateName = "read-only";
460       break;
461     }
462     case State::HIGHLIGHTED:
463     {
464       stateName = "highlighted";
465       break;
466     }
467     case State::HIGHLIGHTABLE:
468     {
469       stateName = "highlightable";
470       break;
471     }
472     case State::MAX_COUNT:
473     {
474       break;
475     }
476   }
477   if(stateName)
478   {
479     auto        addr = obj->GetAddress();
480     std::string p;
481     if(addr)
482       p = ATSPI_PREFIX_PATH + addr.GetPath();
483     else
484       p = ATSPI_NULL_PATH;
485     dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
486       p,
487       AtspiDbusInterfaceEventObject,
488       "StateChanged",
489       stateName,
490       newValue,
491       reserved,
492       {0},
493       {"", "root"});
494   }
495 }
496
497 void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
498 {
499   if(!allowObjectBoundsChangedEvent) return;
500
501   auto        addr       = obj->GetAddress();
502   const auto  prefixPath = "/org/a11y/atspi/accessible/";
503   const auto  nullPath   = "/org/a11y/atspi/null";
504   std::string p;
505   if(addr)
506     p = prefixPath + addr.GetPath();
507   else
508     p = nullPath;
509   DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
510     std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
511   addFilteredEvent(FilteredEvents::boundsChanged, obj, 1.0f, [=]() {
512     dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
513       p,
514       AtspiDbusInterfaceEventObject,
515       "BoundsChanged",
516       "",
517       0,
518       0,
519       tmp,
520       {"", "root"});
521   });
522 }
523
524 void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
525 {
526   auto        addr = obj->GetAddress();
527   std::string p    = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH;
528   dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
529     p,
530     AtspiDbusInterfaceEventObject,
531     "TextCaretMoved",
532     "",
533     cursorPosition,
534     0,
535     {0},
536     {"", "root"});
537 }
538
539 void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content)
540 {
541   const char* stateName = nullptr;
542   switch(state)
543   {
544     case TextChangedState::INSERTED:
545     {
546       stateName = "insert";
547       break;
548     }
549     case TextChangedState::DELETED:
550     {
551       stateName = "delete";
552       break;
553     }
554     case TextChangedState::MAX_COUNT:
555     {
556       break;
557     }
558   }
559   if(stateName)
560   {
561     auto        addr = obj->GetAddress();
562     std::string p    = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH;
563     dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
564       p,
565       AtspiDbusInterfaceEventObject,
566       "TextChanged",
567       stateName,
568       position,
569       length,
570       {content},
571       {"", "root"});
572   }
573 }
574
575 void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type)
576 {
577   auto        addr = obj->GetAddress();
578   std::string p    = addr ? ATSPI_PREFIX_PATH + addr.GetPath() : ATSPI_NULL_PATH;
579   dbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
580     p,
581     AtspiDbusInterfaceEventObject,
582     "MoveOuted",
583     "",
584     static_cast<int>(type),
585     0,
586     {0},
587     {"", "root"});
588 }