[Tizen] Add InsetsChangedSignal to WindowBaseEcoreWl2 40/296440/2 accepted/tizen/7.0/unified/20230811.173919
authorJaehyun Cho <jae_hyun.cho@samsung.com>
Wed, 13 Jul 2022 09:53:09 +0000 (18:53 +0900)
committerJaehyun Cho <jae_hyun.cho@samsung.com>
Thu, 3 Aug 2023 10:43:45 +0000 (19:43 +0900)
Window insets are the inner size between window content and window edge.

Window insets are required when status bar, virtual keyboard, or
clipboard appears on window to avoid window content obsecured by them.

To notify the window insets changes, InsetsChangedSignal is added to
WindowBaseEcoreWl2.

To notice the window insets changes, ECORE_WL2_EVENT_CONFORMANT_CHANGE
is used.

Change-Id: Iaff1b2c121ee5e07769eac9d9950b74b500e192b

dali/devel-api/adaptor-framework/window-devel.cpp
dali/devel-api/adaptor-framework/window-devel.h
dali/internal/window-system/common/window-base.cpp
dali/internal/window-system/common/window-base.h
dali/internal/window-system/common/window-impl.cpp
dali/internal/window-system/common/window-impl.h
dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp
dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h
dali/public-api/adaptor-framework/window-enumerations.h

index 7e0c3dc..e91fa9e 100644 (file)
@@ -299,6 +299,11 @@ MouseInOutEventSignalType& MouseInOutEventSignal(Window window)
   return GetImplementation(window).MouseInOutEventSignal();
 }
 
+InsetsChangedSignalType& InsetsChangedSignal(Window window)
+{
+  return GetImplementation(window).InsetsChangedSignal();
+}
+
 } // namespace DevelWindow
 
 } // namespace Dali
index d2cab95..021ebef 100644 (file)
@@ -52,6 +52,7 @@ typedef Signal<void(Window, Dali::WindowOrientation)>
 typedef Signal<void(Window, const Dali::DevelWindow::MouseInOutEvent&)>              MouseInOutEventSignalType;               ///< MouseInOutEvent signal type
 typedef Signal<void(Window, Dali::Window::WindowPosition)>                           MoveCompletedSignalType;                 ///< Window Moved by Server signal type
 typedef Signal<void(Window, Dali::Window::WindowSize)>                               ResizeCompletedSignalType;               ///< Window Resized by Server signal type
+typedef Signal<void(WindowInsetsPartType, WindowInsetsPartState, const Extents&)>    InsetsChangedSignalType;                 ///< InsetsChanged signal type
 
 /**
  * @brief Creates an initialized handle to a new Window.
@@ -618,6 +619,14 @@ DALI_ADAPTOR_API MoveCompletedSignalType& MoveCompletedSignal(Window window);
  */
 DALI_ADAPTOR_API ResizeCompletedSignalType& ResizeCompletedSignal(Window window);
 
+/**
+ * @brief This signal is emitted when window insets are changed by appearing or disappearing indicator, virtual keyboard, or clipboard.
+ *
+ * @param[in] window The window instance
+ * @return The signal to connect to
+ */
+DALI_ADAPTOR_API InsetsChangedSignalType& InsetsChangedSignal(Window window);
+
 } // namespace DevelWindow
 
 } // namespace Dali
index ddedc2c..633126b 100644 (file)
@@ -43,7 +43,8 @@ WindowBase::WindowBase()
   mAuxiliaryMessageSignal(),
   mMouseInOutEventSignal(),
   mMoveCompletedSignal(),
-  mResizeCompletedSignal()
+  mResizeCompletedSignal(),
+  mInsetsChangedSignal()
 {
 }
 
@@ -151,6 +152,11 @@ WindowBase::ResizeCompletedSignalType& WindowBase::ResizeCompletedSignal()
   return mResizeCompletedSignal;
 }
 
+WindowBase::InsetsChangedSignalType& WindowBase::InsetsChangedSignal()
+{
+  return mInsetsChangedSignal;
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index 055edd0..58f3d8e 100644 (file)
@@ -78,6 +78,7 @@ public:
   typedef Signal<void(const Dali::DevelWindow::MouseInOutEvent&)>                      MouseInOutEventSignalType;
   typedef Signal<void(Dali::Int32Pair&)>                                               MoveCompletedSignalType;
   typedef Signal<void(Dali::Uint16Pair&)>                                              ResizeCompletedSignalType;
+  typedef Signal<void(WindowInsetsPartType, WindowInsetsPartState, const Extents&)>    InsetsChangedSignalType;
 
   // Input events
   typedef Signal<void(Integration::Point&, uint32_t)> TouchEventSignalType;
@@ -571,6 +572,11 @@ public:
    */
   ResizeCompletedSignalType& ResizeCompletedSignal();
 
+  /**
+   * @brief This signal is emitted when window insets are changed by appearing or disappearing indicator, virtual keyboard, or clipboard.
+   */
+  InsetsChangedSignalType& InsetsChangedSignal();
+
 protected:
   // Undefined
   WindowBase(const WindowBase&) = delete;
@@ -599,6 +605,7 @@ protected:
   MouseInOutEventSignalType               mMouseInOutEventSignal;
   MoveCompletedSignalType                 mMoveCompletedSignal;
   ResizeCompletedSignalType               mResizeCompletedSignal;
+  InsetsChangedSignalType                 mInsetsChangedSignal;
 };
 
 } // namespace Adaptor
index c20f287..7e0a6ab 100644 (file)
@@ -97,6 +97,7 @@ Window::Window()
   mMouseInOutEventSignal(),
   mMoveCompletedSignal(),
   mResizeCompletedSignal(),
+  mInsetsChangedSignal(),
   mLastKeyEvent(),
   mLastTouchEvent(),
   mIsTransparent(false),
@@ -168,6 +169,8 @@ void Window::Initialize(Any surface, const PositionSize& positionSize, const std
   mWindowSurface->OutputTransformedSignal().Connect(this, &Window::OnOutputTransformed);
   mWindowSurface->RotationFinishedSignal().Connect(this, &Window::OnRotationFinished);
 
+  mWindowBase->InsetsChangedSignal().Connect(this, &Window::OnInsetsChanged);
+
   AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
 
   SetClass(name, className);
@@ -1101,6 +1104,11 @@ void Window::OnAuxiliaryMessage(const std::string& key, const std::string& value
   mAuxiliaryMessageSignal.Emit(key, value, options);
 }
 
+void Window::OnInsetsChanged(WindowInsetsPartType partType, WindowInsetsPartState partState, const Extents& insets)
+{
+  mInsetsChangedSignal.Emit(partType, partState, insets);
+}
+
 void Window::OnAccessibilityEnabled()
 {
   auto bridge     = Accessibility::Bridge::GetCurrentBridge();
index 757782d..089bcd8 100644 (file)
@@ -73,6 +73,7 @@ public:
   typedef Dali::DevelWindow::MouseInOutEventSignalType               MouseInOutEventSignalType;
   typedef Dali::DevelWindow::MoveCompletedSignalType                 MoveCompletedSignalType;
   typedef Dali::DevelWindow::ResizeCompletedSignalType               ResizeCompletedSignalType;
+  typedef Dali::DevelWindow::InsetsChangedSignalType                 InsetsChangedSignalType;
   typedef Signal<void()>                                             SignalType;
 
   /**
@@ -645,6 +646,16 @@ private:
    */
   bool IsOrientationAvailable(WindowOrientation orientation) const;
 
+  /**
+   * @brief Called when window insets are changed by appearing or disappearing indicator, virtual keyboard, or clipboard.
+   *
+   * @param[in] partType the type of the part that occurs the window insets change.
+   * @param[in] partState the state of the part that occurs the window insets change.
+   * @param[in] insets the extents value of window insets.
+   */
+  void OnInsetsChanged(WindowInsetsPartType partType, WindowInsetsPartState partState, const Extents& insets);
+
+
 private: // Dali::Internal::Adaptor::SceneHolder
   /**
    * @copydoc Dali::Internal::Adaptor::SceneHolder::OnAdaptorSet
@@ -805,6 +816,14 @@ public: // Signals
     return mResizeCompletedSignal;
   }
 
+  /**
+   * @copydoc Dali::DevelWindow::InsetsChangedSignal()
+   */
+  InsetsChangedSignalType& InsetsChangedSignal()
+  {
+    return mInsetsChangedSignal;
+  }
+
 private:
   WindowRenderSurface* mWindowSurface; ///< The window rendering surface
   WindowBase*          mWindowBase;
@@ -838,6 +857,7 @@ private:
   MouseInOutEventSignalType               mMouseInOutEventSignal;
   MoveCompletedSignalType                 mMoveCompletedSignal;
   ResizeCompletedSignalType               mResizeCompletedSignal;
+  InsetsChangedSignalType                 mInsetsChangedSignal;
 
   Dali::KeyEvent   mLastKeyEvent;
   Dali::TouchEvent mLastTouchEvent;
index ef711ba..f86954e 100644 (file)
@@ -739,6 +739,19 @@ static Eina_Bool EcoreEventWindowResizeCompleted(void* data, int type, void* eve
   return ECORE_CALLBACK_RENEW;
 }
 
+/////////////////////////////////////////////////////////////////////////////////////////////////
+// Conformant Change Callback
+/////////////////////////////////////////////////////////////////////////////////////////////////
+static Eina_Bool EcoreEventConformantChange(void* data, int type, void* event)
+{
+  WindowBaseEcoreWl2* windowBase = static_cast<WindowBaseEcoreWl2*>(data);
+  if(windowBase)
+  {
+    windowBase->OnEcoreEventConformantChange(event);
+  }
+  return ECORE_CALLBACK_RENEW;
+}
+
 static void RegistryGlobalCallback(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
 {
   WindowBaseEcoreWl2* windowBase = static_cast<WindowBaseEcoreWl2*>(data);
@@ -763,6 +776,11 @@ static void TizenPolicyConformant(void* data, struct tizen_policy* tizenPolicy,
 
 static void TizenPolicyConformantArea(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t conformantPart, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h)
 {
+  WindowBaseEcoreWl2* windowBase = static_cast<WindowBaseEcoreWl2*>(data);
+  if(windowBase)
+  {
+    windowBase->TizenPolicyConformantArea(data, tizenPolicy, surface, conformantPart, state, x, y, w, h);
+  }
 }
 
 static void TizenPolicyNotificationChangeDone(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, int32_t level, uint32_t state)
@@ -983,6 +1001,9 @@ void WindowBaseEcoreWl2::Initialize(PositionSize positionSize, Any surface, bool
   // Register Window auxiliary event
   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_WL2_EVENT_AUX_MESSAGE, EcoreEventWindowAuxiliaryMessage, this));
 
+  // Register Conformant change event
+  mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, EcoreEventConformantChange, this));
+
 #if defined(VCONF_ENABLED)
   // Register Vconf notify - font name and size
   vconf_notify_key_changed_for_ui_thread(DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, this);
@@ -1008,6 +1029,9 @@ void WindowBaseEcoreWl2::Initialize(PositionSize positionSize, Any surface, bool
 
         wl_registry* registry = wl_display_get_registry(displayWrapper);
         wl_registry_add_listener(registry, &registryListener, this);
+
+        // To support ECORE_WL2_EVENT_CONFORMANT_CHANGE event handler
+        ecore_wl2_window_conformant_set(mEcoreWindow, true);
       }
 
       wl_proxy_wrapper_destroy(displayWrapper);
@@ -1573,6 +1597,106 @@ void WindowBaseEcoreWl2::OnEcoreEventWindowAuxiliaryMessage(void* event)
   }
 }
 
+void WindowBaseEcoreWl2::OnEcoreEventConformantChange(void* event)
+{
+  Ecore_Wl2_Event_Conformant_Change* ev = static_cast<Ecore_Wl2_Event_Conformant_Change*>(event);
+  if(ev && ev->win == static_cast<unsigned int>(ecore_wl2_window_id_get(mEcoreWindow)))
+  {
+    WindowInsetsPartType partType = WindowInsetsPartType::STATUS_BAR;
+
+    int x = 0;
+    int y = 0;
+    int w = 0;
+    int h = 0;
+
+    switch (ev->part_type)
+    {
+      case ECORE_WL2_INDICATOR_PART:
+      {
+        partType = WindowInsetsPartType::STATUS_BAR;
+        ecore_wl2_window_indicator_geometry_get(mEcoreWindow, &x, &y, &w, &h);
+        break;
+      }
+      case ECORE_WL2_KEYBOARD_PART:
+      {
+        partType = WindowInsetsPartType::KEYBOARD;
+        ecore_wl2_window_keyboard_geometry_get(mEcoreWindow, &x, &y, &w, &h);
+        break;
+      }
+      case ECORE_WL2_CLIPBOARD_PART:
+      {
+        partType = WindowInsetsPartType::CLIPBOARD;
+        ecore_wl2_window_clipboard_geometry_get(mEcoreWindow, &x, &y, &w, &h);
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+
+    WindowInsetsPartState partState = WindowInsetsPartState::INVISIBLE;
+
+    int left = 0;
+    int right = 0;
+    int top = 0;
+    int bottom = 0;
+
+    // Insets are applied only if system UI(e.g. virtual keyboard) satisfies the following 2 conditions.
+    // 1. System UI fits to the window width or height.
+    // 2. System UI begins or ends from the edge of window.
+    // Otherwise, we should not resize window content because there would be empty space around system UI.
+    bool applyInsets = false;
+
+    // Zero insets are applied if state is invisible
+    if(!ev->state)
+    {
+      applyInsets = true;
+    }
+    else
+    {
+      partState = WindowInsetsPartState::VISIBLE;
+
+      int winX = mWindowPositionSize.x;
+      int winY = mWindowPositionSize.y;
+      int winW = mWindowPositionSize.width;
+      int winH = mWindowPositionSize.height;
+
+      if((x <= winX) && (x + w >= winX + winW))
+      {
+        if((y <= winY) && (y + h >= winY) && (y + h <= winY + winH))
+        {
+          top = y + h - winY;
+          applyInsets = true;
+        }
+        else if((y + h >= winY + winH) && (y >= winY) && (y <= winY + winH))
+        {
+          bottom = winY + winH - y;
+          applyInsets = true;
+        }
+      }
+      else if((y <= winY) && (y + h >= winY + winH))
+      {
+        if((x <= winX) && (x + w >= winX) && (x + w <= winX + winW))
+        {
+          left = x + w - winX;
+          applyInsets = true;
+        }
+        else if((x + w >= winX + winW) && (x >= winX) && (x <= winX + winW))
+        {
+          right = winX + winW - x;
+          applyInsets = true;
+        }
+      }
+    }
+
+    if(applyInsets)
+    {
+      mInsetsChangedSignal.Emit(partType, partState, Extents(left, right, top, bottom));
+    }
+  }
+}
+
 void WindowBaseEcoreWl2::KeymapChanged(void* data, int type, void* event)
 {
   Ecore_Wl2_Event_Seat_Keymap_Changed* changed = static_cast<Ecore_Wl2_Event_Seat_Keymap_Changed*>(event);
@@ -1648,6 +1772,95 @@ void WindowBaseEcoreWl2::RegistryGlobalCallbackRemove(void* data, struct wl_regi
   mTizenDisplayPolicy = NULL;
 }
 
+void WindowBaseEcoreWl2::TizenPolicyConformantArea(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t conformantPart, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+  int originalX, originalY, originalWidth, originalHeight;
+  bool changed = false;
+
+  if(!surface)
+  {
+    DALI_LOG_ERROR("Failed to get wayland surface in WindowBaseEcoreWl2::TizenPolicyConformantArea()\n");
+    return;
+  }
+
+  if(conformantPart == TIZEN_POLICY_CONFORMANT_PART_INDICATOR)
+  {
+    ecore_wl2_window_indicator_geometry_get(mEcoreWindow, &originalX, &originalY, &originalWidth, &originalHeight);
+    if((originalX != x) || (originalY != y) || (originalWidth != w) || (originalHeight != h))
+    {
+      ecore_wl2_window_indicator_geometry_set(mEcoreWindow, x, y, w, h);
+      changed = true;
+    }
+
+    /**
+     * The given state is based on the visibility value of indicator.
+     * Thus we need to add 1 to it before comparing with indicator state.
+     */
+    Ecore_Wl2_Indicator_State indState =  ecore_wl2_window_indicator_state_get(mEcoreWindow);
+    if((state + 1) != indState)
+    {
+      ecore_wl2_window_indicator_state_set(mEcoreWindow, static_cast<Ecore_Wl2_Indicator_State>(state + 1));
+      changed = true;
+    }
+  }
+  else if(conformantPart == TIZEN_POLICY_CONFORMANT_PART_KEYBOARD)
+  {
+    ecore_wl2_window_keyboard_geometry_get(mEcoreWindow, &originalX, &originalY, &originalWidth, &originalHeight);
+    if((originalX != x) || (originalY != y) || (originalWidth != w) || (originalHeight != h))
+    {
+      ecore_wl2_window_keyboard_geometry_set(mEcoreWindow, x, y, w, h);
+      changed = true;
+    }
+
+    /**
+     * The given state is based on the visibility value of virtual keyboard window.
+     * Thus we need to add 1 to it before comparing with keyboard state.
+     */
+    Ecore_Wl2_Virtual_Keyboard_State kbdState = ecore_wl2_window_keyboard_state_get(mEcoreWindow);
+    if((state + 1) != (kbdState))
+    {
+      ecore_wl2_window_keyboard_state_set(mEcoreWindow, static_cast<Ecore_Wl2_Virtual_Keyboard_State>(state + 1));
+      changed = true;
+    }
+  }
+  else if(conformantPart == TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD)
+  {
+    ecore_wl2_window_clipboard_geometry_get(mEcoreWindow, &originalX, &originalY, &originalWidth, &originalHeight);
+    if((originalX != x) || (originalY != y) || (originalWidth != w) || (originalHeight != h))
+    {
+      ecore_wl2_window_clipboard_geometry_set(mEcoreWindow, x, y, w, h);
+      changed = true;
+    }
+
+    /**
+     * The given state is based on the visibility value of clipboard window.
+     * Thus we need to add 1 to it before comparing with clipboard state.
+     */
+    Ecore_Wl2_Clipboard_State clipState = ecore_wl2_window_clipboard_state_get(mEcoreWindow);
+    if((state + 1) != clipState)
+    {
+      ecore_wl2_window_clipboard_state_set(mEcoreWindow, static_cast<Ecore_Wl2_Clipboard_State>(state + 1));
+      changed = true;
+    }
+  }
+
+  if(changed)
+  {
+    Ecore_Wl2_Event_Conformant_Change *ev = static_cast<Ecore_Wl2_Event_Conformant_Change*>(calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change)));
+
+    if(!ev)
+    {
+      return;
+    }
+    ev->win = GetNativeWindowId();
+    ev->part_type = static_cast<Ecore_Wl2_Conformant_Part_Type>(conformantPart);
+    ev->state = state;
+    ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, NULL, NULL);
+  }
+
+  DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, "WindowBaseEcoreWl2::TizenPolicyConformantArea: conformantPart = %u, state = %u, position = (%d, %d), size = (%d, %d)\n", conformantPart, state, x, y, w, h);
+}
+
 void WindowBaseEcoreWl2::TizenPolicyNotificationChangeDone(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, int32_t level, uint32_t state)
 {
   mNotificationLevel           = level;
index af8054f..c0bd199 100644 (file)
@@ -171,6 +171,11 @@ public:
   void OnEcoreEventWindowRedrawRequest();
 
   /**
+   * @brief Called when a conformant is changed.
+   */
+  void OnEcoreEventConformantChange(void* event);
+
+  /**
    * @brief Called when window's auxiliary is changed then display server send the changed message.
    *
    * @param[in] auxiliary's message data. It has key, value and integer list data.
@@ -211,6 +216,11 @@ public:
   void RegistryGlobalCallbackRemove(void* data, struct wl_registry* registry, uint32_t id);
 
   /**
+   * @brief TizenPolicyConformantArea
+   */
+  void TizenPolicyConformantArea(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t conformantPart, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h);
+
+  /**
    * @brief TizenPolicyNotificationChangeDone
    */
   void TizenPolicyNotificationChangeDone(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, int32_t level, uint32_t state);
index bf6c46b..c861826 100644 (file)
@@ -129,6 +129,25 @@ enum class WindowResizeDirection
   BOTTOM_RIGHT = 8  ///< Start resizing window to the bottom-right edge.
 };
 
+/**
+ * @brief Enumeration of window insets part type.
+ */
+enum class WindowInsetsPartType
+{
+  STATUS_BAR = 0, ///< Status bar
+  KEYBOARD,       ///< Keyboard
+  CLIPBOARD,      ///< Clipboard
+};
+
+/**
+ * @brief Enumeration of window insets part state.
+ */
+enum class WindowInsetsPartState
+{
+  INVISIBLE = 0, ///< Invisible
+  VISIBLE,       ///< Visible
+};
+
 } // namespace Dali
 
 #endif // DALI_WINDOW_ENUMERATIONS_H