1ff0643 by Enrico Ros at 2009-02-20 1
/***************************************************************************
0e5745d by Enrico Ros at 2009-05-31 2
 * Copyright (c) 2009 Enrico Ros                                           *
3
 *         2009 Enrico Ros <enrico.ros@email.it>                           *
4
 *         2009 Alberto Scarpa <skaal.sl@gmail.com>                        *
1ff0643 by Enrico Ros at 2009-02-20 5
 *                                                                         *
6
 * Permission is hereby granted, free of charge, to any person             *
7
 * obtaining a copy of this software and associated documentation          *
8
 * files (the "Software"), to deal in the Software without                 *
9
 * restriction, including without limitation the rights to use,            *
10
 * copy, modify, merge, publish, distribute, sublicense, and/or sell       *
11
 * copies of the Software, and to permit persons to whom the               *
12
 * Software is furnished to do so, subject to the following                *
13
 * conditions:                                                             *
14
 *                                                                         *
15
 * The above copyright notice and this permission notice shall be          *
16
 * included in all copies or substantial portions of the Software.         *
17
 *                                                                         *
18
 ***************************************************************************/
19
20
#include "InputUtils.h"
21
#include <QPoint>
22
#include <QCursor>
23
24
#if defined(Q_WS_X11)
25
#include <QX11Info>
26
#include <X11/extensions/XTest.h>
6d89023 by Enrico Ros at 2009-02-21 27
//include <X11/keysymdef.h> defines:
28
#define KS_X11_BACKSPACE    0xff08
29
#define KS_X11_ESCAPE       0xff1b
30
#define KS_X11_RETURN       0xff0d
31
#define KS_X11_SHIFT_L      0xffe1
32
#define KS_X11_SHIFT_R      0xffe2
33
#define KS_X11_CTRL_L       0xffe3
34
#define KS_X11_CTRL_R       0xffe4
35
#define KS_X11_LEFT         0xff51
36
#define KS_X11_UP           0xff52
37
#define KS_X11_RIGHT        0xff53
38
#define KS_X11_DOWN         0xff54
1ff0643 by Enrico Ros at 2009-02-20 39
#elif defined(Q_WS_WIN)
40
#include <windows.h>
7951f2c by Battista Biggio at 2009-05-31 41
#elif defined(Q_WS_MAC)
42
#import <ApplicationServices/ApplicationServices.h>
1ff0643 by Enrico Ros at 2009-02-20 43
#else
7951f2c by Battista Biggio at 2009-05-31 44
#warning InputUtils not implemented for this Windowing System
1ff0643 by Enrico Ros at 2009-02-20 45
#endif
46
47
void InputUtils::mouseLeftClick()
48
{
49
    mouseLeftPress();
50
    mouseLeftRelease();
51
}
52
53
void InputUtils::mouseLeftPress()
54
{
55
#if defined(Q_WS_X11)
56
    XTestFakeButtonEvent( QX11Info::display(), 1, true, CurrentTime );
a6ab1de by Enrico Ros at 2009-02-21 57
    XFlush( QX11Info::display() );
1ff0643 by Enrico Ros at 2009-02-20 58
#elif defined(Q_WS_WIN)
59
    INPUT Input={0};
60
    Input.type = INPUT_MOUSE;
61
    Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
62
    ::SendInput( 1, &Input, sizeof(INPUT) );
7951f2c by Battista Biggio at 2009-05-31 63
#elif defined(Q_WS_MAC)
64
    QPoint currPos = QCursor::pos();
65
    // The data structure CGPoint represents a point in a two-dimensional
66
    // coordinate system.  Here, X and Y distance from upper left, in pixels.
67
    //
68
    CGPoint pt;
69
    pt.x = currPos.x();
70
    pt.y = currPos.y();
71
    // CGPostMouseEvent( CGPoint        mouseCursorPosition,
72
    //                   boolean_t      updateMouseCursorPosition,
73
    //                   CGButtonCount  buttonCount,
74
    //                   boolean_t      mouseButtonDown, ... )
75
    // So, we feed coordinates to CGPostMouseEvent, put the mouse there,
76
    // then click and release.
77
    CGPostMouseEvent( pt, 1, 1, 1 );
1ff0643 by Enrico Ros at 2009-02-20 78
#endif
79
}
80
81
void InputUtils::mouseLeftRelease()
82
{
83
#if defined(Q_WS_X11)
84
    XTestFakeButtonEvent( QX11Info::display(), 1, false, CurrentTime );
a6ab1de by Enrico Ros at 2009-02-21 85
    XFlush( QX11Info::display() );
1ff0643 by Enrico Ros at 2009-02-20 86
#elif defined(Q_WS_WIN)
87
    INPUT Input={0};
88
    Input.type = INPUT_MOUSE;
89
    Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
90
    ::SendInput( 1, &Input, sizeof(INPUT) );
7951f2c by Battista Biggio at 2009-05-31 91
#elif defined(Q_WS_MAC)
92
    CGPoint pt;
93
    QPoint currPos = QCursor::pos();
94
    pt.x = currPos.x();
95
    pt.y = currPos.y();
96
    CGPostMouseEvent( pt, 1, 1, 0 );
1ff0643 by Enrico Ros at 2009-02-20 97
#endif
98
}
99
100
void InputUtils::mouseMove( int x, int y )
101
{
102
    QCursor::setPos( x, y );
103
}
104
6d89023 by Enrico Ros at 2009-02-21 105
void InputUtils::keyWrite( const QString & string )
1ff0643 by Enrico Ros at 2009-02-20 106
{
6d89023 by Enrico Ros at 2009-02-21 107
    int len = string.length();
108
    for ( int i = 0; i < len; i++ )
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 109
        keyClick( string.at( i ) );
1ff0643 by Enrico Ros at 2009-02-20 110
}
111
a6ab1de by Enrico Ros at 2009-02-21 112
#if defined(Q_WS_X11)
113
static void xSendScanCode( Display * display, unsigned int keyCode )
114
{
115
    XTestFakeKeyEvent( display, keyCode, true, CurrentTime );
116
    XTestFakeKeyEvent( display, keyCode, false, CurrentTime );
117
    XFlush( display );
118
}
119
#endif
120
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 121
void InputUtils::keyClick( const QChar & singleChar )
1ff0643 by Enrico Ros at 2009-02-20 122
{
6d89023 by Enrico Ros at 2009-02-21 123
#if defined(Q_WS_X11)
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 124
    char latin1 = singleChar.toLatin1();
6d89023 by Enrico Ros at 2009-02-21 125
    Display * display = QX11Info::display();
126
    unsigned int keyCode = XKeysymToKeycode( display, latin1 );
127
    if ( !keyCode ) {
128
        if ( latin1 == '\n' )
129
            keyCode = XKeysymToKeycode( display, KS_X11_RETURN );
130
        if ( !keyCode ) {
131
            qWarning( "InputUtils::keyClickKeysym(X11): cannot get keycode of char '%d', please provide the conversion.", latin1 );
132
            return;
133
        }
134
    }
a6ab1de by Enrico Ros at 2009-02-21 135
    xSendScanCode( display, keyCode );
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 136
#elif defined(Q_WS_WIN)
137
    // keypress
138
    SHORT virtKey = VkKeyScan(singleChar.unicode());
139
    INPUT input[2];
140
    input[0].type = INPUT_KEYBOARD;
141
    input[0].ki.wVk = LOBYTE(virtKey);
142
    input[0].ki.wScan = 0;
143
    input[0].ki.dwFlags = 0;
144
    input[0].ki.time = 0;
145
    input[0].ki.dwExtraInfo = 0;
146
    // keyrelease
147
    input[1] = input[0];
148
    input[1].ki.dwFlags |= KEYEVENTF_KEYUP;
149
    // send both
150
    ::SendInput( 2, input, sizeof(INPUT) );
6d89023 by Enrico Ros at 2009-02-21 151
#else
1ff0643 by Enrico Ros at 2009-02-20 152
    qWarning( "InputUtils::keyClick: notImplemented()");
6d89023 by Enrico Ros at 2009-02-21 153
#endif
1ff0643 by Enrico Ros at 2009-02-20 154
}
a6ab1de by Enrico Ros at 2009-02-21 155
156
void InputUtils::keyClickSpecial( int qtKeyCode )
157
{
161ace1 by Enrico Ros at 2009-06-03 158
#if defined(Q_WS_X11)
159
    Display * display = QX11Info::display();
160
#elif defined(Q_WS_WIN)
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 161
    // pre-init Virtual Input structure
162
    INPUT vinput[2];
163
    vinput[0].type = INPUT_KEYBOARD;
164
    vinput[0].ki.wVk = 0;
165
    vinput[0].ki.wScan = 0;
166
    vinput[0].ki.dwFlags = 0;
167
    vinput[0].ki.time = 0;
168
    vinput[0].ki.dwExtraInfo = 0;
169
#endif
170
a6ab1de by Enrico Ros at 2009-02-21 171
    switch ( qtKeyCode ) {
172
        case Qt::Key_Control:
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 173
#if defined(Q_WS_X11)
161ace1 by Enrico Ros at 2009-06-03 174
            xSendScanCode( display, XKeysymToKeycode( display, KS_X11_CTRL_L ) );
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 175
#elif defined(Q_WS_WIN)
176
            vinput[0].ki.wVk = VK_CONTROL;
177
#else
178
            qWarning("InputUtils::keyClickSpecial: CTRL not implemented for this platform");
179
#endif
a6ab1de by Enrico Ros at 2009-02-21 180
            break;
181
182
        default:
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 183
            qWarning( "InputUtils::keyClickSpecial: cannot get keycode of special qtkey '%d', please provide the conversion.", qtKeyCode );
a6ab1de by Enrico Ros at 2009-02-21 184
            break;
185
    }
c03b1c8 by Enrico Ros on Win32 at 2009-06-03 186
187
#if defined(Q_WS_WIN)
188
    // send keypress and keyrelease
189
    if ( vinput[0].ki.wVk ) {
190
        vinput[1] = vinput[0];
191
        vinput[1].ki.dwFlags |= KEYEVENTF_KEYUP;
192
        ::SendInput( 2, vinput, sizeof(INPUT) );
193
    }
a6ab1de by Enrico Ros at 2009-02-21 194
#endif
195
}