From 547b8e079d0051de965bb04745e820823244a04c Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Wed, 7 Jun 2017 16:05:38 +0900 Subject: [PATCH] Support window rotation Change-Id: Ib1fbd9fed50ea2491fc923084581ce12e265e3bc --- adaptors/common/window-impl.h | 9 +- .../devel-api/adaptor-framework/window-devel.cpp | 5 + .../devel-api/adaptor-framework/window-devel.h | 15 +++ adaptors/ecore/wayland/event-handler-ecore-wl.cpp | 65 ++++++++++- adaptors/ecore/wayland/render-surface-ecore-wl.cpp | 2 +- adaptors/ecore/wayland/window-impl-ecore-wl.cpp | 46 +++++++- .../wayland/window-render-surface-ecore-wl.cpp | 130 ++++++++++++++++++++- adaptors/ecore/wayland/window-render-surface.h | 31 ++++- .../public-api/adaptor-framework/application.cpp | 2 + .../public-api/adaptor-framework/application.h | 1 + adaptors/wayland/window-impl-wl.cpp | 6 +- adaptors/x11/window-impl-x.cpp | 6 +- 12 files changed, 299 insertions(+), 19 deletions(-) diff --git a/adaptors/common/window-impl.h b/adaptors/common/window-impl.h index 09a7541..d4774f1 100644 --- a/adaptors/common/window-impl.h +++ b/adaptors/common/window-impl.h @@ -60,6 +60,7 @@ class Window : public Dali::BaseObject, public IndicatorInterface::Observer, pub public: typedef Dali::Window::IndicatorSignalType IndicatorSignalType; typedef Dali::DevelWindow::FocusSignalType FocusSignalType; + typedef Dali::DevelWindow::ResizedSignalType ResizedSignalType; typedef Signal< void () > SignalType; /** @@ -370,11 +371,16 @@ public: // Signals IndicatorSignalType& IndicatorVisibilityChangedSignal() { return mIndicatorVisibilityChangedSignal; } /** - * The user should connect to this signal to get a timing when window gains focus or loses focus. + * @copydoc Dali::DevelWindow::FocusChangedSignal() */ FocusSignalType& FocusChangedSignal() { return mFocusChangedSignal; } /** + * @copydoc Dali::DevelWindow::ResizedSignal() + */ + ResizedSignalType& ResizedSignal() { return mResizedSignal; } + + /** * This signal is emitted when the window is requesting to be deleted */ SignalType& DeleteRequestSignal() { return mDeleteRequestSignal; } @@ -416,6 +422,7 @@ private: // Signals IndicatorSignalType mIndicatorVisibilityChangedSignal; FocusSignalType mFocusChangedSignal; + ResizedSignalType mResizedSignal; SignalType mDeleteRequestSignal; }; diff --git a/adaptors/devel-api/adaptor-framework/window-devel.cpp b/adaptors/devel-api/adaptor-framework/window-devel.cpp index b6f977c..447cdd1 100644 --- a/adaptors/devel-api/adaptor-framework/window-devel.cpp +++ b/adaptors/devel-api/adaptor-framework/window-devel.cpp @@ -145,6 +145,11 @@ int GetBrightness( Window window ) return GetImplementation( window ).GetBrightness(); } +ResizedSignalType& ResizedSignal( Window window ) +{ + return GetImplementation( window ).ResizedSignal(); +} + } // namespace DevelWindow } // namespace Dali diff --git a/adaptors/devel-api/adaptor-framework/window-devel.h b/adaptors/devel-api/adaptor-framework/window-devel.h index 6d07c71..be087f0 100644 --- a/adaptors/devel-api/adaptor-framework/window-devel.h +++ b/adaptors/devel-api/adaptor-framework/window-devel.h @@ -78,6 +78,7 @@ enum Type }; typedef Signal< void (bool) > FocusSignalType; ///< Window focus signal type +typedef Signal< void (int, int) > ResizedSignalType; ///< Window resized signal type /** * @brief The user should connect to this signal to get a timing when window gains focus or loses focus. @@ -293,6 +294,20 @@ DALI_IMPORT_API bool SetBrightness( Window window, int brightness ); */ DALI_IMPORT_API int GetBrightness( Window window ); +/** + * @brief This signal is emitted when the window is resized. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( int width, int height ); + * @endcode + * The parameters are the resized width and height. + * + * @param[in] window The window to get a signal + * @return The signal to connect to + */ +DALI_IMPORT_API ResizedSignalType& ResizedSignal( Window window ); + } // namespace DevelWindow } // namespace Dali diff --git a/adaptors/ecore/wayland/event-handler-ecore-wl.cpp b/adaptors/ecore/wayland/event-handler-ecore-wl.cpp index 71237e1..347339b 100644 --- a/adaptors/ecore/wayland/event-handler-ecore-wl.cpp +++ b/adaptors/ecore/wayland/event-handler-ecore-wl.cpp @@ -249,7 +249,10 @@ struct EventHandler::Impl Impl( EventHandler* handler, Ecore_Wl_Window* window ) : mHandler( handler ), mEcoreEventHandler(), - mWindow( window ) + mWindow( window ), + mRotationAngle( 0 ), + mWindowWidth( 0 ), + mWindowHeight( 0 ) #ifdef DALI_ELDBUS_AVAILABLE , mSystemConnection( NULL ) #endif // DALI_ELDBUS_AVAILABLE @@ -1186,8 +1189,18 @@ struct EventHandler::Impl RotationEvent rotationEvent; rotationEvent.angle = ev->angle; rotationEvent.winResize = 0; - rotationEvent.width = ev->w; - rotationEvent.height = ev->h; + + if( ev->angle == 0 || ev->angle == 180 ) + { + rotationEvent.width = ev->w; + rotationEvent.height = ev->h; + } + else + { + rotationEvent.width = ev->h; + rotationEvent.height = ev->w; + } + handler->SendRotationPrepareEvent( rotationEvent ); return ECORE_CALLBACK_PASS_ON; @@ -1230,10 +1243,48 @@ struct EventHandler::Impl handler->SendEvent( StyleChange::DEFAULT_FONT_SIZE_CHANGE ); } + void ConvertTouchPosition( Integration::Point& point ) + { + Vector2 position = point.GetScreenPosition(); + Vector2 convertedPosition; + + switch( mRotationAngle ) + { + case 90: + { + convertedPosition.x = mWindowWidth - position.y; + convertedPosition.y = position.x; + break; + } + case 180: + { + convertedPosition.x = mWindowWidth - position.x; + convertedPosition.y = mWindowHeight - position.y; + break; + } + case 270: + { + convertedPosition.x = position.y; + convertedPosition.y = mWindowHeight - position.x; + break; + } + default: + { + convertedPosition = position; + break; + } + } + + point.SetScreenPosition( convertedPosition ); + } + // Data EventHandler* mHandler; std::vector mEcoreEventHandler; Ecore_Wl_Window* mWindow; + int mRotationAngle; + int mWindowWidth; + int mWindowHeight; #ifdef DALI_ELDBUS_AVAILABLE Eldbus_Connection* mSystemConnection; #endif // DALI_ELDBUS_AVAILABLE @@ -1281,12 +1332,14 @@ void EventHandler::SendEvent(Integration::Point& point, unsigned long timeStamp) timeStamp = GetCurrentMilliSeconds(); } + mImpl->ConvertTouchPosition( point ); + Integration::TouchEvent touchEvent; Integration::HoverEvent hoverEvent; Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent); if(type != Integration::TouchEventCombiner::DispatchNone ) { - DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetLocalPosition().x, point.GetLocalPosition().y); + DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y); // First the touch and/or hover event & related gesture events are queued if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth) @@ -1344,6 +1397,10 @@ void EventHandler::SendRotationPrepareEvent( const RotationEvent& event ) { if( mRotationObserver != NULL ) { + mImpl->mRotationAngle = event.angle; + mImpl->mWindowWidth = event.width; + mImpl->mWindowHeight = event.height; + mRotationObserver->OnRotationPrepare( event ); mRotationObserver->OnRotationRequest(); } diff --git a/adaptors/ecore/wayland/render-surface-ecore-wl.cpp b/adaptors/ecore/wayland/render-surface-ecore-wl.cpp index 1aaa06e..c2d9a41 100644 --- a/adaptors/ecore/wayland/render-surface-ecore-wl.cpp +++ b/adaptors/ecore/wayland/render-surface-ecore-wl.cpp @@ -31,7 +31,7 @@ namespace Dali { #if defined(DEBUG_ENABLED) -Debug::Filter* gRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_ECORE_X_RENDER_SURFACE"); +Debug::Filter* gRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_ECORE_WL_RENDER_SURFACE"); #endif namespace ECore diff --git a/adaptors/ecore/wayland/window-impl-ecore-wl.cpp b/adaptors/ecore/wayland/window-impl-ecore-wl.cpp index d0dbdb7..692749b 100644 --- a/adaptors/ecore/wayland/window-impl-ecore-wl.cpp +++ b/adaptors/ecore/wayland/window-impl-ecore-wl.cpp @@ -521,7 +521,11 @@ Window::Window() mEventHandler( NULL ), mPreferredOrientation( Dali::Window::PORTRAIT ), mSupportedAuxiliaryHints(), - mAuxiliaryHints() + mAuxiliaryHints(), + mIndicatorVisibilityChangedSignal(), + mFocusChangedSignal(), + mResizedSignal(), + mDeleteRequestSignal() { } @@ -895,7 +899,45 @@ bool Window::IsVisible() const void Window::RotationDone( int orientation, int width, int height ) { - ecore_wl_window_rotation_change_done_send( mEventHandler->mEcoreWindow ); + PositionSize positionSize( 0, 0, width, height ); + + mAdaptor->SurfaceSizeChanged( positionSize ); + + // Emit signal + mResizedSignal.Emit( positionSize.width, positionSize.height ); + + Dali::Window::WindowOrientation windowOrientation; + switch( orientation ) + { + case 0: + { + windowOrientation = Dali::Window::PORTRAIT; + break; + } + case 90: + { + windowOrientation = Dali::Window::LANDSCAPE; + break; + } + case 180: + { + windowOrientation = Dali::Window::PORTRAIT_INVERSE; + break; + } + case 270: + { + windowOrientation = Dali::Window::LANDSCAPE_INVERSE; + break; + } + default: + { + windowOrientation = Dali::Window::PORTRAIT; + break; + } + } + + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + wlSurface->RequestRotation( windowOrientation, positionSize.width, positionSize.height ); } unsigned int Window::GetSupportedAuxiliaryHintCount() diff --git a/adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp b/adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp index 5cb7511..17c5515 100644 --- a/adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp +++ b/adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp @@ -16,17 +16,19 @@ */ // CLASS HEADER -#include "window-render-surface.h" +#include // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include -#include #include #include +#include +#include namespace Dali { @@ -51,7 +53,11 @@ WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, bool isTransparent) : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ), mWlWindow( NULL ), - mEglWindow( NULL ) + mEglWindow( NULL ), + mThreadSynchronization( NULL ), + mRotationTrigger( NULL ), + mRotationSupported( false ), + mRotated( false ) { DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" ); Init( surface ); @@ -69,6 +75,11 @@ WindowRenderSurface::~WindowRenderSurface() { ecore_wl_window_free( mWlWindow ); } + + if( mRotationTrigger ) + { + delete mRotationTrigger; + } } Ecore_Wl_Window* WindowRenderSurface::GetDrawable() @@ -88,6 +99,69 @@ Ecore_Wl_Window* WindowRenderSurface::GetWlWindow() return mWlWindow; } +void WindowRenderSurface::RequestRotation( Dali::Window::WindowOrientation orientation, int width, int height ) +{ + if( !mRotationSupported ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" ); + return; + } + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: orientation = %d\n", orientation ); + + if( !mRotationTrigger ) + { + TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface(); + mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); + } + + mPosition.width = width; + mPosition.height = height; + + mRotated = true; + + int angle; + wl_egl_window_rotation rotation; + + switch( orientation ) + { + case Dali::Window::PORTRAIT: + { + angle = 0; + rotation = ROTATION_0; + break; + } + case Dali::Window::LANDSCAPE: + { + angle = 90; + rotation = ROTATION_270; + break; + } + case Dali::Window::PORTRAIT_INVERSE: + { + angle = 180; + rotation = ROTATION_180; + break; + } + case Dali::Window::LANDSCAPE_INVERSE: + { + angle = 270; + rotation = ROTATION_90; + break; + } + default: + { + angle = 0; + rotation = ROTATION_0; + break; + } + } + + ecore_wl_window_rotation_set( mWlWindow, angle ); + + wl_egl_window_set_rotation( mEglWindow, rotation ); +} + void WindowRenderSurface::InitializeEgl( EglInterface& eglIf ) { DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); @@ -118,6 +192,14 @@ void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf ) mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), mPosition.width, mPosition.height); EGLNativeWindowType windowType( mEglWindow ); eglImpl.CreateSurfaceWindow( windowType, mColorDepth ); + + // Check capability + wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) ); + if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability ); + mRotationSupported = true; + } } void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf ) @@ -210,6 +292,28 @@ bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface ) { + if( mRotated ) + { + // Check viewport size + Dali::Vector< GLint > viewportSize; + viewportSize.Resize( 4 ); + + glAbstraction.GetIntegerv( GL_VIEWPORT, &viewportSize[0] ); + + if( viewportSize[2] == mPosition.width && viewportSize[3] == mPosition.height ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" ); + + mRotationTrigger->Trigger(); + + if( mThreadSynchronization ) + { + // Wait until the event-thread complete the rotation event processing + mThreadSynchronization->PostRenderWaitForCompletion(); + } + } + } + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); eglImpl.SwapBuffers(); @@ -253,9 +357,11 @@ void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId ) mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId ); } -void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ ) +void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ) { - // Nothing to do. + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" ); + + mThreadSynchronization = &threadSynchronization; } void WindowRenderSurface::ReleaseLock() @@ -263,6 +369,20 @@ void WindowRenderSurface::ReleaseLock() // Nothing to do. } +void WindowRenderSurface::ProcessRotationRequest() +{ + mRotated = false; + + ecore_wl_window_rotation_change_done_send( mWlWindow ); + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" ); + + if( mThreadSynchronization ) + { + mThreadSynchronization->PostRenderComplete(); + } +} + } // namespace ECore } // namespace Dali diff --git a/adaptors/ecore/wayland/window-render-surface.h b/adaptors/ecore/wayland/window-render-surface.h index 8fa093a..40a0d2a 100644 --- a/adaptors/ecore/wayland/window-render-surface.h +++ b/adaptors/ecore/wayland/window-render-surface.h @@ -2,7 +2,7 @@ #define __DALI_INTERNAL_ECORE_WL_WINDOW_RENDER_SURFACE_H__ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -18,9 +18,13 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include -#include +#include +#include namespace Dali { @@ -75,6 +79,14 @@ public: // API */ virtual Ecore_Wl_Window* GetWlWindow(); + /** + * Request surface rotation + * @param[in] orientation A new orientation of the surface + * @param[in] width A new width of the surface + * @param[in] height A new height of the surface + */ + void RequestRotation( Dali::Window::WindowOrientation orientation, int width, int height ); + public: // from Dali::RenderSurface /** @@ -149,10 +161,21 @@ protected: */ virtual void UseExistingRenderable( unsigned int surfaceId ); +private: + + /** + * Used as the callback for the rotation-trigger. + */ + void ProcessRotationRequest(); + private: // Data - Ecore_Wl_Window* mWlWindow; ///< Wayland-Window - wl_egl_window* mEglWindow; + Ecore_Wl_Window* mWlWindow; ///< Wayland-Window + wl_egl_window* mEglWindow; + ThreadSynchronizationInterface* mThreadSynchronization; + TriggerEventInterface* mRotationTrigger; + bool mRotationSupported; + bool mRotated; }; // class WindowRenderSurface diff --git a/adaptors/public-api/adaptor-framework/application.cpp b/adaptors/public-api/adaptor-framework/application.cpp index 62908dd..1d4fb36 100644 --- a/adaptors/public-api/adaptor-framework/application.cpp +++ b/adaptors/public-api/adaptor-framework/application.cpp @@ -162,6 +162,8 @@ Application::AppSignalType& Application::ResetSignal() Application::AppSignalType& Application::ResizeSignal() { + DALI_LOG_WARNING_NOFN( "DEPRECATION WARNING: ResizeSignal() is deprecated and will be removed from next release. Use Window::ResizedSignal() instead.\n" ); + return Internal::Adaptor::GetImplementation(*this).ResizeSignal(); } diff --git a/adaptors/public-api/adaptor-framework/application.h b/adaptors/public-api/adaptor-framework/application.h index 615ecc8..9e215c9 100644 --- a/adaptors/public-api/adaptor-framework/application.h +++ b/adaptors/public-api/adaptor-framework/application.h @@ -361,6 +361,7 @@ public: // Signals AppSignalType& ResetSignal(); /** + * @DEPRECATED_1_1.43 Use Window::ResizedSignal() instead. * @brief This signal is emitted when the window application rendering on is resized. * @SINCE_1_0.0 * @return The signal to connect to diff --git a/adaptors/wayland/window-impl-wl.cpp b/adaptors/wayland/window-impl-wl.cpp index 631681f..79e2555 100644 --- a/adaptors/wayland/window-impl-wl.cpp +++ b/adaptors/wayland/window-impl-wl.cpp @@ -121,7 +121,11 @@ Window::Window() mType( Dali::DevelWindow::NORMAL ), mPreferredOrientation( Dali::Window::PORTRAIT ), mSupportedAuxiliaryHints(), - mAuxiliaryHints() + mAuxiliaryHints(), + mIndicatorVisibilityChangedSignal(), + mFocusChangedSignal(), + mResizedSignal(), + mDeleteRequestSignal() { mEventHandler = NULL; } diff --git a/adaptors/x11/window-impl-x.cpp b/adaptors/x11/window-impl-x.cpp index 710d9fb..c748c56 100644 --- a/adaptors/x11/window-impl-x.cpp +++ b/adaptors/x11/window-impl-x.cpp @@ -359,7 +359,11 @@ Window::Window() mEventHandler( NULL ), mPreferredOrientation( Dali::Window::PORTRAIT ), mSupportedAuxiliaryHints(), - mAuxiliaryHints() + mAuxiliaryHints(), + mIndicatorVisibilityChangedSignal(), + mFocusChangedSignal(), + mResizedSignal(), + mDeleteRequestSignal() { // Detect if we're not running in a ecore main loop (e.g. libuv). -- 2.7.4