diff -r e8e63152f320 -r 2a9601315dfc javauis/eswt_qt/xlibutils/native/os.cpp --- /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 +#include +#include + +#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( aKeycode ); + int modifiers = static_cast( 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(event)) == 0 ) + { + throw Java::XlibUtils::SENDEVENT_ERR; + } + ::XFlush( display ); + } + } + catch(Java::XlibUtils::XlibUtilsErr e) + { + retVal = static_cast( 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(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(aX); + int y = static_cast(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(event) ) == 0) + { + throw Java::XlibUtils::SENDEVENT_ERR; + } + + ::XFlush( display ); + } + catch(Java::XlibUtils::XlibUtilsErr e) + { + retVal = static_cast( 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(aX); + int y = static_cast(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(event) ) == 0) + { + throw Java::XlibUtils::SENDEVENT_ERR; + } + + ::XFlush( display ); + } + catch(Java::XlibUtils::XlibUtilsErr e) + { + retVal = static_cast( e ); + } + + if( retVal != Java::XlibUtils::NO_DISPLAY ) + { + ::XCloseDisplay( display ); + } + + return retVal; + } +