Merge "[AT-SPI] Add Socket interface" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-impl.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
20 // EXTERNAL INCLUDES
21 #include <dali/devel-api/common/stage.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/actors/layer.h>
24 #include <iostream>
25 #include <unordered_map>
26
27 // INTERNAL INCLUDES
28 #include <dali/devel-api/adaptor-framework/environment-variable.h>
29 #include <dali/devel-api/adaptor-framework/window-devel.h>
30 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
31 #include <dali/internal/accessibility/bridge/bridge-action.h>
32 #include <dali/internal/accessibility/bridge/bridge-collection.h>
33 #include <dali/internal/accessibility/bridge/bridge-component.h>
34 #include <dali/internal/accessibility/bridge/bridge-editable-text.h>
35 #include <dali/internal/accessibility/bridge/bridge-hypertext.h>
36 #include <dali/internal/accessibility/bridge/bridge-hyperlink.h>
37 #include <dali/internal/accessibility/bridge/bridge-object.h>
38 #include <dali/internal/accessibility/bridge/bridge-selection.h>
39 #include <dali/internal/accessibility/bridge/bridge-socket.h>
40 #include <dali/internal/accessibility/bridge/bridge-text.h>
41 #include <dali/internal/accessibility/bridge/bridge-value.h>
42 #include <dali/internal/accessibility/bridge/bridge-application.h>
43 #include <dali/internal/accessibility/bridge/dummy-atspi.h>
44 #include <dali/internal/adaptor/common/adaptor-impl.h>
45 #include <dali/internal/system/common/environment-variables.h>
46
47 using namespace Dali::Accessibility;
48
49 namespace // unnamed namespace
50 {
51
52 const int RETRY_INTERVAL = 1000;
53
54 } // unnamed namespace
55
56 /**
57  * @brief The BridgeImpl class is to implement some Bridge functions.
58  */
59 class BridgeImpl : public virtual BridgeBase,
60                    public BridgeAccessible,
61                    public BridgeObject,
62                    public BridgeComponent,
63                    public BridgeCollection,
64                    public BridgeAction,
65                    public BridgeValue,
66                    public BridgeText,
67                    public BridgeEditableText,
68                    public BridgeSelection,
69                    public BridgeApplication,
70                    public BridgeHypertext,
71                    public BridgeHyperlink,
72                    public BridgeSocket
73 {
74   DBus::DBusClient                                              mAccessibilityStatusClient;
75   DBus::DBusClient                                              mRegistryClient;
76   DBus::DBusClient                                              mDirectReadingClient;
77   bool                                                          mIsScreenReaderEnabled = false;
78   bool                                                          mIsEnabled             = false;
79   bool                                                          mIsShown               = false;
80   std::unordered_map<int32_t, std::function<void(std::string)>> mDirectReadingCallbacks;
81   Dali::Actor                                                   mHighlightedActor;
82   std::function<void(Dali::Actor)>                              mHighlightClearAction;
83   Dali::CallbackBase*                                           mIdleCallback          = NULL;
84   Dali::Timer                                                   mInitializeTimer;
85   Dali::Timer                                                   mReadIsEnabledTimer;
86   Dali::Timer                                                   mReadScreenReaderEnabledTimer;
87   Dali::Timer                                                   mForceUpTimer;
88
89 public:
90   BridgeImpl()
91   {
92   }
93
94   /**
95    * @copydoc Dali::Accessibility::Bridge::Emit()
96    */
97   Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
98   {
99     if(!IsUp())
100     {
101       return Consumed::NO;
102     }
103
104     unsigned int keyType = 0;
105
106     switch(type)
107     {
108       case KeyEventType::KEY_PRESSED:
109       {
110         keyType = 0;
111         break;
112       }
113       case KeyEventType::KEY_RELEASED:
114       {
115         keyType = 1;
116         break;
117       }
118       default:
119       {
120         return Consumed::NO;
121       }
122     }
123
124     auto methodObject = mRegistryClient.method<bool(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>)>("NotifyListenersSync");
125     auto result       = methodObject.call(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>{keyType, 0, static_cast<int32_t>(keyCode), 0, static_cast<int32_t>(timeStamp), keyName, isText ? 1 : 0});
126     if(!result)
127     {
128       LOG() << result.getError().message;
129       return Consumed::NO;
130     }
131     return std::get<0>(result) ? Consumed::YES : Consumed::NO;
132   }
133
134   /**
135    * @copydoc Dali::Accessibility::Bridge::Pause()
136    */
137   void Pause() override
138   {
139     if(!IsUp())
140     {
141       return;
142     }
143
144     mDirectReadingClient.method<DBus::ValueOrError<void>(bool)>("PauseResume").asyncCall([](DBus::ValueOrError<void> msg) {
145       if(!msg)
146       {
147         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
148       }
149     },
150                                                                                         true);
151   }
152
153   /**
154    * @copydoc Dali::Accessibility::Bridge::Resume()
155    */
156   void Resume() override
157   {
158     if(!IsUp())
159     {
160       return;
161     }
162
163     mDirectReadingClient.method<DBus::ValueOrError<void>(bool)>("PauseResume").asyncCall([](DBus::ValueOrError<void> msg) {
164       if(!msg)
165       {
166         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
167       }
168     },
169                                                                                         false);
170   }
171
172   /**
173    * @copydoc Dali::Accessibility::Bridge::StopReading()
174    */
175   void StopReading(bool alsoNonDiscardable) override
176   {
177     if(!IsUp())
178     {
179       return;
180     }
181
182     mDirectReadingClient.method<DBus::ValueOrError<void>(bool)>("StopReading").asyncCall([](DBus::ValueOrError<void> msg) {
183       if(!msg)
184       {
185         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
186       }
187     },
188                                                                                         alsoNonDiscardable);
189   }
190
191   /**
192    * @copydoc Dali::Accessibility::Bridge::Say()
193    */
194   void Say(const std::string& text, bool discardable, std::function<void(std::string)> callback) override
195   {
196     if(!IsUp())
197     {
198       return;
199     }
200
201     mDirectReadingClient.method<DBus::ValueOrError<std::string, bool, int32_t>(std::string, bool)>("ReadCommand").asyncCall([=](DBus::ValueOrError<std::string, bool, int32_t> msg) {
202       if(!msg)
203       {
204         LOG() << "Direct reading command failed (" << msg.getError().message << ")";
205       }
206       else if(callback)
207       {
208         mDirectReadingCallbacks.emplace(std::get<2>(msg), callback);
209       }
210     },
211                                                                                                                            text,
212                                                                                                                            discardable);
213   }
214
215   /**
216    * @copydoc Dali::Accessibility::Bridge::ForceDown()
217    */
218   void ForceDown() override
219   {
220     if(mData)
221     {
222       if(mData->mCurrentlyHighlightedActor && mData->mHighlightActor)
223       {
224         mData->mCurrentlyHighlightedActor.Remove(mData->mHighlightActor);
225       }
226       mData->mCurrentlyHighlightedActor = {};
227       mData->mHighlightActor            = {};
228
229       mDisabledSignal.Emit();
230     }
231     mHighlightedActor     = {};
232     mHighlightClearAction = {};
233     BridgeAccessible::ForceDown();
234     mRegistryClient       = {};
235     mDirectReadingClient  = {};
236     mDirectReadingCallbacks.clear();
237     mApplication.mChildren.clear();
238     mApplication.mWindows.clear();
239     ClearTimer();
240   }
241
242   void ClearTimer()
243   {
244     if(mInitializeTimer)
245     {
246       mInitializeTimer.Stop();
247       mInitializeTimer.Reset();
248     }
249
250     if(mReadIsEnabledTimer)
251     {
252       mReadIsEnabledTimer.Stop();
253       mReadIsEnabledTimer.Reset();
254     }
255
256     if(mReadScreenReaderEnabledTimer)
257     {
258       mReadScreenReaderEnabledTimer.Stop();
259       mReadScreenReaderEnabledTimer.Reset();
260     }
261
262     if(mForceUpTimer)
263     {
264       mForceUpTimer.Stop();
265       mForceUpTimer.Reset();
266     }
267   }
268
269   /**
270    * @copydoc Dali::Accessibility::Bridge::Terminate()
271    */
272   void Terminate() override
273   {
274     if(mData)
275     {
276       mData->mCurrentlyHighlightedActor = {};
277       mData->mHighlightActor            = {};
278     }
279     ForceDown();
280     if((NULL != mIdleCallback) && Dali::Adaptor::IsAvailable())
281     {
282       Dali::Adaptor::Get().RemoveIdle(mIdleCallback);
283     }
284     mAccessibilityStatusClient        = {};
285     mDbusServer                       = {};
286     mConnectionPtr                    = {};
287   }
288
289   bool ForceUpTimerCallback()
290   {
291     if(ForceUp() != ForceUpResult::FAILED)
292     {
293       return false;
294     }
295     return true;
296   }
297
298   /**
299    * @copydoc Dali::Accessibility::Bridge::ForceUp()
300    */
301   ForceUpResult ForceUp() override
302   {
303     auto forceUpResult = BridgeAccessible::ForceUp();
304     if(forceUpResult == ForceUpResult::ALREADY_UP)
305     {
306       return forceUpResult;
307     }
308     else if(forceUpResult == ForceUpResult::FAILED)
309     {
310       if(!mForceUpTimer)
311       {
312         mForceUpTimer = Dali::Timer::New(RETRY_INTERVAL);
313         mForceUpTimer.TickSignal().Connect(this, &BridgeImpl::ForceUpTimerCallback);
314         mForceUpTimer.Start();
315       }
316       return forceUpResult;
317     }
318
319     BridgeObject::RegisterInterfaces();
320     BridgeAccessible::RegisterInterfaces();
321     BridgeComponent::RegisterInterfaces();
322     BridgeCollection::RegisterInterfaces();
323     BridgeAction::RegisterInterfaces();
324     BridgeValue::RegisterInterfaces();
325     BridgeText::RegisterInterfaces();
326     BridgeEditableText::RegisterInterfaces();
327     BridgeSelection::RegisterInterfaces();
328     BridgeApplication::RegisterInterfaces();
329     BridgeHypertext::RegisterInterfaces();
330     BridgeHyperlink::RegisterInterfaces();
331     BridgeSocket::RegisterInterfaces();
332
333     RegisterOnBridge(&mApplication);
334
335     mRegistryClient      = {AtspiDbusNameRegistry, AtspiDbusPathDec, Accessible::GetInterfaceName(AtspiInterface::DEVICE_EVENT_CONTROLLER), mConnectionPtr};
336     mDirectReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, mConnectionPtr};
337
338     mDirectReadingClient.addSignal<void(int32_t, std::string)>("ReadingStateChanged", [=](int32_t id, std::string readingState) {
339       auto it = mDirectReadingCallbacks.find(id);
340       if(it != mDirectReadingCallbacks.end())
341       {
342         it->second(readingState);
343         if(readingState != "ReadingPaused" && readingState != "ReadingResumed" && readingState != "ReadingStarted")
344         {
345           mDirectReadingCallbacks.erase(it);
346         }
347       }
348     });
349
350     auto    proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, Accessible::GetInterfaceName(AtspiInterface::SOCKET), mConnectionPtr};
351     Address root{"", "root"};
352     auto    res = proxy.method<Address(Address)>("Embed").call(root);
353     if(!res)
354     {
355       LOG() << "Call to Embed failed: " << res.getError().message;
356     }
357     assert(res);
358
359     mApplication.mParent.SetAddress(std::move(std::get<0>(res)));
360
361     mEnabledSignal.Emit();
362
363     if(mIsShown)
364     {
365       auto rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
366       auto window    = Dali::DevelWindow::Get(rootLayer);
367       EmitActivate(window); // Currently, sends a signal that the default window is activated here.
368     }
369
370     return ForceUpResult::JUST_STARTED;
371   }
372
373   /**
374    * @brief Sends a signal to dbus that the window is shown.
375    *
376    * @param[in] window The window to be shown
377    * @see Accessible::EmitShowing() and BridgeObject::EmitStateChanged()
378    */
379   void EmitShown(Dali::Window window)
380   {
381     auto windowAccessible = mApplication.GetWindowAccessible(window);
382     if(windowAccessible)
383     {
384       windowAccessible->EmitShowing(true);
385     }
386   }
387
388   /**
389    * @brief Sends a signal to dbus that the window is hidden.
390    *
391    * @param[in] window The window to be hidden
392    * @see Accessible::EmitShowing() and BridgeObject::EmitStateChanged()
393    */
394   void EmitHidden(Dali::Window window)
395   {
396     auto windowAccessible = mApplication.GetWindowAccessible(window);
397     if(windowAccessible)
398     {
399       windowAccessible->EmitShowing(false);
400     }
401   }
402
403   /**
404    * @brief Sends a signal to dbus that the window is activated.
405    *
406    * @param[in] window The window to be activated
407    * @see BridgeObject::Emit()
408    */
409   void EmitActivate(Dali::Window window)
410   {
411     auto windowAccessible = mApplication.GetWindowAccessible(window);
412     if(windowAccessible)
413     {
414       windowAccessible->Emit(WindowEvent::ACTIVATE, 0);
415     }
416   }
417
418   /**
419    * @brief Sends a signal to dbus that the window is deactivated.
420    *
421    * @param[in] window The window to be deactivated
422    * @see BridgeObject::Emit()
423    */
424   void EmitDeactivate(Dali::Window window)
425   {
426     auto windowAccessible = mApplication.GetWindowAccessible(window);
427     if(windowAccessible)
428     {
429       windowAccessible->Emit(WindowEvent::DEACTIVATE, 0);
430     }
431   }
432
433   /**
434    * @copydoc Dali::Accessibility::Bridge::WindowShown()
435    */
436   void WindowShown(Dali::Window window) override
437   {
438     if(!mIsShown && IsUp())
439     {
440       EmitShown(window);
441     }
442     mIsShown = true;
443   }
444
445   /**
446    * @copydoc Dali::Accessibility::Bridge::WindowHidden()
447    */
448   void WindowHidden(Dali::Window window) override
449   {
450     if(mIsShown && IsUp())
451     {
452       EmitHidden(window);
453     }
454     mIsShown = false;
455   }
456
457   /**
458    * @copydoc Dali::Accessibility::Bridge::WindowFocused()
459    */
460   void WindowFocused(Dali::Window window) override
461   {
462     if(mIsShown && IsUp())
463     {
464       EmitActivate(window);
465     }
466   }
467
468   /**
469    * @copydoc Dali::Accessibility::Bridge::WindowUnfocused()
470    */
471   void WindowUnfocused(Dali::Window window) override
472   {
473     if(mIsShown && IsUp())
474     {
475       EmitDeactivate(window);
476     }
477   }
478
479   /**
480    * @copydoc Dali::Accessibility::Bridge::SuppressScreenReader()
481    */
482   void SuppressScreenReader(bool suppress) override
483   {
484     if(mIsScreenReaderSuppressed == suppress)
485     {
486       return;
487     }
488     mIsScreenReaderSuppressed = suppress;
489     ReadScreenReaderEnabledProperty();
490   }
491
492   void SwitchBridge()
493   {
494     if((!mIsScreenReaderSuppressed && mIsScreenReaderEnabled) || mIsEnabled)
495     {
496       ForceUp();
497     }
498     else
499     {
500       ForceDown();
501     }
502   }
503
504   bool ReadIsEnabledTimerCallback()
505   {
506     ReadIsEnabledProperty();
507     return false;
508   }
509
510   void ReadIsEnabledProperty()
511   {
512     mAccessibilityStatusClient.property<bool>("IsEnabled").asyncGet([this](DBus::ValueOrError<bool> msg) {
513       if(!msg)
514       {
515         DALI_LOG_ERROR("Get IsEnabled property error: %s\n", msg.getError().message.c_str());
516         if(msg.getError().errorType == DBus::ErrorType::INVALID_REPLY)
517         {
518           if(!mReadIsEnabledTimer)
519           {
520             mReadIsEnabledTimer = Dali::Timer::New(RETRY_INTERVAL);
521             mReadIsEnabledTimer.TickSignal().Connect(this, &BridgeImpl::ReadIsEnabledTimerCallback);
522           }
523           mReadIsEnabledTimer.Start();
524         }
525         return;
526       }
527
528       if(mReadIsEnabledTimer)
529       {
530         mReadIsEnabledTimer.Stop();
531         mReadIsEnabledTimer.Reset();
532       }
533
534       mIsEnabled = std::get<0>(msg);
535       SwitchBridge();
536     });
537   }
538
539   void ListenIsEnabledProperty()
540   {
541     mAccessibilityStatusClient.addPropertyChangedEvent<bool>("IsEnabled", [this](bool res) {
542       mIsEnabled = res;
543       SwitchBridge();
544     });
545   }
546
547   bool ReadScreenReaderEnabledTimerCallback()
548   {
549     ReadScreenReaderEnabledProperty();
550     return false;
551   }
552
553   void ReadScreenReaderEnabledProperty()
554   {
555     // can be true because of SuppressScreenReader before init
556     if (!mAccessibilityStatusClient)
557     {
558       return;
559     }
560
561     mAccessibilityStatusClient.property<bool>("ScreenReaderEnabled").asyncGet([this](DBus::ValueOrError<bool> msg) {
562       if(!msg)
563       {
564         DALI_LOG_ERROR("Get ScreenReaderEnabled property error: %s\n", msg.getError().message.c_str());
565         if(msg.getError().errorType == DBus::ErrorType::INVALID_REPLY)
566         {
567           if(!mReadScreenReaderEnabledTimer)
568           {
569             mReadScreenReaderEnabledTimer = Dali::Timer::New(RETRY_INTERVAL);
570             mReadScreenReaderEnabledTimer.TickSignal().Connect(this, &BridgeImpl::ReadScreenReaderEnabledTimerCallback);
571           }
572           mReadScreenReaderEnabledTimer.Start();
573         }
574         return;
575       }
576
577       if(mReadScreenReaderEnabledTimer)
578       {
579         mReadScreenReaderEnabledTimer.Stop();
580         mReadScreenReaderEnabledTimer.Reset();
581       }
582
583       mIsScreenReaderEnabled = std::get<0>(msg);
584       SwitchBridge();
585     });
586   }
587
588   void ListenScreenReaderEnabledProperty()
589   {
590     mAccessibilityStatusClient.addPropertyChangedEvent<bool>("ScreenReaderEnabled", [this](bool res) {
591       mIsScreenReaderEnabled = res;
592       SwitchBridge();
593     });
594   }
595
596   void ReadAndListenProperties()
597   {
598     ReadIsEnabledProperty();
599     ListenIsEnabledProperty();
600
601     ReadScreenReaderEnabledProperty();
602     ListenScreenReaderEnabledProperty();
603   }
604
605   bool InitializeAccessibilityStatusClient()
606   {
607     mAccessibilityStatusClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
608
609     if (!mAccessibilityStatusClient)
610     {
611       DALI_LOG_ERROR("Accessibility Status DbusClient is not ready\n");
612       return false;
613     }
614
615     return true;
616   }
617
618   bool InitializeTimerCallback()
619   {
620     if ( InitializeAccessibilityStatusClient() )
621     {
622       ReadAndListenProperties();
623       return false;
624     }
625     return true;
626   }
627
628   bool OnIdleSignal()
629   {
630     if ( InitializeAccessibilityStatusClient() )
631     {
632       ReadAndListenProperties();
633       mIdleCallback = NULL;
634       return false;
635     }
636
637     if(!mInitializeTimer)
638     {
639       mInitializeTimer = Dali::Timer::New(RETRY_INTERVAL);
640       mInitializeTimer.TickSignal().Connect(this, &BridgeImpl::InitializeTimerCallback);
641     }
642     mInitializeTimer.Start();
643
644     mIdleCallback = NULL;
645     return false;
646   }
647
648   /**
649    * @copydoc Dali::Accessibility::Bridge::Initialize()
650    */
651   void Initialize() override
652   {
653     if ( InitializeAccessibilityStatusClient() )
654     {
655       ReadAndListenProperties();
656       return;
657     }
658
659     // Initialize failed. Try it again on Idle
660     if( Dali::Adaptor::IsAvailable() )
661     {
662       Dali::Adaptor& adaptor = Dali::Adaptor::Get();
663       if( NULL == mIdleCallback )
664       {
665         mIdleCallback = MakeCallback( this, &BridgeImpl::OnIdleSignal );
666         adaptor.AddIdle( mIdleCallback, true );
667       }
668     }
669   }
670
671   /**
672    * @copydoc Dali::Accessibility::Bridge::GetScreenReaderEnabled()
673    */
674   bool GetScreenReaderEnabled() override
675   {
676     return mIsScreenReaderEnabled;
677   }
678
679   /**
680    * @copydoc Dali::Accessibility::Bridge::IsEnabled()
681    */
682   bool IsEnabled() override
683   {
684     return mIsEnabled;
685   }
686 }; // BridgeImpl
687
688 namespace // unnamed namespace
689 {
690
691 bool INITIALIZED_BRIDGE = false;
692
693 /**
694  * @brief Creates BridgeImpl instance.
695  *
696  * @return The BridgeImpl instance
697  * @note This method is to check environment variable first. If ATSPI is disable using env, it returns dummy bridge instance.
698  */
699 std::shared_ptr<Bridge> CreateBridge()
700 {
701   INITIALIZED_BRIDGE = true;
702
703   try
704   {
705     /* check environment variable first */
706     const char* envAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI);
707     if(envAtspiDisabled && std::atoi(envAtspiDisabled) != 0)
708     {
709       return Dali::Accessibility::DummyBridge::GetInstance();
710     }
711
712     return std::make_shared<BridgeImpl>();
713   }
714   catch(const std::exception&)
715   {
716     DALI_LOG_ERROR("Failed to initialize AT-SPI bridge");
717     return Dali::Accessibility::DummyBridge::GetInstance();
718   }
719 }
720
721 } // unnamed namespace
722
723 // Dali::Accessibility::Bridge class implementation
724
725 std::shared_ptr<Bridge> Bridge::GetCurrentBridge()
726 {
727   static std::shared_ptr<Bridge> bridge;
728
729   if(bridge)
730   {
731     return bridge;
732   }
733   else if(mAutoInitState == AutoInitState::ENABLED)
734   {
735     bridge = CreateBridge();
736
737     /* check environment variable for suppressing screen-reader */
738     const char* envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
739     if(envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
740     {
741       bridge->SuppressScreenReader(true);
742     }
743
744     return bridge;
745   }
746
747   return Dali::Accessibility::DummyBridge::GetInstance();
748 }
749
750 void Bridge::DisableAutoInit()
751 {
752   if(INITIALIZED_BRIDGE)
753   {
754     DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization");
755   }
756
757   mAutoInitState = AutoInitState::DISABLED;
758 }
759
760 void Bridge::EnableAutoInit()
761 {
762   mAutoInitState = AutoInitState::ENABLED;
763
764   if(INITIALIZED_BRIDGE)
765   {
766     return;
767   }
768
769   auto rootLayer       = Dali::Stage::GetCurrent().GetRootLayer(); // A root layer of the default window.
770   auto window          = Dali::DevelWindow::Get(rootLayer);
771   auto applicationName = Dali::Internal::Adaptor::Adaptor::GetApplicationPackageName();
772
773   auto accessible = Accessibility::Accessible::Get(rootLayer, true);
774
775   auto bridge = Bridge::GetCurrentBridge();
776   bridge->AddTopLevelWindow(accessible);
777   bridge->SetApplicationName(applicationName);
778   bridge->Initialize();
779
780   if(window && window.IsVisible())
781   {
782     bridge->WindowShown(window);
783   }
784 }