#define DALI_ADAPTOR_ACCESSIBILITY_BRIDGE_H
/*
- * Copyright (c) 2024 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.
// EXTERNAL INCLUDES
#include <dali/public-api/actors/actor.h>
-#include <dali/public-api/events/key-event.h>
#include <dali/public-api/math/rect.h>
#include <functional>
#include <memory>
* Screen-reader might receive this event and reply, that given keycode is consumed. In that case
* further processing of the keycode should be ignored.
*
- * @param[in] keyEvent The key event
- * @param[in] callback Notification if the event was consumed
- * @return true if the event was emitted
- */
- virtual bool EmitKeyEvent(Dali::KeyEvent keyEvent, std::function<void(Dali::KeyEvent, bool)> callback) = 0;
+ * @param[in] type Key event type
+ * @param[in] keyCode Key code
+ * @param[in] keyName Key name
+ * @param[in] timeStamp Time stamp
+ * @param[in] isText Whether it's text or not
+ * @return Whether this event is consumed or not
+ **/
+ virtual Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) = 0;
/**
* @brief Reads given text by screen reader
};\r
\r
/**\r
+ * @brief Enumeration describing type of key event\r
+ * @see Adaptor::AccessibilityObserver::OnAccessibleKeyEvent\r
+ */\r
+enum class KeyEventType\r
+{\r
+ KEY_PRESSED,\r
+ KEY_RELEASED,\r
+};\r
+\r
+/**\r
+ * @brief Enumeration with human readable values describing state of event\r
+ * @see Dali::Accessibility::Bridge::Emit\r
+ */\r
+enum class Consumed\r
+{\r
+ NO,\r
+ YES\r
+};\r
+\r
+/**\r
* @brief Helper class representing two dimensional point with integer coordinates\r
*/\r
struct DALI_ADAPTOR_API Point\r
BridgeImpl() = default;
/**
- * @copydoc Dali::Accessibility::Bridge::EmitKeyEvent()
+ * @copydoc Dali::Accessibility::Bridge::Emit()
*/
- bool EmitKeyEvent(Dali::KeyEvent keyEvent, std::function<void(Dali::KeyEvent, bool)> callback) override
+ Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
{
- using ArgumentTypes = std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>;
-
- static const char* methodName = "NotifyListenersSync";
-
if(!IsUp())
{
- return false;
+ return Consumed::NO;
}
- uint32_t keyType = (keyEvent.GetState() == Dali::KeyEvent::DOWN ? 0U : 1U);
- auto timeStamp = static_cast<std::int32_t>(keyEvent.GetTime());
- bool isText = !keyEvent.GetKeyString().empty();
-
- ArgumentTypes arguments(keyType, 0, keyEvent.GetKeyCode(), 0, timeStamp, keyEvent.GetKeyName(), isText);
+ unsigned int keyType = 0;
- auto functor = [keyEvent = std::move(keyEvent), callback = std::move(callback)](DBus::ValueOrError<bool> reply) {
- bool consumed = false;
-
- if(!reply)
+ switch(type)
+ {
+ case KeyEventType::KEY_PRESSED:
{
- DALI_LOG_ERROR("%s call failed: %s", methodName, reply.getError().message.c_str());
+ keyType = 0;
+ break;
}
- else
+ case KeyEventType::KEY_RELEASED:
{
- consumed = std::get<0>(reply.getValues());
+ keyType = 1;
+ break;
}
+ default:
+ {
+ return Consumed::NO;
+ }
+ }
- callback(std::move(keyEvent), consumed);
- };
-
- mRegistryClient.method<bool(ArgumentTypes)>(methodName).asyncCall(std::move(functor), arguments);
-
- return true;
+ auto methodObject = mRegistryClient.method<bool(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>)>("NotifyListenersSync");
+ 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});
+ if(!result)
+ {
+ LOG() << result.getError().message;
+ return Consumed::NO;
+ }
+ return std::get<0>(result) ? Consumed::YES : Consumed::NO;
}
/**
#define DALI_ADAPTOR_DUMMY_ATSPI_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
{
}
- bool EmitKeyEvent(Dali::KeyEvent keyEvent, std::function<void(Dali::KeyEvent, bool)> callback) override
+ Accessibility::Consumed Emit(Accessibility::KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
{
- return false;
+ return Accessibility::Consumed::YES;
}
void Say(const std::string& text, bool discardable, std::function<void(std::string)> callback) override
mConfigurationManager = Utils::MakeUnique<ConfigurationManager>(systemCachePath, mGraphics.get(), mThreadController);
}
+void Adaptor::AccessibilityObserver::OnAccessibleKeyEvent(const Dali::KeyEvent& event)
+{
+ Accessibility::KeyEventType type;
+ if(event.GetState() == Dali::KeyEvent::DOWN)
+ {
+ type = Accessibility::KeyEventType::KEY_PRESSED;
+ }
+ else if(event.GetState() == Dali::KeyEvent::UP)
+ {
+ type = Accessibility::KeyEventType::KEY_RELEASED;
+ }
+ else
+ {
+ return;
+ }
+ Dali::Accessibility::Bridge::GetCurrentBridge()->Emit(type, event.GetKeyCode(), event.GetKeyName(), event.GetTime(), !event.GetKeyString().empty());
+}
+
Adaptor::~Adaptor()
{
Accessibility::Bridge::GetCurrentBridge()->Terminate();
auto bridge = Accessibility::Bridge::GetCurrentBridge();
bridge->SetApplicationName(appName);
bridge->Initialize();
+ Dali::Stage::GetCurrent().KeyEventSignal().Connect(&mAccessibilityObserver, &AccessibilityObserver::OnAccessibleKeyEvent);
Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
{
class RenderSurfaceInterface;
+namespace Accessibility
+{
+class Bridge;
+}
+
namespace Integration
{
class Core;
std::unique_ptr<Integration::AddOnManager> mAddOnManager; ///< Pointer to the addon manager
+ class AccessibilityObserver : public ConnectionTracker
+ {
+ public:
+ void OnAccessibleKeyEvent(const Dali::KeyEvent& event);
+ };
+ AccessibilityObserver mAccessibilityObserver;
+
public:
inline static Adaptor& GetImplementation(Dali::Adaptor& adaptor)
{
auto bridge = Accessibility::Bridge::GetCurrentBridge();
auto rootLayer = mScene.GetRootLayer();
auto accessible = Accessibility::Accessible::Get(rootLayer);
+ bridge->AddTopLevelWindow(accessible);
DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Accessibility is enabled\n", this, mNativeWindowId);
- bridge->AddTopLevelWindow(accessible);
- InterceptKeyEventSignal().Connect(this, &Window::OnAccessibilityInterceptKeyEvent);
-
Dali::Window handle(this);
if(!mIsEmittedWindowCreatedEvent)
{
auto bridge = Accessibility::Bridge::GetCurrentBridge();
auto rootLayer = mScene.GetRootLayer();
auto accessible = Accessibility::Accessible::Get(rootLayer);
-
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Accessibility is disabled\n", this, mNativeWindowId);
-
- InterceptKeyEventSignal().Disconnect(this, &Window::OnAccessibilityInterceptKeyEvent);
bridge->RemoveTopLevelWindow(accessible);
-}
-
-bool Window::OnAccessibilityInterceptKeyEvent(const Dali::KeyEvent& keyEvent)
-{
- auto bridge = Accessibility::Bridge::GetCurrentBridge();
-
- if(!bridge->IsUp() || keyEvent.IsNoInterceptModifier())
- {
- DALI_LOG_ERROR("This KeyEvent should not have been intercepted!");
-
- return false;
- }
-
- auto callback = [handle = Dali::Window(this)](Dali::KeyEvent keyEvent, bool consumed) {
- if(!consumed)
- {
- Dali::DevelKeyEvent::SetNoInterceptModifier(keyEvent, true);
- Dali::DevelWindow::FeedKeyEvent(handle, keyEvent);
- }
- };
-
- bool emitted = bridge->EmitKeyEvent(keyEvent, callback);
-
- // If emitted, consume the event in order not to have to wait for the D-Bus call
- // to finish. If the event turns out not to be consumed by the remote client,
- // then it is fed back to the window from the D-Bus callback.
- return emitted;
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Accessibility is disabled\n", this, mNativeWindowId);
}
void Window::OnMoveCompleted(Dali::Window::WindowPosition& position)
void OnAccessibilityDisabled();
/**
- * @brief Called in Accessibility mode on every KeyEvent
- *
- * @param[in] keyEvent The key event
- * @return Always true, meaning that the event is consumed
- */
- bool OnAccessibilityInterceptKeyEvent(const Dali::KeyEvent& keyEvent);
-
- /**
* @brief Called when the window rotation is finished.
*
* This signal is emmit when window rotation is finisehd and WindowRotationCompleted() is called.