javauis/eswt_qt/xlibutils/native/os.cpp
changeset 21 2a9601315dfc
child 35 85266cc22c7f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_qt/xlibutils/native/os.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,381 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+// Description: Testing utility for emulating pointer/key input events in X. 
+
+#include <QApplication>
+#include <Xlib.h>
+#include <new>
+
+#include "os.h"
+
+namespace Java {
+    namespace XlibUtils {
+        typedef enum
+        {
+            NO_ERROR        = 0,
+            NO_DISPLAY      = 1,
+            NO_FOCUSWINDOW  = 2,
+            NO_ROOTWINDOW   = 3,
+            NO_MEMORY       = 4,
+            SENDEVENT_ERR   = 5
+        } XlibUtilsErr;
+    }
+}
+
+JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendKeyToFocusWindow
+  ( JNIEnv*, jclass, jint aKeycode, jint aModifiers, jint aPressOrRelease )
+{
+    int keycode      = static_cast<int>( aKeycode );
+    int modifiers    = static_cast<int>( aModifiers );
+    bool press       = ( aPressOrRelease == 0 ? true : false );
+    jint retVal      = 0;
+    Display* display = NULL;
+    
+    try
+    {
+        display = ::XOpenDisplay( NULL ); 
+        if( !display )
+        {
+            throw Java::XlibUtils::NO_DISPLAY;
+        }
+        
+        Window focusWindow  = 0;
+        int focusState      = 0;
+        ::XGetInputFocus( display,  &focusWindow, &focusState );
+        
+        Window rootWindow = ::XDefaultRootWindow( display );
+
+        if( focusWindow == None )
+        {
+            throw Java::XlibUtils::NO_FOCUSWINDOW;
+        }
+        else if( rootWindow == None )
+        {
+            throw Java::XlibUtils::NO_ROOTWINDOW;
+        }
+        else
+        {
+            XKeyEvent* event = new(std::nothrow) XKeyEvent();
+            if( !event )
+            {
+                throw Java::XlibUtils::NO_MEMORY;
+            }
+            event->type        = ( press ? KeyPress : KeyRelease );
+            event->serial      = None;
+            event->send_event  = false;
+            event->display     = display;
+            event->window      = focusWindow;
+            event->root        = rootWindow;
+            event->subwindow   = None;
+            event->time        = CurrentTime;
+            event->x           = 0;
+            event->y           = 0;
+            event->x_root      = 0;
+            event->y_root      = 0;
+            event->state       = modifiers;
+            event->keycode     = keycode;
+            event->same_screen = True;
+
+            if( ::XSendEvent( display,
+                              event->window,
+                              false,
+                              0,
+                              reinterpret_cast<XEvent*>(event)) == 0 )
+            {
+                throw Java::XlibUtils::SENDEVENT_ERR;
+            }
+            ::XFlush( display );
+        }
+     }
+     catch(Java::XlibUtils::XlibUtilsErr e)
+     {
+        retVal = static_cast<jint>( e );
+     }
+    if( retVal != Java::XlibUtils::NO_DISPLAY )
+    {
+        ::XCloseDisplay( display );
+    }
+    return retVal;
+}
+
+JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XKeysymToKeycode
+  (JNIEnv*, jclass, jint aKeysym)
+    {
+    int keysym      = static_cast<int>(aKeysym);
+    KeyCode keycode = 0;
+    
+    Display* display = ::XOpenDisplay( NULL );
+    if( display )
+    {
+        keycode = ::XKeysymToKeycode( display, keysym );
+        ::XCloseDisplay( display );
+    }
+    return keycode;
+    }
+
+JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendPointerEvent
+  (JNIEnv*, jclass, jint aX, jint aY, jint aButton, jint aPressOrRelease)
+    {
+    bool press       = ( aPressOrRelease == 0 ? true : false );
+    int x            = static_cast<int>(aX);
+    int y            = static_cast<int>(aY);
+    jint retVal      = 0;
+    Display* display = NULL;
+    int buttonNMask  = 1 << (7 + aButton); // Button1Mask, Button2Mask, ..., Button5Mask
+    
+    try
+    {
+        display = ::XOpenDisplay( NULL ); 
+        if( !display )
+        {
+            throw Java::XlibUtils::NO_DISPLAY;
+        }
+        
+        Window rootWindow = ::XDefaultRootWindow( display );
+        if( rootWindow == None )
+        {
+            throw Java::XlibUtils::NO_ROOTWINDOW;
+        }
+
+        // Release events don't seem to work if we do pointer warp. 
+        // Pointer is warped only for press events. Releases use the
+        // current cursor position to determine the window where to 
+        // send the event to. 
+        if( press )
+        {
+            ::XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
+        }
+
+        XButtonEvent* event = new(std::nothrow) XButtonEvent();
+        if( !event )
+        {
+            throw Java::XlibUtils::NO_MEMORY;
+        }
+                
+        event->type         = ( press ? ButtonPress : ButtonRelease );
+        event->serial       = None;
+        event->send_event   = False;
+        event->display      = display;
+//      event->window       = ;
+//      event->root         = ;
+//      event->subWindow    = ;
+        event->time         = CurrentTime;
+//      event->x            = ;
+//      event->y            = ;
+//      event->x_root       = ;
+//      event->y_root       = ;
+//      event->state        = ;
+        event->button       = aButton;
+        event->same_screen  = True;
+        
+        ::XQueryPointer( display, 
+                         rootWindow, 
+                         &event->root, 
+                         &event->window,
+                         &event->x_root, 
+                         &event->y_root, 
+                         &event->x, 
+                         &event->y, 
+                         &event->state );
+        
+        event->subwindow    = event->window;
+        event->state        = buttonNMask;
+        
+        // Find the top window at cursor position. 
+        while( event->subwindow )
+        {
+            event->window = event->subwindow;
+            
+            ::XQueryPointer( display, 
+                             event->window,
+                             &event->root, 
+                             &event->subwindow,
+                             &event->x_root, 
+                             &event->y_root,
+                             &event->x, 
+                             &event->y,
+                             &event->state );
+        }
+
+        // For release event just adjust the coordinates in the event. 
+        // Cursor is actually never moved to the release event location. 
+        if( !press )
+        {
+            int delta_x = x - event->x_root;
+            int delta_y = y - event->y_root;
+            
+            event->x      += delta_x;
+            event->y      += delta_y;
+            event->x_root += delta_x;
+            event->y_root += delta_y;
+        }
+
+        // Double click interval is set to zero in QApplication to avoid getting
+        // unwanted double-click events. It's common that test cases just keep
+        // clicking in the middle of a widget and tests execute in rapidly. 
+        QApplication* app = qApp;
+        if(app) app->setDoubleClickInterval( 0 );
+        
+        event->time         = CurrentTime;
+        event->state        = (press ? buttonNMask : 0);
+
+        // Unless the window is a tooltip or other window which will be ignored
+        // by the window manager, set input focus to make window activate like 
+        // clicking with real mouse. 
+        XWindowAttributes attr;
+        ::memset(&attr, 0, sizeof(attr));
+        ::XGetWindowAttributes(display, event->window, &attr);
+        if(attr.override_redirect == False) 
+        {
+            ::XSetInputFocus(display, event->window, RevertToNone, CurrentTime);
+        }
+        
+        if( ::XSendEvent( display, 
+                          PointerWindow, 
+                          True, 
+                          0, 
+                          reinterpret_cast<XEvent*>(event) ) == 0)
+        {
+            throw Java::XlibUtils::SENDEVENT_ERR;
+        }
+
+        ::XFlush( display );
+     }
+     catch(Java::XlibUtils::XlibUtilsErr e)
+     {
+        retVal = static_cast<jint>( e );
+     }
+     
+    if( retVal != Java::XlibUtils::NO_DISPLAY )
+    {
+        ::XCloseDisplay( display );
+    }
+      
+    return retVal;
+    }
+
+
+JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendPointerMoveEvent
+  (JNIEnv *, jclass, jint aX, jint aY, jint aButton)
+    {
+    int x            = static_cast<int>(aX);
+    int y            = static_cast<int>(aY);
+    jint retVal      = 0;
+    Display* display = NULL;
+    int buttonNMask  = 1 << (7 + aButton); // Button1Mask, Button2Mask, ..., Button5Mask
+    
+    try
+    {
+        display = ::XOpenDisplay( NULL ); 
+        if( !display )
+        {
+            throw Java::XlibUtils::NO_DISPLAY;
+        }
+        
+        Window rootWindow = ::XDefaultRootWindow( display );
+        if( rootWindow == None )
+        {
+            throw Java::XlibUtils::NO_ROOTWINDOW;
+        }
+
+        XMotionEvent* event = new(std::nothrow) XMotionEvent();
+        if( !event )
+        {
+            throw Java::XlibUtils::NO_MEMORY;
+        }
+                
+        event->type         = MotionNotify;
+        event->serial       = None;
+        event->send_event   = False;
+        event->display      = display;
+//      event->window       = ;
+//      event->root         = ;
+//      event->subWindow    = ;
+        event->time         = CurrentTime;
+//      event->x            = ;
+//      event->y            = ;
+//      event->x_root       = ;
+//      event->y_root       = ;
+//      event->state        = ;
+        event->is_hint      = NotifyNormal;
+        event->same_screen  = True;
+        
+        ::XQueryPointer( display, 
+                         rootWindow, 
+                         &event->root, 
+                         &event->window,
+                         &event->x_root, 
+                         &event->y_root, 
+                         &event->x, 
+                         &event->y, 
+                         &event->state );
+        
+        event->subwindow    = event->window;
+        event->state        = buttonNMask;
+        
+        // Find the top window at cursor position. 
+        while( event->subwindow )
+        {
+            event->window = event->subwindow;
+            
+            ::XQueryPointer( display, 
+                             event->window,
+                             &event->root, 
+                             &event->subwindow,
+                             &event->x_root, 
+                             &event->y_root,
+                             &event->x, 
+                             &event->y,
+                             &event->state );
+        }
+
+        // For motion event just adjust the coordinates in the event. 
+        // Cursor is actually never moved to the motion event location. 
+        int delta_x = x - event->x_root;
+        int delta_y = y - event->y_root;
+
+        event->x      += delta_x;
+        event->y      += delta_y;
+        event->x_root += delta_x;
+        event->y_root += delta_y;
+
+        event->state   = buttonNMask;
+
+        if( ::XSendEvent( display, 
+                          PointerWindow, 
+                          True, 
+                          0, 
+                          reinterpret_cast<XEvent*>(event) ) == 0)
+        {
+            throw Java::XlibUtils::SENDEVENT_ERR;
+        }
+
+        ::XFlush( display );
+     }
+     catch(Java::XlibUtils::XlibUtilsErr e)
+     {
+        retVal = static_cast<jint>( e );
+     }
+     
+    if( retVal != Java::XlibUtils::NO_DISPLAY )
+    {
+        ::XCloseDisplay( display );
+    }
+      
+    return retVal;
+    }
+