Add SyncKeyEvent for Widget 70/271970/16
authortscholb <scholb.kim@samsung.com>
Thu, 20 Jan 2022 12:35:44 +0000 (21:35 +0900)
committersunghyun kim <scholb.kim@samsung.com>
Thu, 17 Mar 2022 01:42:17 +0000 (01:42 +0000)
In the past, the WidgetApplication used the keyEvent using the screen connector's API.
However, this API is not synchronized.
So WidgetView cannot get feedback from WidgetApplication.
To solve this problem, AppFramework provides a new API to send keyEvent with sync.
So we add a new callback to use this API.

Plus,
Widget Application also needs a new API to send an alarm to the WidgetView when it uses a keyEvent.
So we add a new API called SetUsingKeyEvent().

Change-Id: I92c00b57dfe1c72baadb9fc082e253b1a0385d14

13 files changed:
build/tizen/deps-check.cmake
dali/internal/system/common/widget-controller.h
dali/internal/system/tizen-wayland/widget-application-impl-tizen.cpp
dali/internal/system/tizen-wayland/widget-application-impl-tizen.h
dali/internal/system/tizen-wayland/widget-controller-tizen.cpp
dali/internal/system/tizen-wayland/widget-controller-tizen.h
dali/internal/system/ubuntu-x11/widget-controller-x.cpp
dali/internal/system/ubuntu-x11/widget-controller-x.h
dali/internal/system/windows/widget-controller-win.cpp
dali/internal/system/windows/widget-controller-win.h
dali/public-api/adaptor-framework/widget-impl.cpp
dali/public-api/adaptor-framework/widget-impl.h
packaging/dali-adaptor.spec

index 8eecbda..a13dc7d 100755 (executable)
@@ -369,6 +369,7 @@ IF( enable_appfw )
     ${ECORE_IMF_CFLAGS}
     ${FRIBIDI_CFLAGS}
     ${COMPONENT_BASED_CORE_BASE_CFLAGS}
+    ${SCREENCONNECTORPROVIDER_CFLAGS}
   )
 
   SET( DALI_LDFLAGS ${DALI_LDFLAGS}
@@ -384,6 +385,7 @@ IF( enable_appfw )
     ${ECORE_IMF_LDFLAGS}
     ${FRIBIDI_LDFLAGS}
     ${COMPONENT_BASED_CORE_BASE_LDFLAGS}
+    ${SCREENCONNECTORPROVIDER_LDFLAGS}
   )
 ELSE()
   SET( DALI_CFLAGS ${DALI_CFLAGS}
@@ -440,11 +442,9 @@ IF( WEARABLE_PROFILE )
   SET( DALI_CFLAGS ${DALI_CFLAGS}
     ${HAPTIC_CFLAGS}
     ${EFL_ASSIST_CFLAGS}
-    ${SCREENCONNECTORPROVIDER_CFLAGS}
     ${APPCORE_WATCH_CFLAGS}
   )
   SET( DALI_LDFLAGS ${DALI_LDFLAGS}
-    ${SCREENCONNECTORPROVIDER_LDFLAGS}
     ${APPCORE_WATCH_LDFLAGS}
   )
 ENDIF()
index 99b8995..7353f9b 100644 (file)
@@ -40,6 +40,31 @@ public:
    * Set content information to widget framework
    */
   virtual void SetContentInfo(const std::string& contentInfo) = 0;
+
+  /**
+   * Check Widget is using key
+   */
+  virtual bool IsKeyEventUsing() const = 0;
+
+  /**
+   * Set the flag that widget is using keyEvent
+   */
+  virtual void SetUsingKeyEvent(bool flag) = 0;
+
+  /**
+   * Set the Information of widget
+   */
+  virtual void SetInformation(Dali::Window window, const std::string& widgetId) = 0;
+
+  /**
+   * Get the window
+   */
+  virtual Dali::Window GetWindow() const = 0;
+
+  /**
+   * Get the widget id
+   */
+  virtual std::string GetWidgetId() const = 0;
 };
 
 } // namespace Adaptor
index 227284a..92c7e6c 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/internal/system/tizen-wayland/widget-controller-tizen.h>
 #include <dali/public-api/adaptor-framework/widget-impl.h>
 #include <dali/public-api/adaptor-framework/widget.h>
+#include <dali/devel-api/events/key-event-devel.h>
 
 // EXTERNAL INCLUDES
 #include <bundle.h>
@@ -35,6 +36,43 @@ namespace Internal
 {
 namespace
 {
+/**
+ * This Api is called when widget viewer send keyEvent.
+ * In this API, widget framework create a new keyEvent, find the proper widget and send this event.
+ * Finally widget framework receive feedback from widget.
+ */
+bool OnKeyEventCallback(const char *id, screen_connector_event_type_e eventType, int keyCode, const char *keyName, long long cls, long long subcls, const char* identifier, long long timestamp, void *userData)
+{
+  Dali::Internal::Adaptor::WidgetApplicationTizen* application = static_cast<Dali::Internal::Adaptor::WidgetApplicationTizen*>(userData);
+
+  // Create new key for widget
+  Dali::KeyEvent::State state = Dali::KeyEvent::DOWN;
+  if(eventType == SCREEN_CONNECTOR_EVENT_TYPE_KEY_DOWN)
+  {
+    state = Dali::KeyEvent::DOWN;
+  }
+  else if(eventType == SCREEN_CONNECTOR_EVENT_TYPE_KEY_UP)
+  {
+    state = Dali::KeyEvent::UP;
+  }
+
+  bool consumed = true;
+  std::string keyEventName = std::string(keyName);
+  Dali::KeyEvent event = Dali::DevelKeyEvent::New(keyEventName, "", "", keyCode, 0, timestamp, state, "", "", Device::Class::NONE, Device::Subclass::NONE);
+
+  if(application)
+  {
+    std::string widgetId = std::string(id);
+    widget_base_instance_h instanceHandle = application->GetWidgetInstanceFromWidgetId(widgetId);
+    if(instanceHandle)
+    {
+      consumed = application->FeedKeyEvent(instanceHandle, event);
+    }
+  }
+
+  return consumed;
+}
+
 int OnInstanceInit(widget_base_instance_h instanceHandle, bundle* content, int w, int h, void* classData)
 {
   char* id;
@@ -79,11 +117,12 @@ int OnInstanceInit(widget_base_instance_h instanceHandle, bundle* content, int w
   Dali::WidgetApplication::CreateWidgetFunction                        createFunction = pair.second;
 
   Dali::Widget widgetInstance = createFunction(pair.first);
-  application->AddWidget(instanceHandle, widgetInstance, window);
 
   Dali::Internal::Adaptor::Widget::Impl* widgetImpl = new Dali::Internal::Adaptor::WidgetImplTizen(instanceHandle);
   Internal::Adaptor::GetImplementation(widgetInstance).SetImpl(widgetImpl);
 
+  application->AddWidget(instanceHandle, widgetInstance, window, std::string(id));
+
   std::string encodedContentString = "";
 
   if(bundle_get_count(content))
@@ -98,6 +137,9 @@ int OnInstanceInit(widget_base_instance_h instanceHandle, bundle* content, int w
 
   Internal::Adaptor::GetImplementation(widgetInstance).OnCreate(encodedContentString, window);
 
+  // connect keyEvent for widget
+  application->ConnectKeyEvent(window);
+
   return 0;
 }
 
@@ -172,7 +214,7 @@ int OnInstanceResize(widget_base_instance_h instanceHandle, int w, int h, void*
 
   // Get Dali::Widget instance.
   Dali::Widget widgetInstance = application->GetWidget(instanceHandle);
-  Dali::Window window         = application->GetWindowFromWidget(instanceHandle);
+  Dali::Window window         = application->GetWindowFromWidget(widgetInstance);
   window.SetSize(Dali::Window::WindowSize(w, h));
   Internal::Adaptor::GetImplementation(widgetInstance).OnResize(window);
 
@@ -225,7 +267,9 @@ WidgetApplicationPtr WidgetApplicationTizen::New(
 }
 
 WidgetApplicationTizen::WidgetApplicationTizen(int* argc, char** argv[], const std::string& stylesheet)
-: WidgetApplication(argc, argv, stylesheet)
+: WidgetApplication(argc, argv, stylesheet),
+  mConnectedKeyEvent(false),
+  mReceivedKeyEvent(false)
 {
 }
 
@@ -269,10 +313,10 @@ WidgetApplicationTizen::CreateWidgetFunctionPair WidgetApplicationTizen::GetWidg
   return CreateWidgetFunctionPair("", NULL);
 }
 
-void WidgetApplicationTizen::AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window)
+void WidgetApplicationTizen::AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId)
 {
   mWidgetInstanceContainer.push_back(WidgetInstancePair(widgetBaseInstance, widget));
-  mWindowInstanceContainer.push_back(WindowInstancePair(widgetBaseInstance, window));
+  Internal::Adaptor::GetImplementation(widget).SetInformation(window, widgetId);
 }
 
 Dali::Widget WidgetApplicationTizen::GetWidget(widget_base_instance_h widgetBaseInstance) const
@@ -298,29 +342,29 @@ void WidgetApplicationTizen::DeleteWidget(widget_base_instance_h widgetBaseInsta
   {
     mWidgetInstanceContainer.erase(widgetInstance);
   }
+}
 
-  // Delete WindowInstance
-  auto windowInstance = std::find_if(mWindowInstanceContainer.begin(),
-                                     mWindowInstanceContainer.end(),
-                                     [widgetBaseInstance](WindowInstancePair pair) { return (pair.first == widgetBaseInstance); });
-
-  if(windowInstance != mWindowInstanceContainer.end())
+Dali::Window WidgetApplicationTizen::GetWindowFromWidget(Dali::Widget widgetInstance) const
+{
+  if(widgetInstance)
   {
-    mWindowInstanceContainer.erase(windowInstance);
+    return Internal::Adaptor::GetImplementation(widgetInstance).GetWindow();
   }
+
+  return Dali::Window();
 }
 
-Dali::Window WidgetApplicationTizen::GetWindowFromWidget(widget_base_instance_h widgetBaseInstance) const
+widget_base_instance_h WidgetApplicationTizen::GetWidgetInstanceFromWidgetId(std::string& widgetId) const
 {
-  for(auto&& iter : mWindowInstanceContainer)
+  for(auto&& iter : mWidgetInstanceContainer)
   {
-    if((iter).first == widgetBaseInstance)
+    if(widgetId == Internal::Adaptor::GetImplementation((iter).second).GetWidgetId())
     {
-      Dali::Window ret = (iter).second;
-      return ret;
+      return (iter).first;
     }
   }
-  return Dali::Window();
+
+  return nullptr;
 }
 
 int WidgetApplicationTizen::GetWidgetCount()
@@ -328,6 +372,49 @@ int WidgetApplicationTizen::GetWidgetCount()
   return mWidgetInstanceContainer.size();
 }
 
+void WidgetApplicationTizen::ConnectKeyEvent(Dali::Window window)
+{
+  if(!mConnectedKeyEvent)
+  {
+    screen_connector_provider_set_key_event_cb(OnKeyEventCallback, this);
+    mConnectedKeyEvent = true;
+  }
+  window.KeyEventSignal().Connect(this, &WidgetApplicationTizen::OnWindowKeyEvent);
+}
+
+void WidgetApplicationTizen::OnWindowKeyEvent(const Dali::KeyEvent& event)
+{
+  //If Widget Application consume key event, this api is not called.
+  mReceivedKeyEvent = true;
+}
+
+bool WidgetApplicationTizen::FeedKeyEvent(widget_base_instance_h instanceHandle, const Dali::KeyEvent& keyEvent)
+{
+  bool consumed = true;
+
+  // Check if application consume key event
+  Dali::Widget widgetInstance = GetWidget(instanceHandle);
+  if(widgetInstance)
+  {
+    Dali::Window window = GetWindowFromWidget(widgetInstance);
+
+    // Reset the state of key received
+    mReceivedKeyEvent = false;
+
+    // Feed the keyEvent to widget window
+    DevelWindow::FeedKeyEvent(window, keyEvent);
+
+    // if the application is not using a key event, verify that the window in the widget has received a key event.
+    if(Internal::Adaptor::GetImplementation(widgetInstance).IsKeyEventUsing() == false)
+    {
+      // if the window has received a key event, widget need to consume its key event
+      consumed = (mReceivedKeyEvent) ? false : true;
+    }
+  }
+
+  return consumed;
+}
+
 void WidgetApplicationTizen::OnInit()
 {
   WidgetApplication::OnInit();
index f2462bd..80166bd 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <widget_base.h>
+#include <screen_connector_provider.h>
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/window-devel.h>
@@ -40,7 +41,7 @@ typedef IntrusivePtr<WidgetApplication> WidgetApplicationPtr;
 /**
  * Implementation of the WidgetApplication class.
  */
-class WidgetApplicationTizen : public WidgetApplication
+class WidgetApplicationTizen : public WidgetApplication, public ConnectionTracker
 {
 public:
   typedef std::pair<const std::string, Dali::WidgetApplication::CreateWidgetFunction> CreateWidgetFunctionPair;
@@ -78,7 +79,7 @@ public:
   /**
    * Add widget_base_instance_h - Widget instance pair to container.
    */
-  void AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window);
+  void AddWidget(widget_base_instance_h widgetBaseInstance, Dali::Widget widget, Dali::Window window, const std::string& widgetId);
 
   /**
    * Find and get Widget instance in container by widget_base_instance_h.
@@ -93,13 +94,42 @@ public:
   /**
    * Find and get Window instance in container by widget_base_instance_h.
    */
-  Dali::Window GetWindowFromWidget(widget_base_instance_h widgetBaseInstance) const;
+  Dali::Window GetWindowFromWidget(Dali::Widget widget) const;
 
   /**
+   * Find and get widget_base_instance in container by widget id.
+   */
+  widget_base_instance_h GetWidgetInstanceFromWidgetId(std::string& widgetId) const;
+  /**
    * Get the number of created widget.
    */
   int32_t GetWidgetCount();
 
+  /**
+   * @brief connect the keyEvent for window
+   *
+   * @param[in] window window for connecting keyEvent
+   */
+  void ConnectKeyEvent(Dali::Window window);
+
+  /**
+   * @brief Callback for widget window
+   *
+   * If Widget Application consume key event, this api is not called.
+   *
+   * @param[in] event The key event.
+   */
+  void OnWindowKeyEvent(const Dali::KeyEvent& event);
+
+  /**
+   * @brief Feed keyEvent to Widget.
+   *
+   * @param[in] instanceHandle the handle of widget instance
+   * @param[in] keyEvent The key event for widget
+   * @return True if widget consume keyEvent, false otherwise.
+   */
+  bool FeedKeyEvent(widget_base_instance_h instanceHandle, const Dali::KeyEvent& keyEvent);
+
 protected:
   /**
    * Private Constructor
@@ -124,9 +154,8 @@ private:
   CreateWidgetFunctionContainer mCreateWidgetFunctionContainer;
   WidgetInstanceContainer       mWidgetInstanceContainer;
 
-  typedef std::pair<widget_base_instance_h, Dali::Window> WindowInstancePair;
-  typedef std::vector<WindowInstancePair>                 WindowInstanceContainer;
-  WindowInstanceContainer                                 mWindowInstanceContainer;
+  bool mConnectedKeyEvent; // Check if keyEvent is connected
+  bool mReceivedKeyEvent;  // Check if application receive keyEvent
 };
 
 } // namespace Adaptor
index d4c4498..efe9f16 100644 (file)
@@ -30,7 +30,10 @@ namespace Adaptor
 {
 WidgetImplTizen::WidgetImplTizen(widget_base_instance_h instanceHandle)
 : Widget::Impl(),
-  mInstanceHandle(instanceHandle)
+  mInstanceHandle(instanceHandle),
+  mWindow(),
+  mWidgetId(),
+  mUsingKeyEvent(false)
 {
 }
 
@@ -50,6 +53,32 @@ void WidgetImplTizen::SetContentInfo(const std::string& contentInfo)
   bundle_free(contentBundle);
 }
 
+bool WidgetImplTizen::IsKeyEventUsing() const
+{
+  return mUsingKeyEvent;
+}
+
+void WidgetImplTizen::SetUsingKeyEvent(bool flag)
+{
+  mUsingKeyEvent = flag;
+}
+
+void WidgetImplTizen::SetInformation(Dali::Window window, const std::string& widgetId)
+{
+  mWindow = window;
+  mWidgetId = widgetId;
+}
+
+Dali::Window WidgetImplTizen::GetWindow() const
+{
+  return mWindow;
+}
+
+std::string WidgetImplTizen::GetWidgetId() const
+{
+  return mWidgetId;
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index de6ae1d..5877f42 100644 (file)
@@ -54,8 +54,36 @@ public:
    */
   void SetContentInfo(const std::string& contentInfo) override;
 
+  /**
+   * Check Widget is using key
+   */
+  bool IsKeyEventUsing() const override;
+
+  /**
+   * Set the flag that widget is using keyEvent
+   */
+  void SetUsingKeyEvent(bool flag) override;
+
+  /**
+   * Set the Information of widget
+   */
+  void SetInformation(Dali::Window window, const std::string& widgetId) override;
+
+  /**
+   * Get the window
+   */
+  Dali::Window GetWindow() const override;
+
+  /**
+   * Get the widget id
+   */
+  std::string GetWidgetId() const override;
+
 private:
   widget_base_instance_h mInstanceHandle;
+  Dali::Window           mWindow;
+  std::string            mWidgetId;
+  bool                   mUsingKeyEvent;
 };
 
 } // namespace Adaptor
index dc40cdd..b0f9a50 100644 (file)
@@ -36,6 +36,28 @@ void WidgetImplUbuntu::SetContentInfo(const std::string& contentInfo)
 {
 }
 
+bool WidgetImplUbuntu::IsKeyEventUsing() const
+{
+}
+
+void WidgetImplUbuntu::SetUsingKeyEvent(bool flag)
+{
+}
+
+void WidgetImplUbuntu::SetInformation(Dali::Window window, const std::string& widgetId)
+{
+}
+
+Dali::Window WidgetImplUbuntu::GetWindow() const
+{
+    return Dali::Window();
+}
+
+std::string WidgetImplUbuntu::GetWidgetId() const
+{
+    return std::string();
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index 685e52a..798e066 100644 (file)
@@ -51,6 +51,31 @@ public:
    * Set content information to widget framework
    */
   void SetContentInfo(const std::string& contentInfo) override;
+
+  /**
+   * Check Widget is using key
+   */
+  bool IsKeyEventUsing() const override;
+
+  /**
+   * Set the flag that widget is using keyEvent
+   */
+  void SetUsingKeyEvent(bool flag) override;
+
+  /**
+   * Set the Information of widget
+   */
+  void SetInformation(Dali::Window window, const std::string& widgetId) override;
+
+  /**
+   * Get the window
+   */
+  Dali::Window GetWindow() const override;
+
+  /**
+   * Get the widget id
+   */
+  std::string GetWidgetId() const override;
 };
 
 } // namespace Adaptor
index 7dd6686..bb70910 100644 (file)
@@ -36,6 +36,28 @@ void WidgetImplWin::SetContentInfo(const std::string& contentInfo)
 {
 }
 
+bool WidgetImplWin::IsKeyEventUsing() const
+{
+}
+
+void WidgetImplWin::SetUsingKeyEvent(bool flag)
+{
+}
+
+void WidgetImplWin::SetInformation(Dali::Window window, const std::string& widgetId)
+{
+}
+
+Dali::Window WidgetImplWin::GetWindow() const
+{
+    return Dali::Window();
+}
+
+std::string WidgetImplWin::GetWidgetId() const
+{
+    return std::string();
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index 63fe4e4..de1e896 100644 (file)
@@ -51,6 +51,31 @@ public:
    * Set content information to widget framework
    */
   void SetContentInfo(const std::string& contentInfo) override;
+
+  /**
+   * Check Widget is using key
+   */
+  bool IsKeyEventUsing() const override;
+
+  /**
+   * Set the flag that widget is using keyEvent
+   */
+  void SetUsingKeyEvent(bool flag) override;
+
+  /**
+   * Set the Information of widget
+   */
+  void SetInformation(Dali::Window window, const std::string& widgetId) override;
+
+  /**
+   * Get the window
+   */
+  Dali::Window GetWindow() const override;
+
+  /**
+   * Get the widget id
+   */
+  std::string GetWidgetId() const override;
 };
 
 } // namespace Adaptor
index 6df39a0..8ac4d30 100644 (file)
@@ -87,11 +87,59 @@ void Widget::SetContentInfo(const std::string& contentInfo)
   }
 }
 
+bool Widget::IsKeyEventUsing() const
+{
+  if(mImpl != nullptr)
+  {
+    return mImpl->IsKeyEventUsing();
+  }
+
+  //if mImpl is null, return default value
+  return false;
+}
+
+void Widget::SetUsingKeyEvent(bool flag)
+{
+  if(mImpl != nullptr)
+  {
+    mImpl->SetUsingKeyEvent(flag);
+  }
+}
+
 void Widget::SetImpl(Impl* impl)
 {
   mImpl = impl;
 }
 
+
+void Widget::SetInformation(Dali::Window window, const std::string& widgetId)
+{
+  if(mImpl != nullptr)
+  {
+    mImpl->SetInformation(window, widgetId);
+  }
+}
+
+Dali::Window Widget::GetWindow() const
+{
+  if(mImpl != nullptr)
+  {
+    return mImpl->GetWindow();
+  }
+
+  return Dali::Window();
+}
+
+std::string Widget::GetWidgetId() const
+{
+  if(mImpl != nullptr)
+  {
+    return mImpl->GetWidgetId();
+  }
+
+  return std::string();
+}
+
 Internal::Adaptor::Widget& GetImplementation(Dali::Widget& widget)
 {
   DALI_ASSERT_ALWAYS(widget && "widget handle is empty");
index 3e7e87a..06e990f 100644 (file)
@@ -131,6 +131,22 @@ public:
    */
   void SetContentInfo(const std::string& contentInfo);
 
+  /**
+   * @brief Check Widget is using key
+   *
+   * widget can set flag to SetUsingKeyEvent
+   *
+   * @return True if Widget is using key
+   */
+  bool IsKeyEventUsing() const;
+
+  /**
+   * @brief Set the flag that widget is using keyEvent
+   *
+   * @param[in] flag The flag to set.
+   */
+  void SetUsingKeyEvent(bool flag);
+
 protected:
   /**
    * @brief WidgetImpl constructor
@@ -152,6 +168,28 @@ public:
    */
   void SetImpl(Impl* impl);
 
+  /**
+   * @brief Set the Information of widget
+   *
+   * @param window The window to set the information of widget
+   * @param widgetId The Id of widget
+   */
+  void SetInformation(Dali::Window window, const std::string& widgetId);
+
+  /**
+   * @brief Get the Window of widget
+   *
+   * @return the window of widget
+   */
+  Dali::Window GetWindow() const;
+
+  /**
+   * @brief Get the id of widget
+   *
+   * @return the id of widget
+   */
+  std::string GetWidgetId() const;
+
 private:
   Impl* mImpl;
 
index e59f8e1..702a44f 100644 (file)
@@ -36,9 +36,9 @@ BuildRequires:  pkgconfig(libtzplatform-config)
 %if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
 BuildRequires:  pkgconfig(capi-appfw-watch-application)
 BuildRequires:  pkgconfig(appcore-watch)
-BuildRequires:  pkgconfig(screen_connector_provider)
 %endif
 
+BuildRequires:  pkgconfig(screen_connector_provider)
 BuildRequires:  pkgconfig(gles20)
 BuildRequires:  pkgconfig(glesv2)
 BuildRequires:  pkgconfig(ttrace)