rubyxmacro 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +39 -0
- data/Gemfile +4 -0
- data/README.markdown +56 -0
- data/Rakefile +16 -0
- data/ext/rubyxmacro/controlx.h +199 -0
- data/ext/rubyxmacro/extconf.rb +23 -0
- data/ext/rubyxmacro/opendisplay.h +66 -0
- data/ext/rubyxmacro/rubyxmacro.c +267 -0
- data/lib/keycodes.rb +90 -0
- data/lib/rubyxmacro/version.rb +3 -0
- data/lib/rubyxmacro.rb +37 -0
- data/rubyxmacro.gemspec +23 -0
- data/test/test.rb +29 -0
- metadata +60 -0
data/.gitignore
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
tmp/*
|
2
|
+
pkg/*
|
3
|
+
*.swp
|
4
|
+
*.gem
|
5
|
+
|
6
|
+
# Compiled source #
|
7
|
+
###################
|
8
|
+
*.com
|
9
|
+
*.class
|
10
|
+
*.dll
|
11
|
+
*.exe
|
12
|
+
*.o
|
13
|
+
*.so
|
14
|
+
|
15
|
+
# Packages #
|
16
|
+
############
|
17
|
+
# it's better to unpack these files and commit the raw source
|
18
|
+
# git has its own built in compression methods
|
19
|
+
*.7z
|
20
|
+
*.dmg
|
21
|
+
*.gz
|
22
|
+
*.iso
|
23
|
+
*.jar
|
24
|
+
*.rar
|
25
|
+
*.tar
|
26
|
+
*.zip
|
27
|
+
|
28
|
+
# Logs and databases #
|
29
|
+
######################
|
30
|
+
*.log
|
31
|
+
*.sql
|
32
|
+
*.sqlite
|
33
|
+
|
34
|
+
# OS generated files #
|
35
|
+
######################
|
36
|
+
.DS_Store?
|
37
|
+
ehthumbs.db
|
38
|
+
Icon?
|
39
|
+
Thumbs.db
|
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# RubyXMacro
|
2
|
+
|
3
|
+
## A ruby gem to automate the mouse and keyboard in X Windows.
|
4
|
+
|
5
|
+
Rubyxmacro allows you to automate mouse and keyboard movements on Linux with Ruby. It was created in order to test flash websites, but it could be used for many other purposes.
|
6
|
+
|
7
|
+
The project is hosted on github at [http://github.com/mattddowney/rubyxmacro](http://github.com/mattddowney/rubyxmacro)
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
Your system needs to have the Xtst library installed.
|
12
|
+
On Ubuntu, this is as easy as:
|
13
|
+
sudo apt-get install libxtst-dev
|
14
|
+
On Fedora, try:
|
15
|
+
yum install libXtst-devel
|
16
|
+
|
17
|
+
Then, just install with rubygems:
|
18
|
+
|
19
|
+
gem install rubyxmacro
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Create a display:
|
24
|
+
|
25
|
+
require 'rubyxmacro'
|
26
|
+
d = RubyXMacro::Display.new
|
27
|
+
|
28
|
+
Move the mouse:
|
29
|
+
|
30
|
+
d.moveMouse(100,100)
|
31
|
+
|
32
|
+
Click the mouse:
|
33
|
+
|
34
|
+
d.click
|
35
|
+
d.rightClick
|
36
|
+
|
37
|
+
Type a string of keys:
|
38
|
+
|
39
|
+
d.sendKeys('Hello World!')
|
40
|
+
|
41
|
+
Other methods:
|
42
|
+
|
43
|
+
d.mouseDown #press and hold the mouse button down until mouseUp
|
44
|
+
d.mouseUp #release the mouse button
|
45
|
+
d.rightMouseDown #press and hold the right mouse button down until rightMouseUp
|
46
|
+
d.rightMouseUp #release the right mouse button
|
47
|
+
|
48
|
+
d.keyPress #press a key, only supports letters and numerals
|
49
|
+
d.keycodePress(keycodeNum) #press a key based on it's keycode
|
50
|
+
d.keycodeShiftPress(keycodeNum) #hold down shift, then press key
|
51
|
+
d.keycodeDown(keycodeNum) #press and hold down key with the specified keycode
|
52
|
+
d.keycodeUp(keycodeNum) #release the key with the specified keycode
|
53
|
+
|
54
|
+
## Author
|
55
|
+
|
56
|
+
Matthew Downey - [http://www.writehack.com](http://www.writehack.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "bundler"
|
4
|
+
require "rake/extensiontask"
|
5
|
+
|
6
|
+
Rake::ExtensionTask.new("rubyxmacro") do |extension|
|
7
|
+
extension.lib_dir = "lib/rubyxmacro"
|
8
|
+
end
|
9
|
+
|
10
|
+
task :chmod do
|
11
|
+
File.chmod(0775, 'lib/rubyxmacro/rubyxmacro.so')
|
12
|
+
end
|
13
|
+
|
14
|
+
task :build => [:clean, :compile, :chmod]
|
15
|
+
|
16
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,199 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
*
|
3
|
+
* controlx.h
|
4
|
+
* Copyright (C) 2010 Matthew Downey <mattddowney@gmail*NOSPAM*.com>
|
5
|
+
*
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
9
|
+
* (at your option) any later version.
|
10
|
+
*
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
* GNU General Public License for more details.
|
15
|
+
*
|
16
|
+
* You should have received a copy of the GNU General Public License
|
17
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
*
|
19
|
+
****************************************************************************/
|
20
|
+
|
21
|
+
#include "opendisplay.h"
|
22
|
+
|
23
|
+
/* Globals */
|
24
|
+
Display * display;
|
25
|
+
const int DELAY = 10;
|
26
|
+
const int LEFT_MOUSE_BUTTON = 1;
|
27
|
+
const int RIGHT_MOUSE_BUTTON = 3;
|
28
|
+
const int SHIFT_KEYCODE = 50;
|
29
|
+
|
30
|
+
/* Open the default display.
|
31
|
+
* The default display is contained in the $DISPLAY environment variable. */
|
32
|
+
void openDefaultDisplay() {
|
33
|
+
display = openDisplay(getenv("DISPLAY"));
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
|
37
|
+
/*****************
|
38
|
+
* *
|
39
|
+
* Mouse Related *
|
40
|
+
* *
|
41
|
+
*****************/
|
42
|
+
|
43
|
+
/* push a button down on the mouse */
|
44
|
+
void buttonDown(int buttonNum) {
|
45
|
+
XTestFakeButtonEvent(display, buttonNum, 1, DELAY);
|
46
|
+
XFlush(display); /* flush the buffer to actually make the change */
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* release a button on the mouse */
|
51
|
+
void buttonUp(int buttonNum) {
|
52
|
+
XTestFakeButtonEvent(display, buttonNum, 0, DELAY);
|
53
|
+
XFlush(display); /* flush the buffer to actually make the change */
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
57
|
+
/* click a button on the mouse */
|
58
|
+
void buttonClick(int buttonNum) {
|
59
|
+
buttonDown(buttonNum);
|
60
|
+
buttonUp(buttonNum);
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
/* Move the mouse pointer to position (x,y). */
|
65
|
+
void moveMouse(int x, int y)
|
66
|
+
{
|
67
|
+
XTestFakeMotionEvent(display, -1, x, y, DELAY);
|
68
|
+
XFlush(display); /* flush the buffer to actually make the change */
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
|
72
|
+
/* Left-click the mouse. */
|
73
|
+
void click()
|
74
|
+
{
|
75
|
+
buttonClick(LEFT_MOUSE_BUTTON);
|
76
|
+
return;
|
77
|
+
}
|
78
|
+
|
79
|
+
/* Hold the left mouse button down until mouseUp. */
|
80
|
+
void mouseDown()
|
81
|
+
{
|
82
|
+
buttonDown(LEFT_MOUSE_BUTTON);
|
83
|
+
return;
|
84
|
+
}
|
85
|
+
|
86
|
+
/* Release the left mouse button. Usually used after mouseDown. */
|
87
|
+
void mouseUp()
|
88
|
+
{
|
89
|
+
buttonUp(LEFT_MOUSE_BUTTON);
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
|
93
|
+
/* Right-click the mouse. */
|
94
|
+
void rightClick()
|
95
|
+
{
|
96
|
+
buttonClick(RIGHT_MOUSE_BUTTON);
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
|
100
|
+
/* Hold the right mouse button down until rightMouseUp. */
|
101
|
+
void rightMouseDown()
|
102
|
+
{
|
103
|
+
buttonDown(RIGHT_MOUSE_BUTTON);
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
|
107
|
+
/* Release the right mouse button. Usually used after rightMouseDown. */
|
108
|
+
void rightMouseUp()
|
109
|
+
{
|
110
|
+
buttonUp(RIGHT_MOUSE_BUTTON);
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
|
114
|
+
/********************
|
115
|
+
* *
|
116
|
+
* Keyboard Related *
|
117
|
+
* *
|
118
|
+
********************/
|
119
|
+
|
120
|
+
/* Hold down the key with the value keycode until keycodeUp. */
|
121
|
+
void keycodeDown(int keycode)
|
122
|
+
{
|
123
|
+
XTestFakeKeyEvent(display, keycode, 1, DELAY);
|
124
|
+
XFlush(display); /* flush the buffer to actually make the change */
|
125
|
+
return;
|
126
|
+
}
|
127
|
+
|
128
|
+
/* Release the key with the value keycode. Usually used after keycodeDown. */
|
129
|
+
void keycodeUp(int keycode)
|
130
|
+
{
|
131
|
+
XTestFakeKeyEvent(display, keycode, 0, DELAY);
|
132
|
+
XFlush(display); /* flush the buffer to actually make the change */
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
|
136
|
+
/* Press and release the key with the value keycode. */
|
137
|
+
void keycodePress(int keycode)
|
138
|
+
{
|
139
|
+
keycodeDown(keycode);
|
140
|
+
keycodeUp(keycode);
|
141
|
+
return;
|
142
|
+
}
|
143
|
+
|
144
|
+
/* Hold down shift, then press and release the key with the value keycode. */
|
145
|
+
void keycodeShiftPress(int keycode)
|
146
|
+
{
|
147
|
+
keycodeDown(SHIFT_KEYCODE);
|
148
|
+
keycodePress(keycode);
|
149
|
+
keycodeUp(SHIFT_KEYCODE);
|
150
|
+
return;
|
151
|
+
}
|
152
|
+
|
153
|
+
/* Convert a string to it's keycode. */
|
154
|
+
int stringToKeycode(char * key)
|
155
|
+
{
|
156
|
+
KeySym keyS;
|
157
|
+
KeyCode keyC;
|
158
|
+
|
159
|
+
keyS = XStringToKeysym(key);
|
160
|
+
|
161
|
+
if((keyC = XKeysymToKeycode(display, keyS)) == 0)
|
162
|
+
{
|
163
|
+
fprintf(stderr, "Could not get keycode for %s", key);
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
else
|
167
|
+
return ((int)keyC);
|
168
|
+
}
|
169
|
+
|
170
|
+
/* Hold down the key until keyUp. */
|
171
|
+
void keyDown(char * key)
|
172
|
+
{
|
173
|
+
keycodeDown(stringToKeycode(key));
|
174
|
+
return;
|
175
|
+
}
|
176
|
+
|
177
|
+
/* Release the key. Usually used after keyDown. */
|
178
|
+
void keyUp(char * key)
|
179
|
+
{
|
180
|
+
keycodeUp(stringToKeycode(key));
|
181
|
+
return;
|
182
|
+
}
|
183
|
+
|
184
|
+
/* Press and release the key. */
|
185
|
+
/* needs work to handle special characters */
|
186
|
+
void keyPress(char * key)
|
187
|
+
{
|
188
|
+
KeySym keyS, lowercase, uppercase;
|
189
|
+
|
190
|
+
keyS = XStringToKeysym(key);
|
191
|
+
XConvertCase(keyS, &lowercase, &uppercase);
|
192
|
+
|
193
|
+
if (keyS == lowercase)
|
194
|
+
keycodePress(stringToKeycode(key));
|
195
|
+
else /* uppercase */
|
196
|
+
keycodeShiftPress(stringToKeycode(key));
|
197
|
+
|
198
|
+
return;
|
199
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# extconf.rb
|
2
|
+
# Copyright (C) 2010 Matthew Downey <mattddowney@gmail-NOSPAM-.com>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'mkmf'
|
18
|
+
if have_library("Xtst") then
|
19
|
+
create_makefile("rubyxmacro/rubyxmacro")
|
20
|
+
else
|
21
|
+
puts "Cannot find Xtst library."
|
22
|
+
puts "Try apt-get install libxtst-dev"
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
*
|
3
|
+
* opendisplay.h - a function to open an X11 display.
|
4
|
+
* Portions Copyright (C) 2010 Matthew Downey <mattddowney@gmail-NOSPAM-.com>
|
5
|
+
*
|
6
|
+
* This code was copied and modified from:
|
7
|
+
* xmacro (http://xmacro.sourceforge.net/) which is:
|
8
|
+
* Copyright (C) 2000 Gabor Keresztfalvi <keresztg@mail.com>
|
9
|
+
*
|
10
|
+
* Which was based heavily on:
|
11
|
+
* xremote (http://infa.abo.fi/~chakie/xremote/) which is:
|
12
|
+
* Copyright (C) 2000 Jan Ekholm <chakie@infa.abo.fi>
|
13
|
+
*
|
14
|
+
* This program is free software: you can redistribute it and/or modify
|
15
|
+
* it under the terms of the GNU General Public License as published by
|
16
|
+
* the Free Software Foundation, either version 3 of the License, or
|
17
|
+
* (at your option) any later version.
|
18
|
+
*
|
19
|
+
* This program is distributed in the hope that it will be useful,
|
20
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
22
|
+
* GNU General Public License for more details.
|
23
|
+
*
|
24
|
+
* You should have received a copy of the GNU General Public License
|
25
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
26
|
+
*
|
27
|
+
****************************************************************************/
|
28
|
+
|
29
|
+
#include <X11/extensions/XTest.h>
|
30
|
+
|
31
|
+
// open the X11 display
|
32
|
+
Display * openDisplay (const char * displayName) {
|
33
|
+
int event, error, major, minor;
|
34
|
+
|
35
|
+
// open the display
|
36
|
+
Display * xDisplay = XOpenDisplay(displayName);
|
37
|
+
|
38
|
+
// did we get it?
|
39
|
+
if(!xDisplay) {
|
40
|
+
// nope, so show error and abort
|
41
|
+
fprintf(stderr, "could not open display \"%s\", aborting.\n", XDisplayName(displayName));
|
42
|
+
exit(EXIT_FAILURE);
|
43
|
+
}
|
44
|
+
|
45
|
+
// does the remote display have the Xtest-extension?
|
46
|
+
if(!XTestQueryExtension(xDisplay, &event, &error, &major, &minor)) {
|
47
|
+
// nope, extension not supported
|
48
|
+
fprintf(stderr, "XTest extension not supported on server \"%s\", aborting.\n", DisplayString(xDisplay));
|
49
|
+
|
50
|
+
// close the display and go away
|
51
|
+
XCloseDisplay(xDisplay);
|
52
|
+
exit(EXIT_FAILURE);
|
53
|
+
}
|
54
|
+
|
55
|
+
// take control of the server
|
56
|
+
XTestGrabControl(xDisplay, 1);
|
57
|
+
|
58
|
+
// sync the server
|
59
|
+
XSync(xDisplay, 1);
|
60
|
+
|
61
|
+
// discard all events
|
62
|
+
XTestDiscard (xDisplay);
|
63
|
+
|
64
|
+
// return the display
|
65
|
+
return xDisplay;
|
66
|
+
}
|
@@ -0,0 +1,267 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
*
|
3
|
+
* rubyxmacro.c
|
4
|
+
* Copyright (C) 2010 Matthew Downey <mattddowney@gmail*NOSPAM*.com>
|
5
|
+
*
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
8
|
+
* the Free Software Foundation, either version 3 of the License, or
|
9
|
+
* (at your option) any later version.
|
10
|
+
*
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
* GNU General Public License for more details.
|
15
|
+
*
|
16
|
+
* You should have received a copy of the GNU General Public License
|
17
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
*
|
19
|
+
****************************************************************************/
|
20
|
+
|
21
|
+
#include "ruby.h"
|
22
|
+
#include "controlx.h"
|
23
|
+
|
24
|
+
/*****************************
|
25
|
+
* *
|
26
|
+
* Methods Exposed to Ruby *
|
27
|
+
* *
|
28
|
+
*****************************/
|
29
|
+
|
30
|
+
/*
|
31
|
+
* Document-method: initialize
|
32
|
+
*
|
33
|
+
* Get a RubyXMacro object with the default display.
|
34
|
+
* The default display is stored in the $DISPLAY environment variable.
|
35
|
+
*
|
36
|
+
* display = RubyXMacro.new
|
37
|
+
*/
|
38
|
+
static VALUE init(VALUE self)
|
39
|
+
{
|
40
|
+
openDefaultDisplay();
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
|
44
|
+
/*******************
|
45
|
+
* *
|
46
|
+
* Mouse Related *
|
47
|
+
* *
|
48
|
+
*******************/
|
49
|
+
|
50
|
+
/*
|
51
|
+
* Document-method: move
|
52
|
+
*
|
53
|
+
* Move the mouse pointer to position (x,y).
|
54
|
+
*
|
55
|
+
* display.move(int_x, int_y)
|
56
|
+
*/
|
57
|
+
static VALUE method_moveMouse(VALUE self, VALUE x, VALUE y)
|
58
|
+
{
|
59
|
+
moveMouse(NUM2INT(x), NUM2INT(y));
|
60
|
+
return Qnil;
|
61
|
+
}
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Document-method: click
|
65
|
+
*
|
66
|
+
* Left-click the mouse.
|
67
|
+
*
|
68
|
+
* display.click
|
69
|
+
*/
|
70
|
+
static VALUE method_click(VALUE self)
|
71
|
+
{
|
72
|
+
click();
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
/*
|
77
|
+
* Document-method: mouseDown
|
78
|
+
*
|
79
|
+
* Hold the left mouse button down until mouseUp.
|
80
|
+
*
|
81
|
+
* display.mouseDown
|
82
|
+
*/
|
83
|
+
static VALUE method_mouseDown(VALUE self)
|
84
|
+
{
|
85
|
+
mouseDown();
|
86
|
+
return Qnil;
|
87
|
+
}
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Document-method: mouseUp
|
91
|
+
*
|
92
|
+
* Release the left mouse button. Usually used after mouseDown.
|
93
|
+
*
|
94
|
+
* display.mouseUp
|
95
|
+
*/
|
96
|
+
static VALUE method_mouseUp(VALUE self)
|
97
|
+
{
|
98
|
+
mouseUp();
|
99
|
+
return Qnil;
|
100
|
+
}
|
101
|
+
|
102
|
+
/*
|
103
|
+
* Document-method: rightClick
|
104
|
+
*
|
105
|
+
* Right-click the mouse.
|
106
|
+
*
|
107
|
+
* display.rightClick
|
108
|
+
*/
|
109
|
+
static VALUE method_rightClick(VALUE self)
|
110
|
+
{
|
111
|
+
rightClick();
|
112
|
+
return Qnil;
|
113
|
+
}
|
114
|
+
|
115
|
+
/*
|
116
|
+
* Document-method: rightMouseDown
|
117
|
+
*
|
118
|
+
* Hold the right mouse button down until rightMouseUp.
|
119
|
+
*
|
120
|
+
* display.rightMouseDown
|
121
|
+
*/
|
122
|
+
static VALUE method_rightMouseDown(VALUE self)
|
123
|
+
{
|
124
|
+
rightMouseDown();
|
125
|
+
return Qnil;
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* Document-method: rightMouseUp
|
130
|
+
*
|
131
|
+
* Release the right mouse button. Usually used after rightMouseDown.
|
132
|
+
*
|
133
|
+
* display.rightMouseUp
|
134
|
+
*/
|
135
|
+
static VALUE method_rightMouseUp(VALUE self)
|
136
|
+
{
|
137
|
+
rightMouseUp();
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
141
|
+
/**********************
|
142
|
+
* *
|
143
|
+
* Keyboard Related *
|
144
|
+
* *
|
145
|
+
**********************/
|
146
|
+
|
147
|
+
/*
|
148
|
+
* Document-method: keycodeDown
|
149
|
+
*
|
150
|
+
* Hold down the key with the value keycode until keycodeUp.
|
151
|
+
*
|
152
|
+
* display.keycodeDown(int_keycode)
|
153
|
+
*/
|
154
|
+
static VALUE method_keycodeDown(VALUE self, VALUE keycode)
|
155
|
+
{
|
156
|
+
keycodeDown(NUM2INT(keycode));
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
|
160
|
+
/*
|
161
|
+
* Document-method: keycodeUp
|
162
|
+
*
|
163
|
+
* Release the key with the value keycode. Usually used after keycodeDown.
|
164
|
+
*
|
165
|
+
* display.keycodeUp(int_keycode)
|
166
|
+
*/
|
167
|
+
static VALUE method_keycodeUp(VALUE self, VALUE keycode)
|
168
|
+
{
|
169
|
+
keycodeUp(NUM2INT(keycode));
|
170
|
+
return Qnil;
|
171
|
+
}
|
172
|
+
|
173
|
+
/*
|
174
|
+
* Document-method: keycodePress
|
175
|
+
*
|
176
|
+
* Press and release the key with the value keycode.
|
177
|
+
*
|
178
|
+
* display.keycodePress(int_keycode)
|
179
|
+
*/
|
180
|
+
static VALUE method_keycodePress(VALUE self, VALUE keycode)
|
181
|
+
{
|
182
|
+
keycodePress(NUM2INT(keycode));
|
183
|
+
return Qnil;
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* Document-method: keycodeShiftPress
|
188
|
+
*
|
189
|
+
* Hold down shift, then press and release the key with the value keycode.
|
190
|
+
*
|
191
|
+
* display.keycodeShiftPress(int_keycode)
|
192
|
+
*/
|
193
|
+
static VALUE method_keycodeShiftPress(VALUE self, VALUE keycode)
|
194
|
+
{
|
195
|
+
keycodeShiftPress(NUM2INT(keycode));
|
196
|
+
return Qnil;
|
197
|
+
}
|
198
|
+
|
199
|
+
/*
|
200
|
+
* Document-method: keyDown
|
201
|
+
*
|
202
|
+
* Hold down the key until keyUp.
|
203
|
+
*
|
204
|
+
* display.keyDown(str_key)
|
205
|
+
*/
|
206
|
+
static VALUE method_keyDown(VALUE self, VALUE keycode)
|
207
|
+
{
|
208
|
+
keyDown(StringValuePtr(keycode));
|
209
|
+
return Qnil;
|
210
|
+
}
|
211
|
+
|
212
|
+
/*
|
213
|
+
* Document-method: keyUp
|
214
|
+
*
|
215
|
+
* Release the key. Usually used after keyDown.
|
216
|
+
*
|
217
|
+
* display.keyUp(str_key)
|
218
|
+
*/
|
219
|
+
static VALUE method_keyUp(VALUE self, VALUE keycode)
|
220
|
+
{
|
221
|
+
keyUp(StringValuePtr(keycode));
|
222
|
+
return Qnil;
|
223
|
+
}
|
224
|
+
|
225
|
+
/*
|
226
|
+
* Document-method: keyPress
|
227
|
+
*
|
228
|
+
* Press and release the key.
|
229
|
+
*
|
230
|
+
* display.keyPress(str_key)
|
231
|
+
*/
|
232
|
+
static VALUE method_keyPress(VALUE self, VALUE key)
|
233
|
+
{
|
234
|
+
keyPress(StringValuePtr(key));
|
235
|
+
return Qnil;
|
236
|
+
}
|
237
|
+
|
238
|
+
/******************
|
239
|
+
* *
|
240
|
+
* Ruby Related *
|
241
|
+
* *
|
242
|
+
******************/
|
243
|
+
|
244
|
+
VALUE rubyXMacro;
|
245
|
+
VALUE displayClass;
|
246
|
+
|
247
|
+
/* Automate the mouse and keyboard in X. */
|
248
|
+
void Init_rubyxmacro()
|
249
|
+
{
|
250
|
+
rubyXMacro = rb_define_module("RubyXMacro");
|
251
|
+
displayClass = rb_define_class_under(rubyXMacro, "Display", rb_cObject);
|
252
|
+
rb_define_method(displayClass, "initialize", init, 0);
|
253
|
+
rb_define_method(displayClass, "moveMouse", method_moveMouse, 2);
|
254
|
+
rb_define_method(displayClass, "click", method_click, 0);
|
255
|
+
rb_define_method(displayClass, "mouseDown", method_mouseDown, 0);
|
256
|
+
rb_define_method(displayClass, "mouseUp", method_mouseUp, 0);
|
257
|
+
rb_define_method(displayClass, "rightClick", method_rightClick, 0);
|
258
|
+
rb_define_method(displayClass, "rightMouseDown", method_rightMouseDown, 0);
|
259
|
+
rb_define_method(displayClass, "rightMouseUp", method_rightMouseUp, 0);
|
260
|
+
rb_define_method(displayClass, "keycodeDown", method_keycodeDown, 1);
|
261
|
+
rb_define_method(displayClass, "keycodeUp", method_keycodeUp, 1);
|
262
|
+
rb_define_method(displayClass, "keycodePress", method_keycodePress, 1);
|
263
|
+
rb_define_method(displayClass, "keycodeShiftPress", method_keycodeShiftPress, 1);
|
264
|
+
rb_define_method(displayClass, "keyDown", method_keyDown, 1);
|
265
|
+
rb_define_method(displayClass, "keyUp", method_keyUp, 1);
|
266
|
+
rb_define_method(displayClass, "keyPress", method_keyPress, 1);;
|
267
|
+
}
|
data/lib/keycodes.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module RubyXMacro
|
2
|
+
SPECIAL_KEYCODES = {
|
3
|
+
'BACKSPACE' => 22,
|
4
|
+
'BS' => 22,
|
5
|
+
'BKSP' => 22,
|
6
|
+
'BREAK' => 127,
|
7
|
+
'CAPSLOCK' => 66,
|
8
|
+
'DELETE' => 119,
|
9
|
+
'DEL' => 119,
|
10
|
+
'DOWN' => 116,
|
11
|
+
'END' => 115,
|
12
|
+
'ENTER' => 36,
|
13
|
+
'ESC' => 9,
|
14
|
+
#'HELP' =>
|
15
|
+
'HOME' => 110,
|
16
|
+
'INSERT' => 118,
|
17
|
+
'INS' => 118,
|
18
|
+
'LEFT' => 113,
|
19
|
+
'NUMLOCK' => 77,
|
20
|
+
'PGDN' => 117,
|
21
|
+
'PGUP' => 112,
|
22
|
+
#'PRTSC' =>
|
23
|
+
'RIGHT' => 114,
|
24
|
+
#'SCROLLLOCK' =>
|
25
|
+
'TAB' => 23,
|
26
|
+
'UP' => 111,
|
27
|
+
'F1' => 67,
|
28
|
+
'F2' => 68,
|
29
|
+
'F3' => 69,
|
30
|
+
'F4' => 70,
|
31
|
+
'F5' => 71,
|
32
|
+
'F6' => 72,
|
33
|
+
'F7' => 73,
|
34
|
+
'F8' => 74,
|
35
|
+
'F9' => 75,
|
36
|
+
'F10' => 76,
|
37
|
+
'F11' => 95,
|
38
|
+
'F12' => 96
|
39
|
+
#'F13' =>
|
40
|
+
#'F14' =>
|
41
|
+
#'F15' =>
|
42
|
+
#'F16' =>
|
43
|
+
}
|
44
|
+
|
45
|
+
KEYCODES = {
|
46
|
+
' ' => '65l',
|
47
|
+
'`' => '49l',
|
48
|
+
'~' => '49u',
|
49
|
+
'1' => '10l',
|
50
|
+
'!' => '10u',
|
51
|
+
'2' => '11l',
|
52
|
+
'@' => '11u',
|
53
|
+
'3' => '12l',
|
54
|
+
'#' => '12u',
|
55
|
+
'4' => '13l',
|
56
|
+
'$' => '13u',
|
57
|
+
'5' => '14l',
|
58
|
+
'%' => '14u',
|
59
|
+
'6' => '15l',
|
60
|
+
'^' => '15u',
|
61
|
+
'7' => '16l',
|
62
|
+
'&' => '16u',
|
63
|
+
'8' => '17l',
|
64
|
+
'*' => '17u',
|
65
|
+
'9' => '18l',
|
66
|
+
'(' => '18u',
|
67
|
+
'0' => '19l',
|
68
|
+
')' => '19u',
|
69
|
+
'-' => '20l',
|
70
|
+
'_' => '20u',
|
71
|
+
'=' => '21l',
|
72
|
+
'+' => '21u',
|
73
|
+
'[' => '34l',
|
74
|
+
'{' => '34u',
|
75
|
+
']' => '35l',
|
76
|
+
'}' => '35u',
|
77
|
+
'\\' => '51l',
|
78
|
+
'|' => '51u',
|
79
|
+
';' => '47l',
|
80
|
+
':' => '47u',
|
81
|
+
"'" => '48l',
|
82
|
+
'"' => '48u',
|
83
|
+
',' => '59l',
|
84
|
+
'<' => '59u',
|
85
|
+
'.' => '60l',
|
86
|
+
'>' => '60u',
|
87
|
+
'/' => '61l',
|
88
|
+
'?' => '61u'
|
89
|
+
}
|
90
|
+
end
|
data/lib/rubyxmacro.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubyxmacro/rubyxmacro'
|
2
|
+
require 'keycodes'
|
3
|
+
|
4
|
+
module RubyXMacro
|
5
|
+
class Display
|
6
|
+
# Press and release a string of keys.
|
7
|
+
def sendKeys(keyString)
|
8
|
+
while keyString.length > 0 do
|
9
|
+
keyStringArray = keyString.partition(/\{(.*?)\}/)
|
10
|
+
keyString = keyStringArray[0]
|
11
|
+
|
12
|
+
keyString.each_char do |key|
|
13
|
+
if RubyXMacro::KEYCODES[key] == nil then
|
14
|
+
self.keyPress(key)
|
15
|
+
else
|
16
|
+
keycode = RubyXMacro::KEYCODES[key]
|
17
|
+
keyCase = keycode[-1]
|
18
|
+
keycode = keycode.chop.to_i
|
19
|
+
if keyCase == 'l' then
|
20
|
+
keycodePress(keycode)
|
21
|
+
else
|
22
|
+
keycodeShiftPress(keycode)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
specialKey = keyStringArray[1].slice(1..(keyStringArray[1].length - 2))
|
28
|
+
if specialKey != nil && specialKey.length > 0 then
|
29
|
+
specialKey.upcase!
|
30
|
+
keycodePress(RubyXMacro::SPECIAL_KEYCODES[specialKey])
|
31
|
+
end
|
32
|
+
|
33
|
+
keyString = keyStringArray[2]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/rubyxmacro.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rubyxmacro/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rubyxmacro"
|
7
|
+
s.version = RubyXMacro::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Matthew Downey"]
|
10
|
+
s.email = ["mattddowney@gmail.com"]
|
11
|
+
s.homepage = "http://www.github.com/mattddowney/rubyxmacro"
|
12
|
+
s.summary = "Automate the mouse and keyboard in X"
|
13
|
+
s.description = "A ruby C extension to automate the mouse and keyboard in X Windows"
|
14
|
+
|
15
|
+
#s.rubyforge_project = "rubyxmacro"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n") #<< "lib/rubyxmacro/rubyxmacro.so"
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
# s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib", "ext/rubyxmacro"]
|
21
|
+
s.extensions = ["ext/rubyxmacro/extconf.rb"]
|
22
|
+
#s.executables = ["rubyxmacro"]
|
23
|
+
end
|
data/test/test.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubyxmacro'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class TestRubyXMacro < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@d = RubyXMacro::Display.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_display
|
11
|
+
assert_instance_of(RubyXMacro::Display, @d)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_mouse_1
|
15
|
+
assert_nil(@d.moveMouse(100,200))
|
16
|
+
assert_nil(@d.click)
|
17
|
+
sleep 0.1
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_special
|
21
|
+
assert_nil(@d.sendKeys '~!@#$%^&*()_+{}|:"<>?{ENTER}')
|
22
|
+
assert_nil(@d.sendKeys "`1234567890-=[]\;',./{ENTER}")
|
23
|
+
assert_nil(@d.sendKeys "This text should be highlighted")
|
24
|
+
3.times do
|
25
|
+
assert_nil(@d.click)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubyxmacro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthew Downey
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-20 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: A ruby C extension to automate the mouse and keyboard in X Windows
|
15
|
+
email:
|
16
|
+
- mattddowney@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions:
|
19
|
+
- ext/rubyxmacro/extconf.rb
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- README.markdown
|
25
|
+
- Rakefile
|
26
|
+
- ext/rubyxmacro/controlx.h
|
27
|
+
- ext/rubyxmacro/extconf.rb
|
28
|
+
- ext/rubyxmacro/opendisplay.h
|
29
|
+
- ext/rubyxmacro/rubyxmacro.c
|
30
|
+
- lib/keycodes.rb
|
31
|
+
- lib/rubyxmacro.rb
|
32
|
+
- lib/rubyxmacro/version.rb
|
33
|
+
- rubyxmacro.gemspec
|
34
|
+
- test/test.rb
|
35
|
+
homepage: http://www.github.com/mattddowney/rubyxmacro
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
- ext/rubyxmacro
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.6
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Automate the mouse and keyboard in X
|
60
|
+
test_files: []
|