Merge "Add native render surface for wayland" into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / wayland / wayland-manager.cpp
index 8ba0f12..a03807e 100644 (file)
 #include "wayland-manager.h"
 
 // EXTERNAL INCLUDES
-#include <stdio.h>
 #include <cstring>
+#include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <base/interfaces/window-event-interface.h>
 #include <base/interfaces/performance-interface.h>
-#include <input/input-listeners.h>
-#include <input/seat.h>
+
 
 namespace Dali
 {
@@ -37,6 +36,9 @@ namespace Adaptor
 namespace
 {
 
+const int NO_EVENTS_ALREADY_IN_QUEUE = 0;
+
+
 void ShellSurfacePing( void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
 {
   // The ping event comes from the compositor to checks if we're still alive.
@@ -65,22 +67,7 @@ struct xdg_shell_listener XdgShellListener=
   XdgShellPing,
 };
 
-void RegisterSeatListener( WaylandManager* client,
-                          struct wl_registry *wlRegistry,
-                          uint32_t name,
-                          const char *interface,
-                          uint32_t version)
-{
-  Dali::WlSeat* seatInterface = static_cast<Dali::WlSeat*>( wl_registry_bind( wlRegistry, name,  &wl_seat_interface, version ));
-
-  Seat* seat = new Seat( &client->mInputManager, seatInterface );
 
-  client->mInputManager.AddSeat( seat );
-
-  // listen to seat events
-  wl_seat_add_listener( seatInterface, Wayland::GetSeatListener(), &client->mInputManager );
-
-}
 void RegistryGlobalCallback( void *data,
            struct wl_registry *wlRegistry,
            uint32_t name,
@@ -90,25 +77,39 @@ void RegistryGlobalCallback( void *data,
 
   WaylandManager* client = static_cast<   WaylandManager* >( data );
 
-  if (strcmp( interface, wl_compositor_interface.name) == 0)
+  if( strcmp( interface, wl_compositor_interface.name ) == 0 )
   {
-    client->mCompositor = static_cast<Dali::WlCompositor*>(wl_registry_bind( wlRegistry, name , &wl_compositor_interface, version ));
+    client->mCompositor = static_cast< Dali::WlCompositor* >( wl_registry_bind( wlRegistry, name, &wl_compositor_interface, version ) );
   }
-  else if( strcmp( interface, wl_seat_interface.name) == 0  )
+  else if( strcmp( interface, wl_seat_interface.name ) == 0 )
   {
     // register for seat callbacks and add a new seat to the input manager
-    RegisterSeatListener( client, wlRegistry, name, interface, version);
+    Dali::WlSeat* seatInterface = static_cast< Dali::WlSeat* >( wl_registry_bind( wlRegistry, name, &wl_seat_interface, version ) );
+
+    client->mInputManager.AddSeatListener( seatInterface );
   }
-  else if (strcmp(interface, wl_shell_interface.name) == 0)
+  else if( strcmp( interface, wl_output_interface.name ) == 0 )
   {
-    client->mShell = static_cast<Dali::WlShell*>(wl_registry_bind( wlRegistry, name , &wl_shell_interface, version));
+    // get the interface and add the listener
+    Dali::WlOutput* output = static_cast< Dali::WlOutput* >( wl_registry_bind( wlRegistry, name, &wl_output_interface, version ) );
+    client->mCompositorOutput.AddListener( output );
   }
-  else if ( strcmp( interface, xdg_shell_interface.name ) == 0)
+  else if( strcmp( interface, wl_shell_interface.name ) == 0 )
   {
-    client->mXdgShell  =  static_cast< struct xdg_shell* >(wl_registry_bind(wlRegistry, name, &xdg_shell_interface, version));
+    client->mShell = static_cast< Dali::WlShell* >( wl_registry_bind( wlRegistry, name, &wl_shell_interface, version ) );
+  }
+  else if( strcmp( interface, xdg_shell_interface.name ) == 0 )
+  {
+    client->mXdgShell = static_cast< struct xdg_shell* >( wl_registry_bind( wlRegistry, name, &xdg_shell_interface, version ) );
     // without this line Tizen 3 reports...
     // xdg_shell@7: error 0: Must call use_unstable_version first
-    xdg_shell_use_unstable_version(client->mXdgShell, 5);
+    xdg_shell_use_unstable_version( client->mXdgShell, 5 );
+  }
+  else if( strcmp( interface, wl_text_input_manager_interface.name ) == 0 )
+  {
+    Dali::WlTextInputManager* inputManager = static_cast< Dali::WlTextInputManager* >( wl_registry_bind( wlRegistry, name, &wl_text_input_manager_interface, version ) );
+
+    client->mInputManager.AddTextInputManager( inputManager );
   }
 
 
@@ -179,11 +180,42 @@ void WaylandManager::Initialise()
   // Monitor the display file descriptor used to communicate with Wayland server
   InstallFileDescriptorMonitor();
 
+  mInputManager.AssignDisplay( mDisplay );
+
   // Get the interfaces to compositor / shell etc
   GetWaylandInterfaces();
 
 }
+void WaylandManager::ReadAndDispatchEvents()
+{
+  // Wayland client uses a single file descriptor to communicate with the compositor.
+  // Because DALi can have multiple client threads ( event thread for input, render thread for Tizen buffer management / TPL )
+  // it has to use the Wayland client thread safe API to prevent a dead lock
 
+  // prepare_read announces the calling thread's intention to read from the file descriptor
+  // If there is already events queued up in the default queue, then dispatch those first
+  while( wl_display_prepare_read( mDisplay ) != NO_EVENTS_ALREADY_IN_QUEUE )
+  {
+    // dispatch the event, e.g. a touch event or a clipboard event
+    wl_display_dispatch_pending( mDisplay );
+  }
+
+  // At this point the default queue is empty.
+  // We read data from the file descriptor in their respective queues
+  // This is thread safe. No other threads will read from the fd and queue events during this operation.
+  int ret = wl_display_read_events( mDisplay );
+
+  if( ret == 0 )
+  {
+    // dispatch the events from the default queue
+    wl_display_dispatch_pending( mDisplay );
+  }
+  else
+  {
+    DALI_LOG_ERROR("wl_display_read_events error\n");
+  }
+
+}
 void WaylandManager::AssignWindowEventInterface( WindowEventInterface* eventInterface)
 {
   mInputManager.AssignWindowEventInterface( eventInterface );
@@ -195,10 +227,16 @@ void WaylandManager::GetWaylandInterfaces()
 
   wl_registry_add_listener( registry, &RegistryListener, this);
 
-  // send and receive, to trigger the registry listener callback
-  wl_display_roundtrip( mDisplay );
-
+  // adaptor wants the DPI instantly, so we have wait for the data
+  while( !mCompositorOutput.DataReady() )
+  {
+    // This is the first and last time we use wl_display_roundtrip as its not thread safe
+    // however at this point we haven't started rendering it is safe.
+    wl_display_flush( mDisplay );
+    wl_display_roundtrip( mDisplay );
+  }
   wl_registry_destroy( registry );
+
 }
 
 void WaylandManager::InstallFileDescriptorMonitor()
@@ -215,15 +253,17 @@ void WaylandManager::InstallFileDescriptorMonitor()
   mFileDescriptorMonitor = new FileDescriptorMonitor( mDisplayFileDescriptor, callback, events );
 
 }
+
 void WaylandManager::FileDescriptorCallback( FileDescriptorMonitor::EventType eventTypeMask )
 {
   if( eventTypeMask & FileDescriptorMonitor::FD_READABLE )
   {
-    // read and dispatch
-    wl_display_dispatch( mDisplay );
+    // read and dispatch events
+    ReadAndDispatchEvents();
   }
 }
 
+
 void WaylandManager::CreateSurface( Dali::Wayland::Window& window )
 {
   // Create the surface
@@ -232,6 +272,9 @@ void WaylandManager::CreateSurface( Dali::Wayland::Window& window )
 
   mSurface = wl_compositor_create_surface( mCompositor );
 
+  // the Input panel (Virtual keyboard ) needs to know which surface it should display on.
+  mInputManager.AssignSurface( mSurface );
+
   DALI_ASSERT_ALWAYS( mSurface && "wl_compositor_create_surface failed" );
 
   // keep track of the surface id
@@ -250,7 +293,8 @@ void WaylandManager::CreateSurface( Dali::Wayland::Window& window )
 
     if( window.mTitle.length() )
     {
-      xdg_surface_set_title(  mXdgSurface, window.mTitle.c_str() );
+      xdg_surface_set_title( mXdgSurface, window.mTitle.c_str() );
+      xdg_surface_set_app_id(mXdgSurface, window.mTitle.c_str() );
     }
     xdg_shell_add_listener( mXdgShell, &XdgShellListener, 0);
   }
@@ -270,8 +314,8 @@ void WaylandManager::CreateSurface( Dali::Wayland::Window& window )
     wl_shell_surface_add_listener( mShellSurface , &ShellSurfaceListener, 0);
   }
 
-  // send / receive all commands
-  wl_display_roundtrip( mDisplay );
+  wl_display_flush( mDisplay );
+
 }
 
 WlSurface* WaylandManager::GetSurface()