X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Faccessibility%2Fbridge%2Fbridge-impl.cpp;h=ea95081a6f00f8c18ff203bf4adb6a64b779565e;hb=0ed267a55279935b6c85e8938b9f5016c6286a50;hp=06d940ec09de995ea3ced839397a9ff8bc5437fd;hpb=d9335fa0ba5472d558fa40ad20af58db76bfbd7a;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/accessibility/bridge/bridge-impl.cpp b/dali/internal/accessibility/bridge/bridge-impl.cpp index 06d940e..ea95081 100644 --- a/dali/internal/accessibility/bridge/bridge-impl.cpp +++ b/dali/internal/accessibility/bridge/bridge-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,10 +27,13 @@ #include #include #include +#include #include -#include #include -#include +#include +#include +#include +#include using namespace Dali::Accessibility; @@ -44,59 +47,55 @@ class BridgeImpl : public virtual BridgeBase, public BridgeText, public BridgeEditableText { - DBus::DBusClient listenOnAtspiEnabledSignalClient; - DBus::DBusClient registryClient, directReadingClient; - bool screenReaderEnabled = false; - bool isEnabled = false; - bool isShown = false; - std::unordered_map > directReadingCallbacks; - Dali::Actor highlightedActor; - std::function highlightClearAction; + DBus::DBusClient listenOnAtspiEnabledSignalClient; + DBus::DBusClient registryClient, directReadingClient; + bool screenReaderEnabled = false; + bool isEnabled = false; + bool isShown = false; + std::unordered_map> directReadingCallbacks; + Dali::Actor highlightedActor; + std::function highlightClearAction; public: BridgeImpl() { - listenOnAtspiEnabledSignalClient = DBus::DBusClient{ A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION }; + listenOnAtspiEnabledSignalClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION}; - listenOnAtspiEnabledSignalClient.addPropertyChangedEvent< bool >( "ScreenReaderEnabled", [this]( bool res ) + listenOnAtspiEnabledSignalClient.addPropertyChangedEvent("ScreenReaderEnabled", [this](bool res) { + screenReaderEnabled = res; + if(screenReaderEnabled || isEnabled) { - screenReaderEnabled = res; - if( screenReaderEnabled || isEnabled ) - { - ForceUp(); - } - else - { - ForceDown(); - } + ForceUp(); } - ); + else + { + ForceDown(); + } + }); - listenOnAtspiEnabledSignalClient.addPropertyChangedEvent< bool >( "IsEnabled", [this]( bool res ) + listenOnAtspiEnabledSignalClient.addPropertyChangedEvent("IsEnabled", [this](bool res) { + isEnabled = res; + if(screenReaderEnabled || isEnabled) + { + ForceUp(); + } + else { - isEnabled = res; - if( screenReaderEnabled || isEnabled ) - { - ForceUp(); - } - else - { - ForceDown(); - } + ForceDown(); } - ); + }); } - Consumed Emit( KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText ) override + Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override { - if (!IsUp()) + if(!IsUp()) { return Consumed::NO; } unsigned int evType = 0; - switch( type ) + switch(type) { case KeyEventType::KEY_PRESSED: { @@ -113,82 +112,120 @@ public: return Consumed::NO; } } - auto m = registryClient.method< bool( std::tuple< uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool > ) >( "NotifyListenersSync" ); - auto result = m.call( std::tuple< uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool >{evType, 0, static_cast< int32_t >( keyCode ), 0, static_cast< int32_t >( timeStamp ), keyName, isText ? 1 : 0} ); - if( !result ) + auto m = registryClient.method)>("NotifyListenersSync"); + auto result = m.call(std::tuple{evType, 0, static_cast(keyCode), 0, static_cast(timeStamp), keyName, isText ? 1 : 0}); + if(!result) { LOG() << result.getError().message; return Consumed::NO; } - return std::get< 0 >( result ) ? Consumed::YES : Consumed::NO; + return std::get<0>(result) ? Consumed::YES : Consumed::NO; } void Pause() override { - auto r = directReadingClient.method< DBus::ValueOrError< void >( bool ) > ( "PauseResume" ).call( true ); - if (!r) + if(!IsUp()) { - LOG() << "Direct reading command failed (" << r.getError().message << ")"; + return; } + + directReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { + if(!msg) + { + LOG() << "Direct reading command failed (" << msg.getError().message << ")"; + } + }, + true); } void Resume() override { - auto r = directReadingClient.method< DBus::ValueOrError< void >( bool ) > ( "PauseResume" ).call( false ); - if (!r) + if(!IsUp()) { - LOG() << "Direct reading command failed (" << r.getError().message << ")"; + return; } + + directReadingClient.method(bool)>("PauseResume").asyncCall([](DBus::ValueOrError msg) { + if(!msg) + { + LOG() << "Direct reading command failed (" << msg.getError().message << ")"; + } + }, + false); } - void Say( const std::string& text, bool discardable, std::function< void(std::string) > callback ) override + void StopReading(bool alsoNonDiscardable) override { - auto commandId = directReadingClient.method< DBus::ValueOrError< std::string, bool, int32_t >( std::string, bool ) > ( "ReadCommand" ).call( text, discardable ); - if ( !commandId ) + if(!IsUp()) { - LOG() << "Direct reading command failed (" << commandId.getError().message << ")"; + return; } - else if( callback ) + + directReadingClient.method(bool)>("StopReading").asyncCall([](DBus::ValueOrError msg) { + if(!msg) + { + LOG() << "Direct reading command failed (" << msg.getError().message << ")"; + } + }, + alsoNonDiscardable); + } + + void Say(const std::string& text, bool discardable, std::function callback) override + { + if(!IsUp()) { - directReadingCallbacks.emplace( std::get< 2 >( commandId ), callback); + return; } + + directReadingClient.method(std::string, bool)>("ReadCommand").asyncCall([=](DBus::ValueOrError msg) { + if(!msg) + { + LOG() << "Direct reading command failed (" << msg.getError().message << ")"; + } + else if(callback) + { + directReadingCallbacks.emplace(std::get<2>(msg), callback); + } + }, + text, + discardable); } void ForceDown() override { - if (data) + if(data) { - if (data->currentlyHighlightedActor && data->highlightActor) + if(data->currentlyHighlightedActor && data->highlightActor) { data->currentlyHighlightedActor.Remove(data->highlightActor); } data->currentlyHighlightedActor = {}; - data->highlightActor = {}; + data->highlightActor = {}; } - highlightedActor = {}; + highlightedActor = {}; highlightClearAction = {}; BridgeAccessible::ForceDown(); - registryClient = {}; + registryClient = {}; directReadingClient = {}; directReadingCallbacks.clear(); } void Terminate() override { - if (data) + if(data) { data->currentlyHighlightedActor = {}; - data->highlightActor = {}; + data->highlightActor = {}; } ForceDown(); listenOnAtspiEnabledSignalClient = {}; - dbusServer = {}; - con = {}; + dbusServer = {}; + con = {}; } ForceUpResult ForceUp() override { - if( BridgeAccessible::ForceUp() == ForceUpResult::ALREADY_UP ) + if(BridgeAccessible::ForceUp() == ForceUpResult::ALREADY_UP) { return ForceUpResult::ALREADY_UP; } @@ -202,31 +239,30 @@ public: BridgeText::RegisterInterfaces(); BridgeEditableText::RegisterInterfaces(); - RegisterOnBridge( &application ); + RegisterOnBridge(&application); - registryClient = { AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, con }; - directReadingClient = DBus::DBusClient{ DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, con }; - directReadingClient.addSignal< void(int32_t, std::string) >( "ReadingStateChanged", [=]( int32_t id, std::string readingState ) + registryClient = {AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, con}; + directReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, con}; + directReadingClient.addSignal("ReadingStateChanged", [=](int32_t id, std::string readingState) { + auto it = directReadingCallbacks.find(id); + if(it != directReadingCallbacks.end()) { - auto it = directReadingCallbacks.find( id ); - if (it != directReadingCallbacks.end()) - { - it->second( readingState ); - directReadingCallbacks.erase( it ); - } + it->second(readingState); + if(readingState != "ReadingPaused" && readingState != "ReadingResumed" && readingState != "ReadingStarted") + directReadingCallbacks.erase(it); } - ); + }); - auto proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, con}; + auto proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, con}; Address root{"", "root"}; - auto res = proxy.method< Address( Address ) >( "Embed" ).call( root ); - if (!res) + auto res = proxy.method("Embed").call(root); + if(!res) { LOG() << "Call to Embed failed: " << res.getError().message; } - assert( res ); - application.parent.SetAddress( std::move( std::get< 0 >( res ) ) ); - if (isShown) + assert(res); + application.parent.SetAddress(std::move(std::get<0>(res))); + if(isShown) { EmitActivate(); } @@ -236,24 +272,24 @@ public: void EmitActivate() { auto win = application.getActiveWindow(); - if (win) + if(win) { - win->Emit( WindowEvent::ACTIVATE, 0 ); + win->Emit(WindowEvent::ACTIVATE, 0); } } void EmitDeactivate() { auto win = application.getActiveWindow(); - if (win) + if(win) { - win->Emit( WindowEvent::DEACTIVATE, 0 ); + win->Emit(WindowEvent::DEACTIVATE, 0); } } void ApplicationHidden() override { - if ( isShown && IsUp() ) + if(isShown && IsUp()) { EmitDeactivate(); } @@ -262,7 +298,7 @@ public: void ApplicationShown() override { - if ( !isShown && IsUp() ) + if(!isShown && IsUp()) { EmitActivate(); } @@ -272,17 +308,17 @@ public: void Initialize() override { auto req = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION}; - auto p = req.property< bool >( "ScreenReaderEnabled" ).get(); - if( p ) + auto p = req.property("ScreenReaderEnabled").get(); + if(p) { - screenReaderEnabled = std::get< 0 >( p ); + screenReaderEnabled = std::get<0>(p); } - p = req.property< bool >( "IsEnabled" ).get(); - if( p ) + p = req.property("IsEnabled").get(); + if(p) { - isEnabled = std::get< 0 >( p ); + isEnabled = std::get<0>(p); } - if( screenReaderEnabled || isEnabled ) + if(screenReaderEnabled || isEnabled) { ForceUp(); } @@ -297,12 +333,78 @@ public: { return isEnabled; } - }; +static bool bridgeInitialized; + +static Bridge* CreateBridge() +{ + bridgeInitialized = true; + + try + { + /* check environment variable first */ + const char *envAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI); + if (envAtspiDisabled && std::atoi(envAtspiDisabled) != 0) + { + return Dali::Accessibility::DummyBridge::GetInstance(); + } + + return new BridgeImpl; + } + catch (const std::exception&) + { + DALI_LOG_ERROR("Failed to initialize AT-SPI bridge"); + return Dali::Accessibility::DummyBridge::GetInstance(); + } +} + Bridge* Bridge::GetCurrentBridge() { - static BridgeImpl *bridge = new BridgeImpl; - return bridge; + static Bridge* bridge; + + if (bridge) + { + return bridge; + } + else if (autoInitState == AutoInitState::ENABLED) + { + bridge = CreateBridge(); + + /* check environment variable for suppressing screen-reader */ + const char *envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER); + if (envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0) + { + bridge->SuppressScreenReader(true); + } + + return bridge; + } + + return Dali::Accessibility::DummyBridge::GetInstance(); +} + +void Bridge::DisableAutoInit() +{ + if (bridgeInitialized) + { + DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization"); + } + + autoInitState = AutoInitState::DISABLED; } +void Bridge::EnableAutoInit(Accessible* topLevelWindow, const std::string& applicationName) +{ + autoInitState = AutoInitState::ENABLED; + + if (bridgeInitialized) + { + return; + } + + auto* bridge = Bridge::GetCurrentBridge(); + bridge->AddTopLevelWindow(topLevelWindow); + bridge->SetApplicationName(applicationName); + bridge->Initialize(); +}