javauis/eswt_qt/xlibutils/native/os.cpp
changeset 21 2a9601315dfc
child 35 85266cc22c7f
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 // Description: Testing utility for emulating pointer/key input events in X. 
       
    18 
       
    19 #include <QApplication>
       
    20 #include <Xlib.h>
       
    21 #include <new>
       
    22 
       
    23 #include "os.h"
       
    24 
       
    25 namespace Java {
       
    26     namespace XlibUtils {
       
    27         typedef enum
       
    28         {
       
    29             NO_ERROR        = 0,
       
    30             NO_DISPLAY      = 1,
       
    31             NO_FOCUSWINDOW  = 2,
       
    32             NO_ROOTWINDOW   = 3,
       
    33             NO_MEMORY       = 4,
       
    34             SENDEVENT_ERR   = 5
       
    35         } XlibUtilsErr;
       
    36     }
       
    37 }
       
    38 
       
    39 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendKeyToFocusWindow
       
    40   ( JNIEnv*, jclass, jint aKeycode, jint aModifiers, jint aPressOrRelease )
       
    41 {
       
    42     int keycode      = static_cast<int>( aKeycode );
       
    43     int modifiers    = static_cast<int>( aModifiers );
       
    44     bool press       = ( aPressOrRelease == 0 ? true : false );
       
    45     jint retVal      = 0;
       
    46     Display* display = NULL;
       
    47     
       
    48     try
       
    49     {
       
    50         display = ::XOpenDisplay( NULL ); 
       
    51         if( !display )
       
    52         {
       
    53             throw Java::XlibUtils::NO_DISPLAY;
       
    54         }
       
    55         
       
    56         Window focusWindow  = 0;
       
    57         int focusState      = 0;
       
    58         ::XGetInputFocus( display,  &focusWindow, &focusState );
       
    59         
       
    60         Window rootWindow = ::XDefaultRootWindow( display );
       
    61 
       
    62         if( focusWindow == None )
       
    63         {
       
    64             throw Java::XlibUtils::NO_FOCUSWINDOW;
       
    65         }
       
    66         else if( rootWindow == None )
       
    67         {
       
    68             throw Java::XlibUtils::NO_ROOTWINDOW;
       
    69         }
       
    70         else
       
    71         {
       
    72             XKeyEvent* event = new(std::nothrow) XKeyEvent();
       
    73             if( !event )
       
    74             {
       
    75                 throw Java::XlibUtils::NO_MEMORY;
       
    76             }
       
    77             event->type        = ( press ? KeyPress : KeyRelease );
       
    78             event->serial      = None;
       
    79             event->send_event  = false;
       
    80             event->display     = display;
       
    81             event->window      = focusWindow;
       
    82             event->root        = rootWindow;
       
    83             event->subwindow   = None;
       
    84             event->time        = CurrentTime;
       
    85             event->x           = 0;
       
    86             event->y           = 0;
       
    87             event->x_root      = 0;
       
    88             event->y_root      = 0;
       
    89             event->state       = modifiers;
       
    90             event->keycode     = keycode;
       
    91             event->same_screen = True;
       
    92 
       
    93             if( ::XSendEvent( display,
       
    94                               event->window,
       
    95                               false,
       
    96                               0,
       
    97                               reinterpret_cast<XEvent*>(event)) == 0 )
       
    98             {
       
    99                 throw Java::XlibUtils::SENDEVENT_ERR;
       
   100             }
       
   101             ::XFlush( display );
       
   102         }
       
   103      }
       
   104      catch(Java::XlibUtils::XlibUtilsErr e)
       
   105      {
       
   106         retVal = static_cast<jint>( e );
       
   107      }
       
   108     if( retVal != Java::XlibUtils::NO_DISPLAY )
       
   109     {
       
   110         ::XCloseDisplay( display );
       
   111     }
       
   112     return retVal;
       
   113 }
       
   114 
       
   115 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XKeysymToKeycode
       
   116   (JNIEnv*, jclass, jint aKeysym)
       
   117     {
       
   118     int keysym      = static_cast<int>(aKeysym);
       
   119     KeyCode keycode = 0;
       
   120     
       
   121     Display* display = ::XOpenDisplay( NULL );
       
   122     if( display )
       
   123     {
       
   124         keycode = ::XKeysymToKeycode( display, keysym );
       
   125         ::XCloseDisplay( display );
       
   126     }
       
   127     return keycode;
       
   128     }
       
   129 
       
   130 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendPointerEvent
       
   131   (JNIEnv*, jclass, jint aX, jint aY, jint aButton, jint aPressOrRelease)
       
   132     {
       
   133     bool press       = ( aPressOrRelease == 0 ? true : false );
       
   134     int x            = static_cast<int>(aX);
       
   135     int y            = static_cast<int>(aY);
       
   136     jint retVal      = 0;
       
   137     Display* display = NULL;
       
   138     int buttonNMask  = 1 << (7 + aButton); // Button1Mask, Button2Mask, ..., Button5Mask
       
   139     
       
   140     try
       
   141     {
       
   142         display = ::XOpenDisplay( NULL ); 
       
   143         if( !display )
       
   144         {
       
   145             throw Java::XlibUtils::NO_DISPLAY;
       
   146         }
       
   147         
       
   148         Window rootWindow = ::XDefaultRootWindow( display );
       
   149         if( rootWindow == None )
       
   150         {
       
   151             throw Java::XlibUtils::NO_ROOTWINDOW;
       
   152         }
       
   153 
       
   154         // Release events don't seem to work if we do pointer warp. 
       
   155         // Pointer is warped only for press events. Releases use the
       
   156         // current cursor position to determine the window where to 
       
   157         // send the event to. 
       
   158         if( press )
       
   159         {
       
   160             ::XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
       
   161         }
       
   162 
       
   163         XButtonEvent* event = new(std::nothrow) XButtonEvent();
       
   164         if( !event )
       
   165         {
       
   166             throw Java::XlibUtils::NO_MEMORY;
       
   167         }
       
   168                 
       
   169         event->type         = ( press ? ButtonPress : ButtonRelease );
       
   170         event->serial       = None;
       
   171         event->send_event   = False;
       
   172         event->display      = display;
       
   173 //      event->window       = ;
       
   174 //      event->root         = ;
       
   175 //      event->subWindow    = ;
       
   176         event->time         = CurrentTime;
       
   177 //      event->x            = ;
       
   178 //      event->y            = ;
       
   179 //      event->x_root       = ;
       
   180 //      event->y_root       = ;
       
   181 //      event->state        = ;
       
   182         event->button       = aButton;
       
   183         event->same_screen  = True;
       
   184         
       
   185         ::XQueryPointer( display, 
       
   186                          rootWindow, 
       
   187                          &event->root, 
       
   188                          &event->window,
       
   189                          &event->x_root, 
       
   190                          &event->y_root, 
       
   191                          &event->x, 
       
   192                          &event->y, 
       
   193                          &event->state );
       
   194         
       
   195         event->subwindow    = event->window;
       
   196         event->state        = buttonNMask;
       
   197         
       
   198         // Find the top window at cursor position. 
       
   199         while( event->subwindow )
       
   200         {
       
   201             event->window = event->subwindow;
       
   202             
       
   203             ::XQueryPointer( display, 
       
   204                              event->window,
       
   205                              &event->root, 
       
   206                              &event->subwindow,
       
   207                              &event->x_root, 
       
   208                              &event->y_root,
       
   209                              &event->x, 
       
   210                              &event->y,
       
   211                              &event->state );
       
   212         }
       
   213 
       
   214         // For release event just adjust the coordinates in the event. 
       
   215         // Cursor is actually never moved to the release event location. 
       
   216         if( !press )
       
   217         {
       
   218             int delta_x = x - event->x_root;
       
   219             int delta_y = y - event->y_root;
       
   220             
       
   221             event->x      += delta_x;
       
   222             event->y      += delta_y;
       
   223             event->x_root += delta_x;
       
   224             event->y_root += delta_y;
       
   225         }
       
   226 
       
   227         // Double click interval is set to zero in QApplication to avoid getting
       
   228         // unwanted double-click events. It's common that test cases just keep
       
   229         // clicking in the middle of a widget and tests execute in rapidly. 
       
   230         QApplication* app = qApp;
       
   231         if(app) app->setDoubleClickInterval( 0 );
       
   232         
       
   233         event->time         = CurrentTime;
       
   234         event->state        = (press ? buttonNMask : 0);
       
   235 
       
   236         // Unless the window is a tooltip or other window which will be ignored
       
   237         // by the window manager, set input focus to make window activate like 
       
   238         // clicking with real mouse. 
       
   239         XWindowAttributes attr;
       
   240         ::memset(&attr, 0, sizeof(attr));
       
   241         ::XGetWindowAttributes(display, event->window, &attr);
       
   242         if(attr.override_redirect == False) 
       
   243         {
       
   244             ::XSetInputFocus(display, event->window, RevertToNone, CurrentTime);
       
   245         }
       
   246         
       
   247         if( ::XSendEvent( display, 
       
   248                           PointerWindow, 
       
   249                           True, 
       
   250                           0, 
       
   251                           reinterpret_cast<XEvent*>(event) ) == 0)
       
   252         {
       
   253             throw Java::XlibUtils::SENDEVENT_ERR;
       
   254         }
       
   255 
       
   256         ::XFlush( display );
       
   257      }
       
   258      catch(Java::XlibUtils::XlibUtilsErr e)
       
   259      {
       
   260         retVal = static_cast<jint>( e );
       
   261      }
       
   262      
       
   263     if( retVal != Java::XlibUtils::NO_DISPLAY )
       
   264     {
       
   265         ::XCloseDisplay( display );
       
   266     }
       
   267       
       
   268     return retVal;
       
   269     }
       
   270 
       
   271 
       
   272 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_uitestutils_XlibUtils_XSendPointerMoveEvent
       
   273   (JNIEnv *, jclass, jint aX, jint aY, jint aButton)
       
   274     {
       
   275     int x            = static_cast<int>(aX);
       
   276     int y            = static_cast<int>(aY);
       
   277     jint retVal      = 0;
       
   278     Display* display = NULL;
       
   279     int buttonNMask  = 1 << (7 + aButton); // Button1Mask, Button2Mask, ..., Button5Mask
       
   280     
       
   281     try
       
   282     {
       
   283         display = ::XOpenDisplay( NULL ); 
       
   284         if( !display )
       
   285         {
       
   286             throw Java::XlibUtils::NO_DISPLAY;
       
   287         }
       
   288         
       
   289         Window rootWindow = ::XDefaultRootWindow( display );
       
   290         if( rootWindow == None )
       
   291         {
       
   292             throw Java::XlibUtils::NO_ROOTWINDOW;
       
   293         }
       
   294 
       
   295         XMotionEvent* event = new(std::nothrow) XMotionEvent();
       
   296         if( !event )
       
   297         {
       
   298             throw Java::XlibUtils::NO_MEMORY;
       
   299         }
       
   300                 
       
   301         event->type         = MotionNotify;
       
   302         event->serial       = None;
       
   303         event->send_event   = False;
       
   304         event->display      = display;
       
   305 //      event->window       = ;
       
   306 //      event->root         = ;
       
   307 //      event->subWindow    = ;
       
   308         event->time         = CurrentTime;
       
   309 //      event->x            = ;
       
   310 //      event->y            = ;
       
   311 //      event->x_root       = ;
       
   312 //      event->y_root       = ;
       
   313 //      event->state        = ;
       
   314         event->is_hint      = NotifyNormal;
       
   315         event->same_screen  = True;
       
   316         
       
   317         ::XQueryPointer( display, 
       
   318                          rootWindow, 
       
   319                          &event->root, 
       
   320                          &event->window,
       
   321                          &event->x_root, 
       
   322                          &event->y_root, 
       
   323                          &event->x, 
       
   324                          &event->y, 
       
   325                          &event->state );
       
   326         
       
   327         event->subwindow    = event->window;
       
   328         event->state        = buttonNMask;
       
   329         
       
   330         // Find the top window at cursor position. 
       
   331         while( event->subwindow )
       
   332         {
       
   333             event->window = event->subwindow;
       
   334             
       
   335             ::XQueryPointer( display, 
       
   336                              event->window,
       
   337                              &event->root, 
       
   338                              &event->subwindow,
       
   339                              &event->x_root, 
       
   340                              &event->y_root,
       
   341                              &event->x, 
       
   342                              &event->y,
       
   343                              &event->state );
       
   344         }
       
   345 
       
   346         // For motion event just adjust the coordinates in the event. 
       
   347         // Cursor is actually never moved to the motion event location. 
       
   348         int delta_x = x - event->x_root;
       
   349         int delta_y = y - event->y_root;
       
   350 
       
   351         event->x      += delta_x;
       
   352         event->y      += delta_y;
       
   353         event->x_root += delta_x;
       
   354         event->y_root += delta_y;
       
   355 
       
   356         event->state   = buttonNMask;
       
   357 
       
   358         if( ::XSendEvent( display, 
       
   359                           PointerWindow, 
       
   360                           True, 
       
   361                           0, 
       
   362                           reinterpret_cast<XEvent*>(event) ) == 0)
       
   363         {
       
   364             throw Java::XlibUtils::SENDEVENT_ERR;
       
   365         }
       
   366 
       
   367         ::XFlush( display );
       
   368      }
       
   369      catch(Java::XlibUtils::XlibUtilsErr e)
       
   370      {
       
   371         retVal = static_cast<jint>( e );
       
   372      }
       
   373      
       
   374     if( retVal != Java::XlibUtils::NO_DISPLAY )
       
   375     {
       
   376         ::XCloseDisplay( display );
       
   377     }
       
   378       
       
   379     return retVal;
       
   380     }
       
   381