Merge "Support window rotation" into devel/master
authorHeeyong Song <heeyong.song@samsung.com>
Tue, 13 Jun 2017 10:55:17 +0000 (10:55 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Tue, 13 Jun 2017 10:55:17 +0000 (10:55 +0000)
12 files changed:
adaptors/common/window-impl.h
adaptors/devel-api/adaptor-framework/window-devel.cpp
adaptors/devel-api/adaptor-framework/window-devel.h
adaptors/ecore/wayland/event-handler-ecore-wl.cpp
adaptors/ecore/wayland/render-surface-ecore-wl.cpp
adaptors/ecore/wayland/window-impl-ecore-wl.cpp
adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp
adaptors/ecore/wayland/window-render-surface.h
adaptors/public-api/adaptor-framework/application.cpp
adaptors/public-api/adaptor-framework/application.h
adaptors/wayland/window-impl-wl.cpp
adaptors/x11/window-impl-x.cpp

index 09a7541..d4774f1 100644 (file)
@@ -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;
 };
 
index b6f977c..447cdd1 100644 (file)
@@ -145,6 +145,11 @@ int GetBrightness( Window window )
   return GetImplementation( window ).GetBrightness();
 }
 
+ResizedSignalType& ResizedSignal( Window window )
+{
+  return GetImplementation( window ).ResizedSignal();
+}
+
 } // namespace DevelWindow
 
 } // namespace Dali
index 6d07c71..be087f0 100644 (file)
@@ -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
index 71237e1..347339b 100644 (file)
@@ -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<Ecore_Event_Handler*> 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();
   }
index 1aaa06e..c2d9a41 100644 (file)
@@ -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
index d0dbdb7..692749b 100644 (file)
@@ -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()
index 5cb7511..17c5515 100644 (file)
  */
 
 // CLASS HEADER
-#include "window-render-surface.h"
+#include <window-render-surface.h>
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/gl-defines.h>
 
 // INTERNAL INCLUDES
 #include <wl-types.h>
-#include <trigger-event.h>
 #include <gl/egl-implementation.h>
 #include <base/display-connection.h>
+#include <adaptors/common/adaptor-impl.h>
+#include <integration-api/trigger-event-factory-interface.h>
 
 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<Internal::Adaptor::EglImplementation&>( 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
index 8fa093a..40a0d2a 100644 (file)
@@ -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.
  *
  */
 
+// EXTERNAL INCLUDES
+#include <wayland-egl.h>
+
 // INTERNAL INCLUDES
 #include <ecore-wl-render-surface.h>
-#include <wayland-egl.h>
+#include <window.h>
+#include <integration-api/thread-synchronization-interface.h>
 
 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
 
index 62908dd..1d4fb36 100644 (file)
@@ -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();
 }
 
index 615ecc8..9e215c9 100644 (file)
@@ -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
index 631681f..79e2555 100644 (file)
@@ -121,7 +121,11 @@ Window::Window()
   mType( Dali::DevelWindow::NORMAL ),
   mPreferredOrientation( Dali::Window::PORTRAIT ),
   mSupportedAuxiliaryHints(),
-  mAuxiliaryHints()
+  mAuxiliaryHints(),
+  mIndicatorVisibilityChangedSignal(),
+  mFocusChangedSignal(),
+  mResizedSignal(),
+  mDeleteRequestSignal()
 {
   mEventHandler = NULL;
 }
index 710d9fb..c748c56 100644 (file)
@@ -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).