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