From e4d8a8b01e4fcfb11c90c35f0049a3df086a3c20 Mon Sep 17 00:00:00 2001 From: Jaehyun Cho Date: Wed, 13 Jul 2022 18:53:09 +0900 Subject: [PATCH] [Tizen] Add InsetsChangedSignal to WindowBaseEcoreWl2 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 | 5 + dali/devel-api/adaptor-framework/window-devel.h | 9 + dali/internal/window-system/common/window-base.cpp | 8 +- dali/internal/window-system/common/window-base.h | 7 + dali/internal/window-system/common/window-impl.cpp | 8 + dali/internal/window-system/common/window-impl.h | 20 ++ .../ecore-wl2/window-base-ecore-wl2.cpp | 213 +++++++++++++++++++++ .../ecore-wl2/window-base-ecore-wl2.h | 10 + .../adaptor-framework/window-enumerations.h | 19 ++ 9 files changed, 298 insertions(+), 1 deletion(-) diff --git a/dali/devel-api/adaptor-framework/window-devel.cpp b/dali/devel-api/adaptor-framework/window-devel.cpp index 7e0c3dc..e91fa9e 100644 --- a/dali/devel-api/adaptor-framework/window-devel.cpp +++ b/dali/devel-api/adaptor-framework/window-devel.cpp @@ -299,6 +299,11 @@ MouseInOutEventSignalType& MouseInOutEventSignal(Window window) return GetImplementation(window).MouseInOutEventSignal(); } +InsetsChangedSignalType& InsetsChangedSignal(Window window) +{ + return GetImplementation(window).InsetsChangedSignal(); +} + } // namespace DevelWindow } // namespace Dali diff --git a/dali/devel-api/adaptor-framework/window-devel.h b/dali/devel-api/adaptor-framework/window-devel.h index d2cab95..021ebef 100644 --- a/dali/devel-api/adaptor-framework/window-devel.h +++ b/dali/devel-api/adaptor-framework/window-devel.h @@ -52,6 +52,7 @@ typedef Signal typedef Signal MouseInOutEventSignalType; ///< MouseInOutEvent signal type typedef Signal MoveCompletedSignalType; ///< Window Moved by Server signal type typedef Signal ResizeCompletedSignalType; ///< Window Resized by Server signal type +typedef Signal 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 diff --git a/dali/internal/window-system/common/window-base.cpp b/dali/internal/window-system/common/window-base.cpp index ddedc2c..633126b 100644 --- a/dali/internal/window-system/common/window-base.cpp +++ b/dali/internal/window-system/common/window-base.cpp @@ -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 diff --git a/dali/internal/window-system/common/window-base.h b/dali/internal/window-system/common/window-base.h index 055edd0..58f3d8e 100644 --- a/dali/internal/window-system/common/window-base.h +++ b/dali/internal/window-system/common/window-base.h @@ -78,6 +78,7 @@ public: typedef Signal MouseInOutEventSignalType; typedef Signal MoveCompletedSignalType; typedef Signal ResizeCompletedSignalType; + typedef Signal InsetsChangedSignalType; // Input events typedef Signal 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 diff --git a/dali/internal/window-system/common/window-impl.cpp b/dali/internal/window-system/common/window-impl.cpp index c20f287..7e0a6ab 100644 --- a/dali/internal/window-system/common/window-impl.cpp +++ b/dali/internal/window-system/common/window-impl.cpp @@ -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(); diff --git a/dali/internal/window-system/common/window-impl.h b/dali/internal/window-system/common/window-impl.h index 757782d..089bcd8 100644 --- a/dali/internal/window-system/common/window-impl.h +++ b/dali/internal/window-system/common/window-impl.h @@ -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 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; diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp index ef711ba..f86954e 100644 --- a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp @@ -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(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(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(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, ®istryListener, 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(event); + if(ev && ev->win == static_cast(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(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(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(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(state + 1)); + changed = true; + } + } + + if(changed) + { + Ecore_Wl2_Event_Conformant_Change *ev = static_cast(calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change))); + + if(!ev) + { + return; + } + ev->win = GetNativeWindowId(); + ev->part_type = static_cast(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; diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h index af8054f..c0bd199 100644 --- a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.h @@ -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); diff --git a/dali/public-api/adaptor-framework/window-enumerations.h b/dali/public-api/adaptor-framework/window-enumerations.h index bf6c46b..c861826 100644 --- a/dali/public-api/adaptor-framework/window-enumerations.h +++ b/dali/public-api/adaptor-framework/window-enumerations.h @@ -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 -- 2.7.4