Support for key events on Tizen TV 2.4 35/65835/2
authorNick Holland <nick.holland@partner.samsung.com>
Wed, 13 Apr 2016 09:11:46 +0000 (10:11 +0100)
committerNick Holland <nick.holland@partner.samsung.com>
Wed, 13 Apr 2016 09:24:07 +0000 (10:24 +0100)
In November 2015, Input framework on Tizen TV 2.4
changed from using XKeyEvents to using XClientMessages

Change-Id: I2268126f912b1a04b33bfc5c034287474e992735

adaptors/x11/x-events/x-event-manager.cpp
adaptors/x11/x-events/x-input2.cpp
adaptors/x11/x-events/x-input2.h

index 89745ef..a632b42 100644 (file)
@@ -46,6 +46,8 @@ void XEventManager::Initialize()
     return;
   }
 
+  XSelectInput( mDisplay, mWindow, StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask );
+
   mXInput2.Initialize();
 
   // Start monitoring for X events on a file descriptor return via ConnectionNumber.
@@ -75,13 +77,26 @@ void XEventManager::XEventReceived( FileDescriptorMonitor::EventType eventMask )
     // cookie data pointer is undefined until XGetEventData is called.
     XGenericEventCookie* cookie = &xEvent.xcookie;
 
-    if (XGetEventData( mDisplay, cookie))
+    // Tizen 2.4 TV current uses client messages for key presses instead of KeyPress type
+    if( xEvent.type == ClientMessage)
+    {
+      // Process Client Message
+      mXInput2.ProcessClientMessage( &xEvent );
+    }
+    else if( xEvent.type == KeyPress )
+    {
+      mXInput2.ProcessKeyEvent( (XKeyEvent*)&xEvent );
+    }
+    else if( xEvent.type == GenericEvent )
     {
-      if( cookie->extension == mXInput2.GetExtensionId() )
+      if( XGetEventData( mDisplay, cookie ) )
       {
-        mXInput2.ProcessEvent( cookie );
+        if( cookie->extension == mXInput2.GetExtensionId() )
+        {
+          mXInput2.ProcessGenericEvent( cookie );
+        }
+        XFreeEventData( mDisplay, cookie );
       }
-      XFreeEventData( mDisplay, cookie );
     }
   }
 }
index b965609..d015c91 100644 (file)
@@ -111,7 +111,63 @@ void XInput2::CreateKeyEvent( const XIDeviceEvent* deviceEvent, KeyEvent& keyEve
 
 }
 
-void XInput2::ProcessEvent( XGenericEventCookie* cookie )
+// prototyping implementation
+void XInput2::ProcessKeyEvent( XKeyEvent* xEvent )
+{
+  KeyEvent keyEvent;
+  keyEvent.keyCode = xEvent->keycode;
+  keyEvent.state = KeyEvent::Down;
+
+  KeySym sym = XkbKeycodeToKeysym( mDisplay, xEvent->keycode, 0 /* group */ , keyEvent.IsShiftModifier() );
+  char* keyname = XKeysymToString( sym );
+  keyEvent.keyPressedName = keyname;
+  keyEvent.time = xEvent->time;
+
+  mEventInterface->KeyEvent( keyEvent );
+}
+void XInput2::ProcessClientMessage( XEvent* event )
+{
+  // Format for client message for key event
+  // XEvent xev;
+  // xev.xclient.type = ClientMessage;
+  // xev.xclient.display = keyrouter.disp;
+  // xev.xclient.window = window;
+  // xev.xclient.format = 32;
+  // xev.xclient.message_type = ecore_x_atom_get("VDINPUT_KEYEVENT");
+  // xev.xclient.data.l[0] = ev->time; /* time */
+  // xev.xclient.data.l[1] = ev->state; /* modifier */
+  // xev.xclient.data.l[2] = ev->code; /* keycode */
+  // xev.xclient.data.l[3] = ev->value; /* press/release */
+  // xev.xclient.data.l[4] = ev->device_id; /* deviceId */
+
+  Atom input_atom = XInternAtom( mDisplay, "VDINPUT_KEYEVENT", false);
+  KeyEvent keyEvent;
+
+  keyEvent.state = KeyEvent::Down;
+
+  // if atom is "VDINPUT_KEYEVENT"
+  if( input_atom == event->xclient.message_type )
+  {
+
+    keyEvent.keyModifier = event->xclient.data.l[1];
+    keyEvent.keyCode = event->xclient.data.l[2];
+
+    // only transmit keydown events
+    if( event->xclient.data.l[3] != 2)
+    {
+      return; // 2 = key down, 3 = key release
+    }
+
+    KeySym sym = XkbKeycodeToKeysym( mDisplay,  keyEvent.keyCode, 0 /* group */ , keyEvent.IsShiftModifier() );
+    char* keyname = XKeysymToString( sym );
+    keyEvent.keyPressedName = keyname;
+    keyEvent.time = event->xclient.data.l[0];
+
+    mEventInterface->KeyEvent( keyEvent );
+  }
+}
+
+void XInput2::ProcessGenericEvent( XGenericEventCookie* cookie )
 {
   XIDeviceEvent* deviceEvent = static_cast< XIDeviceEvent* >(cookie->data);
 
@@ -280,7 +336,8 @@ void XInput2::SelectInputEvents()
 
     eventFilter.Clear();
 
-    if( ( device.use == XIFloatingSlave ) || ( device.use == XISlavePointer ))
+    // Floating slave devices also can generate key events. For example, TV remote controllers.
+    if( ( device.use == XIFloatingSlave ) || ( device.use == XISlavePointer ) || ( device.use == XISlaveKeyboard ) )
     {
       if( device.buttonClass )
       {
@@ -294,19 +351,16 @@ void XInput2::SelectInputEvents()
         eventFilter.PushBack( XI_TouchBegin );
         eventFilter.PushBack( XI_TouchEnd );
       }
-      SelectEvents( device.deviceId, eventFilter );
-    }
-    // @todo work out if we should just be listening to MasterKeyboard
-    else if( device.use == XISlaveKeyboard )
-    {
       if( device.keyClass )
       {
         eventFilter.PushBack( XI_KeyPress );
         eventFilter.PushBack( XI_KeyRelease );
-
-        SelectEvents( device.deviceId, eventFilter );
       }
+    }
 
+    if( eventFilter.Count() > 0 )
+    {
+      SelectEvents( device.deviceId, eventFilter );
     }
   }
 }
index abc3f5b..b2d30f7 100644 (file)
@@ -73,11 +73,22 @@ public:
   int GetExtensionId() const;
 
   /**
-   * @brief process an XInput2 event
-   * @param cookie X cookie
+   * @brief process a generic X event
+   * @param[in] cookie X cookie
    */
-  void ProcessEvent( XGenericEventCookie* cookie );
+  void ProcessGenericEvent( XGenericEventCookie* cookie );
 
+  /**
+   * @brief process XKeyEvent
+   * @param[in] XKeyEvent key event
+   */
+   void ProcessKeyEvent( XKeyEvent* xKeyEvent );
+
+   /**
+    * @brief process XKeyEvent
+    * @param[in] event x-event
+    */
+   void ProcessClientMessage( XEvent* event );
 
 private: